Example #1
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;
	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;
}
Example #2
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;
}