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; }
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; }