diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2014-01-23 21:42:00 -0500 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-02-03 07:41:38 -0500 |
commit | 629509c5bc478c0343d94c8c70812396f44447fb (patch) | |
tree | cdeab0938f68fe265bdd54b219c369213988f0b4 | |
parent | eb854f6dff24a59378acc8d8eda57a3543a25acc (diff) |
ASoC: rsnd: add Gen2 SRC and DMAEngine support
Renesas sound Gen2 has SRC (= Sampling Rate Converter)
which needs 2 DMAC.
The data path image when you use SRC on Gen2 is
[mem] -> Audio-DMAC -> SRC -> Audio-DMAC-peri-peri -> SSIU -> SSI
This patch support SRC and DMAEnine.
It is tested on R-Car H2 Lager board
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | include/sound/rcar_snd.h | 6 | ||||
-rw-r--r-- | sound/soc/sh/rcar/adg.c | 138 | ||||
-rw-r--r-- | sound/soc/sh/rcar/gen.c | 26 | ||||
-rw-r--r-- | sound/soc/sh/rcar/rsnd.h | 25 | ||||
-rw-r--r-- | sound/soc/sh/rcar/scu.c | 117 |
5 files changed, 312 insertions, 0 deletions
diff --git a/include/sound/rcar_snd.h b/include/sound/rcar_snd.h index 1d19bfc2486d..2be05aea54f9 100644 --- a/include/sound/rcar_snd.h +++ b/include/sound/rcar_snd.h | |||
@@ -56,9 +56,15 @@ struct rsnd_ssi_platform_info { | |||
56 | */ | 56 | */ |
57 | #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ | 57 | #define RSND_SCU_USE_HPBIF (1 << 31) /* it needs RSND_SSI_DEPENDENT */ |
58 | 58 | ||
59 | #define RSND_SCU_SET(rate, _dma_id) \ | ||
60 | { .flags = RSND_SCU_USE_HPBIF, .convert_rate = rate, .dma_id = _dma_id, } | ||
61 | #define RSND_SCU_UNUSED \ | ||
62 | { .flags = 0, .convert_rate = 0, .dma_id = 0, } | ||
63 | |||
59 | struct rsnd_scu_platform_info { | 64 | struct rsnd_scu_platform_info { |
60 | u32 flags; | 65 | u32 flags; |
61 | u32 convert_rate; /* sampling rate convert */ | 66 | u32 convert_rate; /* sampling rate convert */ |
67 | int dma_id; /* for Gen2 SCU */ | ||
62 | }; | 68 | }; |
63 | 69 | ||
64 | /* | 70 | /* |
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index 5bdffa480245..821791e15d04 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c | |||
@@ -30,6 +30,144 @@ struct rsnd_adg { | |||
30 | i++, (pos) = adg->clk[i]) | 30 | i++, (pos) = adg->clk[i]) |
31 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) | 31 | #define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) |
32 | 32 | ||
33 | |||
34 | static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_mod *mod) | ||
35 | { | ||
36 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
37 | int id = rsnd_mod_id(mod); | ||
38 | int ws = id; | ||
39 | |||
40 | if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) { | ||
41 | switch (id) { | ||
42 | case 1: | ||
43 | case 2: | ||
44 | ws = 0; | ||
45 | break; | ||
46 | case 4: | ||
47 | ws = 3; | ||
48 | break; | ||
49 | case 8: | ||
50 | ws = 7; | ||
51 | break; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | return (0x6 + ws) << 8; | ||
56 | } | ||
57 | |||
58 | static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai, | ||
59 | struct rsnd_mod *mod, | ||
60 | struct rsnd_dai_stream *io, | ||
61 | u32 timsel) | ||
62 | { | ||
63 | int is_play = rsnd_dai_is_play(rdai, io); | ||
64 | int id = rsnd_mod_id(mod); | ||
65 | int shift = (id % 2) ? 16 : 0; | ||
66 | u32 mask, ws; | ||
67 | u32 in, out; | ||
68 | |||
69 | ws = rsnd_adg_ssi_ws_timing_gen2(mod); | ||
70 | |||
71 | in = (is_play) ? timsel : ws; | ||
72 | out = (is_play) ? ws : timsel; | ||
73 | |||
74 | in = in << shift; | ||
75 | out = out << shift; | ||
76 | mask = 0xffff << shift; | ||
77 | |||
78 | switch (id / 2) { | ||
79 | case 0: | ||
80 | rsnd_mod_bset(mod, SRCIN_TIMSEL0, mask, in); | ||
81 | rsnd_mod_bset(mod, SRCOUT_TIMSEL0, mask, out); | ||
82 | break; | ||
83 | case 1: | ||
84 | rsnd_mod_bset(mod, SRCIN_TIMSEL1, mask, in); | ||
85 | rsnd_mod_bset(mod, SRCOUT_TIMSEL1, mask, out); | ||
86 | break; | ||
87 | case 2: | ||
88 | rsnd_mod_bset(mod, SRCIN_TIMSEL2, mask, in); | ||
89 | rsnd_mod_bset(mod, SRCOUT_TIMSEL2, mask, out); | ||
90 | break; | ||
91 | case 3: | ||
92 | rsnd_mod_bset(mod, SRCIN_TIMSEL3, mask, in); | ||
93 | rsnd_mod_bset(mod, SRCOUT_TIMSEL3, mask, out); | ||
94 | break; | ||
95 | case 4: | ||
96 | rsnd_mod_bset(mod, SRCIN_TIMSEL4, mask, in); | ||
97 | rsnd_mod_bset(mod, SRCOUT_TIMSEL4, mask, out); | ||
98 | break; | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, | ||
105 | struct rsnd_dai *rdai, | ||
106 | struct rsnd_dai_stream *io, | ||
107 | unsigned int src_rate, | ||
108 | unsigned int dst_rate) | ||
109 | { | ||
110 | struct rsnd_priv *priv = rsnd_mod_to_priv(mod); | ||
111 | struct rsnd_adg *adg = rsnd_priv_to_adg(priv); | ||
112 | struct device *dev = rsnd_priv_to_dev(priv); | ||
113 | int idx, sel, div, step; | ||
114 | u32 val; | ||
115 | unsigned int min, diff; | ||
116 | unsigned int sel_rate [] = { | ||
117 | clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */ | ||
118 | clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */ | ||
119 | clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */ | ||
120 | adg->rbga_rate_for_441khz_div_6,/* 0011: RBGA */ | ||
121 | adg->rbgb_rate_for_48khz_div_6, /* 0100: RBGB */ | ||
122 | }; | ||
123 | |||
124 | min = ~0; | ||
125 | val = 0; | ||
126 | for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { | ||
127 | idx = 0; | ||
128 | step = 2; | ||
129 | |||
130 | if (!sel_rate[sel]) | ||
131 | continue; | ||
132 | |||
133 | for (div = 2; div <= 98304; div += step) { | ||
134 | diff = abs(src_rate - sel_rate[sel] / div); | ||
135 | if (min > diff) { | ||
136 | val = (sel << 8) | idx; | ||
137 | min = diff; | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * step of 0_0000 / 0_0001 / 0_1101 | ||
142 | * are out of order | ||
143 | */ | ||
144 | if ((idx > 2) && (idx % 2)) | ||
145 | step *= 2; | ||
146 | if (idx == 0x1c) { | ||
147 | div += step; | ||
148 | step *= 2; | ||
149 | } | ||
150 | idx++; | ||
151 | } | ||
152 | } | ||
153 | |||
154 | if (min == ~0) { | ||
155 | dev_err(dev, "no Input clock\n"); | ||
156 | return -EIO; | ||
157 | } | ||
158 | |||
159 | return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); | ||
160 | } | ||
161 | |||
162 | int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, | ||
163 | struct rsnd_dai *rdai, | ||
164 | struct rsnd_dai_stream *io) | ||
165 | { | ||
166 | u32 val = rsnd_adg_ssi_ws_timing_gen2(mod); | ||
167 | |||
168 | return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val); | ||
169 | } | ||
170 | |||
33 | int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, | 171 | int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, |
34 | struct rsnd_mod *mod, | 172 | struct rsnd_mod *mod, |
35 | unsigned int src_rate, | 173 | unsigned int src_rate, |
diff --git a/sound/soc/sh/rcar/gen.c b/sound/soc/sh/rcar/gen.c index db486aae6b8b..3e03a8bc4f75 100644 --- a/sound/soc/sh/rcar/gen.c +++ b/sound/soc/sh/rcar/gen.c | |||
@@ -229,14 +229,40 @@ static int rsnd_gen2_regmap_init(struct rsnd_priv *priv, struct rsnd_gen *gen) | |||
229 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), | 229 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE0, 0x800), |
230 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), | 230 | RSND_GEN2_S_REG(gen, SSIU, SSI_MODE1, 0x804), |
231 | /* FIXME: it needs SSI_MODE2/3 in the future */ | 231 | /* FIXME: it needs SSI_MODE2/3 in the future */ |
232 | RSND_GEN2_S_REG(gen, SSIU, SSI_CONTROL, 0x810), | ||
233 | RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_MODE, 0x0, 0x80), | ||
234 | RSND_GEN2_M_REG(gen, SSIU, SSI_BUSIF_ADINR,0x4, 0x80), | ||
235 | RSND_GEN2_M_REG(gen, SSIU, SSI_CTRL, 0x10, 0x80), | ||
232 | RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), | 236 | RSND_GEN2_M_REG(gen, SSIU, INT_ENABLE, 0x18, 0x80), |
233 | 237 | ||
238 | RSND_GEN2_M_REG(gen, SCU, SRC_BUSIF_MODE, 0x0, 0x20), | ||
239 | RSND_GEN2_M_REG(gen, SCU, SRC_ROUTE_MODE0,0xc, 0x20), | ||
240 | RSND_GEN2_M_REG(gen, SCU, SRC_CTRL, 0x10, 0x20), | ||
241 | RSND_GEN2_M_REG(gen, SCU, SRC_SWRSR, 0x200, 0x40), | ||
242 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCIR, 0x204, 0x40), | ||
243 | RSND_GEN2_M_REG(gen, SCU, SRC_ADINR, 0x214, 0x40), | ||
244 | RSND_GEN2_M_REG(gen, SCU, SRC_IFSCR, 0x21c, 0x40), | ||
245 | RSND_GEN2_M_REG(gen, SCU, SRC_IFSVR, 0x220, 0x40), | ||
246 | RSND_GEN2_M_REG(gen, SCU, SRC_SRCCR, 0x224, 0x40), | ||
247 | RSND_GEN2_M_REG(gen, SCU, SRC_BSDSR, 0x22c, 0x40), | ||
248 | RSND_GEN2_M_REG(gen, SCU, SRC_BSISR, 0x238, 0x40), | ||
249 | |||
234 | RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), | 250 | RSND_GEN2_S_REG(gen, ADG, BRRA, 0x00), |
235 | RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), | 251 | RSND_GEN2_S_REG(gen, ADG, BRRB, 0x04), |
236 | RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), | 252 | RSND_GEN2_S_REG(gen, ADG, SSICKR, 0x08), |
237 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), | 253 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL0, 0x0c), |
238 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), | 254 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL1, 0x10), |
239 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), | 255 | RSND_GEN2_S_REG(gen, ADG, AUDIO_CLK_SEL2, 0x14), |
256 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL0, 0x34), | ||
257 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL1, 0x38), | ||
258 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL2, 0x3c), | ||
259 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL3, 0x40), | ||
260 | RSND_GEN2_S_REG(gen, ADG, SRCIN_TIMSEL4, 0x44), | ||
261 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL0, 0x48), | ||
262 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL1, 0x4c), | ||
263 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL2, 0x50), | ||
264 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL3, 0x54), | ||
265 | RSND_GEN2_S_REG(gen, ADG, SRCOUT_TIMSEL4, 0x58), | ||
240 | 266 | ||
241 | RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), | 267 | RSND_GEN2_M_REG(gen, SSI, SSICR, 0x00, 0x40), |
242 | RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), | 268 | RSND_GEN2_M_REG(gen, SSI, SSISR, 0x04, 0x40), |
diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index b2c717d2ba7e..8b66dc15fa73 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h | |||
@@ -37,6 +37,11 @@ enum rsnd_reg { | |||
37 | RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ | 37 | RSND_REG_SRC_TMG_SEL1, /* for Gen1 */ |
38 | RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ | 38 | RSND_REG_SRC_TMG_SEL2, /* for Gen1 */ |
39 | RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ | 39 | RSND_REG_SRC_ROUTE_CTRL, /* for Gen1 */ |
40 | RSND_REG_SRC_CTRL, /* for Gen2 */ | ||
41 | RSND_REG_SSI_CTRL, /* for Gen2 */ | ||
42 | RSND_REG_SSI_CONTROL, | ||
43 | RSND_REG_SSI_BUSIF_MODE, /* for Gen2 */ | ||
44 | RSND_REG_SSI_BUSIF_ADINR, /* for Gen2 */ | ||
40 | RSND_REG_SSI_MODE0, | 45 | RSND_REG_SSI_MODE0, |
41 | RSND_REG_SSI_MODE1, | 46 | RSND_REG_SSI_MODE1, |
42 | RSND_REG_INT_ENABLE, /* for Gen2 */ | 47 | RSND_REG_INT_ENABLE, /* for Gen2 */ |
@@ -49,6 +54,8 @@ enum rsnd_reg { | |||
49 | RSND_REG_SRC_IFSVR, | 54 | RSND_REG_SRC_IFSVR, |
50 | RSND_REG_SRC_SRCCR, | 55 | RSND_REG_SRC_SRCCR, |
51 | RSND_REG_SRC_MNFSR, /* for Gen1 */ | 56 | RSND_REG_SRC_MNFSR, /* for Gen1 */ |
57 | RSND_REG_SRC_BSDSR, /* for Gen2 */ | ||
58 | RSND_REG_SRC_BSISR, /* for Gen2 */ | ||
52 | 59 | ||
53 | /* ADG */ | 60 | /* ADG */ |
54 | RSND_REG_BRRA, | 61 | RSND_REG_BRRA, |
@@ -60,6 +67,16 @@ enum rsnd_reg { | |||
60 | RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ | 67 | RSND_REG_AUDIO_CLK_SEL3, /* for Gen1 */ |
61 | RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ | 68 | RSND_REG_AUDIO_CLK_SEL4, /* for Gen1 */ |
62 | RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ | 69 | RSND_REG_AUDIO_CLK_SEL5, /* for Gen1 */ |
70 | RSND_REG_SRCIN_TIMSEL0, /* for Gen2 */ | ||
71 | RSND_REG_SRCIN_TIMSEL1, /* for Gen2 */ | ||
72 | RSND_REG_SRCIN_TIMSEL2, /* for Gen2 */ | ||
73 | RSND_REG_SRCIN_TIMSEL3, /* for Gen2 */ | ||
74 | RSND_REG_SRCIN_TIMSEL4, /* for Gen2 */ | ||
75 | RSND_REG_SRCOUT_TIMSEL0, /* for Gen2 */ | ||
76 | RSND_REG_SRCOUT_TIMSEL1, /* for Gen2 */ | ||
77 | RSND_REG_SRCOUT_TIMSEL2, /* for Gen2 */ | ||
78 | RSND_REG_SRCOUT_TIMSEL3, /* for Gen2 */ | ||
79 | RSND_REG_SRCOUT_TIMSEL4, /* for Gen2 */ | ||
63 | 80 | ||
64 | /* SSI */ | 81 | /* SSI */ |
65 | RSND_REG_SSICR, | 82 | RSND_REG_SSICR, |
@@ -250,6 +267,14 @@ int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, | |||
250 | struct rsnd_mod *mod, | 267 | struct rsnd_mod *mod, |
251 | unsigned int src_rate, | 268 | unsigned int src_rate, |
252 | unsigned int dst_rate); | 269 | unsigned int dst_rate); |
270 | int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod, | ||
271 | struct rsnd_dai *rdai, | ||
272 | struct rsnd_dai_stream *io, | ||
273 | unsigned int src_rate, | ||
274 | unsigned int dst_rate); | ||
275 | int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod, | ||
276 | struct rsnd_dai *rdai, | ||
277 | struct rsnd_dai_stream *io); | ||
253 | 278 | ||
254 | /* | 279 | /* |
255 | * R-Car sound priv | 280 | * R-Car sound priv |
diff --git a/sound/soc/sh/rcar/scu.c b/sound/soc/sh/rcar/scu.c index 29d8990e3f0f..6e5c763e1040 100644 --- a/sound/soc/sh/rcar/scu.c +++ b/sound/soc/sh/rcar/scu.c | |||
@@ -33,6 +33,8 @@ struct rsnd_scu { | |||
33 | container_of((_mod), struct rsnd_scu, mod) | 33 | container_of((_mod), struct rsnd_scu, mod) |
34 | #define rsnd_scu_hpbif_is_enable(scu) \ | 34 | #define rsnd_scu_hpbif_is_enable(scu) \ |
35 | (rsnd_scu_mode_flags(scu) & RSND_SCU_USE_HPBIF) | 35 | (rsnd_scu_mode_flags(scu) & RSND_SCU_USE_HPBIF) |
36 | #define rsnd_scu_dma_available(scu) \ | ||
37 | rsnd_dma_available(rsnd_mod_to_dma(&(scu)->mod)) | ||
36 | 38 | ||
37 | #define for_each_rsnd_scu(pos, priv, i) \ | 39 | #define for_each_rsnd_scu(pos, priv, i) \ |
38 | for ((i) = 0; \ | 40 | for ((i) = 0; \ |
@@ -472,6 +474,103 @@ static struct rsnd_mod_ops rsnd_scu_non_gen1_ops = { | |||
472 | /* | 474 | /* |
473 | * Gen2 functions | 475 | * Gen2 functions |
474 | */ | 476 | */ |
477 | static int rsnd_scu_set_convert_rate_gen2(struct rsnd_mod *mod, | ||
478 | struct rsnd_dai *rdai, | ||
479 | struct rsnd_dai_stream *io) | ||
480 | { | ||
481 | int ret; | ||
482 | |||
483 | ret = rsnd_scu_set_convert_rate(mod, rdai, io); | ||
484 | if (ret < 0) | ||
485 | return ret; | ||
486 | |||
487 | rsnd_mod_write(mod, SSI_BUSIF_ADINR, rsnd_mod_read(mod, SRC_ADINR)); | ||
488 | rsnd_mod_write(mod, SSI_BUSIF_MODE, rsnd_mod_read(mod, SRC_BUSIF_MODE)); | ||
489 | |||
490 | rsnd_mod_write(mod, SRC_SRCCR, 0x00011110); | ||
491 | |||
492 | rsnd_mod_write(mod, SRC_BSDSR, 0x01800000); | ||
493 | rsnd_mod_write(mod, SRC_BSISR, 0x00100060); | ||
494 | |||
495 | return 0; | ||
496 | } | ||
497 | |||
498 | static int rsnd_scu_set_convert_timing_gen2(struct rsnd_mod *mod, | ||
499 | struct rsnd_dai *rdai, | ||
500 | struct rsnd_dai_stream *io) | ||
501 | { | ||
502 | struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); | ||
503 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
504 | u32 convert_rate = rsnd_scu_convert_rate(scu); | ||
505 | int ret; | ||
506 | |||
507 | if (convert_rate) | ||
508 | ret = rsnd_adg_set_convert_clk_gen2(mod, rdai, io, | ||
509 | runtime->rate, | ||
510 | convert_rate); | ||
511 | else | ||
512 | ret = rsnd_adg_set_convert_timing_gen2(mod, rdai, io); | ||
513 | |||
514 | return ret; | ||
515 | } | ||
516 | |||
517 | static int rsnd_scu_init_gen2(struct rsnd_mod *mod, | ||
518 | struct rsnd_dai *rdai, | ||
519 | struct rsnd_dai_stream *io) | ||
520 | { | ||
521 | int ret; | ||
522 | |||
523 | ret = rsnd_scu_init(mod, rdai, io); | ||
524 | if (ret < 0) | ||
525 | return ret; | ||
526 | |||
527 | ret = rsnd_scu_set_convert_rate_gen2(mod, rdai, io); | ||
528 | if (ret < 0) | ||
529 | return ret; | ||
530 | |||
531 | ret = rsnd_scu_set_convert_timing_gen2(mod, rdai, io); | ||
532 | if (ret < 0) | ||
533 | return ret; | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static int rsnd_scu_start_gen2(struct rsnd_mod *mod, | ||
539 | struct rsnd_dai *rdai, | ||
540 | struct rsnd_dai_stream *io) | ||
541 | { | ||
542 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
543 | |||
544 | rsnd_dma_start(rsnd_mod_to_dma(&scu->mod)); | ||
545 | |||
546 | rsnd_mod_write(mod, SSI_CTRL, 0x1); | ||
547 | rsnd_mod_write(mod, SRC_CTRL, 0x11); | ||
548 | |||
549 | return rsnd_scu_start(mod, rdai, io); | ||
550 | } | ||
551 | |||
552 | static int rsnd_scu_stop_gen2(struct rsnd_mod *mod, | ||
553 | struct rsnd_dai *rdai, | ||
554 | struct rsnd_dai_stream *io) | ||
555 | { | ||
556 | struct rsnd_scu *scu = rsnd_mod_to_scu(mod); | ||
557 | |||
558 | rsnd_mod_write(mod, SSI_CTRL, 0); | ||
559 | rsnd_mod_write(mod, SRC_CTRL, 0); | ||
560 | |||
561 | rsnd_dma_stop(rsnd_mod_to_dma(&scu->mod)); | ||
562 | |||
563 | return rsnd_scu_stop(mod, rdai, io); | ||
564 | } | ||
565 | |||
566 | static struct rsnd_mod_ops rsnd_scu_gen2_ops = { | ||
567 | .name = "scu (gen2)", | ||
568 | .init = rsnd_scu_init_gen2, | ||
569 | .quit = rsnd_scu_quit, | ||
570 | .start = rsnd_scu_start_gen2, | ||
571 | .stop = rsnd_scu_stop_gen2, | ||
572 | }; | ||
573 | |||
475 | static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, | 574 | static int rsnd_scu_start_non_gen2(struct rsnd_mod *mod, |
476 | struct rsnd_dai *rdai, | 575 | struct rsnd_dai *rdai, |
477 | struct rsnd_dai_stream *io) | 576 | struct rsnd_dai_stream *io) |
@@ -534,6 +633,17 @@ int rsnd_scu_probe(struct platform_device *pdev, | |||
534 | if (rsnd_scu_hpbif_is_enable(scu)) { | 633 | if (rsnd_scu_hpbif_is_enable(scu)) { |
535 | if (rsnd_is_gen1(priv)) | 634 | if (rsnd_is_gen1(priv)) |
536 | ops = &rsnd_scu_gen1_ops; | 635 | ops = &rsnd_scu_gen1_ops; |
636 | if (rsnd_is_gen2(priv)) { | ||
637 | struct rsnd_mod *ssi = rsnd_ssi_mod_get(priv, i); | ||
638 | int ret = rsnd_dma_init(priv, | ||
639 | rsnd_mod_to_dma(&scu->mod), | ||
640 | rsnd_ssi_is_play(ssi), | ||
641 | scu->info->dma_id); | ||
642 | if (ret < 0) | ||
643 | return ret; | ||
644 | |||
645 | ops = &rsnd_scu_gen2_ops; | ||
646 | } | ||
537 | } else { | 647 | } else { |
538 | if (rsnd_is_gen1(priv)) | 648 | if (rsnd_is_gen1(priv)) |
539 | ops = &rsnd_scu_non_gen1_ops; | 649 | ops = &rsnd_scu_non_gen1_ops; |
@@ -553,4 +663,11 @@ int rsnd_scu_probe(struct platform_device *pdev, | |||
553 | void rsnd_scu_remove(struct platform_device *pdev, | 663 | void rsnd_scu_remove(struct platform_device *pdev, |
554 | struct rsnd_priv *priv) | 664 | struct rsnd_priv *priv) |
555 | { | 665 | { |
666 | struct rsnd_scu *scu; | ||
667 | int i; | ||
668 | |||
669 | for_each_rsnd_scu(scu, priv, i) { | ||
670 | if (rsnd_scu_dma_available(scu)) | ||
671 | rsnd_dma_quit(priv, rsnd_mod_to_dma(&scu->mod)); | ||
672 | } | ||
556 | } | 673 | } |