xref: /openbmc/linux/sound/soc/sh/rcar/dvc.c (revision 8a26af30)
1 /*
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  */
11 #include "rsnd.h"
12 
13 #define RSND_DVC_NAME_SIZE	16
14 #define RSND_DVC_VOLUME_MAX	100
15 #define RSND_DVC_VOLUME_NUM	2
16 
17 #define DVC_NAME "dvc"
18 
19 struct rsnd_dvc {
20 	struct rsnd_dvc_platform_info *info; /* rcar_snd.h */
21 	struct rsnd_mod mod;
22 	struct clk *clk;
23 	long volume[RSND_DVC_VOLUME_NUM];
24 };
25 
26 #define rsnd_mod_to_dvc(_mod)	\
27 	container_of((_mod), struct rsnd_dvc, mod)
28 
29 #define for_each_rsnd_dvc(pos, priv, i)				\
30 	for ((i) = 0;						\
31 	     ((i) < rsnd_dvc_nr(priv)) &&			\
32 	     ((pos) = (struct rsnd_dvc *)(priv)->dvc + i);	\
33 	     i++)
34 
35 static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
36 {
37 	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
38 	u32 max = (0x00800000 - 1);
39 	u32 vol[RSND_DVC_VOLUME_NUM];
40 	int i;
41 
42 	for (i = 0; i < RSND_DVC_VOLUME_NUM; i++)
43 		vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i];
44 
45 	rsnd_mod_write(mod, DVC_VOL0R, vol[0]);
46 	rsnd_mod_write(mod, DVC_VOL1R, vol[1]);
47 }
48 
49 static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod,
50 			       struct rsnd_dai *rdai)
51 {
52 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
53 	struct device *dev = rsnd_priv_to_dev(priv);
54 
55 	dev_dbg(dev, "%s (Gen2) is probed\n", rsnd_mod_name(mod));
56 
57 	return 0;
58 }
59 
60 static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
61 			 struct rsnd_dai *rdai)
62 {
63 	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(dvc_mod);
64 	struct rsnd_dai_stream *io = rsnd_mod_to_io(dvc_mod);
65 	struct rsnd_priv *priv = rsnd_mod_to_priv(dvc_mod);
66 	struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io);
67 	struct device *dev = rsnd_priv_to_dev(priv);
68 	int dvc_id = rsnd_mod_id(dvc_mod);
69 	int src_id = rsnd_mod_id(src_mod);
70 	u32 route[] = {
71 		[0] = 0x30000,
72 		[1] = 0x30001,
73 		[2] = 0x40000,
74 		[3] = 0x10000,
75 		[4] = 0x20000,
76 		[5] = 0x40100
77 	};
78 
79 	if (src_id >= ARRAY_SIZE(route)) {
80 		dev_err(dev, "DVC%d isn't connected to SRC%d\n", dvc_id, src_id);
81 		return -EINVAL;
82 	}
83 
84 	clk_prepare_enable(dvc->clk);
85 
86 	/*
87 	 * fixme
88 	 * it doesn't support CTU/MIX
89 	 */
90 	rsnd_mod_write(dvc_mod, CMD_ROUTE_SLCT, route[src_id]);
91 
92 	rsnd_mod_write(dvc_mod, DVC_SWRSR, 0);
93 	rsnd_mod_write(dvc_mod, DVC_SWRSR, 1);
94 
95 	rsnd_mod_write(dvc_mod, DVC_DVUIR, 1);
96 
97 	rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod));
98 
99 	/*  enable Volume  */
100 	rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x100);
101 
102 	/* ch0/ch1 Volume */
103 	rsnd_dvc_volume_update(dvc_mod);
104 
105 	rsnd_mod_write(dvc_mod, DVC_DVUIR, 0);
106 
107 	rsnd_mod_write(dvc_mod, DVC_DVUER, 1);
108 
109 	rsnd_adg_set_cmd_timsel_gen2(rdai, dvc_mod, io);
110 
111 	return 0;
112 }
113 
114 static int rsnd_dvc_quit(struct rsnd_mod *mod,
115 			 struct rsnd_dai *rdai)
116 {
117 	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
118 
119 	clk_disable_unprepare(dvc->clk);
120 
121 	return 0;
122 }
123 
124 static int rsnd_dvc_start(struct rsnd_mod *mod,
125 			  struct rsnd_dai *rdai)
126 {
127 	rsnd_mod_write(mod, CMD_CTRL, 0x10);
128 
129 	return 0;
130 }
131 
132 static int rsnd_dvc_stop(struct rsnd_mod *mod,
133 			 struct rsnd_dai *rdai)
134 {
135 	rsnd_mod_write(mod, CMD_CTRL, 0);
136 
137 	return 0;
138 }
139 
140 static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
141 			       struct snd_ctl_elem_info *uinfo)
142 {
143 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
144 	uinfo->count = RSND_DVC_VOLUME_NUM;
145 	uinfo->value.integer.min = 0;
146 	uinfo->value.integer.max = RSND_DVC_VOLUME_MAX;
147 
148 	return 0;
149 }
150 
151 static int rsnd_dvc_volume_get(struct snd_kcontrol *kctrl,
152 			      struct snd_ctl_elem_value *ucontrol)
153 {
154 	struct rsnd_mod *mod = snd_kcontrol_chip(kctrl);
155 	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
156 	int i;
157 
158 	for (i = 0; i < RSND_DVC_VOLUME_NUM; i++)
159 		ucontrol->value.integer.value[i] = dvc->volume[i];
160 
161 	return 0;
162 }
163 
164 static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl,
165 			      struct snd_ctl_elem_value *ucontrol)
166 {
167 	struct rsnd_mod *mod = snd_kcontrol_chip(kctrl);
168 	struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
169 	int i, change = 0;
170 
171 	for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) {
172 		if (ucontrol->value.integer.value[i] < 0 ||
173 		    ucontrol->value.integer.value[i] > RSND_DVC_VOLUME_MAX)
174 			return -EINVAL;
175 
176 		change |= (ucontrol->value.integer.value[i] != dvc->volume[i]);
177 	}
178 
179 	if (change) {
180 		for (i = 0; i < RSND_DVC_VOLUME_NUM; i++)
181 			dvc->volume[i] = ucontrol->value.integer.value[i];
182 
183 		rsnd_dvc_volume_update(mod);
184 	}
185 
186 	return change;
187 }
188 
189 static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
190 			    struct rsnd_dai *rdai,
191 			    struct snd_soc_pcm_runtime *rtd)
192 {
193 	struct rsnd_dai_stream *io = rsnd_mod_to_io(mod);
194 	struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
195 	struct device *dev = rsnd_priv_to_dev(priv);
196 	struct snd_card *card = rtd->card->snd_card;
197 	struct snd_kcontrol *kctrl;
198 	static struct snd_kcontrol_new knew = {
199 		.iface		= SNDRV_CTL_ELEM_IFACE_MIXER,
200 		.name		= "Playback Volume",
201 		.info		= rsnd_dvc_volume_info,
202 		.get		= rsnd_dvc_volume_get,
203 		.put		= rsnd_dvc_volume_put,
204 	};
205 	int ret;
206 
207 	if (!rsnd_dai_is_play(rdai, io)) {
208 		dev_err(dev, "DVC%d is connected to Capture DAI\n",
209 			rsnd_mod_id(mod));
210 		return -EINVAL;
211 	}
212 
213 	kctrl = snd_ctl_new1(&knew, mod);
214 	if (!kctrl)
215 		return -ENOMEM;
216 
217 	ret = snd_ctl_add(card, kctrl);
218 	if (ret < 0)
219 		return ret;
220 
221 	return 0;
222 }
223 
224 static struct rsnd_mod_ops rsnd_dvc_ops = {
225 	.name		= DVC_NAME,
226 	.probe		= rsnd_dvc_probe_gen2,
227 	.init		= rsnd_dvc_init,
228 	.quit		= rsnd_dvc_quit,
229 	.start		= rsnd_dvc_start,
230 	.stop		= rsnd_dvc_stop,
231 	.pcm_new	= rsnd_dvc_pcm_new,
232 };
233 
234 struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
235 {
236 	if (WARN_ON(id < 0 || id >= rsnd_dvc_nr(priv)))
237 		id = 0;
238 
239 	return &((struct rsnd_dvc *)(priv->dvc) + id)->mod;
240 }
241 
242 int rsnd_dvc_probe(struct platform_device *pdev,
243 		   const struct rsnd_of_data *of_data,
244 		   struct rsnd_priv *priv)
245 {
246 	struct rcar_snd_info *info = rsnd_priv_to_info(priv);
247 	struct device *dev = rsnd_priv_to_dev(priv);
248 	struct rsnd_dvc *dvc;
249 	struct clk *clk;
250 	char name[RSND_DVC_NAME_SIZE];
251 	int i, nr;
252 
253 	nr = info->dvc_info_nr;
254 	if (!nr)
255 		return 0;
256 
257 	/* This driver doesn't support Gen1 at this point */
258 	if (rsnd_is_gen1(priv)) {
259 		dev_warn(dev, "CMD is not supported on Gen1\n");
260 		return -EINVAL;
261 	}
262 
263 	dvc	= devm_kzalloc(dev, sizeof(*dvc) * nr, GFP_KERNEL);
264 	if (!dvc) {
265 		dev_err(dev, "CMD allocate failed\n");
266 		return -ENOMEM;
267 	}
268 
269 	priv->dvc_nr	= nr;
270 	priv->dvc	= dvc;
271 
272 	for_each_rsnd_dvc(dvc, priv, i) {
273 		snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d",
274 			 DVC_NAME, i);
275 
276 		clk = devm_clk_get(dev, name);
277 		if (IS_ERR(clk))
278 			return PTR_ERR(clk);
279 
280 		dvc->info = &info->dvc_info[i];
281 		dvc->clk  = clk;
282 
283 		rsnd_mod_init(priv, &dvc->mod, &rsnd_dvc_ops, RSND_MOD_DVC, i);
284 
285 		dev_dbg(dev, "CMD%d probed\n", i);
286 	}
287 
288 	return 0;
289 }
290