Re: ASoC: pxa2xx-ssp

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Em Sex, 2008-10-24 às 16:54 +0100, Liam Girdwood escreveu:
> On Thu, 2008-10-23 at 22:54 -0200, Daniel Ribeiro wrote:
> > Hi!
> > 
> > What is needed for [0] to be accepted on mainline linux?
> > 
> > [0]http://opensource.wolfsonmicro.com/cgi-bin/gitweb.cgi?p=linux-2.6-asoc.git;a=blob;f=sound/soc/pxa/pxa2xx-ssp.c;h=6b1baeece184e990c4254e2f43495013d4562c95;hb=e4d89cdd854b4a40c963adf434d261070c67b6bb
> > 
> 
> When I last worked on this it was in need of updates for SSP register
> IO, clk API and more testing. It has the IO and clk stuff now.
> 
> Does this code work well on your platform/board ?

	Not as it is.

	My sound codec needs 32bit ssp frames, even considering that it only
supports 16bit mono/stereo audio. I guess that it works with I2S
emulation mode, which pxa2xx-ssp.c dont support yet.

	After some time trying to understand the very poorly documented I2S/SSP
emulation on the pxa manual, i ended up with [1]. It works perfectly on
my board, with SND_SOC_DAIFMT_MSB.

	To ease your reading, attached is a diff against [0]. It is updated to
build on the latest linus tree and handles DAIFMT_I2S and DAIFMT_MSB
differently.

> 
> If so, I guess we could scratch off the more testing part and consider
> it for the next merge window. Iirc it was also waiting on some pxa
> dependencies going upstream, so it may wait a little longer.
> 
> I'm sure it's on Mark's long todo list....
> 
> Liam 
> 

[1]http://git.openezx.org/?p=openezx.git;a=blob;f=sound/soc/pxa/pxa2xx-ssp.c;h=cdbc15e243094fd232119b342c39be26c8ac4c7d;hb=cacec205c17b9924db3ca625347a33d0ddd2b694

-- 
Daniel Ribeiro
--- /tmp/pxa2xx-ssp.c	2008-10-25 03:22:44.000000000 -0200
+++ pxa2xx-ssp.c	2008-10-24 20:19:29.000000000 -0200
@@ -28,12 +28,13 @@
 #include <sound/initval.h>
 #include <sound/pcm_params.h>
 #include <sound/soc.h>
+#include <sound/pxa2xx-lib.h>
 
-#include <asm/hardware.h>
-#include <asm/arch/pxa-regs.h>
-#include <asm/arch/regs-ssp.h>
-#include <asm/arch/audio.h>
-#include <asm/arch/ssp.h>
+#include <mach/hardware.h>
+#include <mach/pxa-regs.h>
+#include <mach/regs-ssp.h>
+#include <mach/audio.h>
+#include <mach/ssp.h>
 
 #include "pxa2xx-pcm.h"
 #include "pxa2xx-ssp.h"
@@ -58,7 +59,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_mono_out = {
 	.name			= "SSP1 PCM Mono out",
 	.dev_addr		= PXA2xx_SSP1_BASE + SSDR,
-	.drcmr			= &DRCMRTXSSDR,
+	.drcmr			= &DRCMR(14),
 	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
 				  DCMD_BURST16 | DCMD_WIDTH2,
 };
@@ -66,7 +67,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_mono_in = {
 	.name			= "SSP1 PCM Mono in",
 	.dev_addr		= PXA2xx_SSP1_BASE + SSDR,
-	.drcmr			= &DRCMRRXSSDR,
+	.drcmr			= &DRCMR(13),
 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
 				  DCMD_BURST16 | DCMD_WIDTH2,
 };
@@ -74,7 +75,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_stereo_out = {
 	.name			= "SSP1 PCM Stereo out",
 	.dev_addr		= PXA2xx_SSP1_BASE + SSDR,
-	.drcmr			= &DRCMRTXSSDR,
+	.drcmr			= &DRCMR(14),
 	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
 				  DCMD_BURST16 | DCMD_WIDTH4,
 };
@@ -82,7 +83,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp1_pcm_stereo_in = {
 	.name			= "SSP1 PCM Stereo in",
 	.dev_addr		= PXA2xx_SSP1_BASE + SSDR,
-	.drcmr			= &DRCMRRXSSDR,
+	.drcmr			= &DRCMR(13),
 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
 				  DCMD_BURST16 | DCMD_WIDTH4,
 };
@@ -90,7 +91,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_mono_out = {
 	.name			= "SSP2 PCM Mono out",
 	.dev_addr		= PXA27x_SSP2_BASE + SSDR,
-	.drcmr			= &DRCMRTXSS2DR,
+	.drcmr			= &DRCMR(16),
 	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
 				  DCMD_BURST16 | DCMD_WIDTH2,
 };
@@ -98,7 +99,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_mono_in = {
 	.name			= "SSP2 PCM Mono in",
 	.dev_addr		= PXA27x_SSP2_BASE + SSDR,
-	.drcmr			= &DRCMRRXSS2DR,
+	.drcmr			= &DRCMR(15),
 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
 				  DCMD_BURST16 | DCMD_WIDTH2,
 };
@@ -106,7 +107,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_stereo_out = {
 	.name			= "SSP2 PCM Stereo out",
 	.dev_addr		= PXA27x_SSP2_BASE + SSDR,
-	.drcmr			= &DRCMRTXSS2DR,
+	.drcmr			= &DRCMR(16),
 	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
 				  DCMD_BURST16 | DCMD_WIDTH4,
 };
@@ -114,7 +115,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp2_pcm_stereo_in = {
 	.name			= "SSP2 PCM Stereo in",
 	.dev_addr		= PXA27x_SSP2_BASE + SSDR,
-	.drcmr			= &DRCMRRXSS2DR,
+	.drcmr			= &DRCMR(15),
 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
 				  DCMD_BURST16 | DCMD_WIDTH4,
 };
@@ -122,7 +123,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_mono_out = {
 	.name			= "SSP3 PCM Mono out",
 	.dev_addr		= PXA27x_SSP3_BASE + SSDR,
-	.drcmr			= &DRCMRTXSS3DR,
+	.drcmr			= &DRCMR(67),
 	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
 				  DCMD_BURST16 | DCMD_WIDTH2,
 };
@@ -130,7 +131,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_mono_in = {
 	.name			= "SSP3 PCM Mono in",
 	.dev_addr		= PXA27x_SSP3_BASE + SSDR,
-	.drcmr			= &DRCMRRXSS3DR,
+	.drcmr			= &DRCMR(66),
 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
 				  DCMD_BURST16 | DCMD_WIDTH2,
 };
@@ -138,7 +139,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_stereo_out = {
 	.name			= "SSP3 PCM Stereo out",
 	.dev_addr		= PXA27x_SSP3_BASE + SSDR,
-	.drcmr			= &DRCMRTXSS3DR,
+	.drcmr			= &DRCMR(67),
 	.dcmd			= DCMD_INCSRCADDR | DCMD_FLOWTRG |
 				  DCMD_BURST16 | DCMD_WIDTH4,
 };
@@ -146,7 +147,7 @@
 static struct pxa2xx_pcm_dma_params pxa2xx_ssp3_pcm_stereo_in = {
 	.name			= "SSP3 PCM Stereo in",
 	.dev_addr		= PXA27x_SSP3_BASE + SSDR,
-	.drcmr			= &DRCMRRXSS3DR,
+	.drcmr			= &DRCMR(66),
 	.dcmd			= DCMD_INCTRGADDR | DCMD_FLOWSRC |
 				  DCMD_BURST16 | DCMD_WIDTH4,
 };
@@ -163,7 +164,7 @@
 static int pxa2xx_ssp_startup(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 	int ret = 0;
 
 	if (!rtd->dai->cpu_dai->active) {
@@ -179,7 +180,7 @@
 static void pxa2xx_ssp_shutdown(struct snd_pcm_substream *substream)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 
 	if (!cpu_dai->active) {
 		ssp_disable(&ssp[cpu_dai->id]);
@@ -190,7 +191,7 @@
 #ifdef CONFIG_PM
 
 static int pxa2xx_ssp_suspend(struct platform_device *pdev,
-	struct snd_soc_cpu_dai *dai)
+	struct snd_soc_dai *dai)
 {
 	if (!dai->active)
 		return 0;
@@ -201,7 +202,7 @@
 }
 
 static int pxa2xx_ssp_resume(struct platform_device *pdev,
-	struct snd_soc_cpu_dai *dai)
+	struct snd_soc_dai *dai)
 {
 	if (!dai->active)
 		return 0;
@@ -233,7 +234,7 @@
 /*
  * Set the SSP ports SYSCLK.
  */
-static int pxa2xx_ssp_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
+static int pxa2xx_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
 	int clk_id, unsigned int freq, int dir)
 {
 	void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
@@ -283,7 +284,7 @@
 /*
  * Set the SSP clock dividers.
  */
-static int pxa2xx_ssp_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
+static int pxa2xx_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
 	int div_id, int div)
 {
 	void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
@@ -313,7 +314,7 @@
 /*
  * Configure the PLL frequency pxa27x and (afaik - pxa320 only)
  */
-static int pxa2xx_ssp_set_dai_pll(struct snd_soc_cpu_dai *cpu_dai,
+static int pxa2xx_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai,
 	int pll_id, unsigned int freq_in, unsigned int freq_out)
 {
 	void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
@@ -346,7 +347,7 @@
 /*
  * Set the active slots in TDM/Network mode
  */
-static int pxa2xx_ssp_set_dai_tdm_slot(struct snd_soc_cpu_dai *cpu_dai,
+static int pxa2xx_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
 	unsigned int mask, int slots)
 {
 	void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
@@ -367,7 +368,7 @@
 /*
  * Tristate the SSP DAI lines
  */
-static int pxa2xx_ssp_set_dai_tristate(struct snd_soc_cpu_dai *cpu_dai,
+static int pxa2xx_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
 	int tristate)
 {
 	void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
@@ -388,53 +389,23 @@
  * The SSP Port must be inactive before calling this function as the
  * physical interface format is changed.
  */
-static int pxa2xx_ssp_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
+static int pxa2xx_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
 		unsigned int fmt)
 {
 	void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
-	int val;
+	int val, tmp;
 
 	/* reset port settings */
 	__raw_writel(0, mmio_base + SSCR0);
 	__raw_writel(0, mmio_base + SSCR1);
 	__raw_writel(0, mmio_base + SSPSP);
 
-	/* NOTE: I2S emulation is still very much work in progress here */
-
-	/* FIXME: this is what wince uses for msb */
-	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_MSB) {
-		__raw_writel(SSCR0_EDSS | SSCR0_TISSP | SSCR0_DataSize(16),
-				mmio_base + SSCR0);
-		goto master;
-	}
-
-	/* check for I2S emulation mode - handle it separately  */
-	if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S) {
-		/* 8.4.11 */
-
-		/* Only SSCR0[NCS] or SSCR0[ECS] bit fields settings are optional */
-		__raw_writel(SSCR0_EDSS | SSCR0_PSP | SSCR0_DataSize(16),
-				mmio_base + SSCR0);
-
-		/* set FIFO thresholds */
-		__raw_writel(SSCR1_RxTresh(14) | SSCR1_TxTresh(1),
-				mmio_base + SSCR1);
-
-		/* normal: */
-		/* all bit fields must be cleared except: FSRT = 1 and
-		 * SFRMWDTH = 16, DMYSTART=0,1) */
-		__raw_writel(SSPSP_FSRT | SSPSP_SFRMWDTH(16) | SSPSP_DMYSTRT(0),
-				mmio_base + SSPSP);
-		goto master;
-	}
-
 	val = __raw_readl(mmio_base + SSCR0) | SSCR0_PSP;
 	__raw_writel(val, mmio_base + SSCR0);
 	__raw_writel(SSCR1_RxTresh(14) | SSCR1_TxTresh(1) |
 			SSCR1_TRAIL | SSCR1_RWOT,
 			mmio_base + SSCR1);
 
-master:
 	val = __raw_readl(mmio_base + SSCR1);
 	switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
 	case SND_SOC_DAIFMT_CBM_CFM:
@@ -465,15 +436,20 @@
 	}
 
 	val = __raw_readl(mmio_base + SSPSP);
+	val |= SSPSP_SCMODE(2);
 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
 	case SND_SOC_DAIFMT_DSP_A:
 		val |= SSPSP_DMYSTRT(1);
 	case SND_SOC_DAIFMT_DSP_B:
-		val |= SSPSP_SCMODE(2);
 		break;
 	case SND_SOC_DAIFMT_I2S:
+		val |= SSPSP_FSRT;
 	case SND_SOC_DAIFMT_MSB:
-		/* handled above */
+		val |= SSPSP_SFRMWDTH(16);
+
+		tmp = __raw_readl(mmio_base + SSCR0) | SSCR0_EDSS |
+			SSCR0_DataSize(16);
+		__raw_writel(tmp, mmio_base + SSCR0);
 		break;
 	default:
 		return -EINVAL;
@@ -491,7 +467,7 @@
 				struct snd_pcm_hw_params *params)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 	int dma = 0, chn = params_channels(params);
 	void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
 	u32 sscr0;
@@ -505,12 +481,20 @@
 
 	pr_debug("pxa2xx_ssp_hw_params: dma %d", dma);
 
+	sscr0 = __raw_readl(mmio_base + SSCR0);
+
 	/* we can only change the settings if the port is not in use */
-	if (__raw_readl(mmio_base + SSCR0) & SSCR0_SSE)
-		return 0;
+	if (sscr0 & SSCR0_SSE)
+		goto ret;
+
+	/* check if we are running on I2S mode */
+	/* FIXME: Is there a better way to check this? */
+	if ((sscr0 & (SSCR0_EDSS | SSCR0_DataSize(16) | SSCR0_PSP)) ==
+			(SSCR0_EDSS | SSCR0_DataSize(16) | SSCR0_PSP))
+		goto ret;
 
 	/* clear selected SSP bits */
-	sscr0 = __raw_readl(mmio_base + SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS);
+	sscr0 &= ~(SSCR0_DSS | SSCR0_EDSS);
 	__raw_writel(sscr0, mmio_base + SSCR0);
 
 	/* bit size */
@@ -530,6 +514,7 @@
 	}
 	__raw_writel(sscr0, mmio_base + SSCR0);
 
+ret:
 	pr_debug("SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x",
 		__raw_readl(mmio_base + SSCR0), __raw_readl(mmio_base + SSCR1),
 		__raw_readl(mmio_base + SSTO), __raw_readl(mmio_base + SSPSP),
@@ -541,7 +526,7 @@
 static int pxa2xx_ssp_trigger(struct snd_pcm_substream *substream, int cmd)
 {
 	struct snd_soc_pcm_runtime *rtd = substream->private_data;
-	struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
+	struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
 	int ret = 0;
 	void __iomem *mmio_base = ssp[cpu_dai->id].ssp->mmio_base;
 	int val;
@@ -609,7 +594,7 @@
 #define PXA2XX_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
 	SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
 
-struct snd_soc_cpu_dai pxa_ssp_dai[] = {
+struct snd_soc_dai pxa_ssp_dai[] = {
 	{	.name = "pxa2xx-ssp1",
 		.id = 0,
 		.type = SND_SOC_DAI_PCM,
_______________________________________________
Alsa-devel mailing list
Alsa-devel@xxxxxxxxxxxxxxxx
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

[Index of Archives]     [ALSA User]     [Linux Audio Users]     [Kernel Archive]     [Asterisk PBX]     [Photo Sharing]     [Linux Sound]     [Video 4 Linux]     [Gimp]     [Yosemite News]

  Powered by Linux