blob: 02d971f69eff78731df462937bcc69a50149dff3 [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#define rsnd_dvc_of_node(priv) \
52 of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, "rcar_sound,dvc")
53
Kuninori Morimotobff58ea2014-05-08 17:44:49 -070054#define rsnd_mod_to_dvc(_mod) \
55 container_of((_mod), struct rsnd_dvc, mod)
56
57#define for_each_rsnd_dvc(pos, priv, i) \
58 for ((i) = 0; \
59 ((i) < rsnd_dvc_nr(priv)) && \
60 ((pos) = (struct rsnd_dvc *)(priv)->dvc + i); \
61 i++)
62
Krzysztof Kozlowski2f4b1e62015-03-24 11:47:43 +010063static const char * const dvc_ramp_rate[] = {
Kuninori Morimoto3539cac2014-11-09 19:52:06 -080064 "128 dB/1 step", /* 00000 */
65 "64 dB/1 step", /* 00001 */
66 "32 dB/1 step", /* 00010 */
67 "16 dB/1 step", /* 00011 */
68 "8 dB/1 step", /* 00100 */
69 "4 dB/1 step", /* 00101 */
70 "2 dB/1 step", /* 00110 */
71 "1 dB/1 step", /* 00111 */
72 "0.5 dB/1 step", /* 01000 */
73 "0.25 dB/1 step", /* 01001 */
74 "0.125 dB/1 step", /* 01010 */
75 "0.125 dB/2 steps", /* 01011 */
76 "0.125 dB/4 steps", /* 01100 */
77 "0.125 dB/8 steps", /* 01101 */
78 "0.125 dB/16 steps", /* 01110 */
79 "0.125 dB/32 steps", /* 01111 */
80 "0.125 dB/64 steps", /* 10000 */
81 "0.125 dB/128 steps", /* 10001 */
82 "0.125 dB/256 steps", /* 10010 */
83 "0.125 dB/512 steps", /* 10011 */
84 "0.125 dB/1024 steps", /* 10100 */
85 "0.125 dB/2048 steps", /* 10101 */
86 "0.125 dB/4096 steps", /* 10110 */
87 "0.125 dB/8192 steps", /* 10111 */
88};
89
Kuninori Morimoto87a6c5a2015-11-30 08:51:15 +000090static void rsnd_dvc_activation(struct rsnd_mod *mod)
Kuninori Morimoto636e4ba2015-07-15 07:12:00 +000091{
92 rsnd_mod_write(mod, DVC_SWRSR, 0);
93 rsnd_mod_write(mod, DVC_SWRSR, 1);
94}
95
Kuninori Morimotof13edb82015-11-30 08:52:21 +000096static void rsnd_dvc_halt(struct rsnd_mod *mod)
97{
98 rsnd_mod_write(mod, DVC_DVUIR, 1);
99 rsnd_mod_write(mod, DVC_SWRSR, 0);
100}
101
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000102#define rsnd_dvc_get_vrpdr(dvc) (dvc->rup.val << 8 | dvc->rdown.val)
103#define rsnd_dvc_get_vrdbr(dvc) (0x3ff - (dvc->volume.val[0] >> 13))
Kuninori Morimoto3bb3d362015-07-15 07:13:29 +0000104
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000105static void rsnd_dvc_volume_parameter(struct rsnd_dai_stream *io,
106 struct rsnd_mod *mod)
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700107{
108 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
Kuninori Morimotod2240f02016-02-18 08:13:13 +0000109 u32 val[RSND_MAX_CHANNELS];
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700110 int i;
111
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000112 /* Enable Ramp */
113 if (dvc->ren.val)
Kuninori Morimotod2240f02016-02-18 08:13:13 +0000114 for (i = 0; i < RSND_MAX_CHANNELS; i++)
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000115 val[i] = dvc->volume.cfg.max;
116 else
Kuninori Morimotod2240f02016-02-18 08:13:13 +0000117 for (i = 0; i < RSND_MAX_CHANNELS; i++)
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000118 val[i] = dvc->volume.val[i];
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700119
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000120 /* Enable Digital Volume */
121 rsnd_mod_write(mod, DVC_VOL0R, val[0]);
122 rsnd_mod_write(mod, DVC_VOL1R, val[1]);
Kuninori Morimoto42ab9a72015-11-30 08:53:44 +0000123 rsnd_mod_write(mod, DVC_VOL2R, val[2]);
124 rsnd_mod_write(mod, DVC_VOL3R, val[3]);
125 rsnd_mod_write(mod, DVC_VOL4R, val[4]);
126 rsnd_mod_write(mod, DVC_VOL5R, val[5]);
127 rsnd_mod_write(mod, DVC_VOL6R, val[6]);
128 rsnd_mod_write(mod, DVC_VOL7R, val[7]);
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000129}
130
131static void rsnd_dvc_volume_init(struct rsnd_dai_stream *io,
132 struct rsnd_mod *mod)
133{
134 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
Kuninori Morimotoc45f7262015-11-30 08:49:33 +0000135 u32 adinr = 0;
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000136 u32 dvucr = 0;
137 u32 vrctr = 0;
138 u32 vrpdr = 0;
139 u32 vrdbr = 0;
140
Kuninori Morimotoc45f7262015-11-30 08:49:33 +0000141 adinr = rsnd_get_adinr_bit(mod, io) |
Kuninori Morimotoeed76bb2016-02-25 05:54:58 +0000142 rsnd_runtime_channel_after_ctu(io);
Kuninori Morimotoc45f7262015-11-30 08:49:33 +0000143
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000144 /* Enable Digital Volume, Zero Cross Mute Mode */
145 dvucr |= 0x101;
Kuninori Morimoto140bab82014-11-04 20:27:18 -0800146
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800147 /* Enable Ramp */
148 if (dvc->ren.val) {
149 dvucr |= 0x10;
150
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800151 /*
152 * FIXME !!
153 * use scale-downed Digital Volume
154 * as Volume Ramp
155 * 7F FFFF -> 3FF
156 */
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000157 vrctr = 0xff;
158 vrpdr = rsnd_dvc_get_vrpdr(dvc);
159 vrdbr = rsnd_dvc_get_vrdbr(dvc);
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800160 }
161
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000162 /* Initialize operation */
163 rsnd_mod_write(mod, DVC_DVUIR, 1);
Kuninori Morimotocd2b6572014-08-01 03:10:55 -0700164
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000165 /* General Information */
Kuninori Morimotoc45f7262015-11-30 08:49:33 +0000166 rsnd_mod_write(mod, DVC_ADINR, adinr);
Kuninori Morimoto1c5d1c92014-11-04 20:26:53 -0800167 rsnd_mod_write(mod, DVC_DVUCR, dvucr);
Kuninori Morimoto140bab82014-11-04 20:27:18 -0800168
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000169 /* Volume Ramp Parameter */
170 rsnd_mod_write(mod, DVC_VRCTR, vrctr);
171 rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
172 rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
173
174 /* Digital Volume Function Parameter */
175 rsnd_dvc_volume_parameter(io, mod);
176
177 /* cancel operation */
178 rsnd_mod_write(mod, DVC_DVUIR, 0);
179}
180
181static void rsnd_dvc_volume_update(struct rsnd_dai_stream *io,
182 struct rsnd_mod *mod)
183{
184 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
185 u32 zcmcr = 0;
186 u32 vrpdr = 0;
187 u32 vrdbr = 0;
188 int i;
189
190 for (i = 0; i < dvc->mute.cfg.size; i++)
191 zcmcr |= (!!dvc->mute.cfg.val[i]) << i;
192
193 if (dvc->ren.val) {
194 vrpdr = rsnd_dvc_get_vrpdr(dvc);
195 vrdbr = rsnd_dvc_get_vrdbr(dvc);
196 }
197
198 /* Disable DVC Register access */
199 rsnd_mod_write(mod, DVC_DVUER, 0);
200
201 /* Zero Cross Mute Function */
202 rsnd_mod_write(mod, DVC_ZCMCR, zcmcr);
203
204 /* Volume Ramp Function */
205 rsnd_mod_write(mod, DVC_VRPDR, vrpdr);
206 rsnd_mod_write(mod, DVC_VRDBR, vrdbr);
207 /* add DVC_VRWTR here */
208
209 /* Digital Volume Function Parameter */
210 rsnd_dvc_volume_parameter(io, mod);
211
Kuninori Morimoto140bab82014-11-04 20:27:18 -0800212 /* Enable DVC Register access */
213 rsnd_mod_write(mod, DVC_DVUER, 1);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700214}
215
Kuninori Morimoto1b2ca0a2015-10-26 08:43:21 +0000216static int rsnd_dvc_probe_(struct rsnd_mod *mod,
217 struct rsnd_dai_stream *io,
218 struct rsnd_priv *priv)
219{
220 return rsnd_cmd_attach(io, rsnd_mod_id(mod));
221}
222
223static int rsnd_dvc_remove_(struct rsnd_mod *mod,
224 struct rsnd_dai_stream *io,
225 struct rsnd_priv *priv)
Kuninori Morimotod1f83d62015-02-02 04:53:53 +0000226{
227 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
228
229 rsnd_kctrl_remove(dvc->volume);
230 rsnd_kctrl_remove(dvc->mute);
231 rsnd_kctrl_remove(dvc->ren);
232 rsnd_kctrl_remove(dvc->rup);
233 rsnd_kctrl_remove(dvc->rdown);
234
235 return 0;
236}
237
Kuninori Morimotoe2c08412015-07-15 07:13:10 +0000238static int rsnd_dvc_init(struct rsnd_mod *mod,
Kuninori Morimoto2c0fac12015-06-15 06:25:20 +0000239 struct rsnd_dai_stream *io,
Kuninori Morimoto690602f2015-01-15 08:07:47 +0000240 struct rsnd_priv *priv)
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700241{
Kuninori Morimotoc9929342015-10-22 03:15:04 +0000242 rsnd_mod_power_on(mod);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700243
Kuninori Morimoto87a6c5a2015-11-30 08:51:15 +0000244 rsnd_dvc_activation(mod);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700245
Kuninori Morimotoca16cc62015-11-04 08:44:12 +0000246 rsnd_dvc_volume_init(io, mod);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700247
Kuninori Morimotoe2c08412015-07-15 07:13:10 +0000248 rsnd_dvc_volume_update(io, mod);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700249
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700250 return 0;
251}
252
253static int rsnd_dvc_quit(struct rsnd_mod *mod,
Kuninori Morimoto2c0fac12015-06-15 06:25:20 +0000254 struct rsnd_dai_stream *io,
Kuninori Morimoto690602f2015-01-15 08:07:47 +0000255 struct rsnd_priv *priv)
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700256{
Kuninori Morimotof13edb82015-11-30 08:52:21 +0000257 rsnd_dvc_halt(mod);
258
Kuninori Morimotoc9929342015-10-22 03:15:04 +0000259 rsnd_mod_power_off(mod);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700260
261 return 0;
262}
263
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700264static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
Kuninori Morimoto2c0fac12015-06-15 06:25:20 +0000265 struct rsnd_dai_stream *io,
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700266 struct snd_soc_pcm_runtime *rtd)
267{
Kuninori Morimoto486b09c2014-08-01 03:10:47 -0700268 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000269 int is_play = rsnd_io_is_play(io);
Kuninori Morimotoc1402842015-12-17 02:57:27 +0000270 int slots = rsnd_get_slot(io);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700271 int ret;
272
Kuninori Morimoto486b09c2014-08-01 03:10:47 -0700273 /* Volume */
Kuninori Morimotob65a7cc2015-06-15 06:27:28 +0000274 ret = rsnd_kctrl_new_m(mod, io, rtd,
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000275 is_play ?
Kuninori Morimoto486b09c2014-08-01 03:10:47 -0700276 "DVC Out Playback Volume" : "DVC In Capture Volume",
Kuninori Morimoto170a2492014-11-27 08:06:14 +0000277 rsnd_dvc_volume_update,
Kuninori Morimoto42ab9a72015-11-30 08:53:44 +0000278 &dvc->volume, slots,
279 0x00800000 - 1);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700280 if (ret < 0)
281 return ret;
282
Kuninori Morimotocd2b6572014-08-01 03:10:55 -0700283 /* Mute */
Kuninori Morimotob65a7cc2015-06-15 06:27:28 +0000284 ret = rsnd_kctrl_new_m(mod, io, rtd,
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000285 is_play ?
Kuninori Morimotocd2b6572014-08-01 03:10:55 -0700286 "DVC Out Mute Switch" : "DVC In Mute Switch",
Kuninori Morimoto170a2492014-11-27 08:06:14 +0000287 rsnd_dvc_volume_update,
Kuninori Morimoto42ab9a72015-11-30 08:53:44 +0000288 &dvc->mute, slots,
289 1);
Kuninori Morimotocd2b6572014-08-01 03:10:55 -0700290 if (ret < 0)
291 return ret;
292
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800293 /* Ramp */
Kuninori Morimotob65a7cc2015-06-15 06:27:28 +0000294 ret = rsnd_kctrl_new_s(mod, io, rtd,
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000295 is_play ?
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800296 "DVC Out Ramp Switch" : "DVC In Ramp Switch",
Kuninori Morimoto170a2492014-11-27 08:06:14 +0000297 rsnd_dvc_volume_update,
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800298 &dvc->ren, 1);
299 if (ret < 0)
300 return ret;
301
Kuninori Morimotob65a7cc2015-06-15 06:27:28 +0000302 ret = rsnd_kctrl_new_e(mod, io, rtd,
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000303 is_play ?
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800304 "DVC Out Ramp Up Rate" : "DVC In Ramp Up Rate",
305 &dvc->rup,
Kuninori Morimoto170a2492014-11-27 08:06:14 +0000306 rsnd_dvc_volume_update,
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800307 dvc_ramp_rate, ARRAY_SIZE(dvc_ramp_rate));
308 if (ret < 0)
309 return ret;
310
Kuninori Morimotob65a7cc2015-06-15 06:27:28 +0000311 ret = rsnd_kctrl_new_e(mod, io, rtd,
Kuninori Morimoto985a4f62015-01-15 08:06:49 +0000312 is_play ?
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800313 "DVC Out Ramp Down Rate" : "DVC In Ramp Down Rate",
314 &dvc->rdown,
Kuninori Morimoto170a2492014-11-27 08:06:14 +0000315 rsnd_dvc_volume_update,
Kuninori Morimoto3539cac2014-11-09 19:52:06 -0800316 dvc_ramp_rate, ARRAY_SIZE(dvc_ramp_rate));
317
318 if (ret < 0)
319 return ret;
320
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700321 return 0;
322}
323
Kuninori Morimoto9b99e9a2015-06-15 06:26:25 +0000324static struct dma_chan *rsnd_dvc_dma_req(struct rsnd_dai_stream *io,
325 struct rsnd_mod *mod)
Kuninori Morimoto72adc612015-02-20 10:31:23 +0000326{
327 struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
328
329 return rsnd_dma_request_channel(rsnd_dvc_of_node(priv),
330 mod, "tx");
331}
332
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700333static struct rsnd_mod_ops rsnd_dvc_ops = {
Kuninori Morimoto8aefda52014-05-22 23:25:43 -0700334 .name = DVC_NAME,
Kuninori Morimoto72adc612015-02-20 10:31:23 +0000335 .dma_req = rsnd_dvc_dma_req,
Kuninori Morimoto1b2ca0a2015-10-26 08:43:21 +0000336 .probe = rsnd_dvc_probe_,
337 .remove = rsnd_dvc_remove_,
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700338 .init = rsnd_dvc_init,
339 .quit = rsnd_dvc_quit,
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700340 .pcm_new = rsnd_dvc_pcm_new,
341};
342
343struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
344{
345 if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv)))
346 id = 0;
347
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000348 return rsnd_mod_get(rsnd_dvc_get(priv, id));
Kuninori Morimoto34cb6122014-06-22 17:59:28 -0700349}
350
Kuninori Morimoto2ea6b072015-11-10 05:14:12 +0000351int rsnd_dvc_probe(struct rsnd_priv *priv)
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700352{
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000353 struct device_node *node;
354 struct device_node *np;
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700355 struct device *dev = rsnd_priv_to_dev(priv);
356 struct rsnd_dvc *dvc;
357 struct clk *clk;
358 char name[RSND_DVC_NAME_SIZE];
Kuninori Morimoto2f78dd72015-03-26 04:02:09 +0000359 int i, nr, ret;
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700360
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700361 /* This driver doesn't support Gen1 at this point */
Kuninori Morimoto8a98b422015-10-15 03:25:28 +0000362 if (rsnd_is_gen1(priv))
363 return 0;
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700364
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000365 node = rsnd_dvc_of_node(priv);
366 if (!node)
367 return 0; /* not used is not error */
Kuninori Morimoto9469b8b2015-07-15 07:15:47 +0000368
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000369 nr = of_get_child_count(node);
370 if (!nr) {
371 ret = -EINVAL;
372 goto rsnd_dvc_probe_done;
373 }
Kuninori Morimoto9469b8b2015-07-15 07:15:47 +0000374
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700375 dvc = devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL);
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000376 if (!dvc) {
377 ret = -ENOMEM;
378 goto rsnd_dvc_probe_done;
379 }
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700380
381 priv->dvc_nr = nr;
382 priv->dvc = dvc;
383
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000384 i = 0;
Mark Brown2e4118d2015-12-14 12:05:17 +0000385 ret = 0;
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000386 for_each_child_of_node(node, np) {
387 dvc = rsnd_dvc_get(priv, i);
388
Kuninori Morimoto8aefda52014-05-22 23:25:43 -0700389 snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d",
390 DVC_NAME, i);
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700391
392 clk = devm_clk_get(dev, name);
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000393 if (IS_ERR(clk)) {
394 ret = PTR_ERR(clk);
395 goto rsnd_dvc_probe_done;
396 }
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700397
Kuninori Morimotob76e2182015-09-10 07:02:21 +0000398 ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops,
Kuninori Morimoto5ba17b422016-01-21 01:58:07 +0000399 clk, rsnd_mod_get_status, RSND_MOD_DVC, i);
Kuninori Morimoto2f78dd72015-03-26 04:02:09 +0000400 if (ret)
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000401 goto rsnd_dvc_probe_done;
402
403 i++;
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700404 }
405
Kuninori Morimoto9eaa1a62015-11-10 05:12:50 +0000406rsnd_dvc_probe_done:
407 of_node_put(node);
408
409 return ret;
Kuninori Morimotobff58ea2014-05-08 17:44:49 -0700410}
Kuninori Morimoto2f78dd72015-03-26 04:02:09 +0000411
Kuninori Morimoto2ea6b072015-11-10 05:14:12 +0000412void rsnd_dvc_remove(struct rsnd_priv *priv)
Kuninori Morimoto2f78dd72015-03-26 04:02:09 +0000413{
414 struct rsnd_dvc *dvc;
415 int i;
416
417 for_each_rsnd_dvc(dvc, priv, i) {
Kuninori Morimotob76e2182015-09-10 07:02:21 +0000418 rsnd_mod_quit(rsnd_mod_get(dvc));
Kuninori Morimoto2f78dd72015-03-26 04:02:09 +0000419 }
420}