static int pxa95x_pcm_ssp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_pcm_runtime *runtime = substream->runtime; struct pxa95x_runtime_data *prtd = runtime->private_data; struct snd_soc_pcm_runtime *rtd = substream->private_data; struct pxa95x_pcm_dma_params *dma; size_t totsize = params_buffer_bytes(params); size_t period = params_period_bytes(params); pxa_dma_desc *dma_desc; dma_addr_t dma_buff_phys, next_desc_phys; int ret; dma = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? rtd->dai->cpu_dai->playback.dma_data : rtd->dai->cpu_dai->capture.dma_data; /* return if this is a bufferless transfer e.g. * codec <--> BT codec or GSM modem -- lg FIXME */ if (!dma) return 0; /* this may get called several times by oss emulation * with different params */ if (prtd->params == NULL) { prtd->params = dma; ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW, pxa95x_pcm_dma_irq, substream); if (ret < 0) return ret; prtd->dma_ch = ret; } else if (prtd->params != dma) { pxa_free_dma(prtd->dma_ch); prtd->params = dma; ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW, pxa95x_pcm_dma_irq, substream); if (ret < 0) return ret; prtd->dma_ch = ret; } snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); runtime->dma_bytes = totsize; dma_desc = prtd->dma_desc_array; next_desc_phys = prtd->dma_desc_array_phys; dma_buff_phys = runtime->dma_addr; do { next_desc_phys += sizeof(pxa_dma_desc); dma_desc->ddadr = next_desc_phys; if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { dma_desc->dsadr = dma_buff_phys; dma_desc->dtadr = prtd->params->dev_addr; } else { dma_desc->dsadr = prtd->params->dev_addr; dma_desc->dtadr = dma_buff_phys; } if (period > totsize) period = totsize; dma_desc->dcmd = prtd->params->dcmd | period | DCMD_ENDIRQEN; dma_desc++; dma_buff_phys += period; } while (totsize -= period); dma_desc[-1].ddadr = prtd->dma_desc_array_phys; return 0; }
int pxa_audio_attach(struct inode *inode, struct file *file, audio_state_t *state) { audio_stream_t *is = state->input_stream; audio_stream_t *os = state->output_stream; int err; down(&state->sem); /* access control */ err = -ENODEV; if ((file->f_mode & FMODE_WRITE) && !os) goto out; if ((file->f_mode & FMODE_READ) && !is) 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; /* request DMA channels */ if (file->f_mode & FMODE_WRITE) { err = pxa_request_dma(os->name, DMA_PRIO_LOW, audio_dma_irq, os); if (err < 0) goto out; os->dma_ch = err; } if (file->f_mode & FMODE_READ) { err = pxa_request_dma(is->name, DMA_PRIO_LOW, audio_dma_irq, is); if (err < 0) { if (file->f_mode & FMODE_WRITE) { *os->drcmr = 0; pxa_free_dma(os->dma_ch); } goto out; } is->dma_ch = err; } 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 = no_llseek; if ((file->f_mode & FMODE_WRITE)) { state->wr_ref = 1; os->fragsize = AUDIO_FRAGSIZE_DEFAULT; os->nbfrags = AUDIO_NBFRAGS_DEFAULT; os->output = 1; os->mapped = 0; init_waitqueue_head(&os->frag_wq); init_waitqueue_head(&os->stop_wq); *os->drcmr = os->dma_ch | DRCMR_MAPVLD; } if (file->f_mode & FMODE_READ) { state->rd_ref = 1; is->fragsize = AUDIO_FRAGSIZE_DEFAULT; is->nbfrags = AUDIO_NBFRAGS_DEFAULT; is->output = 0; is->mapped = 0; init_waitqueue_head(&is->frag_wq); init_waitqueue_head(&is->stop_wq); *is->drcmr = is->dma_ch | DRCMR_MAPVLD; } err = 0; out: up(&state->sem); return err; }
static int __devinit pxa_ata_probe(struct platform_device *pdev) { struct ata_host *host; struct ata_port *ap; struct pata_pxa_data *data; struct resource *cmd_res; struct resource *ctl_res; struct resource *dma_res; struct resource *irq_res; struct pata_pxa_pdata *pdata = pdev->dev.platform_data; int ret = 0; /* * Resource validation, three resources are needed: * - CMD port base address * - CTL port base address * - DMA port base address * - IRQ pin */ if (pdev->num_resources != 4) { dev_err(&pdev->dev, "invalid number of resources\n"); return -EINVAL; } /* * CMD port base address */ cmd_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (unlikely(cmd_res == NULL)) return -EINVAL; /* * CTL port base address */ ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1); if (unlikely(ctl_res == NULL)) return -EINVAL; /* * DMA port base address */ dma_res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (unlikely(dma_res == NULL)) return -EINVAL; /* * IRQ pin */ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (unlikely(irq_res == NULL)) return -EINVAL; /* * Allocate the host */ host = ata_host_alloc(&pdev->dev, 1); if (!host) return -ENOMEM; ap = host->ports[0]; ap->ops = &pxa_ata_port_ops; ap->pio_mask = ATA_PIO4; ap->mwdma_mask = ATA_MWDMA2; ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, cmd_res->start, resource_size(cmd_res)); ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start, resource_size(ctl_res)); ap->ioaddr.bmdma_addr = devm_ioremap(&pdev->dev, dma_res->start, resource_size(dma_res)); /* * Adjust register offsets */ ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr; ap->ioaddr.data_addr = ap->ioaddr.cmd_addr + (ATA_REG_DATA << pdata->reg_shift); ap->ioaddr.error_addr = ap->ioaddr.cmd_addr + (ATA_REG_ERR << pdata->reg_shift); ap->ioaddr.feature_addr = ap->ioaddr.cmd_addr + (ATA_REG_FEATURE << pdata->reg_shift); ap->ioaddr.nsect_addr = ap->ioaddr.cmd_addr + (ATA_REG_NSECT << pdata->reg_shift); ap->ioaddr.lbal_addr = ap->ioaddr.cmd_addr + (ATA_REG_LBAL << pdata->reg_shift); ap->ioaddr.lbam_addr = ap->ioaddr.cmd_addr + (ATA_REG_LBAM << pdata->reg_shift); ap->ioaddr.lbah_addr = ap->ioaddr.cmd_addr + (ATA_REG_LBAH << pdata->reg_shift); ap->ioaddr.device_addr = ap->ioaddr.cmd_addr + (ATA_REG_DEVICE << pdata->reg_shift); ap->ioaddr.status_addr = ap->ioaddr.cmd_addr + (ATA_REG_STATUS << pdata->reg_shift); ap->ioaddr.command_addr = ap->ioaddr.cmd_addr + (ATA_REG_CMD << pdata->reg_shift); /* * Allocate and load driver's internal data structure */ data = devm_kzalloc(&pdev->dev, sizeof(struct pata_pxa_data), GFP_KERNEL); if (!data) return -ENOMEM; ap->private_data = data; data->dma_dreq = pdata->dma_dreq; data->dma_io_addr = dma_res->start; /* * Allocate space for the DMA descriptors */ data->dma_desc = dmam_alloc_coherent(&pdev->dev, PAGE_SIZE, &data->dma_desc_addr, GFP_KERNEL); if (!data->dma_desc) return -EINVAL; /* * Request the DMA channel */ data->dma_channel = pxa_request_dma(DRV_NAME, DMA_PRIO_LOW, pxa_ata_dma_irq, ap); if (data->dma_channel < 0) return -EBUSY; /* * Stop and clear the DMA channel */ DCSR(data->dma_channel) = 0; /* * Activate the ATA host */ ret = ata_host_activate(host, irq_res->start, ata_sff_interrupt, pdata->irq_flags, &pxa_ata_sht); if (ret) pxa_free_dma(data->dma_channel); return ret; }
static int pxa_irda_start(struct net_device *dev) { struct pxa_irda *si = netdev_priv(dev); int err; si->speed = 9600; err = request_irq(IRQ_STUART, pxa_irda_sir_irq, 0, dev->name, dev); if (err) goto err_irq1; err = request_irq(IRQ_ICP, pxa_irda_fir_irq, 0, dev->name, dev); if (err) goto err_irq2; /* * The interrupt must remain disabled for now. */ disable_irq(IRQ_STUART); disable_irq(IRQ_ICP); err = -EBUSY; si->rxdma = pxa_request_dma("FICP_RX",DMA_PRIO_LOW, pxa_irda_fir_dma_rx_irq, dev); if (si->rxdma < 0) goto err_rx_dma; si->txdma = pxa_request_dma("FICP_TX",DMA_PRIO_LOW, pxa_irda_fir_dma_tx_irq, dev); if (si->txdma < 0) goto err_tx_dma; err = -ENOMEM; si->dma_rx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, &si->dma_rx_buff_phy, GFP_KERNEL ); if (!si->dma_rx_buff) goto err_dma_rx_buff; si->dma_tx_buff = dma_alloc_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, &si->dma_tx_buff_phy, GFP_KERNEL ); if (!si->dma_tx_buff) goto err_dma_tx_buff; /* Setup the serial port for the initial speed. */ pxa_irda_startup(si); /* * Open a new IrLAP layer instance. */ si->irlap = irlap_open(dev, &si->qos, "pxa"); err = -ENOMEM; if (!si->irlap) goto err_irlap; /* * Now enable the interrupt and start the queue */ enable_irq(IRQ_STUART); enable_irq(IRQ_ICP); netif_start_queue(dev); printk(KERN_DEBUG "pxa_ir: irda driver opened\n"); return 0; err_irlap: pxa_irda_shutdown(si); dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_tx_buff, si->dma_tx_buff_phy); err_dma_tx_buff: dma_free_coherent(si->dev, IRDA_FRAME_SIZE_LIMIT, si->dma_rx_buff, si->dma_rx_buff_phy); err_dma_rx_buff: pxa_free_dma(si->txdma); err_tx_dma: pxa_free_dma(si->rxdma); err_rx_dma: free_irq(IRQ_ICP, dev); err_irq2: free_irq(IRQ_STUART, dev); err_irq1: return err; }