blob: 99d2d9459e755a46f630b36f93611e88c4feeae6 [file] [log] [blame]
Kuninori Morimotobff58ea2014-05-08 17:44:49 -07001/*
2 * Renesas R-Car DVC support
3 *
4 * Copyright (C) 2014 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
Kuninori Morimotof1511a12016-03-10 05:29:21 +000011
12/*
13 * Playback Volume
14 * amixer set "DVC Out" 100%
15 *
16 * Capture Volume
17 * amixer set "DVC In" 100%
18 *
19 * Playback Mute
20 * amixer set "DVC Out Mute" on
21 *
22 * Capture Mute
23 * amixer set "DVC In Mute" on
24 *
25 * Volume Ramp
26 * amixer set "DVC Out Ramp Up Rate" "0.125 dB/64 steps"
27 * amixer set "DVC Out Ramp Down Rate" "0.125 dB/512 steps"
28 * amixer set "DVC Out Ramp" on
29 * aplay xxx.wav &
30 * amixer set "DVC Out" 80% // Volume Down
31 * amixer set "DVC Out" 100% // Volume Up
32 */
33
Kuninori Morimotobff58ea2014-05-08 17:44:49 -070034#include "rsnd.h"
35
36#define RSND_DVC_NAME_SIZE 16
Kuninori Morimoto8aefda52014-05-22 23:25:43 -070037
38#define DVC_NAME "dvc"
39
Kuninori Morimotobff58ea2014-05-08 17:44:49 -070040struct rsnd_dvc {
Kuninori Morimotobff58ea2014-05-08 17:44:49 -070041 struct rsnd_mod mod;
Kuninori Morimoto170a2492014-11-27 08:06:14 +000042 struct rsnd_kctrl_cfg_m volume;
43 struct rsnd_kctrl_cfg_m mute;
44 struct rsnd_kctrl_cfg_s ren; /* Ramp Enable */
45 struct rsnd_kctrl_cfg_s rup; /* Ramp Rate Up */
46 struct rsnd_kctrl_cfg_s rdown; /* Ramp Rate Down */
Kuninori Morimotobff58ea2014-05-08 17:44:49 -070047};
48
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +000049#define rsnd_dvc_get(priv, id) ((struct rsnd_dvc *)(priv->dvc) + id)
Kuninori Morimoto4f35fab2015-07-15 07:11:02 +000050#define rsnd_dvc_nr(priv) ((priv)->dvc_nr)
Kuninori Morimoto93b986e2015-02-20 10:30:41 +000051
Kuninori Morimotobff58ea2014-05-08 17:44:49 -070052#define rsnd_mod_to_dvc(_mod) \
53 container_of((_mod), struct rsnd_dvc, mod)
54
55#define for_each_rsnd_dvc(pos, priv, i) \
56 for ((i) = 0; \
57 ((i) < rsnd_dvc_nr(priv)) && \
58 ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \
59 i++)
60
Krzysztof Kozlowski2f4b1e62015-03-24 11:47:43 +010061static const char * const dvc_ramp_rate[] = {
Kuninori Morimoto3539cac2014-11-09 19:52:06 -080062 "128 dB/1 step", /* 00000 */
63 "64 dB/1 step", /* 00001 */
64 "32 dB/1 step", /* 00010 */
65 "16 dB/1 step", /* 00011 */
66 "8 dB/1 step", /* 00100 */
67 "4 dB/1 step", /* 00101 */
68 "2 dB/1 step", /* 00110 */
69 "1 dB/1 step", /* 00111 */
70 "0.5 dB/1 step", /* 01000 */
71 "0.25 dB/1 step", /* 01001 */
72 "0.125 dB/1 step", /* 01010 */
73 "0.125 dB/2 steps", /* 01011 */
74 "0.125 dB/4 steps", /* 01100 */
75 "0.125 dB/8 steps", /* 01101 */
76 "0.125 dB/16 steps", /* 01110 */
77 "0.125 dB/32 steps", /* 01111 */
78 "0.125 dB/64 steps", /* 10000 */
79 "0.125 dB/128 steps", /* 10001 */
80 "0.125 dB/256 steps", /* 10010 */
81 "0.125 dB/512 steps", /* 10011 */
82 "0.125 dB/1024 steps", /* 10100 */
83 "0.125 dB/2048 steps", /* 10101 */
84 "0.125 dB/4096 steps", /* 10110 */
85 "0.125 dB/8192 steps", /* 10111 */
86};
87
Kuninori Morimoto87a6c5a2015-11-30 08:51:15 +000088static void rsnd_dvc_activation(struct rsnd_mod *mod)
Kuninori Morimoto636e4ba2015-07-15 07:12:00 +000089{
90 rsnd_mod_write(mod, DVC_SWRSR, 0);
91 rsnd_mod_write(mod, DVC_SWRSR, 1);
92}
93
Kuninori Morimotof13edb82015-11-30 08:52:21 +000094static void rsnd_dvc_halt(struct rsnd_mod *mod)
95{
96 rsnd_mod_write(mod, DVC_DVUIR, 1);
97 rsnd_mod_write(mod, DVC_SWRSR, 0);
98}
99
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000100#define rsnd_dvc_get_vrpdr(dvc) (dvc->rup.val << 8 | dvc->rdown.val)
101#define rsnd_dvc_get_vrdbr(dvc) (0x3ff - (dvc->volume.val[0] >> 13))
Kuninori Morimoto3bb3d362015-07-15 07:13:29 +0000102
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000103static void rsnd_dvc_volume_parameter(struct rsnd_dai_stream *io,
104 struct rsnd_mod *mod)
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700105{
106 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
Kuninori Morimotod2240f02016-02-18 08:13:13 +0000107 u32 val[RSND_MAX_CHANNELS];
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700108 int i;
109
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000110 /* Enable Ramp */
111 if (dvc->ren.val)
Kuninori Morimotod2240f02016-02-18 08:13:13 +0000112 for (i = 0; i < RSND_MAX_CHANNELS; i++)
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000113 val[i] = dvc->volume.cfg.max;
114 else
Kuninori Morimotod2240f02016-02-18 08:13:13 +0000115 for (i = 0; i < RSND_MAX_CHANNELS; i++)
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000116 val[i] = dvc->volume.val[i];
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700117
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000118 /* Enable Digital Volume */
119 rsnd_mod_write(mod, DVC_VOL0R, val[0]);
120 rsnd_mod_write(mod, DVC_VOL1R, val[1]);
Kuninori Morimoto42ab9a72015-11-30 08:53:44 +0000121 rsnd_mod_write(mod, DVC_VOL2R, val[2]);
122 rsnd_mod_write(mod, DVC_VOL3R, val[3]);
123 rsnd_mod_write(mod, DVC_VOL4R, val[4]);
124 rsnd_mod_write(mod, DVC_VOL5R, val[5]);
125 rsnd_mod_write(mod, DVC_VOL6R, val[6]);
126 rsnd_mod_write(mod, DVC_VOL7R, val[7]);
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000127}
128
129static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io,
130 struct rsnd_mod *mod)
131{
132 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
Kuninori Morimotoc45f7262015-11-30 08:49:33 +0000133 u32 adinr = 0;
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000134 u32 dvucr = 0;
135 u32 vrctr = 0;
136 u32 vrpdr = 0;
137 u32 vrdbr = 0;
138
Kuninori Morimotoc45f7262015-11-30 08:49:33 +0000139 adinr = rsnd_get_adinr_bit(mod, io) |
Kuninori Morimotoeed76bb2016-02-25 05:54:58 +0000140 rsnd_runtime_channel_after_ctu(io);
Kuninori Morimotoc45f7262015-11-30 08:49:33 +0000141
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000142 /* Enable Digital Volume, Zero Cross Mute Mode */
143 dvucr |= 0x101;
Kuninori Morimoto140bab82014-11-04 20:27:18 -0800144
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800145 /* Enable Ramp */
146 if (dvc->ren.val) {
147 dvucr |= 0x10;
148
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800149 /*
150 * FIXME !!
151 * use scale-downed Digital Volume
152 * as Volume Ramp
153 * 7F FFFF -> 3FF
154 */
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000155 vrctr = 0xff;
156 vrpdr = rsnd_dvc_get_vrpdr(dvc);
157 vrdbr = rsnd_dvc_get_vrdbr(dvc);
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800158 }
159
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000160 /* Initialize operation */
161 rsnd_mod_write(mod, DVC_DVUIR, 1);
Kuninori Morimotocd2b6572014-08-01 03:10:55 -0700162
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000163 /* General Information */
Kuninori Morimotoc45f7262015-11-30 08:49:33 +0000164 rsnd_mod_write(mod, DVC_ADINR, adinr);
Kuninori Morimoto1c5d1c92014-11-04 20:26:53 -0800165 rsnd_mod_write(mod, DVC_DVUCR, dvucr);
Kuninori Morimoto140bab82014-11-04 20:27:18 -0800166
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000167 /* Volume Ramp Parameter */
168 rsnd_mod_write(mod, DVC_VRCTR, vrctr);
169 rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
170 rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
171
172 /* Digital Volume Function Parameter */
173 rsnd_dvc_volume_parameter(io, mod);
174
175 /* cancel operation */
176 rsnd_mod_write(mod, DVC_DVUIR, 0);
177}
178
179static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
180 struct rsnd_mod *mod)
181{
182 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
183 u32 zcmcr = 0;
184 u32 vrpdr = 0;
185 u32 vrdbr = 0;
186 int i;
187
188 for (i = 0; i < dvc->mute.cfg.size; i++)
189 zcmcr |= (!!dvc->mute.cfg.val[i]) << i;
190
191 if (dvc->ren.val) {
192 vrpdr = rsnd_dvc_get_vrpdr(dvc);
193 vrdbr = rsnd_dvc_get_vrdbr(dvc);
194 }
195
196 /* Disable DVC Register access */
197 rsnd_mod_write(mod, DVC_DVUER, 0);
198
199 /* Zero Cross Mute Function */
200 rsnd_mod_write(mod, DVC_ZCMCR, zcmcr);
201
202 /* Volume Ramp Function */
203 rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
204 rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
205 /* add DVC_VRWTR here */
206
207 /* Digital Volume Function Parameter */
208 rsnd_dvc_volume_parameter(io, mod);
209
Kuninori Morimoto140bab82014-11-04 20:27:18 -0800210 /* Enable DVC Register access */
211 rsnd_mod_write(mod, DVC_DVUER, 1);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700212}
213
Kuninori Morimoto1b2ca0a2015-10-26 08:43:21 +0000214static int rsnd_dvc_probe_(struct rsnd_mod *mod,
215 struct rsnd_dai_stream *io,
216 struct rsnd_priv *priv)
217{
218 return rsnd_cmd_attach(io, rsnd_mod_id(mod));
219}
220
Kuninori Morimotoe2c08412015-07-15 07:13:10 +0000221static int rsnd_dvc_init(struct rsnd_mod *mod,
Kuninori Morimoto2c0fac12015-06-15 06:25:20 +0000222 struct rsnd_dai_stream *io,
Kuninori Morimoto690602f2015-01-15 08:07:47 +0000223 struct rsnd_priv *priv)
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700224{
Kuninori Morimotoc9929342015-10-22 03:15:04 +0000225 rsnd_mod_power_on(mod);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700226
Kuninori Morimoto87a6c5a2015-11-30 08:51:15 +0000227 rsnd_dvc_activation(mod);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700228
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000229 rsnd_dvc_volume_init(io, mod);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700230
Kuninori Morimotoe2c08412015-07-15 07:13:10 +0000231 rsnd_dvc_volume_update(io, mod);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700232
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700233 return 0;
234}
235
236static int rsnd_dvc_quit(struct rsnd_mod *mod,
Kuninori Morimoto2c0fac12015-06-15 06:25:20 +0000237 struct rsnd_dai_stream *io,
Kuninori Morimoto690602f2015-01-15 08:07:47 +0000238 struct rsnd_priv *priv)
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700239{
Kuninori Morimotof13edb82015-11-30 08:52:21 +0000240 rsnd_dvc_halt(mod);
241
Kuninori Morimotoc9929342015-10-22 03:15:04 +0000242 rsnd_mod_power_off(mod);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700243
244 return 0;
245}
246
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700247static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
Kuninori Morimoto2c0fac12015-06-15 06:25:20 +0000248 struct rsnd_dai_stream *io,
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700249 struct snd_soc_pcm_runtime *rtd)
250{
Kuninori Morimoto486b09c2014-08-01 03:10:47 -0700251 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
Kuninori Morimoto1ff95932017-06-15 00:49:27 +0000252 struct rsnd_dai *rdai = rsnd_io_to_rdai(io);
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000253 int is_play = rsnd_io_is_play(io);
Kuninori Morimoto1ff95932017-06-15 00:49:27 +0000254 int channels = rsnd_rdai_channels_get(rdai);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700255 int ret;
256
Kuninori Morimoto486b09c2014-08-01 03:10:47 -0700257 /* Volume */
Kuninori Morimotob65a7cc2015-06-15 06:27:28 +0000258 ret = rsnd_kctrl_new_m(mod, io, rtd,
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000259 is_play ?
Kuninori Morimoto486b09c2014-08-01 03:10:47 -0700260 "DVC Out Playback Volume" : "DVC In Capture Volume",
Kuninori Morimotof0b04d82017-06-07 00:11:48 +0000261 rsnd_kctrl_accept_anytime,
Kuninori Morimoto170a2492014-11-27 08:06:14 +0000262 rsnd_dvc_volume_update,
Kuninori Morimoto1ff95932017-06-15 00:49:27 +0000263 &dvc->volume, channels,
Kuninori Morimoto42ab9a72015-11-30 08:53:44 +0000264 0x00800000 - 1);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700265 if (ret < 0)
266 return ret;
267
Kuninori Morimotocd2b6572014-08-01 03:10:55 -0700268 /* Mute */
Kuninori Morimotob65a7cc2015-06-15 06:27:28 +0000269 ret = rsnd_kctrl_new_m(mod, io, rtd,
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000270 is_play ?
Kuninori Morimotocd2b6572014-08-01 03:10:55 -0700271 "DVC Out Mute Switch" : "DVC In Mute Switch",
Kuninori Morimotof0b04d82017-06-07 00:11:48 +0000272 rsnd_kctrl_accept_anytime,
Kuninori Morimoto170a2492014-11-27 08:06:14 +0000273 rsnd_dvc_volume_update,
Kuninori Morimoto1ff95932017-06-15 00:49:27 +0000274 &dvc->mute, channels,
Kuninori Morimoto42ab9a72015-11-30 08:53:44 +0000275 1);
Kuninori Morimotocd2b6572014-08-01 03:10:55 -0700276 if (ret < 0)
277 return ret;
278
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800279 /* Ramp */
Kuninori Morimotob65a7cc2015-06-15 06:27:28 +0000280 ret = rsnd_kctrl_new_s(mod, io, rtd,
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000281 is_play ?
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800282 "DVC Out Ramp Switch" : "DVC In Ramp Switch",
Kuninori Morimotof0b04d82017-06-07 00:11:48 +0000283 rsnd_kctrl_accept_anytime,
Kuninori Morimoto170a2492014-11-27 08:06:14 +0000284 rsnd_dvc_volume_update,
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800285 &dvc->ren, 1);
286 if (ret < 0)
287 return ret;
288
Kuninori Morimotob65a7cc2015-06-15 06:27:28 +0000289 ret = rsnd_kctrl_new_e(mod, io, rtd,
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000290 is_play ?
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800291 "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate",
Kuninori Morimotof0b04d82017-06-07 00:11:48 +0000292 rsnd_kctrl_accept_anytime,
Kuninori Morimoto170a2492014-11-27 08:06:14 +0000293 rsnd_dvc_volume_update,
Kuninori Morimoto32973dc2017-04-06 07:25:13 +0000294 &dvc->rup,
295 dvc_ramp_rate);
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800296 if (ret < 0)
297 return ret;
298
Kuninori Morimotob65a7cc2015-06-15 06:27:28 +0000299 ret = rsnd_kctrl_new_e(mod, io, rtd,
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000300 is_play ?
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800301 "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate",
Kuninori Morimotof0b04d82017-06-07 00:11:48 +0000302 rsnd_kctrl_accept_anytime,
Kuninori Morimoto170a2492014-11-27 08:06:14 +0000303 rsnd_dvc_volume_update,
Kuninori Morimoto32973dc2017-04-06 07:25:13 +0000304 &dvc->rdown,
305 dvc_ramp_rate);
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800306
307 if (ret < 0)
308 return ret;
309
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700310 return 0;
311}
312
Kuninori Morimoto9b99e9a2015-06-15 06:26:25 +0000313static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_dai_stream *io,
314 struct rsnd_mod *mod)
Kuninori Morimoto72adc612015-02-20 10:31:23 +0000315{
316 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
317
318 return rsnd_dma_request_channel(rsnd_dvc_of_node(priv),
319 mod, "tx");
320}
321
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700322static struct rsnd_mod_ops rsnd_dvc_ops = {
Kuninori Morimoto8aefda52014-05-22 23:25:43 -0700323 .name = DVC_NAME,
Kuninori Morimoto72adc612015-02-20 10:31:23 +0000324 .dma_req = rsnd_dvc_dma_req,
Kuninori Morimoto1b2ca0a2015-10-26 08:43:21 +0000325 .probe = rsnd_dvc_probe_,
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700326 .init = rsnd_dvc_init,
327 .quit = rsnd_dvc_quit,
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700328 .pcm_new = rsnd_dvc_pcm_new,
329};
330
331struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
332{
333 if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv)))
334 id = 0;
335
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000336 return rsnd_mod_get(rsnd_dvc_get(priv, id));
Kuninori Morimoto34cb6122014-06-22 17:59:28 -0700337}
338
Kuninori Morimoto2ea6b072015-11-10 05:14:12 +0000339int rsnd_dvc_probe(struct rsnd_priv *priv)
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700340{
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000341 struct device_node *node;
342 struct device_node *np;
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700343 struct device *dev = rsnd_priv_to_dev(priv);
344 struct rsnd_dvc *dvc;
345 struct clk *clk;
346 char name[RSND_DVC_NAME_SIZE];
Kuninori Morimoto2f78dd72015-03-26 04:02:09 +0000347 int i, nr, ret;
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700348
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700349 /* This driver doesn't support Gen1 at this point */
Kuninori Morimoto8a98b422015-10-15 03:25:28 +0000350 if (rsnd_is_gen1(priv))
351 return 0;
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700352
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000353 node = rsnd_dvc_of_node(priv);
354 if (!node)
355 return 0; /* not used is not error */
Kuninori Morimoto9469b8b2015-07-15 07:15:47 +0000356
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000357 nr = of_get_child_count(node);
358 if (!nr) {
359 ret = -EINVAL;
360 goto rsnd_dvc_probe_done;
361 }
Kuninori Morimoto9469b8b2015-07-15 07:15:47 +0000362
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700363 dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL);
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000364 if (!dvc) {
365 ret = -ENOMEM;
366 goto rsnd_dvc_probe_done;
367 }
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700368
369 priv->dvc_nr = nr;
370 priv->dvc = dvc;
371
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000372 i = 0;
Mark Brown2e4118d2015-12-14 12:05:17 +0000373 ret = 0;
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000374 for_each_child_of_node(node, np) {
375 dvc = rsnd_dvc_get(priv, i);
376
Kuninori Morimoto8aefda52014-05-22 23:25:43 -0700377 snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d",
378 DVC_NAME, i);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700379
380 clk = devm_clk_get(dev, name);
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000381 if (IS_ERR(clk)) {
382 ret = PTR_ERR(clk);
383 goto rsnd_dvc_probe_done;
384 }
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700385
Kuninori Morimotob76e2182015-09-10 07:02:21 +0000386 ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops,
Kuninori Morimoto5ba17b422016-01-21 01:58:07 +0000387 clk, rsnd_mod_get_status, RSND_MOD_DVC, i);
Kuninori Morimoto2f78dd72015-03-26 04:02:09 +0000388 if (ret)
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000389 goto rsnd_dvc_probe_done;
390
391 i++;
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700392 }
393
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000394rsnd_dvc_probe_done:
395 of_node_put(node);
396
397 return ret;
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700398}
Kuninori Morimoto2f78dd72015-03-26 04:02:09 +0000399
Kuninori Morimoto2ea6b072015-11-10 05:14:12 +0000400void rsnd_dvc_remove(struct rsnd_priv *priv)
Kuninori Morimoto2f78dd72015-03-26 04:02:09 +0000401{
402 struct rsnd_dvc *dvc;
403 int i;
404
405 for_each_rsnd_dvc(dvc, priv, i) {
Kuninori Morimotob76e2182015-09-10 07:02:21 +0000406 rsnd_mod_quit(rsnd_mod_get(dvc));
Kuninori Morimoto2f78dd72015-03-26 04:02:09 +0000407 }
408}