aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKuninori Morimoto <kuninori.morimoto.gx@renesas.com>2011-01-23 20:43:19 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-01-26 06:25:47 -0500
commitf17c13ca52d5c5a6a164536244a6debb8cd17983 (patch)
treea3a9a1fd3a0ed7cf1bb49f6c8c8591826fa58940
parentd7c5762bc72ea4184c413166c063899dffae7385 (diff)
ASoC: sh: fsi: modify selection method of I2S/PCM/SPDIF format
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@renesas.com> Acked-by: Paul Mundt <lethal@linux-sh.org> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--arch/arm/mach-shmobile/board-ag5evm.c8
-rw-r--r--arch/arm/mach-shmobile/board-ap4evb.c6
-rw-r--r--arch/arm/mach-shmobile/board-mackerel.c6
-rw-r--r--arch/sh/boards/mach-ecovec24/setup.c4
-rw-r--r--arch/sh/boards/mach-se/7724/setup.c4
-rw-r--r--include/sound/sh_fsi.h70
-rw-r--r--sound/soc/sh/fsi-ak4642.c3
-rw-r--r--sound/soc/sh/fsi-da7210.c3
-rw-r--r--sound/soc/sh/fsi.c106
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 9ee55e0fbeb1..343362d02075 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 = {
118}; 118};
119 119
120/* FSI A */ 120/* FSI A */
121static struct sh_fsi_platform_info fsi_info = {
122 .porta_flags = SH_FSI_OFMT(I2S) |
123 SH_FSI_IFMT(I2S),
124};
125
126static struct resource fsi_resources[] = { 121static struct resource fsi_resources[] = {
127 [0] = { 122 [0] = {
128 .name = "FSI", 123 .name = "FSI",
@@ -141,9 +136,6 @@ static struct platform_device fsi_device = {
141 .id = -1, 136 .id = -1,
142 .num_resources = ARRAY_SIZE(fsi_resources), 137 .num_resources = ARRAY_SIZE(fsi_resources),
143 .resource = fsi_resources, 138 .resource = fsi_resources,
144 .dev = {
145 .platform_data = &fsi_info,
146 },
147}; 139};
148 140
149static struct resource sh_mmcif_resources[] = { 141static struct resource sh_mmcif_resources[] = {
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 920ed81f1c61..17f528a76a1c 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)
673} 673}
674 674
675static struct sh_fsi_platform_info fsi_info = { 675static struct sh_fsi_platform_info fsi_info = {
676 .porta_flags = SH_FSI_BRS_INV | 676 .porta_flags = SH_FSI_BRS_INV,
677 SH_FSI_OFMT(PCM) |
678 SH_FSI_IFMT(PCM),
679 677
680 .portb_flags = SH_FSI_BRS_INV | 678 .portb_flags = SH_FSI_BRS_INV |
681 SH_FSI_BRM_INV | 679 SH_FSI_BRM_INV |
682 SH_FSI_LRS_INV | 680 SH_FSI_LRS_INV |
683 SH_FSI_OFMT(SPDIF), 681 SH_FSI_FMT_SPDIF,
684 .set_rate = fsi_set_rate, 682 .set_rate = fsi_set_rate,
685}; 683};
686 684
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index aa4bcc347044..73b8c90b5072 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:
614} 614}
615 615
616static struct sh_fsi_platform_info fsi_info = { 616static struct sh_fsi_platform_info fsi_info = {
617 .porta_flags = SH_FSI_BRS_INV | 617 .porta_flags = SH_FSI_BRS_INV,
618 SH_FSI_OFMT(PCM) |
619 SH_FSI_IFMT(PCM),
620 618
621 .portb_flags = SH_FSI_BRS_INV | 619 .portb_flags = SH_FSI_BRS_INV |
622 SH_FSI_BRM_INV | 620 SH_FSI_BRM_INV |
623 SH_FSI_LRS_INV | 621 SH_FSI_LRS_INV |
624 SH_FSI_OFMT(SPDIF), 622 SH_FSI_FMT_SPDIF,
625 623
626 .set_rate = fsi_set_rate, 624 .set_rate = fsi_set_rate,
627}; 625};
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 037416f346cf..b96b79b970b2 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[] = {
723 723
724/* FSI */ 724/* FSI */
725static struct sh_fsi_platform_info fsi_info = { 725static struct sh_fsi_platform_info fsi_info = {
726 .portb_flags = SH_FSI_BRS_INV | 726 .portb_flags = SH_FSI_BRS_INV,
727 SH_FSI_OFMT(I2S) |
728 SH_FSI_IFMT(I2S),
729}; 727};
730 728
731static struct resource fsi_resources[] = { 729static 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 b4aef05dd8b5..c8bcf6a19b55 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 = {
286/* FSI */ 286/* FSI */
287/* change J20, J21, J22 pin to 1-2 connection to use slave mode */ 287/* change J20, J21, J22 pin to 1-2 connection to use slave mode */
288static struct sh_fsi_platform_info fsi_info = { 288static struct sh_fsi_platform_info fsi_info = {
289 .porta_flags = SH_FSI_BRS_INV | 289 .porta_flags = SH_FSI_BRS_INV,
290 SH_FSI_OFMT(PCM) |
291 SH_FSI_IFMT(PCM),
292}; 290};
293 291
294static struct resource fsi_resources[] = { 292static struct resource fsi_resources[] = {
diff --git a/include/sound/sh_fsi.h b/include/sound/sh_fsi.h
index 18e43279f70f..9a155f9d0a12 100644
--- a/include/sound/sh_fsi.h
+++ b/include/sound/sh_fsi.h
@@ -15,61 +15,29 @@
15#define FSI_PORT_A 0 15#define FSI_PORT_A 0
16#define FSI_PORT_B 1 16#define FSI_PORT_B 1
17 17
18/* flags format
19
20 * 0xABC0EEFF
21 *
22 * A: channel size for TDM (input)
23 * B: channel size for TDM (ooutput)
24 * C: inversion
25 * E: input format
26 * F: output format
27 */
28
29#include <linux/clk.h> 18#include <linux/clk.h>
30#include <sound/soc.h> 19#include <sound/soc.h>
31 20
32/* TDM channel */ 21/*
33#define SH_FSI_SET_CH_I(x) ((x & 0xF) << 28) 22 * flags format
34#define SH_FSI_SET_CH_O(x) ((x & 0xF) << 24) 23 *
35 24 * 0x000000BA
36#define SH_FSI_CH_IMASK 0xF0000000 25 *
37#define SH_FSI_CH_OMASK 0x0F000000 26 * A: inversion
38#define SH_FSI_GET_CH_I(x) ((x & SH_FSI_CH_IMASK) >> 28) 27 * B: format mode
39#define SH_FSI_GET_CH_O(x) ((x & SH_FSI_CH_OMASK) >> 24) 28 */
40
41/* clock inversion */
42#define SH_FSI_INVERSION_MASK 0x00F00000
43#define SH_FSI_LRM_INV (1 << 20)
44#define SH_FSI_BRM_INV (1 << 21)
45#define SH_FSI_LRS_INV (1 << 22)
46#define SH_FSI_BRS_INV (1 << 23)
47
48/* DI format */
49#define SH_FSI_FMT_MASK 0x000000FF
50#define SH_FSI_IFMT(x) (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 8)
51#define SH_FSI_OFMT(x) (((SH_FSI_FMT_ ## x) & SH_FSI_FMT_MASK) << 0)
52#define SH_FSI_GET_IFMT(x) ((x >> 8) & SH_FSI_FMT_MASK)
53#define SH_FSI_GET_OFMT(x) ((x >> 0) & SH_FSI_FMT_MASK)
54
55#define SH_FSI_FMT_MONO 0
56#define SH_FSI_FMT_MONO_DELAY 1
57#define SH_FSI_FMT_PCM 2
58#define SH_FSI_FMT_I2S 3
59#define SH_FSI_FMT_TDM 4
60#define SH_FSI_FMT_TDM_DELAY 5
61#define SH_FSI_FMT_SPDIF 6
62
63
64#define SH_FSI_IFMT_TDM_CH(x) \
65 (SH_FSI_IFMT(TDM) | SH_FSI_SET_CH_I(x))
66#define SH_FSI_IFMT_TDM_DELAY_CH(x) \
67 (SH_FSI_IFMT(TDM_DELAY) | SH_FSI_SET_CH_I(x))
68 29
69#define SH_FSI_OFMT_TDM_CH(x) \ 30/* A: clock inversion */
70 (SH_FSI_OFMT(TDM) | SH_FSI_SET_CH_O(x)) 31#define SH_FSI_INVERSION_MASK 0x0000000F
71#define SH_FSI_OFMT_TDM_DELAY_CH(x) \ 32#define SH_FSI_LRM_INV (1 << 0)
72 (SH_FSI_OFMT(TDM_DELAY) | SH_FSI_SET_CH_O(x)) 33#define SH_FSI_BRM_INV (1 << 1)
34#define SH_FSI_LRS_INV (1 << 2)
35#define SH_FSI_BRS_INV (1 << 3)
36
37/* B: format mode */
38#define SH_FSI_FMT_MASK 0x000000F0
39#define SH_FSI_FMT_DAI (0 << 4)
40#define SH_FSI_FMT_SPDIF (1 << 4)
73 41
74 42
75/* 43/*
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
index ce058c749e6a..d6f4703b3c07 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)
36 if (ret < 0) 36 if (ret < 0)
37 return ret; 37 return ret;
38 38
39 ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBS_CFS); 39 ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_LEFT_J |
40 SND_SOC_DAIFMT_CBS_CFS);
40 41
41 return ret; 42 return ret;
42} 43}
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
index 9b24ed466ab1..dbafd7ac5590 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)
25 if (ret < 0) 25 if (ret < 0)
26 return ret; 26 return ret;
27 27
28 ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBS_CFS); 28 ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_I2S |
29 SND_SOC_DAIFMT_CBS_CFS);
29 30
30 return ret; 31 return ret;
31} 32}
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 3c53693d7266..0c9997e2d8c0 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,
757 struct snd_soc_dai *dai) 757 struct snd_soc_dai *dai)
758{ 758{
759 struct fsi_priv *fsi = fsi_get_priv(substream); 759 struct fsi_priv *fsi = fsi_get_priv(substream);
760 struct fsi_master *master = fsi_get_master(fsi);
761 u32 flags = fsi_get_info_flags(fsi); 760 u32 flags = fsi_get_info_flags(fsi);
762 u32 fmt;
763 u32 data; 761 u32 data;
764 int is_play = fsi_is_play(substream); 762 int is_play = fsi_is_play(substream);
765 763
@@ -779,54 +777,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
779 777
780 fsi_reg_write(fsi, CKG2, data); 778 fsi_reg_write(fsi, CKG2, data);
781 779
782 /* do fmt, di fmt */
783 data = 0;
784 fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags);
785 switch (fmt) {
786 case SH_FSI_FMT_MONO:
787 data = CR_MONO;
788 fsi->chan_num = 1;
789 break;
790 case SH_FSI_FMT_MONO_DELAY:
791 data = CR_MONO_D;
792 fsi->chan_num = 1;
793 break;
794 case SH_FSI_FMT_PCM:
795 data = CR_PCM;
796 fsi->chan_num = 2;
797 break;
798 case SH_FSI_FMT_I2S:
799 data = CR_I2S;
800 fsi->chan_num = 2;
801 break;
802 case SH_FSI_FMT_TDM:
803 fsi->chan_num = is_play ?
804 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
805 data = CR_TDM | (fsi->chan_num - 1);
806 break;
807 case SH_FSI_FMT_TDM_DELAY:
808 fsi->chan_num = is_play ?
809 SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags);
810 data = CR_TDM_D | (fsi->chan_num - 1);
811 break;
812 case SH_FSI_FMT_SPDIF:
813 if (master->core->ver < 2) {
814 dev_err(dai->dev, "This FSI can not use SPDIF\n");
815 return -EINVAL;
816 }
817 data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
818 fsi->chan_num = 2;
819 fsi_spdif_clk_ctrl(fsi, 1);
820 fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
821 break;
822 default:
823 dev_err(dai->dev, "unknown format.\n");
824 return -EINVAL;
825 }
826 is_play ?
827 fsi_reg_write(fsi, DO_FMT, data) :
828 fsi_reg_write(fsi, DI_FMT, data);
829
830 /* irq clear */ 780 /* irq clear */
831 fsi_irq_disable(fsi, is_play); 781 fsi_irq_disable(fsi, is_play);
832 fsi_irq_clear_status(fsi); 782 fsi_irq_clear_status(fsi);
@@ -881,9 +831,52 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
881 return ret; 831 return ret;
882} 832}
883 833
834static int fsi_set_fmt_dai(struct fsi_priv *fsi, unsigned int fmt)
835{
836 u32 data = 0;
837
838 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
839 case SND_SOC_DAIFMT_I2S:
840 data = CR_I2S;
841 fsi->chan_num = 2;
842 break;
843 case SND_SOC_DAIFMT_LEFT_J:
844 data = CR_PCM;
845 fsi->chan_num = 2;
846 break;
847 default:
848 return -EINVAL;
849 }
850
851 fsi_reg_write(fsi, DO_FMT, data);
852 fsi_reg_write(fsi, DI_FMT, data);
853
854 return 0;
855}
856
857static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
858{
859 struct fsi_master *master = fsi_get_master(fsi);
860 u32 data = 0;
861
862 if (master->core->ver < 2)
863 return -EINVAL;
864
865 data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM;
866 fsi->chan_num = 2;
867 fsi_spdif_clk_ctrl(fsi, 1);
868 fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
869
870 fsi_reg_write(fsi, DO_FMT, data);
871 fsi_reg_write(fsi, DI_FMT, data);
872
873 return 0;
874}
875
884static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) 876static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
885{ 877{
886 struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); 878 struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
879 u32 flags = fsi_get_info_flags(fsi);
887 u32 data = 0; 880 u32 data = 0;
888 int ret; 881 int ret;
889 882
@@ -901,7 +894,18 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
901 goto set_fmt_exit; 894 goto set_fmt_exit;
902 } 895 }
903 fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); 896 fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data);
904 ret = 0; 897
898 /* set format */
899 switch (flags & SH_FSI_FMT_MASK) {
900 case SH_FSI_FMT_DAI:
901 ret = fsi_set_fmt_dai(fsi, fmt & SND_SOC_DAIFMT_FORMAT_MASK);
902 break;
903 case SH_FSI_FMT_SPDIF:
904 ret = fsi_set_fmt_spdif(fsi);
905 break;
906 default:
907 ret = -EINVAL;
908 }
905 909
906set_fmt_exit: 910set_fmt_exit:
907 pm_runtime_put_sync(dai->dev); 911 pm_runtime_put_sync(dai->dev);