[alsa-devel] [RFC][PATCH 3/3] ASoC: sh: fsi: modify selection method of I2S/PCM/SPDIF format

Kuninori Morimoto kuninori.morimoto.gx at renesas.com
Mon Jan 24 02:43:19 CET 2011


Current format selection of FSI-codecs depended on platform information for FSI,
and chip default settings for codecs. It is not understandable/formal method.
This patch modify FSI and FSI-codecs to use snd_soc_dai_set_fmt.

But FSI can use I2S/PCM and SPDIF format today.
It can be selected to I2S/PCM by snd_soc_dai_set_fmt, but can not select SPDIF.
So, this patch change FSI platform information to have DAI/SPDIF mode.

If platform selects DAI mode (default),
FSI-codecs can select I2S/PCM by snd_soc_dai_set_fmt,
and if it is SPDIF mode, FSI become SPDIF format.

Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
---
 arch/arm/mach-shmobile/board-ag5evm.c   |    8 ---
 arch/arm/mach-shmobile/board-ap4evb.c   |    6 +-
 arch/arm/mach-shmobile/board-mackerel.c |    6 +-
 arch/sh/boards/mach-ecovec24/setup.c    |    4 +-
 arch/sh/boards/mach-se/7724/setup.c     |    4 +-
 include/sound/sh_fsi.h                  |   70 ++++++---------------
 sound/soc/sh/fsi-ak4642.c               |    3 +-
 sound/soc/sh/fsi-da7210.c               |    3 +-
 sound/soc/sh/fsi.c                      |  106 ++++++++++++++++---------------
 9 files changed, 84 insertions(+), 126 deletions(-)

diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index 9ee55e0..343362d 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -118,11 +118,6 @@ static struct platform_device keysc_device = {
 };
 
 /* FSI A */
-static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags = SH_FSI_OFMT(I2S)		|
-		       SH_FSI_IFMT(I2S),
-};
-
 static struct resource fsi_resources[] = {
 	[0] = {
 		.name	= "FSI",
@@ -141,9 +136,6 @@ static struct platform_device fsi_device = {
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(fsi_resources),
 	.resource	= fsi_resources,
-	.dev	= {
-		.platform_data	= &fsi_info,
-	},
 };
 
 static struct resource sh_mmcif_resources[] = {
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 920ed81..17f528a 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -673,14 +673,12 @@ static int fsi_set_rate(struct device *dev, int is_porta, int rate, int enable)
 }
 
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags = SH_FSI_BRS_INV |
-		       SH_FSI_OFMT(PCM) |
-		       SH_FSI_IFMT(PCM),
+	.porta_flags = SH_FSI_BRS_INV,
 
 	.portb_flags = SH_FSI_BRS_INV |
 		       SH_FSI_BRM_INV |
 		       SH_FSI_LRS_INV |
-		       SH_FSI_OFMT(SPDIF),
+		       SH_FSI_FMT_SPDIF,
 	.set_rate = fsi_set_rate,
 };
 
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index aa4bcc3..73b8c90 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -614,14 +614,12 @@ fsi_set_rate_end:
 }
 
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags =	SH_FSI_BRS_INV		|
-			SH_FSI_OFMT(PCM)	|
-			SH_FSI_IFMT(PCM),
+	.porta_flags =	SH_FSI_BRS_INV,
 
 	.portb_flags =	SH_FSI_BRS_INV	|
 			SH_FSI_BRM_INV	|
 			SH_FSI_LRS_INV	|
-			SH_FSI_OFMT(SPDIF),
+			SH_FSI_FMT_SPDIF,
 
 	.set_rate = fsi_set_rate,
 };
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 037416f..b96b79b 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -723,9 +723,7 @@ static struct platform_device camera_devices[] = {
 
 /* FSI */
 static struct sh_fsi_platform_info fsi_info = {
-	.portb_flags = SH_FSI_BRS_INV |
-		       SH_FSI_OFMT(I2S) |
-		       SH_FSI_IFMT(I2S),
+	.portb_flags = SH_FSI_BRS_INV,
 };
 
 static struct resource fsi_resources[] = {
diff --git a/arch/sh/boards/mach-se/7724/setup.c b/arch/sh/boards/mach-se/7724/setup.c
index b4aef05..c8bcf6a 100644
--- a/arch/sh/boards/mach-se/7724/setup.c
+++ b/arch/sh/boards/mach-se/7724/setup.c
@@ -286,9 +286,7 @@ static struct platform_device ceu1_device = {
 /* FSI */
 /* change J20, J21, J22 pin to 1-2 connection to use slave mode */
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags = SH_FSI_BRS_INV |
-		       SH_FSI_OFMT(PCM) |
-		       SH_FSI_IFMT(PCM),
+	.porta_flags = SH_FSI_BRS_INV,
 };
 
 static struct resource fsi_resources[] = {
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index 18e4327..9a155f9 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -15,61 +15,29 @@
 #define FSI_PORT_A	0
 #define FSI_PORT_B	1
 
-/* flags format
-
- * 0xABC0EEFF
- *
- * A:  channel size for TDM (input)
- * B:  channel size for TDM (ooutput)
- * C:  inversion
- * E:  input format
- * F:  output format
- */
-
 #include <linux/clk.h>
 #include <sound/soc.h>
 
-/* TDM channel */
-#define SH_FSI_SET_CH_I(x)	((x & 0xF) << 28)
-#define SH_FSI_SET_CH_O(x)	((x & 0xF) << 24)
-
-#define SH_FSI_CH_IMASK		0xF0000000
-#define SH_FSI_CH_OMASK		0x0F000000
-#define SH_FSI_GET_CH_I(x)	((x & SH_FSI_CH_IMASK) >> 28)
-#define SH_FSI_GET_CH_O(x)	((x & SH_FSI_CH_OMASK) >> 24)
-
-/* clock inversion */
-#define SH_FSI_INVERSION_MASK	0x00F00000
-#define SH_FSI_LRM_INV		(1 << 20)
-#define SH_FSI_BRM_INV		(1 << 21)
-#define SH_FSI_LRS_INV		(1 << 22)
-#define SH_FSI_BRS_INV		(1 << 23)
-
-/* DI format */
-#define SH_FSI_FMT_MASK		0x000000FF
-#define SH_FSI_IFMT(x)		(((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 8)
-#define SH_FSI_OFMT(x)		(((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 0)
-#define SH_FSI_GET_IFMT(x)	((x >> 8) & SH_FSI_FMT_MASK)
-#define SH_FSI_GET_OFMT(x)	((x >> 0) & SH_FSI_FMT_MASK)
-
-#define SH_FSI_FMT_MONO		0
-#define SH_FSI_FMT_MONO_DELAY	1
-#define SH_FSI_FMT_PCM		2
-#define SH_FSI_FMT_I2S		3
-#define SH_FSI_FMT_TDM		4
-#define SH_FSI_FMT_TDM_DELAY	5
-#define SH_FSI_FMT_SPDIF	6
-
-
-#define SH_FSI_IFMT_TDM_CH(x) \
-	(SH_FSI_IFMT(TDM)	| SH_FSI_SET_CH_I(x))
-#define SH_FSI_IFMT_TDM_DELAY_CH(x) \
-	(SH_FSI_IFMT(TDM_DELAY)	| SH_FSI_SET_CH_I(x))
+/*
+ * flags format
+ *
+ * 0x000000BA
+ *
+ * A:  inversion
+ * B:  format mode
+ */
 
-#define SH_FSI_OFMT_TDM_CH(x) \
-	(SH_FSI_OFMT(TDM)	| SH_FSI_SET_CH_O(x))
-#define SH_FSI_OFMT_TDM_DELAY_CH(x) \
-	(SH_FSI_OFMT(TDM_DELAY)	| SH_FSI_SET_CH_O(x))
+/* A: clock inversion */
+#define SH_FSI_INVERSION_MASK	0x0000000F
+#define SH_FSI_LRM_INV		(1 << 0)
+#define SH_FSI_BRM_INV		(1 << 1)
+#define SH_FSI_LRS_INV		(1 << 2)
+#define SH_FSI_BRS_INV		(1 << 3)
+
+/* B: format mode */
+#define SH_FSI_FMT_MASK		0x000000F0
+#define SH_FSI_FMT_DAI		(0 << 4)
+#define SH_FSI_FMT_SPDIF	(1 << 4)
 
 
 /*
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
index ce058c7..d6f4703 100644
--- a/sound/soc/sh/fsi-ak4642.c
+++ b/sound/soc/sh/fsi-ak4642.c
@@ -36,7 +36,8 @@ static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd)
 	if (ret < 0)
 		return ret;
 
-	ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBS_CFS);
+	ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_LEFT_J |
+				       SND_SOC_DAIFMT_CBS_CFS);
 
 	return ret;
 }
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
index 9b24ed4..dbafd7a 100644
--- a/sound/soc/sh/fsi-da7210.c
+++ b/sound/soc/sh/fsi-da7210.c
@@ -25,7 +25,8 @@ static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd)
 	if (ret < 0)
 		return ret;
 
-	ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBS_CFS);
+	ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_I2S |
+				       SND_SOC_DAIFMT_CBS_CFS);
 
 	return ret;
 }
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 3c53693..0c9997e 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -757,9 +757,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
 			   struct snd_soc_dai *dai)
 {
 	struct fsi_priv *fsi = fsi_get_priv(substream);
-	struct fsi_master *master = fsi_get_master(fsi);
 	u32 flags = fsi_get_info_flags(fsi);
-	u32 fmt;
 	u32 data;
 	int is_play = fsi_is_play(substream);
 
@@ -779,54 +777,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
 
 	fsi_reg_write(fsi, CKG2, data);
 
-	/* do fmt, di fmt */
-	data = 0;
-	fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags);
-	switch (fmt) {
-	case SH_FSI_FMT_MONO:
-		data = CR_MONO;
-		fsi->chan_num = 1;
-		break;
-	case SH_FSI_FMT_MONO_DELAY:
-		data = CR_MONO_D;
-		fsi->chan_num = 1;
-		break;
-	case SH_FSI_FMT_PCM:
-		data = CR_PCM;
-		fsi->chan_num = 2;
-		break;
-	case SH_FSI_FMT_I2S:
-		data = CR_I2S;
-		fsi->chan_num = 2;
-		break;
-	case SH_FSI_FMT_TDM:
-		fsi->chan_num = is_play ?
-			SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
-		data = CR_TDM | (fsi->chan_num - 1);
-		break;
-	case SH_FSI_FMT_TDM_DELAY:
-		fsi->chan_num = is_play ?
-			SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
-		data = CR_TDM_D | (fsi->chan_num - 1);
-		break;
-	case SH_FSI_FMT_SPDIF:
-		if (master->core->ver < 2) {
-			dev_err(dai->dev, "This FSI can not use SPDIF\n");
-			return -EINVAL;
-		}
-		data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
-		fsi->chan_num = 2;
-		fsi_spdif_clk_ctrl(fsi, 1);
-		fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
-		break;
-	default:
-		dev_err(dai->dev, "unknown format.\n");
-		return -EINVAL;
-	}
-	is_play ?
-		fsi_reg_write(fsi, DO_FMT, data) :
-		fsi_reg_write(fsi, DI_FMT, data);
-
 	/* irq clear */
 	fsi_irq_disable(fsi, is_play);
 	fsi_irq_clear_status(fsi);
@@ -881,9 +831,52 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
 	return ret;
 }
 
+static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt)
+{
+	u32 data = 0;
+
+	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+	case SND_SOC_DAIFMT_I2S:
+		data = CR_I2S;
+		fsi->chan_num = 2;
+		break;
+	case SND_SOC_DAIFMT_LEFT_J:
+		data = CR_PCM;
+		fsi->chan_num = 2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	fsi_reg_write(fsi, DO_FMT, data);
+	fsi_reg_write(fsi, DI_FMT, data);
+
+	return 0;
+}
+
+static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
+{
+	struct fsi_master *master = fsi_get_master(fsi);
+	u32 data = 0;
+
+	if (master->core->ver < 2)
+		return -EINVAL;
+
+	data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
+	fsi->chan_num = 2;
+	fsi_spdif_clk_ctrl(fsi, 1);
+	fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
+
+	fsi_reg_write(fsi, DO_FMT, data);
+	fsi_reg_write(fsi, DI_FMT, data);
+
+	return 0;
+}
+
 static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
+	u32 flags = fsi_get_info_flags(fsi);
 	u32 data = 0;
 	int ret;
 
@@ -901,7 +894,18 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 		goto set_fmt_exit;
 	}
 	fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data);
-	ret = 0;
+
+	/* set format */
+	switch (flags & SH_FSI_FMT_MASK) {
+	case SH_FSI_FMT_DAI:
+		ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+		break;
+	case SH_FSI_FMT_SPDIF:
+		ret = fsi_set_fmt_spdif(fsi);
+		break;
+	default:
+		ret = -EINVAL;
+	}
 
 set_fmt_exit:
 	pm_runtime_put_sync(dai->dev);
-- 
1.7.1



More information about the Alsa-devel mailing list