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