コード例 #1
0
ファイル: sa1100-audio.c プロジェクト: muromec/linux-ezxdev
int sa1100_audio_attach(struct inode *inode, struct file *file,
			  audio_state_t *state)
{
	int err, need_tx_dma;

	DPRINTK("audio_open\n");

	down(&state->sem);

	/* access control */
	err = -ENODEV;
	if ((file->f_mode & FMODE_WRITE) && !state->output_stream)
		goto out;
	if ((file->f_mode & FMODE_READ) && !state->input_stream)
		goto out;
	err = -EBUSY;
	if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
		goto out;
	if ((file->f_mode & FMODE_READ) && state->rd_ref)
		goto out;
	err = -EINVAL;
	if ((file->f_mode & FMODE_READ) && state->need_tx_for_rx && !state->output_stream)
		goto out;

	/* request DMA channels */
	if (state->skip_dma_init)
		goto skip_dma;
	need_tx_dma = ((file->f_mode & FMODE_WRITE) ||
		       ((file->f_mode & FMODE_READ) && state->need_tx_for_rx));
	if (state->wr_ref || (state->rd_ref && state->need_tx_for_rx))
		need_tx_dma = 0;
	if (need_tx_dma) {
		err = sa1100_request_dma(&state->output_stream->dma_ch,
					 state->output_id,
					 state->output_dma);
		if (err)
			goto out;
	}
	if (file->f_mode & FMODE_READ) {
		err = sa1100_request_dma(&state->input_stream->dma_ch,
					 state->input_id,
					 state->input_dma);
		if (err) {
			if (need_tx_dma)
				sa1100_free_dma(state->output_stream->dma_ch);
			goto out;
		}
	}
skip_dma:

	/* now complete initialisation */
	if (!AUDIO_ACTIVE(state)) {
		if (state->hw_init)
			state->hw_init(state->data);
#ifdef CONFIG_PM
		state->pm_dev = pm_register(PM_SYS_DEV, 0, audio_pm_callback);
		if (state->pm_dev)
			state->pm_dev->data = state;
#endif
	}

	if ((file->f_mode & FMODE_WRITE)) {
		state->wr_ref = 1;
		audio_clear_buf(state->output_stream);
		state->output_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;
		state->output_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;
		state->output_stream->mapped = 0;
		sa1100_dma_set_callback(state->output_stream->dma_ch,
					audio_dmaout_done_callback);
		init_waitqueue_head(&state->output_stream->wq);
	}
	if (file->f_mode & FMODE_READ) {
		state->rd_ref = 1;
		audio_clear_buf(state->input_stream);
		state->input_stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;
		state->input_stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;
		state->input_stream->mapped = 0;
		sa1100_dma_set_callback(state->input_stream->dma_ch,
					audio_dmain_done_callback);
		init_waitqueue_head(&state->input_stream->wq);
	}

	file->private_data	= state;
	file->f_op->release	= audio_release;
	file->f_op->write	= audio_write;
	file->f_op->read	= audio_read;
	file->f_op->mmap	= audio_mmap;
	file->f_op->poll	= audio_poll;
	file->f_op->ioctl	= audio_ioctl;
	file->f_op->llseek	= audio_llseek;
	err = 0;

out:
	up(&state->sem);
	return err;
}
コード例 #2
0
ファイル: sa1100_ir.c プロジェクト: froggatt/edimax-br-6528n
static int sa1100_irda_start(struct net_device *dev)
{
	struct sa1100_irda *si = dev->priv;
	int err;

	MOD_INC_USE_COUNT;

	si->speed = 9600;

	err = request_irq(dev->irq, sa1100_irda_irq, 0, dev->name, dev);
	if (err)
		goto err_irq;

	err = sa1100_request_dma(&si->rxdma, "IrDA receive", DMA_Ser2HSSPRd);
	if (err)
		goto err_rx_dma;

	err = sa1100_request_dma(&si->txdma, "IrDA transmit", DMA_Ser2HSSPWr);
	if (err)
		goto err_tx_dma;

	/*
	 * The interrupt must remain disabled for now.
	 */
	disable_irq(dev->irq);

	/*
	 * Setup the serial port for the specified speed.
	 */
	err = sa1100_irda_startup(si);
	if (err)
		goto err_startup;

	/*
	 * Open a new IrLAP layer instance.
	 */
	si->irlap = irlap_open(dev, &si->qos, "sa1100");
	err = -ENOMEM;
	if (!si->irlap)
		goto err_irlap;

	sa1100_dma_set_callback(si->txdma, sa1100_irda_txdma_irq);

	/*
	 * Now enable the interrupt and start the queue
	 */
	si->open = 1;
	sa1100_set_power(si, power_level); /* low power mode */
	enable_irq(dev->irq);
	netif_start_queue(dev);
	return 0;

err_irlap:
	si->open = 0;
	sa1100_irda_shutdown(si);
err_startup:
	sa1100_free_dma(si->txdma);
err_tx_dma:
	sa1100_free_dma(si->rxdma);
err_rx_dma:
	free_irq(dev->irq, dev);
err_irq:
	MOD_DEC_USE_COUNT;
	return err;
}