aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/sh/rcar/adg.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/sh/rcar/adg.c')
-rw-r--r--sound/soc/sh/rcar/adg.c228
1 files changed, 192 insertions, 36 deletions
diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c
index a53235c4d1b0..953f1cce982d 100644
--- a/sound/soc/sh/rcar/adg.c
+++ b/sound/soc/sh/rcar/adg.c
@@ -25,15 +25,165 @@ struct rsnd_adg {
25}; 25};
26 26
27#define for_each_rsnd_clk(pos, adg, i) \ 27#define for_each_rsnd_clk(pos, adg, i) \
28 for (i = 0, (pos) = adg->clk[i]; \ 28 for (i = 0; \
29 i < CLKMAX; \ 29 (i < CLKMAX) && \
30 i++, (pos) = adg->clk[i]) 30 ((pos) = adg->clk[i]); \
31 i++)
31#define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg) 32#define rsnd_priv_to_adg(priv) ((struct rsnd_adg *)(priv)->adg)
32 33
33static int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv, 34
34 struct rsnd_mod *mod, 35static u32 rsnd_adg_ssi_ws_timing_gen2(struct rsnd_dai_stream *io)
35 unsigned int src_rate, 36{
36 unsigned int dst_rate) 37 struct rsnd_mod *mod = rsnd_io_to_mod_ssi(io);
38 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
39 int id = rsnd_mod_id(mod);
40 int ws = id;
41
42 if (rsnd_ssi_is_pin_sharing(rsnd_ssi_mod_get(priv, id))) {
43 switch (id) {
44 case 1:
45 case 2:
46 ws = 0;
47 break;
48 case 4:
49 ws = 3;
50 break;
51 case 8:
52 ws = 7;
53 break;
54 }
55 }
56
57 return (0x6 + ws) << 8;
58}
59
60static int rsnd_adg_set_src_timsel_gen2(struct rsnd_dai *rdai,
61 struct rsnd_mod *mod,
62 struct rsnd_dai_stream *io,
63 u32 timsel)
64{
65 int is_play = rsnd_dai_is_play(rdai, io);
66 int id = rsnd_mod_id(mod);
67 int shift = (id % 2) ? 16 : 0;
68 u32 mask, ws;
69 u32 in, out;
70
71 ws = rsnd_adg_ssi_ws_timing_gen2(io);
72
73 in = (is_play) ? timsel : ws;
74 out = (is_play) ? ws : timsel;
75
76 in = in << shift;
77 out = out << shift;
78 mask = 0xffff << shift;
79
80 switch (id / 2) {
81 case 0:
82 rsnd_mod_bset(mod, SRCIN_TIMSEL0, mask, in);
83 rsnd_mod_bset(mod, SRCOUT_TIMSEL0, mask, out);
84 break;
85 case 1:
86 rsnd_mod_bset(mod, SRCIN_TIMSEL1, mask, in);
87 rsnd_mod_bset(mod, SRCOUT_TIMSEL1, mask, out);
88 break;
89 case 2:
90 rsnd_mod_bset(mod, SRCIN_TIMSEL2, mask, in);
91 rsnd_mod_bset(mod, SRCOUT_TIMSEL2, mask, out);
92 break;
93 case 3:
94 rsnd_mod_bset(mod, SRCIN_TIMSEL3, mask, in);
95 rsnd_mod_bset(mod, SRCOUT_TIMSEL3, mask, out);
96 break;
97 case 4:
98 rsnd_mod_bset(mod, SRCIN_TIMSEL4, mask, in);
99 rsnd_mod_bset(mod, SRCOUT_TIMSEL4, mask, out);
100 break;
101 }
102
103 return 0;
104}
105
106int rsnd_adg_set_convert_clk_gen2(struct rsnd_mod *mod,
107 struct rsnd_dai *rdai,
108 struct rsnd_dai_stream *io,
109 unsigned int src_rate,
110 unsigned int dst_rate)
111{
112 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
113 struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
114 struct device *dev = rsnd_priv_to_dev(priv);
115 int idx, sel, div, step, ret;
116 u32 val, en;
117 unsigned int min, diff;
118 unsigned int sel_rate [] = {
119 clk_get_rate(adg->clk[CLKA]), /* 0000: CLKA */
120 clk_get_rate(adg->clk[CLKB]), /* 0001: CLKB */
121 clk_get_rate(adg->clk[CLKC]), /* 0010: CLKC */
122 adg->rbga_rate_for_441khz_div_6,/* 0011: RBGA */
123 adg->rbgb_rate_for_48khz_div_6, /* 0100: RBGB */
124 };
125
126 min = ~0;
127 val = 0;
128 en = 0;
129 for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) {
130 idx = 0;
131 step = 2;
132
133 if (!sel_rate[sel])
134 continue;
135
136 for (div = 2; div <= 98304; div += step) {
137 diff = abs(src_rate - sel_rate[sel] / div);
138 if (min > diff) {
139 val = (sel << 8) | idx;
140 min = diff;
141 en = 1 << (sel + 1); /* fixme */
142 }
143
144 /*
145 * step of 0_0000 / 0_0001 / 0_1101
146 * are out of order
147 */
148 if ((idx > 2) && (idx % 2))
149 step *= 2;
150 if (idx == 0x1c) {
151 div += step;
152 step *= 2;
153 }
154 idx++;
155 }
156 }
157
158 if (min == ~0) {
159 dev_err(dev, "no Input clock\n");
160 return -EIO;
161 }
162
163 ret = rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val);
164 if (ret < 0) {
165 dev_err(dev, "timsel error\n");
166 return ret;
167 }
168
169 rsnd_mod_bset(mod, DIV_EN, en, en);
170
171 return 0;
172}
173
174int rsnd_adg_set_convert_timing_gen2(struct rsnd_mod *mod,
175 struct rsnd_dai *rdai,
176 struct rsnd_dai_stream *io)
177{
178 u32 val = rsnd_adg_ssi_ws_timing_gen2(io);
179
180 return rsnd_adg_set_src_timsel_gen2(rdai, mod, io, val);
181}
182
183int rsnd_adg_set_convert_clk_gen1(struct rsnd_priv *priv,
184 struct rsnd_mod *mod,
185 unsigned int src_rate,
186 unsigned int dst_rate)
37{ 187{
38 struct rsnd_adg *adg = rsnd_priv_to_adg(priv); 188 struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
39 struct device *dev = rsnd_priv_to_dev(priv); 189 struct device *dev = rsnd_priv_to_dev(priv);
@@ -91,18 +241,6 @@ find_rate:
91 return 0; 241 return 0;
92} 242}
93 243
94int rsnd_adg_set_convert_clk(struct rsnd_priv *priv,
95 struct rsnd_mod *mod,
96 unsigned int src_rate,
97 unsigned int dst_rate)
98{
99 if (rsnd_is_gen1(priv))
100 return rsnd_adg_set_convert_clk_gen1(priv, mod,
101 src_rate, dst_rate);
102
103 return -EINVAL;
104}
105
106static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val) 244static void rsnd_adg_set_ssi_clk(struct rsnd_mod *mod, u32 val)
107{ 245{
108 int id = rsnd_mod_id(mod); 246 int id = rsnd_mod_id(mod);
@@ -254,13 +392,13 @@ static void rsnd_adg_ssi_clk_init(struct rsnd_priv *priv, struct rsnd_adg *adg)
254} 392}
255 393
256int rsnd_adg_probe(struct platform_device *pdev, 394int rsnd_adg_probe(struct platform_device *pdev,
257 struct rcar_snd_info *info,
258 struct rsnd_priv *priv) 395 struct rsnd_priv *priv)
259{ 396{
260 struct rsnd_adg *adg; 397 struct rsnd_adg *adg;
261 struct device *dev = rsnd_priv_to_dev(priv); 398 struct device *dev = rsnd_priv_to_dev(priv);
262 struct clk *clk; 399 struct clk *clk, *clk_orig;
263 int i; 400 int i;
401 bool use_old_style = false;
264 402
265 adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL); 403 adg = devm_kzalloc(dev, sizeof(*adg), GFP_KERNEL);
266 if (!adg) { 404 if (!adg) {
@@ -268,10 +406,39 @@ int rsnd_adg_probe(struct platform_device *pdev,
268 return -ENOMEM; 406 return -ENOMEM;
269 } 407 }
270 408
271 adg->clk[CLKA] = clk_get(NULL, "audio_clk_a"); 409 clk_orig = devm_clk_get(dev, NULL);
272 adg->clk[CLKB] = clk_get(NULL, "audio_clk_b"); 410 adg->clk[CLKA] = devm_clk_get(dev, "clk_a");
273 adg->clk[CLKC] = clk_get(NULL, "audio_clk_c"); 411 adg->clk[CLKB] = devm_clk_get(dev, "clk_b");
274 adg->clk[CLKI] = clk_get(NULL, "audio_clk_internal"); 412 adg->clk[CLKC] = devm_clk_get(dev, "clk_c");
413 adg->clk[CLKI] = devm_clk_get(dev, "clk_i");
414
415 /*
416 * It request device dependent audio clock.
417 * But above all clks will indicate rsnd module clock
418 * if platform doesn't it
419 */
420 for_each_rsnd_clk(clk, adg, i) {
421 if (clk_orig == clk) {
422 dev_warn(dev,
423 "doesn't have device dependent clock, use independent clock\n");
424 use_old_style = true;
425 break;
426 }
427 }
428
429 /*
430 * note:
431 * these exist in order to keep compatible with
432 * platform which has device independent audio clock,
433 * but will be removed soon
434 */
435 if (use_old_style) {
436 adg->clk[CLKA] = devm_clk_get(NULL, "audio_clk_a");
437 adg->clk[CLKB] = devm_clk_get(NULL, "audio_clk_b");
438 adg->clk[CLKC] = devm_clk_get(NULL, "audio_clk_c");
439 adg->clk[CLKI] = devm_clk_get(NULL, "audio_clk_internal");
440 }
441
275 for_each_rsnd_clk(clk, adg, i) { 442 for_each_rsnd_clk(clk, adg, i) {
276 if (IS_ERR(clk)) { 443 if (IS_ERR(clk)) {
277 dev_err(dev, "Audio clock failed\n"); 444 dev_err(dev, "Audio clock failed\n");
@@ -287,14 +454,3 @@ int rsnd_adg_probe(struct platform_device *pdev,
287 454
288 return 0; 455 return 0;
289} 456}
290
291void rsnd_adg_remove(struct platform_device *pdev,
292 struct rsnd_priv *priv)
293{
294 struct rsnd_adg *adg = priv->adg;
295 struct clk *clk;
296 int i;
297
298 for_each_rsnd_clk(clk, adg, i)
299 clk_put(clk);
300}