diff options
Diffstat (limited to 'sound/soc/sh')
-rw-r--r-- | sound/soc/sh/fsi-ak4642.c | 24 | ||||
-rw-r--r-- | sound/soc/sh/fsi-da7210.c | 13 | ||||
-rw-r--r-- | sound/soc/sh/fsi-hdmi.c | 77 | ||||
-rw-r--r-- | sound/soc/sh/fsi.c | 203 |
4 files changed, 217 insertions, 100 deletions
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c index a14820ac9665..d6f4703b3c07 100644 --- a/sound/soc/sh/fsi-ak4642.c +++ b/sound/soc/sh/fsi-ak4642.c | |||
@@ -18,18 +18,26 @@ struct fsi_ak4642_data { | |||
18 | const char *cpu_dai; | 18 | const char *cpu_dai; |
19 | const char *codec; | 19 | const char *codec; |
20 | const char *platform; | 20 | const char *platform; |
21 | int id; | ||
21 | }; | 22 | }; |
22 | 23 | ||
23 | static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd) | 24 | static int fsi_ak4642_dai_init(struct snd_soc_pcm_runtime *rtd) |
24 | { | 25 | { |
25 | struct snd_soc_dai *dai = rtd->codec_dai; | 26 | struct snd_soc_dai *codec = rtd->codec_dai; |
27 | struct snd_soc_dai *cpu = rtd->cpu_dai; | ||
26 | int ret; | 28 | int ret; |
27 | 29 | ||
28 | ret = snd_soc_dai_set_fmt(dai, SND_SOC_DAIFMT_CBM_CFM); | 30 | ret = snd_soc_dai_set_fmt(codec, SND_SOC_DAIFMT_LEFT_J | |
31 | SND_SOC_DAIFMT_CBM_CFM); | ||
29 | if (ret < 0) | 32 | if (ret < 0) |
30 | return ret; | 33 | return ret; |
31 | 34 | ||
32 | ret = snd_soc_dai_set_sysclk(dai, 0, 11289600, 0); | 35 | ret = snd_soc_dai_set_sysclk(codec, 0, 11289600, 0); |
36 | if (ret < 0) | ||
37 | return ret; | ||
38 | |||
39 | ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_LEFT_J | | ||
40 | SND_SOC_DAIFMT_CBS_CFS); | ||
33 | 41 | ||
34 | return ret; | 42 | return ret; |
35 | } | 43 | } |
@@ -60,7 +68,7 @@ static int fsi_ak4642_probe(struct platform_device *pdev) | |||
60 | 68 | ||
61 | pdata = (struct fsi_ak4642_data *)id_entry->driver_data; | 69 | pdata = (struct fsi_ak4642_data *)id_entry->driver_data; |
62 | 70 | ||
63 | fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_A); | 71 | fsi_snd_device = platform_device_alloc("soc-audio", pdata->id); |
64 | if (!fsi_snd_device) | 72 | if (!fsi_snd_device) |
65 | goto out; | 73 | goto out; |
66 | 74 | ||
@@ -93,6 +101,7 @@ static struct fsi_ak4642_data fsi_a_ak4642 = { | |||
93 | .cpu_dai = "fsia-dai", | 101 | .cpu_dai = "fsia-dai", |
94 | .codec = "ak4642-codec.0-0012", | 102 | .codec = "ak4642-codec.0-0012", |
95 | .platform = "sh_fsi.0", | 103 | .platform = "sh_fsi.0", |
104 | .id = FSI_PORT_A, | ||
96 | }; | 105 | }; |
97 | 106 | ||
98 | static struct fsi_ak4642_data fsi_b_ak4642 = { | 107 | static struct fsi_ak4642_data fsi_b_ak4642 = { |
@@ -101,6 +110,7 @@ static struct fsi_ak4642_data fsi_b_ak4642 = { | |||
101 | .cpu_dai = "fsib-dai", | 110 | .cpu_dai = "fsib-dai", |
102 | .codec = "ak4642-codec.0-0012", | 111 | .codec = "ak4642-codec.0-0012", |
103 | .platform = "sh_fsi.0", | 112 | .platform = "sh_fsi.0", |
113 | .id = FSI_PORT_B, | ||
104 | }; | 114 | }; |
105 | 115 | ||
106 | static struct fsi_ak4642_data fsi_a_ak4643 = { | 116 | static struct fsi_ak4642_data fsi_a_ak4643 = { |
@@ -109,6 +119,7 @@ static struct fsi_ak4642_data fsi_a_ak4643 = { | |||
109 | .cpu_dai = "fsia-dai", | 119 | .cpu_dai = "fsia-dai", |
110 | .codec = "ak4642-codec.0-0013", | 120 | .codec = "ak4642-codec.0-0013", |
111 | .platform = "sh_fsi.0", | 121 | .platform = "sh_fsi.0", |
122 | .id = FSI_PORT_A, | ||
112 | }; | 123 | }; |
113 | 124 | ||
114 | static struct fsi_ak4642_data fsi_b_ak4643 = { | 125 | static struct fsi_ak4642_data fsi_b_ak4643 = { |
@@ -117,6 +128,7 @@ static struct fsi_ak4642_data fsi_b_ak4643 = { | |||
117 | .cpu_dai = "fsib-dai", | 128 | .cpu_dai = "fsib-dai", |
118 | .codec = "ak4642-codec.0-0013", | 129 | .codec = "ak4642-codec.0-0013", |
119 | .platform = "sh_fsi.0", | 130 | .platform = "sh_fsi.0", |
131 | .id = FSI_PORT_B, | ||
120 | }; | 132 | }; |
121 | 133 | ||
122 | static struct fsi_ak4642_data fsi2_a_ak4642 = { | 134 | static struct fsi_ak4642_data fsi2_a_ak4642 = { |
@@ -125,6 +137,7 @@ static struct fsi_ak4642_data fsi2_a_ak4642 = { | |||
125 | .cpu_dai = "fsia-dai", | 137 | .cpu_dai = "fsia-dai", |
126 | .codec = "ak4642-codec.0-0012", | 138 | .codec = "ak4642-codec.0-0012", |
127 | .platform = "sh_fsi2", | 139 | .platform = "sh_fsi2", |
140 | .id = FSI_PORT_A, | ||
128 | }; | 141 | }; |
129 | 142 | ||
130 | static struct fsi_ak4642_data fsi2_b_ak4642 = { | 143 | static struct fsi_ak4642_data fsi2_b_ak4642 = { |
@@ -133,6 +146,7 @@ static struct fsi_ak4642_data fsi2_b_ak4642 = { | |||
133 | .cpu_dai = "fsib-dai", | 146 | .cpu_dai = "fsib-dai", |
134 | .codec = "ak4642-codec.0-0012", | 147 | .codec = "ak4642-codec.0-0012", |
135 | .platform = "sh_fsi2", | 148 | .platform = "sh_fsi2", |
149 | .id = FSI_PORT_B, | ||
136 | }; | 150 | }; |
137 | 151 | ||
138 | static struct fsi_ak4642_data fsi2_a_ak4643 = { | 152 | static struct fsi_ak4642_data fsi2_a_ak4643 = { |
@@ -141,6 +155,7 @@ static struct fsi_ak4642_data fsi2_a_ak4643 = { | |||
141 | .cpu_dai = "fsia-dai", | 155 | .cpu_dai = "fsia-dai", |
142 | .codec = "ak4642-codec.0-0013", | 156 | .codec = "ak4642-codec.0-0013", |
143 | .platform = "sh_fsi2", | 157 | .platform = "sh_fsi2", |
158 | .id = FSI_PORT_A, | ||
144 | }; | 159 | }; |
145 | 160 | ||
146 | static struct fsi_ak4642_data fsi2_b_ak4643 = { | 161 | static struct fsi_ak4642_data fsi2_b_ak4643 = { |
@@ -149,6 +164,7 @@ static struct fsi_ak4642_data fsi2_b_ak4643 = { | |||
149 | .cpu_dai = "fsib-dai", | 164 | .cpu_dai = "fsib-dai", |
150 | .codec = "ak4642-codec.0-0013", | 165 | .codec = "ak4642-codec.0-0013", |
151 | .platform = "sh_fsi2", | 166 | .platform = "sh_fsi2", |
167 | .id = FSI_PORT_B, | ||
152 | }; | 168 | }; |
153 | 169 | ||
154 | static struct platform_device_id fsi_id_table[] = { | 170 | static struct platform_device_id fsi_id_table[] = { |
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c index e8df9da92f71..dbafd7ac5590 100644 --- a/sound/soc/sh/fsi-da7210.c +++ b/sound/soc/sh/fsi-da7210.c | |||
@@ -15,11 +15,20 @@ | |||
15 | 15 | ||
16 | static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd) | 16 | static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd) |
17 | { | 17 | { |
18 | struct snd_soc_dai *dai = rtd->codec_dai; | 18 | struct snd_soc_dai *codec = rtd->codec_dai; |
19 | struct snd_soc_dai *cpu = rtd->cpu_dai; | ||
20 | int ret; | ||
19 | 21 | ||
20 | return snd_soc_dai_set_fmt(dai, | 22 | ret = snd_soc_dai_set_fmt(codec, |
21 | SND_SOC_DAIFMT_I2S | | 23 | SND_SOC_DAIFMT_I2S | |
22 | SND_SOC_DAIFMT_CBM_CFM); | 24 | SND_SOC_DAIFMT_CBM_CFM); |
25 | if (ret < 0) | ||
26 | return ret; | ||
27 | |||
28 | ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_I2S | | ||
29 | SND_SOC_DAIFMT_CBS_CFS); | ||
30 | |||
31 | return ret; | ||
23 | } | 32 | } |
24 | 33 | ||
25 | static struct snd_soc_dai_link fsi_da7210_dai = { | 34 | static struct snd_soc_dai_link fsi_da7210_dai = { |
diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c index a52dd8ec71d3..9719985eb82d 100644 --- a/sound/soc/sh/fsi-hdmi.c +++ b/sound/soc/sh/fsi-hdmi.c | |||
@@ -12,31 +12,59 @@ | |||
12 | #include <linux/platform_device.h> | 12 | #include <linux/platform_device.h> |
13 | #include <sound/sh_fsi.h> | 13 | #include <sound/sh_fsi.h> |
14 | 14 | ||
15 | struct fsi_hdmi_data { | ||
16 | const char *cpu_dai; | ||
17 | const char *card; | ||
18 | int id; | ||
19 | }; | ||
20 | |||
21 | static int fsi_hdmi_dai_init(struct snd_soc_pcm_runtime *rtd) | ||
22 | { | ||
23 | struct snd_soc_dai *cpu = rtd->cpu_dai; | ||
24 | int ret; | ||
25 | |||
26 | ret = snd_soc_dai_set_fmt(cpu, SND_SOC_DAIFMT_CBM_CFM); | ||
27 | |||
28 | return ret; | ||
29 | } | ||
30 | |||
15 | static struct snd_soc_dai_link fsi_dai_link = { | 31 | static struct snd_soc_dai_link fsi_dai_link = { |
16 | .name = "HDMI", | 32 | .name = "HDMI", |
17 | .stream_name = "HDMI", | 33 | .stream_name = "HDMI", |
18 | .cpu_dai_name = "fsib-dai", /* fsi B */ | ||
19 | .codec_dai_name = "sh_mobile_hdmi-hifi", | 34 | .codec_dai_name = "sh_mobile_hdmi-hifi", |
20 | .platform_name = "sh_fsi2", | 35 | .platform_name = "sh_fsi2", |
21 | .codec_name = "sh-mobile-hdmi", | 36 | .codec_name = "sh-mobile-hdmi", |
37 | .init = fsi_hdmi_dai_init, | ||
22 | }; | 38 | }; |
23 | 39 | ||
24 | static struct snd_soc_card fsi_soc_card = { | 40 | static struct snd_soc_card fsi_soc_card = { |
25 | .name = "FSI (SH MOBILE HDMI)", | ||
26 | .dai_link = &fsi_dai_link, | 41 | .dai_link = &fsi_dai_link, |
27 | .num_links = 1, | 42 | .num_links = 1, |
28 | }; | 43 | }; |
29 | 44 | ||
30 | static struct platform_device *fsi_snd_device; | 45 | static struct platform_device *fsi_snd_device; |
31 | 46 | ||
32 | static int __init fsi_hdmi_init(void) | 47 | static int fsi_hdmi_probe(struct platform_device *pdev) |
33 | { | 48 | { |
34 | int ret = -ENOMEM; | 49 | int ret = -ENOMEM; |
50 | const struct platform_device_id *id_entry; | ||
51 | struct fsi_hdmi_data *pdata; | ||
52 | |||
53 | id_entry = pdev->id_entry; | ||
54 | if (!id_entry) { | ||
55 | dev_err(&pdev->dev, "unknown fsi hdmi\n"); | ||
56 | return -ENODEV; | ||
57 | } | ||
35 | 58 | ||
36 | fsi_snd_device = platform_device_alloc("soc-audio", FSI_PORT_B); | 59 | pdata = (struct fsi_hdmi_data *)id_entry->driver_data; |
60 | |||
61 | fsi_snd_device = platform_device_alloc("soc-audio", pdata->id); | ||
37 | if (!fsi_snd_device) | 62 | if (!fsi_snd_device) |
38 | goto out; | 63 | goto out; |
39 | 64 | ||
65 | fsi_dai_link.cpu_dai_name = pdata->cpu_dai; | ||
66 | fsi_soc_card.name = pdata->card; | ||
67 | |||
40 | platform_set_drvdata(fsi_snd_device, &fsi_soc_card); | 68 | platform_set_drvdata(fsi_snd_device, &fsi_soc_card); |
41 | ret = platform_device_add(fsi_snd_device); | 69 | ret = platform_device_add(fsi_snd_device); |
42 | 70 | ||
@@ -47,9 +75,48 @@ out: | |||
47 | return ret; | 75 | return ret; |
48 | } | 76 | } |
49 | 77 | ||
50 | static void __exit fsi_hdmi_exit(void) | 78 | static int fsi_hdmi_remove(struct platform_device *pdev) |
51 | { | 79 | { |
52 | platform_device_unregister(fsi_snd_device); | 80 | platform_device_unregister(fsi_snd_device); |
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static struct fsi_hdmi_data fsi2_a_hdmi = { | ||
85 | .cpu_dai = "fsia-dai", | ||
86 | .card = "FSI2A (SH MOBILE HDMI)", | ||
87 | .id = FSI_PORT_A, | ||
88 | }; | ||
89 | |||
90 | static struct fsi_hdmi_data fsi2_b_hdmi = { | ||
91 | .cpu_dai = "fsib-dai", | ||
92 | .card = "FSI2B (SH MOBILE HDMI)", | ||
93 | .id = FSI_PORT_B, | ||
94 | }; | ||
95 | |||
96 | static struct platform_device_id fsi_id_table[] = { | ||
97 | /* FSI 2 */ | ||
98 | { "sh_fsi2_a_hdmi", (kernel_ulong_t)&fsi2_a_hdmi }, | ||
99 | { "sh_fsi2_b_hdmi", (kernel_ulong_t)&fsi2_b_hdmi }, | ||
100 | {}, | ||
101 | }; | ||
102 | |||
103 | static struct platform_driver fsi_hdmi = { | ||
104 | .driver = { | ||
105 | .name = "fsi-hdmi-audio", | ||
106 | }, | ||
107 | .probe = fsi_hdmi_probe, | ||
108 | .remove = fsi_hdmi_remove, | ||
109 | .id_table = fsi_id_table, | ||
110 | }; | ||
111 | |||
112 | static int __init fsi_hdmi_init(void) | ||
113 | { | ||
114 | return platform_driver_register(&fsi_hdmi); | ||
115 | } | ||
116 | |||
117 | static void __exit fsi_hdmi_exit(void) | ||
118 | { | ||
119 | platform_driver_unregister(&fsi_hdmi); | ||
53 | } | 120 | } |
54 | 121 | ||
55 | module_init(fsi_hdmi_init); | 122 | module_init(fsi_hdmi_init); |
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index 2b06402801ef..0c9997e2d8c0 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -78,6 +78,8 @@ | |||
78 | /* CKG1 */ | 78 | /* CKG1 */ |
79 | #define ACKMD_MASK 0x00007000 | 79 | #define ACKMD_MASK 0x00007000 |
80 | #define BPFMD_MASK 0x00000700 | 80 | #define BPFMD_MASK 0x00000700 |
81 | #define DIMD (1 << 4) | ||
82 | #define DOMD (1 << 0) | ||
81 | 83 | ||
82 | /* A/B MST_CTLR */ | 84 | /* A/B MST_CTLR */ |
83 | #define BP (1 << 4) /* Fix the signal of Biphase output */ | 85 | #define BP (1 << 4) /* Fix the signal of Biphase output */ |
@@ -111,6 +113,8 @@ | |||
111 | 113 | ||
112 | #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) | 114 | #define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE) |
113 | 115 | ||
116 | typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int enable); | ||
117 | |||
114 | /* | 118 | /* |
115 | * FSI driver use below type name for variable | 119 | * FSI driver use below type name for variable |
116 | * | 120 | * |
@@ -128,7 +132,6 @@ struct fsi_stream { | |||
128 | struct snd_pcm_substream *substream; | 132 | struct snd_pcm_substream *substream; |
129 | 133 | ||
130 | int fifo_max_num; | 134 | int fifo_max_num; |
131 | int chan_num; | ||
132 | 135 | ||
133 | int buff_offset; | 136 | int buff_offset; |
134 | int buff_len; | 137 | int buff_len; |
@@ -143,6 +146,7 @@ struct fsi_priv { | |||
143 | void __iomem *base; | 146 | void __iomem *base; |
144 | struct fsi_master *master; | 147 | struct fsi_master *master; |
145 | 148 | ||
149 | int chan_num; | ||
146 | struct fsi_stream playback; | 150 | struct fsi_stream playback; |
147 | struct fsi_stream capture; | 151 | struct fsi_stream capture; |
148 | 152 | ||
@@ -252,9 +256,8 @@ static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream) | |||
252 | return rtd->cpu_dai; | 256 | return rtd->cpu_dai; |
253 | } | 257 | } |
254 | 258 | ||
255 | static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) | 259 | static struct fsi_priv *fsi_get_priv_frm_dai(struct snd_soc_dai *dai) |
256 | { | 260 | { |
257 | struct snd_soc_dai *dai = fsi_get_dai(substream); | ||
258 | struct fsi_master *master = snd_soc_dai_get_drvdata(dai); | 261 | struct fsi_master *master = snd_soc_dai_get_drvdata(dai); |
259 | 262 | ||
260 | if (dai->id == 0) | 263 | if (dai->id == 0) |
@@ -263,11 +266,27 @@ static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) | |||
263 | return &master->fsib; | 266 | return &master->fsib; |
264 | } | 267 | } |
265 | 268 | ||
269 | static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream) | ||
270 | { | ||
271 | return fsi_get_priv_frm_dai(fsi_get_dai(substream)); | ||
272 | } | ||
273 | |||
274 | static set_rate_func fsi_get_info_set_rate(struct fsi_master *master) | ||
275 | { | ||
276 | if (!master->info) | ||
277 | return NULL; | ||
278 | |||
279 | return master->info->set_rate; | ||
280 | } | ||
281 | |||
266 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) | 282 | static u32 fsi_get_info_flags(struct fsi_priv *fsi) |
267 | { | 283 | { |
268 | int is_porta = fsi_is_port_a(fsi); | 284 | int is_porta = fsi_is_port_a(fsi); |
269 | struct fsi_master *master = fsi_get_master(fsi); | 285 | struct fsi_master *master = fsi_get_master(fsi); |
270 | 286 | ||
287 | if (!master->info) | ||
288 | return 0; | ||
289 | |||
271 | return is_porta ? master->info->porta_flags : | 290 | return is_porta ? master->info->porta_flags : |
272 | master->info->portb_flags; | 291 | master->info->portb_flags; |
273 | } | 292 | } |
@@ -288,21 +307,6 @@ static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi, | |||
288 | return is_play ? &fsi->playback : &fsi->capture; | 307 | return is_play ? &fsi->playback : &fsi->capture; |
289 | } | 308 | } |
290 | 309 | ||
291 | static int fsi_is_master_mode(struct fsi_priv *fsi, int is_play) | ||
292 | { | ||
293 | u32 mode; | ||
294 | u32 flags = fsi_get_info_flags(fsi); | ||
295 | |||
296 | mode = is_play ? SH_FSI_OUT_SLAVE_MODE : SH_FSI_IN_SLAVE_MODE; | ||
297 | |||
298 | /* return | ||
299 | * 1 : master mode | ||
300 | * 0 : slave mode | ||
301 | */ | ||
302 | |||
303 | return (mode & flags) != mode; | ||
304 | } | ||
305 | |||
306 | static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) | 310 | static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play) |
307 | { | 311 | { |
308 | int is_porta = fsi_is_port_a(fsi); | 312 | int is_porta = fsi_is_port_a(fsi); |
@@ -357,7 +361,6 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play) | |||
357 | static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) | 361 | static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) |
358 | { | 362 | { |
359 | u32 status; | 363 | u32 status; |
360 | struct fsi_stream *io = fsi_get_stream(fsi, is_play); | ||
361 | int data_num; | 364 | int data_num; |
362 | 365 | ||
363 | status = is_play ? | 366 | status = is_play ? |
@@ -365,7 +368,7 @@ static int fsi_get_fifo_data_num(struct fsi_priv *fsi, int is_play) | |||
365 | fsi_reg_read(fsi, DIFF_ST); | 368 | fsi_reg_read(fsi, DIFF_ST); |
366 | 369 | ||
367 | data_num = 0x1ff & (status >> 8); | 370 | data_num = 0x1ff & (status >> 8); |
368 | data_num *= io->chan_num; | 371 | data_num *= fsi->chan_num; |
369 | 372 | ||
370 | return data_num; | 373 | return data_num; |
371 | } | 374 | } |
@@ -387,7 +390,7 @@ static int fsi_get_frame_width(struct fsi_priv *fsi, int is_play) | |||
387 | struct snd_pcm_substream *substream = io->substream; | 390 | struct snd_pcm_substream *substream = io->substream; |
388 | struct snd_pcm_runtime *runtime = substream->runtime; | 391 | struct snd_pcm_runtime *runtime = substream->runtime; |
389 | 392 | ||
390 | return frames_to_bytes(runtime, 1) / io->chan_num; | 393 | return frames_to_bytes(runtime, 1) / fsi->chan_num; |
391 | } | 394 | } |
392 | 395 | ||
393 | static void fsi_count_fifo_err(struct fsi_priv *fsi) | 396 | static void fsi_count_fifo_err(struct fsi_priv *fsi) |
@@ -580,10 +583,10 @@ static void fsi_fifo_init(struct fsi_priv *fsi, | |||
580 | * 7 channels: 32 ( 32 x 7 = 224) | 583 | * 7 channels: 32 ( 32 x 7 = 224) |
581 | * 8 channels: 32 ( 32 x 8 = 256) | 584 | * 8 channels: 32 ( 32 x 8 = 256) |
582 | */ | 585 | */ |
583 | for (i = 1; i < io->chan_num; i <<= 1) | 586 | for (i = 1; i < fsi->chan_num; i <<= 1) |
584 | io->fifo_max_num >>= 1; | 587 | io->fifo_max_num >>= 1; |
585 | dev_dbg(dai->dev, "%d channel %d store\n", | 588 | dev_dbg(dai->dev, "%d channel %d store\n", |
586 | io->chan_num, io->fifo_max_num); | 589 | fsi->chan_num, io->fifo_max_num); |
587 | 590 | ||
588 | /* | 591 | /* |
589 | * set interrupt generation factor | 592 | * set interrupt generation factor |
@@ -659,7 +662,7 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream) | |||
659 | * data_num_max : number of FSI fifo free space | 662 | * data_num_max : number of FSI fifo free space |
660 | * data_num : number of ALSA residue data | 663 | * data_num : number of ALSA residue data |
661 | */ | 664 | */ |
662 | data_num_max = io->fifo_max_num * io->chan_num; | 665 | data_num_max = io->fifo_max_num * fsi->chan_num; |
663 | data_num_max -= fsi_get_fifo_data_num(fsi, is_play); | 666 | data_num_max -= fsi_get_fifo_data_num(fsi, is_play); |
664 | 667 | ||
665 | data_num = data_residue_num; | 668 | data_num = data_residue_num; |
@@ -754,25 +757,12 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
754 | struct snd_soc_dai *dai) | 757 | struct snd_soc_dai *dai) |
755 | { | 758 | { |
756 | struct fsi_priv *fsi = fsi_get_priv(substream); | 759 | struct fsi_priv *fsi = fsi_get_priv(substream); |
757 | struct fsi_master *master = fsi_get_master(fsi); | ||
758 | struct fsi_stream *io; | ||
759 | u32 flags = fsi_get_info_flags(fsi); | 760 | u32 flags = fsi_get_info_flags(fsi); |
760 | u32 fmt; | ||
761 | u32 data; | 761 | u32 data; |
762 | int is_play = fsi_is_play(substream); | 762 | int is_play = fsi_is_play(substream); |
763 | int is_master; | ||
764 | |||
765 | io = fsi_get_stream(fsi, is_play); | ||
766 | 763 | ||
767 | pm_runtime_get_sync(dai->dev); | 764 | pm_runtime_get_sync(dai->dev); |
768 | 765 | ||
769 | /* CKG1 */ | ||
770 | data = is_play ? (1 << 0) : (1 << 4); | ||
771 | is_master = fsi_is_master_mode(fsi, is_play); | ||
772 | if (is_master) | ||
773 | fsi_reg_mask_set(fsi, CKG1, data, data); | ||
774 | else | ||
775 | fsi_reg_mask_set(fsi, CKG1, data, 0); | ||
776 | 766 | ||
777 | /* clock inversion (CKG2) */ | 767 | /* clock inversion (CKG2) */ |
778 | data = 0; | 768 | data = 0; |
@@ -787,54 +777,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream, | |||
787 | 777 | ||
788 | fsi_reg_write(fsi, CKG2, data); | 778 | fsi_reg_write(fsi, CKG2, data); |
789 | 779 | ||
790 | /* do fmt, di fmt */ | ||
791 | data = 0; | ||
792 | fmt = is_play ? SH_FSI_GET_OFMT(flags) : SH_FSI_GET_IFMT(flags); | ||
793 | switch (fmt) { | ||
794 | case SH_FSI_FMT_MONO: | ||
795 | data = CR_MONO; | ||
796 | io->chan_num = 1; | ||
797 | break; | ||
798 | case SH_FSI_FMT_MONO_DELAY: | ||
799 | data = CR_MONO_D; | ||
800 | io->chan_num = 1; | ||
801 | break; | ||
802 | case SH_FSI_FMT_PCM: | ||
803 | data = CR_PCM; | ||
804 | io->chan_num = 2; | ||
805 | break; | ||
806 | case SH_FSI_FMT_I2S: | ||
807 | data = CR_I2S; | ||
808 | io->chan_num = 2; | ||
809 | break; | ||
810 | case SH_FSI_FMT_TDM: | ||
811 | io->chan_num = is_play ? | ||
812 | SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); | ||
813 | data = CR_TDM | (io->chan_num - 1); | ||
814 | break; | ||
815 | case SH_FSI_FMT_TDM_DELAY: | ||
816 | io->chan_num = is_play ? | ||
817 | SH_FSI_GET_CH_O(flags) : SH_FSI_GET_CH_I(flags); | ||
818 | data = CR_TDM_D | (io->chan_num - 1); | ||
819 | break; | ||
820 | case SH_FSI_FMT_SPDIF: | ||
821 | if (master->core->ver < 2) { | ||
822 | dev_err(dai->dev, "This FSI can not use SPDIF\n"); | ||
823 | return -EINVAL; | ||
824 | } | ||
825 | data = CR_BWS_16 | CR_DTMD_SPDIF_PCM | CR_PCM; | ||
826 | io->chan_num = 2; | ||
827 | fsi_spdif_clk_ctrl(fsi, 1); | ||
828 | fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD); | ||
829 | break; | ||
830 | default: | ||
831 | dev_err(dai->dev, "unknown format.\n"); | ||
832 | return -EINVAL; | ||
833 | } | ||
834 | is_play ? | ||
835 | fsi_reg_write(fsi, DO_FMT, data) : | ||
836 | fsi_reg_write(fsi, DI_FMT, data); | ||
837 | |||
838 | /* irq clear */ | 780 | /* irq clear */ |
839 | fsi_irq_disable(fsi, is_play); | 781 | fsi_irq_disable(fsi, is_play); |
840 | fsi_irq_clear_status(fsi); | 782 | fsi_irq_clear_status(fsi); |
@@ -851,12 +793,12 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream, | |||
851 | struct fsi_priv *fsi = fsi_get_priv(substream); | 793 | struct fsi_priv *fsi = fsi_get_priv(substream); |
852 | int is_play = fsi_is_play(substream); | 794 | int is_play = fsi_is_play(substream); |
853 | struct fsi_master *master = fsi_get_master(fsi); | 795 | struct fsi_master *master = fsi_get_master(fsi); |
854 | int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); | 796 | set_rate_func set_rate; |
855 | 797 | ||
856 | fsi_irq_disable(fsi, is_play); | 798 | fsi_irq_disable(fsi, is_play); |
857 | fsi_clk_ctrl(fsi, 0); | 799 | fsi_clk_ctrl(fsi, 0); |
858 | 800 | ||
859 | set_rate = master->info->set_rate; | 801 | set_rate = fsi_get_info_set_rate(master); |
860 | if (set_rate && fsi->rate) | 802 | if (set_rate && fsi->rate) |
861 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); | 803 | set_rate(dai->dev, fsi_is_port_a(fsi), fsi->rate, 0); |
862 | fsi->rate = 0; | 804 | fsi->rate = 0; |
@@ -889,18 +831,100 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, | |||
889 | return ret; | 831 | return ret; |
890 | } | 832 | } |
891 | 833 | ||
834 | static 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 | |||
857 | static 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 | |||
876 | static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
877 | { | ||
878 | struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai); | ||
879 | u32 flags = fsi_get_info_flags(fsi); | ||
880 | u32 data = 0; | ||
881 | int ret; | ||
882 | |||
883 | pm_runtime_get_sync(dai->dev); | ||
884 | |||
885 | /* set master/slave audio interface */ | ||
886 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
887 | case SND_SOC_DAIFMT_CBM_CFM: | ||
888 | data = DIMD | DOMD; | ||
889 | break; | ||
890 | case SND_SOC_DAIFMT_CBS_CFS: | ||
891 | break; | ||
892 | default: | ||
893 | ret = -EINVAL; | ||
894 | goto set_fmt_exit; | ||
895 | } | ||
896 | fsi_reg_mask_set(fsi, CKG1, (DIMD | DOMD), data); | ||
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 | } | ||
909 | |||
910 | set_fmt_exit: | ||
911 | pm_runtime_put_sync(dai->dev); | ||
912 | |||
913 | return ret; | ||
914 | } | ||
915 | |||
892 | static int fsi_dai_hw_params(struct snd_pcm_substream *substream, | 916 | static int fsi_dai_hw_params(struct snd_pcm_substream *substream, |
893 | struct snd_pcm_hw_params *params, | 917 | struct snd_pcm_hw_params *params, |
894 | struct snd_soc_dai *dai) | 918 | struct snd_soc_dai *dai) |
895 | { | 919 | { |
896 | struct fsi_priv *fsi = fsi_get_priv(substream); | 920 | struct fsi_priv *fsi = fsi_get_priv(substream); |
897 | struct fsi_master *master = fsi_get_master(fsi); | 921 | struct fsi_master *master = fsi_get_master(fsi); |
898 | int (*set_rate)(struct device *dev, int is_porta, int rate, int enable); | 922 | set_rate_func set_rate; |
899 | int fsi_ver = master->core->ver; | 923 | int fsi_ver = master->core->ver; |
900 | long rate = params_rate(params); | 924 | long rate = params_rate(params); |
901 | int ret; | 925 | int ret; |
902 | 926 | ||
903 | set_rate = master->info->set_rate; | 927 | set_rate = fsi_get_info_set_rate(master); |
904 | if (!set_rate) | 928 | if (!set_rate) |
905 | return 0; | 929 | return 0; |
906 | 930 | ||
@@ -975,6 +999,7 @@ static struct snd_soc_dai_ops fsi_dai_ops = { | |||
975 | .startup = fsi_dai_startup, | 999 | .startup = fsi_dai_startup, |
976 | .shutdown = fsi_dai_shutdown, | 1000 | .shutdown = fsi_dai_shutdown, |
977 | .trigger = fsi_dai_trigger, | 1001 | .trigger = fsi_dai_trigger, |
1002 | .set_fmt = fsi_dai_set_fmt, | ||
978 | .hw_params = fsi_dai_hw_params, | 1003 | .hw_params = fsi_dai_hw_params, |
979 | }; | 1004 | }; |
980 | 1005 | ||