xref: /openbmc/linux/sound/soc/uniphier/aio-cpu.c (revision 2359ccdd)
1 // SPDX-License-Identifier: GPL-2.0
2 //
3 // Socionext UniPhier AIO ALSA CPU DAI driver.
4 //
5 // Copyright (c) 2016-2018 Socionext Inc.
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; version 2
10 // of the License.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, see <http://www.gnu.org/licenses/>.
19 
20 #include <linux/clk.h>
21 #include <linux/errno.h>
22 #include <linux/kernel.h>
23 #include <linux/mfd/syscon.h>
24 #include <linux/module.h>
25 #include <linux/of.h>
26 #include <linux/of_platform.h>
27 #include <linux/platform_device.h>
28 #include <linux/reset.h>
29 #include <sound/core.h>
30 #include <sound/pcm.h>
31 #include <sound/pcm_params.h>
32 #include <sound/soc.h>
33 
34 #include "aio.h"
35 
36 static bool is_valid_pll(struct uniphier_aio_chip *chip, int pll_id)
37 {
38 	struct device *dev = &chip->pdev->dev;
39 
40 	if (pll_id < 0 || chip->num_plls <= pll_id) {
41 		dev_err(dev, "PLL(%d) is not supported\n", pll_id);
42 		return false;
43 	}
44 
45 	return chip->plls[pll_id].enable;
46 }
47 
48 static bool match_spec(const struct uniphier_aio_spec *spec,
49 		       const char *name, int dir)
50 {
51 	if (dir == SNDRV_PCM_STREAM_PLAYBACK &&
52 	    spec->swm.dir != PORT_DIR_OUTPUT) {
53 		return false;
54 	}
55 
56 	if (dir == SNDRV_PCM_STREAM_CAPTURE &&
57 	    spec->swm.dir != PORT_DIR_INPUT) {
58 		return false;
59 	}
60 
61 	if (spec->name && strcmp(spec->name, name) == 0)
62 		return true;
63 
64 	if (spec->gname && strcmp(spec->gname, name) == 0)
65 		return true;
66 
67 	return false;
68 }
69 
70 /**
71  * find_spec - find HW specification info by name
72  * @aio: the AIO device pointer
73  * @name: name of device
74  * @direction: the direction of substream, SNDRV_PCM_STREAM_*
75  *
76  * Find hardware specification information from list by device name. This
77  * information is used for telling the difference of SoCs to driver.
78  *
79  * Specification list is array of 'struct uniphier_aio_spec' which is defined
80  * in each drivers (see: aio-i2s.c).
81  *
82  * Return: The pointer of hardware specification of AIO if successful,
83  * otherwise NULL on error.
84  */
85 static const struct uniphier_aio_spec *find_spec(struct uniphier_aio *aio,
86 						 const char *name,
87 						 int direction)
88 {
89 	const struct uniphier_aio_chip_spec *chip_spec = aio->chip->chip_spec;
90 	int i;
91 
92 	for (i = 0; i < chip_spec->num_specs; i++) {
93 		const struct uniphier_aio_spec *spec = &chip_spec->specs[i];
94 
95 		if (match_spec(spec, name, direction))
96 			return spec;
97 	}
98 
99 	return NULL;
100 }
101 
102 /**
103  * find_divider - find clock divider by frequency
104  * @aio: the AIO device pointer
105  * @pll_id: PLL ID, should be AUD_PLL_XX
106  * @freq: required frequency
107  *
108  * Find suitable clock divider by frequency.
109  *
110  * Return: The ID of PLL if successful, otherwise negative error value.
111  */
112 static int find_divider(struct uniphier_aio *aio, int pll_id, unsigned int freq)
113 {
114 	struct uniphier_aio_pll *pll;
115 	int mul[] = { 1, 1, 1, 2, };
116 	int div[] = { 2, 3, 1, 3, };
117 	int i;
118 
119 	if (!is_valid_pll(aio->chip, pll_id))
120 		return -EINVAL;
121 
122 	pll = &aio->chip->plls[pll_id];
123 	for (i = 0; i < ARRAY_SIZE(mul); i++)
124 		if (pll->freq * mul[i] / div[i] == freq)
125 			return i;
126 
127 	return -ENOTSUPP;
128 }
129 
130 static int uniphier_aio_set_sysclk(struct snd_soc_dai *dai, int clk_id,
131 				   unsigned int freq, int dir)
132 {
133 	struct uniphier_aio *aio = uniphier_priv(dai);
134 	struct device *dev = &aio->chip->pdev->dev;
135 	bool pll_auto = false;
136 	int pll_id, div_id;
137 
138 	switch (clk_id) {
139 	case AUD_CLK_IO:
140 		return -ENOTSUPP;
141 	case AUD_CLK_A1:
142 		pll_id = AUD_PLL_A1;
143 		break;
144 	case AUD_CLK_F1:
145 		pll_id = AUD_PLL_F1;
146 		break;
147 	case AUD_CLK_A2:
148 		pll_id = AUD_PLL_A2;
149 		break;
150 	case AUD_CLK_F2:
151 		pll_id = AUD_PLL_F2;
152 		break;
153 	case AUD_CLK_A:
154 		pll_id = AUD_PLL_A1;
155 		pll_auto = true;
156 		break;
157 	case AUD_CLK_F:
158 		pll_id = AUD_PLL_F1;
159 		pll_auto = true;
160 		break;
161 	case AUD_CLK_APLL:
162 		pll_id = AUD_PLL_APLL;
163 		break;
164 	case AUD_CLK_RX0:
165 		pll_id = AUD_PLL_RX0;
166 		break;
167 	case AUD_CLK_USB0:
168 		pll_id = AUD_PLL_USB0;
169 		break;
170 	case AUD_CLK_HSC0:
171 		pll_id = AUD_PLL_HSC0;
172 		break;
173 	default:
174 		dev_err(dev, "Sysclk(%d) is not supported\n", clk_id);
175 		return -EINVAL;
176 	}
177 
178 	if (pll_auto) {
179 		for (pll_id = 0; pll_id < aio->chip->num_plls; pll_id++) {
180 			div_id = find_divider(aio, pll_id, freq);
181 			if (div_id >= 0) {
182 				aio->plldiv = div_id;
183 				break;
184 			}
185 		}
186 		if (pll_id == aio->chip->num_plls) {
187 			dev_err(dev, "Sysclk frequency is not supported(%d)\n",
188 				freq);
189 			return -EINVAL;
190 		}
191 	}
192 
193 	if (dir == SND_SOC_CLOCK_OUT)
194 		aio->pll_out = pll_id;
195 	else
196 		aio->pll_in = pll_id;
197 
198 	return 0;
199 }
200 
201 static int uniphier_aio_set_pll(struct snd_soc_dai *dai, int pll_id,
202 				int source, unsigned int freq_in,
203 				unsigned int freq_out)
204 {
205 	struct uniphier_aio *aio = uniphier_priv(dai);
206 	struct device *dev = &aio->chip->pdev->dev;
207 	int ret;
208 
209 	if (!is_valid_pll(aio->chip, pll_id))
210 		return -EINVAL;
211 	if (!aio->chip->plls[pll_id].enable) {
212 		dev_err(dev, "PLL(%d) is not implemented\n", pll_id);
213 		return -ENOTSUPP;
214 	}
215 
216 	ret = aio_chip_set_pll(aio->chip, pll_id, freq_out);
217 	if (ret < 0)
218 		return ret;
219 
220 	return 0;
221 }
222 
223 static int uniphier_aio_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
224 {
225 	struct uniphier_aio *aio = uniphier_priv(dai);
226 	struct device *dev = &aio->chip->pdev->dev;
227 
228 	switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
229 	case SND_SOC_DAIFMT_LEFT_J:
230 	case SND_SOC_DAIFMT_RIGHT_J:
231 	case SND_SOC_DAIFMT_I2S:
232 		aio->fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
233 		break;
234 	default:
235 		dev_err(dev, "Format is not supported(%d)\n",
236 			fmt & SND_SOC_DAIFMT_FORMAT_MASK);
237 		return -EINVAL;
238 	}
239 
240 	return 0;
241 }
242 
243 static int uniphier_aio_startup(struct snd_pcm_substream *substream,
244 				struct snd_soc_dai *dai)
245 {
246 	struct uniphier_aio *aio = uniphier_priv(dai);
247 	struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
248 	int ret;
249 
250 	sub->substream = substream;
251 	sub->pass_through = 0;
252 	sub->use_mmap = true;
253 
254 	ret = aio_init(sub);
255 	if (ret)
256 		return ret;
257 
258 	return 0;
259 }
260 
261 static void uniphier_aio_shutdown(struct snd_pcm_substream *substream,
262 				  struct snd_soc_dai *dai)
263 {
264 	struct uniphier_aio *aio = uniphier_priv(dai);
265 	struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
266 
267 	sub->substream = NULL;
268 }
269 
270 static int uniphier_aio_hw_params(struct snd_pcm_substream *substream,
271 				  struct snd_pcm_hw_params *params,
272 				  struct snd_soc_dai *dai)
273 {
274 	struct uniphier_aio *aio = uniphier_priv(dai);
275 	struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
276 	struct device *dev = &aio->chip->pdev->dev;
277 	int freq, ret;
278 
279 	switch (params_rate(params)) {
280 	case 48000:
281 	case 32000:
282 	case 24000:
283 		freq = 12288000;
284 		break;
285 	case 44100:
286 	case 22050:
287 		freq = 11289600;
288 		break;
289 	default:
290 		dev_err(dev, "Rate is not supported(%d)\n",
291 			params_rate(params));
292 		return -EINVAL;
293 	}
294 	ret = snd_soc_dai_set_sysclk(dai, AUD_CLK_A,
295 				     freq, SND_SOC_CLOCK_OUT);
296 	if (ret)
297 		return ret;
298 
299 	sub->params = *params;
300 	sub->setting = 1;
301 
302 	aio_port_reset(sub);
303 	aio_src_reset(sub);
304 
305 	return 0;
306 }
307 
308 static int uniphier_aio_hw_free(struct snd_pcm_substream *substream,
309 				struct snd_soc_dai *dai)
310 {
311 	struct uniphier_aio *aio = uniphier_priv(dai);
312 	struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
313 
314 	sub->setting = 0;
315 
316 	return 0;
317 }
318 
319 static int uniphier_aio_prepare(struct snd_pcm_substream *substream,
320 				struct snd_soc_dai *dai)
321 {
322 	struct uniphier_aio *aio = uniphier_priv(dai);
323 	struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
324 	int ret;
325 
326 	ret = aio_port_set_param(sub, sub->pass_through, &sub->params);
327 	if (ret)
328 		return ret;
329 	ret = aio_src_set_param(sub, &sub->params);
330 	if (ret)
331 		return ret;
332 	aio_port_set_enable(sub, 1);
333 
334 	ret = aio_if_set_param(sub, sub->pass_through);
335 	if (ret)
336 		return ret;
337 
338 	if (sub->swm->type == PORT_TYPE_CONV) {
339 		ret = aio_srcif_set_param(sub);
340 		if (ret)
341 			return ret;
342 		ret = aio_srcch_set_param(sub);
343 		if (ret)
344 			return ret;
345 		aio_srcch_set_enable(sub, 1);
346 	}
347 
348 	return 0;
349 }
350 
351 const struct snd_soc_dai_ops uniphier_aio_i2s_ops = {
352 	.set_sysclk  = uniphier_aio_set_sysclk,
353 	.set_pll     = uniphier_aio_set_pll,
354 	.set_fmt     = uniphier_aio_set_fmt,
355 	.startup     = uniphier_aio_startup,
356 	.shutdown    = uniphier_aio_shutdown,
357 	.hw_params   = uniphier_aio_hw_params,
358 	.hw_free     = uniphier_aio_hw_free,
359 	.prepare     = uniphier_aio_prepare,
360 };
361 EXPORT_SYMBOL_GPL(uniphier_aio_i2s_ops);
362 
363 const struct snd_soc_dai_ops uniphier_aio_spdif_ops = {
364 	.set_sysclk  = uniphier_aio_set_sysclk,
365 	.set_pll     = uniphier_aio_set_pll,
366 	.startup     = uniphier_aio_startup,
367 	.shutdown    = uniphier_aio_shutdown,
368 	.hw_params   = uniphier_aio_hw_params,
369 	.hw_free     = uniphier_aio_hw_free,
370 	.prepare     = uniphier_aio_prepare,
371 };
372 EXPORT_SYMBOL_GPL(uniphier_aio_spdif_ops);
373 
374 int uniphier_aio_dai_probe(struct snd_soc_dai *dai)
375 {
376 	struct uniphier_aio *aio = uniphier_priv(dai);
377 	int i;
378 
379 	for (i = 0; i < ARRAY_SIZE(aio->sub); i++) {
380 		struct uniphier_aio_sub *sub = &aio->sub[i];
381 		const struct uniphier_aio_spec *spec;
382 
383 		spec = find_spec(aio, dai->name, i);
384 		if (!spec)
385 			continue;
386 
387 		sub->swm = &spec->swm;
388 		sub->spec = spec;
389 	}
390 
391 	aio_iecout_set_enable(aio->chip, true);
392 	aio_chip_init(aio->chip);
393 	aio->chip->active = 1;
394 
395 	return 0;
396 }
397 EXPORT_SYMBOL_GPL(uniphier_aio_dai_probe);
398 
399 int uniphier_aio_dai_remove(struct snd_soc_dai *dai)
400 {
401 	struct uniphier_aio *aio = uniphier_priv(dai);
402 
403 	aio->chip->active = 0;
404 
405 	return 0;
406 }
407 EXPORT_SYMBOL_GPL(uniphier_aio_dai_remove);
408 
409 int uniphier_aio_dai_suspend(struct snd_soc_dai *dai)
410 {
411 	struct uniphier_aio *aio = uniphier_priv(dai);
412 
413 	reset_control_assert(aio->chip->rst);
414 	clk_disable_unprepare(aio->chip->clk);
415 
416 	return 0;
417 }
418 EXPORT_SYMBOL_GPL(uniphier_aio_dai_suspend);
419 
420 int uniphier_aio_dai_resume(struct snd_soc_dai *dai)
421 {
422 	struct uniphier_aio *aio = uniphier_priv(dai);
423 	int ret, i;
424 
425 	if (!aio->chip->active)
426 		return 0;
427 
428 	ret = clk_prepare_enable(aio->chip->clk);
429 	if (ret)
430 		return ret;
431 
432 	ret = reset_control_deassert(aio->chip->rst);
433 	if (ret)
434 		goto err_out_clock;
435 
436 	aio_iecout_set_enable(aio->chip, true);
437 	aio_chip_init(aio->chip);
438 
439 	for (i = 0; i < ARRAY_SIZE(aio->sub); i++) {
440 		struct uniphier_aio_sub *sub = &aio->sub[i];
441 
442 		if (!sub->spec || !sub->substream)
443 			continue;
444 
445 		ret = aio_init(sub);
446 		if (ret)
447 			goto err_out_clock;
448 
449 		if (!sub->setting)
450 			continue;
451 
452 		aio_port_reset(sub);
453 		aio_src_reset(sub);
454 	}
455 
456 	return 0;
457 
458 err_out_clock:
459 	clk_disable_unprepare(aio->chip->clk);
460 
461 	return ret;
462 }
463 EXPORT_SYMBOL_GPL(uniphier_aio_dai_resume);
464 
465 static const struct snd_soc_component_driver uniphier_aio_component = {
466 	.name = "uniphier-aio",
467 };
468 
469 int uniphier_aio_probe(struct platform_device *pdev)
470 {
471 	struct uniphier_aio_chip *chip;
472 	struct device *dev = &pdev->dev;
473 	int ret, i, j;
474 
475 	chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
476 	if (!chip)
477 		return -ENOMEM;
478 
479 	chip->chip_spec = of_device_get_match_data(dev);
480 	if (!chip->chip_spec)
481 		return -EINVAL;
482 
483 	chip->regmap_sg = syscon_regmap_lookup_by_phandle(dev->of_node,
484 							  "socionext,syscon");
485 	if (IS_ERR(chip->regmap_sg)) {
486 		if (PTR_ERR(chip->regmap_sg) == -EPROBE_DEFER)
487 			return -EPROBE_DEFER;
488 		chip->regmap_sg = NULL;
489 	}
490 
491 	chip->clk = devm_clk_get(dev, "aio");
492 	if (IS_ERR(chip->clk))
493 		return PTR_ERR(chip->clk);
494 
495 	chip->rst = devm_reset_control_get_shared(dev, "aio");
496 	if (IS_ERR(chip->rst))
497 		return PTR_ERR(chip->rst);
498 
499 	chip->num_aios = chip->chip_spec->num_dais;
500 	chip->aios = devm_kzalloc(dev,
501 				  sizeof(struct uniphier_aio) * chip->num_aios,
502 				  GFP_KERNEL);
503 	if (!chip->aios)
504 		return -ENOMEM;
505 
506 	chip->num_plls = chip->chip_spec->num_plls;
507 	chip->plls = devm_kzalloc(dev, sizeof(struct uniphier_aio_pll) *
508 				  chip->num_plls, GFP_KERNEL);
509 	if (!chip->plls)
510 		return -ENOMEM;
511 	memcpy(chip->plls, chip->chip_spec->plls,
512 	       sizeof(struct uniphier_aio_pll) * chip->num_plls);
513 
514 	for (i = 0; i < chip->num_aios; i++) {
515 		struct uniphier_aio *aio = &chip->aios[i];
516 
517 		aio->chip = chip;
518 		aio->fmt = SND_SOC_DAIFMT_I2S;
519 
520 		for (j = 0; j < ARRAY_SIZE(aio->sub); j++) {
521 			struct uniphier_aio_sub *sub = &aio->sub[j];
522 
523 			sub->aio = aio;
524 			spin_lock_init(&sub->lock);
525 		}
526 	}
527 
528 	chip->pdev = pdev;
529 	platform_set_drvdata(pdev, chip);
530 
531 	ret = clk_prepare_enable(chip->clk);
532 	if (ret)
533 		return ret;
534 
535 	ret = reset_control_deassert(chip->rst);
536 	if (ret)
537 		goto err_out_clock;
538 
539 	ret = devm_snd_soc_register_component(dev, &uniphier_aio_component,
540 					      chip->chip_spec->dais,
541 					      chip->chip_spec->num_dais);
542 	if (ret) {
543 		dev_err(dev, "Register component failed.\n");
544 		goto err_out_reset;
545 	}
546 
547 	ret = uniphier_aiodma_soc_register_platform(pdev);
548 	if (ret) {
549 		dev_err(dev, "Register platform failed.\n");
550 		goto err_out_reset;
551 	}
552 
553 	return 0;
554 
555 err_out_reset:
556 	reset_control_assert(chip->rst);
557 
558 err_out_clock:
559 	clk_disable_unprepare(chip->clk);
560 
561 	return ret;
562 }
563 EXPORT_SYMBOL_GPL(uniphier_aio_probe);
564 
565 int uniphier_aio_remove(struct platform_device *pdev)
566 {
567 	struct uniphier_aio_chip *chip = platform_get_drvdata(pdev);
568 
569 	reset_control_assert(chip->rst);
570 	clk_disable_unprepare(chip->clk);
571 
572 	return 0;
573 }
574 EXPORT_SYMBOL_GPL(uniphier_aio_remove);
575 
576 MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
577 MODULE_DESCRIPTION("UniPhier AIO CPU DAI driver.");
578 MODULE_LICENSE("GPL v2");
579