static void pxa_irda_startup(struct pxa_irda *si) { /* Disable STUART interrupts */ STIER = 0; /* enable STUART interrupt to the processor */ STMCR = MCR_OUT2; /* configure SIR frame format: StartBit - Data 7 ... Data 0 - Stop Bit */ STLCR = LCR_WLS0 | LCR_WLS1; /* enable FIFO, we use FIFO to improve performance */ STFCR = FCR_TRFIFOE | FCR_ITL_32; /* disable FICP */ ICCR0 = 0; /* configure FICP ICCR2 */ ICCR2 = ICCR2_TXP | ICCR2_TRIG_32; /* configure DMAC */ DRCMR(17) = si->rxdma | DRCMR_MAPVLD; DRCMR(18) = si->txdma | DRCMR_MAPVLD; /* force SIR reinitialization */ si->speed = 4000000; pxa_irda_set_speed(si, 9600); printk(KERN_DEBUG "pxa_ir: irda startup\n"); }
static void pxa_irda_shutdown(struct pxa_irda *si) { unsigned long flags; local_irq_save(flags); /* disable STUART and interrupt */ STIER = 0; /* disable STUART SIR mode */ STISR = 0; /* disable DMA */ DCSR(si->txdma) &= ~DCSR_RUN; DCSR(si->rxdma) &= ~DCSR_RUN; /* disable FICP */ ICCR0 = 0; /* disable the STUART or FICP clocks */ pxa_irda_disable_clk(si); DRCMR(17) = 0; DRCMR(18) = 0; local_irq_restore(flags); /* power off board transceiver */ si->pdata->transceiver_mode(si->dev, IR_OFF); printk(KERN_DEBUG "pxa_ir: irda shutdown\n"); }
int pxa2xx_spi_dma_setup(struct driver_data *drv_data) { struct device *dev = &drv_data->pdev->dev; struct ssp_device *ssp = drv_data->ssp; /* Get two DMA channels (rx and tx) */ drv_data->rx_channel = pxa_request_dma("pxa2xx_spi_ssp_rx", DMA_PRIO_HIGH, pxa2xx_spi_dma_handler, drv_data); if (drv_data->rx_channel < 0) { dev_err(dev, "problem (%d) requesting rx channel\n", drv_data->rx_channel); return -ENODEV; } drv_data->tx_channel = pxa_request_dma("pxa2xx_spi_ssp_tx", DMA_PRIO_MEDIUM, pxa2xx_spi_dma_handler, drv_data); if (drv_data->tx_channel < 0) { dev_err(dev, "problem (%d) requesting tx channel\n", drv_data->tx_channel); pxa_free_dma(drv_data->rx_channel); return -ENODEV; } DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel; DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel; return 0; }
static void pxa_irda_shutdown(struct pxa_irda *si) { unsigned long flags; local_irq_save(flags); STIER = 0; STISR = 0; DCSR(si->txdma) &= ~DCSR_RUN; DCSR(si->rxdma) &= ~DCSR_RUN; ICCR0 = 0; pxa_irda_disable_clk(si); DRCMR(17) = 0; DRCMR(18) = 0; local_irq_restore(flags); pxa_irda_set_mode(si, IR_OFF); printk(KERN_DEBUG "pxa_ir: irda shutdown\n"); }
static void pxa_irda_startup(struct pxa_irda *si) { STIER = 0; STMCR = MCR_OUT2; STLCR = LCR_WLS0 | LCR_WLS1; STFCR = FCR_TRFIFOE | FCR_ITL_32; ICCR0 = 0; ICCR2 = ICCR2_TXP | ICCR2_TRIG_32; DRCMR(17) = si->rxdma | DRCMR_MAPVLD; DRCMR(18) = si->txdma | DRCMR_MAPVLD; si->speed = 4000000; pxa_irda_set_speed(si, 9600); printk(KERN_DEBUG "pxa_ir: irda startup\n"); }
void pxa2xx_spi_dma_resume(struct driver_data *drv_data) { if (drv_data->rx_channel != -1) DRCMR(drv_data->ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel; if (drv_data->tx_channel != -1) DRCMR(drv_data->ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel; }
void pxa2xx_spi_dma_release(struct driver_data *drv_data) { struct ssp_device *ssp = drv_data->ssp; DRCMR(ssp->drcmr_rx) = 0; DRCMR(ssp->drcmr_tx) = 0; if (drv_data->tx_channel != 0) pxa_free_dma(drv_data->tx_channel); if (drv_data->rx_channel != 0) pxa_free_dma(drv_data->rx_channel); }
/* * Prepare taskfile for submission. */ static void pxa_qc_prep(struct ata_queued_cmd *qc) { struct pata_pxa_data *pd = qc->ap->private_data; int si = 0; struct scatterlist *sg; if (!(qc->flags & ATA_QCFLAG_DMAMAP)) return; pd->dma_desc_id = 0; DCSR(pd->dma_channel) = 0; DALGN &= ~(1 << pd->dma_dreq); for_each_sg(qc->sg, sg, qc->n_elem, si) pxa_load_dmac(sg, qc); pd->dma_desc[pd->dma_desc_id - 1].ddadr = DDADR_STOP; /* Fire IRQ only at the end of last block */ pd->dma_desc[pd->dma_desc_id - 1].dcmd |= DCMD_ENDIRQEN; DDADR(pd->dma_channel) = pd->dma_desc_addr; DRCMR(pd->dma_dreq) = DRCMR_MAPVLD | pd->dma_channel; }
int __pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream) { struct pxa2xx_runtime_data *rtd = substream->runtime->private_data; if (rtd && rtd->params && rtd->params->filter_data) { unsigned long req = *(unsigned long *) rtd->params->filter_data; DRCMR(req) = 0; } snd_pcm_set_runtime_buffer(substream, NULL); return 0; }
int __pxa2xx_pcm_prepare(struct snd_pcm_substream *substream) { struct pxa2xx_runtime_data *prtd = substream->runtime->private_data; unsigned long req; if (!prtd || !prtd->params) return 0; if (prtd->dma_ch == -1) return -EINVAL; DCSR(prtd->dma_ch) &= ~DCSR_RUN; DCSR(prtd->dma_ch) = 0; DCMD(prtd->dma_ch) = 0; req = *(unsigned long *) prtd->params->filter_data; DRCMR(req) = prtd->dma_ch | DRCMR_MAPVLD; return 0; }
static struct pxa2xx_pcm_dma_params * pxa_ssp_get_dma_params(struct ssp_device *ssp, int width4, int out) { struct pxa2xx_pcm_dma_data *dma; dma = kzalloc(sizeof(struct pxa2xx_pcm_dma_data), GFP_KERNEL); if (dma == NULL) return NULL; snprintf(dma->name, 20, "SSP%d PCM %s %s", ssp->port_id, width4 ? "32-bit" : "16-bit", out ? "out" : "in"); dma->params.name = dma->name; dma->params.drcmr = &DRCMR(out ? ssp->drcmr_tx : ssp->drcmr_rx); dma->params.dcmd = (out ? (DCMD_INCSRCADDR | DCMD_FLOWTRG) : (DCMD_INCTRGADDR | DCMD_FLOWSRC)) | (width4 ? DCMD_WIDTH4 : DCMD_WIDTH2) | DCMD_BURST16; dma->params.dev_addr = ssp->phys_base + SSDR; return &dma->params; }
/* * Set the SSP audio DMA parameters and sample size. * Can be called multiple times by oss emulation. */ static int pxa3xx_ssp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai * dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct ssp_device *ssp = cpu_dai->private_data; struct pxa3xx_pcm_dma_params *pcm; u32 sscr0, sspsp; u32 width; pcm = kmalloc(sizeof(struct pxa3xx_pcm_dma_params), GFP_KERNEL); if (pcm == NULL) return -ENOMEM; /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: sscr0 = __raw_readl(ssp->mmio_base + SSCR0); sscr0 |= SSCR0_DataSize(16); __raw_writel(sscr0, ssp->mmio_base + SSCR0); if ((sscr0 & SSCR0_FPCKE ) || (sscr0 & SSCR0_EDSS)) width = DCMD_WIDTH4; else width = DCMD_WIDTH2; break; case SNDRV_PCM_FORMAT_S32_LE: sscr0 = __raw_readl(ssp->mmio_base + SSCR0); sscr0 |= SSCR0_EDSS | SSCR0_DataSize(16); __raw_writel(sscr0, ssp->mmio_base + SSCR0); width = DCMD_WIDTH4; break; default: return -EINVAL; } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { pcm->name = ssp_names[cpu_dai->id][0]; pcm->dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG; pcm->drcmr = &DRCMR(ssp->drcmr_tx); pcm->dev_addr = ssp->phys_base + SSDR; } else { pcm->name = ssp_names[cpu_dai->id][1]; pcm->dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC; pcm->drcmr = &DRCMR(ssp->drcmr_rx); pcm->dev_addr = ssp->phys_base + SSDR; } pcm->dcmd |= DCMD_BURST16 | width; kfree(snd_soc_dai_get_dma_data(cpu_dai, substream)); snd_soc_dai_set_dma_data(cpu_dai, substream, pcm); if (ssp_clk[cpu_dai->id].dai_fmt == SND_SOC_DAIFMT_I2S) { int sfrmwidth = snd_pcm_format_physical_width(params_format(params)); sspsp = __raw_readl(ssp->mmio_base + SSPSP); sspsp |= SSPSP_SFRMWDTH(sfrmwidth); __raw_writel(sspsp, ssp->mmio_base + SSPSP); } return 0; }
pxa2xx_ac97_try_cold_reset(ac97); pxa2xx_ac97_finish_reset(ac97); } struct snd_ac97_bus_ops soc_ac97_ops = { .read = pxa2xx_ac97_read, .write = pxa2xx_ac97_write, .warm_reset = pxa2xx_ac97_warm_reset, .reset = pxa2xx_ac97_cold_reset, }; static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { .name = "AC97 PCM Stereo out", .dev_addr = __PREG(PCDR), .drcmr = &DRCMR(12), .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST32 | DCMD_WIDTH4, }; static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = { .name = "AC97 PCM Stereo in", .dev_addr = __PREG(PCDR), .drcmr = &DRCMR(11), .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST32 | DCMD_WIDTH4, }; static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = { .name = "AC97 Aux PCM (Slot 5) Mono out", .dev_addr = __PREG(MODR),
pxa2xx_ac97_try_warm_reset(ac97); } pxa2xx_ac97_finish_reset(ac97); } static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { .read = pxa2xx_ac97_read, .write = pxa2xx_ac97_write, .reset = pxa2xx_ac97_reset, }; static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_out = { .name = "AC97 PCM out", .dev_addr = __PREG(PCDR), .drcmr = &DRCMR(12), .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST32 | DCMD_WIDTH4, }; static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_in = { .name = "AC97 PCM in", .dev_addr = __PREG(PCDR), .drcmr = &DRCMR(11), .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST32 | DCMD_WIDTH4, }; static struct snd_pcm *pxa2xx_ac97_pcm; static struct snd_ac97 *pxa2xx_ac97_ac97;
/* * Set the SSP audio DMA parameters and sample size. * Can be called multiple times by oss emulation. */ static int pxa3xx_ssp_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai * dai) { struct snd_soc_pcm_runtime *rtd = substream->private_data; struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; struct ssp_device *ssp = cpu_dai->private_data; struct pxa3xx_pcm_dma_params *pcm_o, *pcm_i; u32 sscr0, sspsp; u32 width; pcm_o = kmalloc(sizeof(struct pxa3xx_pcm_dma_params), GFP_KERNEL); pcm_i = kmalloc(sizeof(struct pxa3xx_pcm_dma_params), GFP_KERNEL); pcm_o->name = ssp_names[cpu_dai->id][0]; pcm_i->name = ssp_names[cpu_dai->id][1]; //printk("pxa3xx_ssp_hw_params()\n"); /* bit size */ switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: // printk("SNDRV_PCM_FORMAT_S16_LE\n"); sscr0 = __raw_readl(ssp->mmio_base + SSCR0); sscr0 |= SSCR0_DataSize(16); __raw_writel(sscr0, ssp->mmio_base + SSCR0); if ((sscr0 & SSCR0_FPCKE ) || (sscr0 & SSCR0_EDSS)) width = DCMD_WIDTH4; else width = DCMD_WIDTH2; break; case SNDRV_PCM_FORMAT_S32_LE: //printk("SNDRV_PCM_FORMAT_S32_LE\n"); sscr0 = __raw_readl(ssp->mmio_base + SSCR0); sscr0 |= SSCR0_EDSS | SSCR0_DataSize(16); __raw_writel(sscr0, ssp->mmio_base + SSCR0); width = DCMD_WIDTH4; break; default: return -EINVAL; } pcm_o->dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG | DCMD_BURST16 | width; pcm_i->dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC | DCMD_BURST16 | width; pcm_o->drcmr = &DRCMR(ssp->drcmr_tx); pcm_i->drcmr = &DRCMR(ssp->drcmr_rx); pcm_o->dev_addr = ssp->phys_base + SSDR; pcm_i->dev_addr = ssp->phys_base + SSDR; /* select correct DMA params */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) cpu_dai->dma_data = pcm_o; else cpu_dai->dma_data = pcm_i; if (ssp_clk[cpu_dai->id].dai_fmt == SND_SOC_DAIFMT_I2S) { int sfrmwidth = snd_pcm_format_physical_width(params_format(params)); sspsp = __raw_readl(ssp->mmio_base + SSPSP); sspsp |= SSPSP_SFRMWDTH(sfrmwidth); __raw_writel(sspsp, ssp->mmio_base + SSPSP); } /* printk("SSPSP: 0x%08lX\n", __raw_readl(ssp->mmio_base + SSPSP)); printk("SSCR0: 0x%08lX\n", __raw_readl(ssp->mmio_base + SSCR0)); printk("SSCR1: 0x%08lX\n", __raw_readl(ssp->mmio_base + SSCR1)); */ return 0; }