blob: 1e5eb8e6f8c7697d0e6dbbe21664bc347ae76d9d [file] [log] [blame]
Katsuhiro Suzuki139a3422018-01-19 18:25:31 +09001// 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>
Katsuhiro Suzuki7c3c20f2018-03-16 16:08:13 +090023#include <linux/mfd/syscon.h>
Katsuhiro Suzuki139a3422018-01-19 18:25:31 +090024#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
36static 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
48static 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 */
85static 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 */
112static 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
130static 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
Katsuhiro Suzuki139a3422018-01-19 18:25:31 +0900138 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
201static 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
223static 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
243static 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
261static 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
270static 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
308static 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
319static 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
351const 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};
361EXPORT_SYMBOL_GPL(uniphier_aio_i2s_ops);
362
363const 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};
372EXPORT_SYMBOL_GPL(uniphier_aio_spdif_ops);
373
374int 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
Katsuhiro Suzuki7c3c20f2018-03-16 16:08:13 +0900391 aio_iecout_set_enable(aio->chip, true);
Katsuhiro Suzuki139a3422018-01-19 18:25:31 +0900392 aio_chip_init(aio->chip);
393 aio->chip->active = 1;
394
395 return 0;
396}
397EXPORT_SYMBOL_GPL(uniphier_aio_dai_probe);
398
399int 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}
407EXPORT_SYMBOL_GPL(uniphier_aio_dai_remove);
408
409int 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}
418EXPORT_SYMBOL_GPL(uniphier_aio_dai_suspend);
419
420int 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
Katsuhiro Suzuki7c3c20f2018-03-16 16:08:13 +0900436 aio_iecout_set_enable(aio->chip, true);
Katsuhiro Suzuki139a3422018-01-19 18:25:31 +0900437 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
458err_out_clock:
459 clk_disable_unprepare(aio->chip->clk);
460
461 return ret;
462}
463EXPORT_SYMBOL_GPL(uniphier_aio_dai_resume);
464
465static const struct snd_soc_component_driver uniphier_aio_component = {
466 .name = "uniphier-aio",
467};
468
469int 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
Katsuhiro Suzuki7c3c20f2018-03-16 16:08:13 +0900483 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
Katsuhiro Suzuki139a3422018-01-19 18:25:31 +0900491 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
555err_out_reset:
556 reset_control_assert(chip->rst);
557
558err_out_clock:
559 clk_disable_unprepare(chip->clk);
560
561 return ret;
562}
563EXPORT_SYMBOL_GPL(uniphier_aio_probe);
564
565int 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}
574EXPORT_SYMBOL_GPL(uniphier_aio_remove);
575
576MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
577MODULE_DESCRIPTION("UniPhier AIO CPU DAI driver.");
578MODULE_LICENSE("GPL v2");