1 // SPDX-License-Identifier: GPL-2.0
3 // Socionext UniPhier AIO ALSA CPU DAI driver.
5 // Copyright (c) 2016-2018 Socionext Inc.
8 #include <linux/errno.h>
9 #include <linux/kernel.h>
10 #include <linux/mfd/syscon.h>
11 #include <linux/module.h>
13 #include <linux/of_platform.h>
14 #include <linux/platform_device.h>
15 #include <linux/reset.h>
16 #include <sound/core.h>
17 #include <sound/pcm.h>
18 #include <sound/pcm_params.h>
19 #include <sound/soc.h>
23 static bool is_valid_pll(struct uniphier_aio_chip
*chip
, int pll_id
)
25 struct device
*dev
= &chip
->pdev
->dev
;
27 if (pll_id
< 0 || chip
->num_plls
<= pll_id
) {
28 dev_err(dev
, "PLL(%d) is not supported\n", pll_id
);
32 return chip
->plls
[pll_id
].enable
;
36 * find_volume - find volume supported HW port by HW port number
37 * @chip: the AIO chip pointer
38 * @oport_hw: HW port number, one of AUD_HW_XXXX
40 * Find AIO device from device list by HW port number. Volume feature is
41 * available only in Output and PCM ports, this limitation comes from HW
44 * Return: The pointer of AIO substream if successful, otherwise NULL on error.
46 static struct uniphier_aio_sub
*find_volume(struct uniphier_aio_chip
*chip
,
51 for (i
= 0; i
< chip
->num_aios
; i
++) {
52 struct uniphier_aio_sub
*sub
= &chip
->aios
[i
].sub
[0];
57 if (sub
->swm
->oport
.hw
== oport_hw
)
64 static bool match_spec(const struct uniphier_aio_spec
*spec
,
65 const char *name
, int dir
)
67 if (dir
== SNDRV_PCM_STREAM_PLAYBACK
&&
68 spec
->swm
.dir
!= PORT_DIR_OUTPUT
) {
72 if (dir
== SNDRV_PCM_STREAM_CAPTURE
&&
73 spec
->swm
.dir
!= PORT_DIR_INPUT
) {
77 if (spec
->name
&& strcmp(spec
->name
, name
) == 0)
80 if (spec
->gname
&& strcmp(spec
->gname
, name
) == 0)
87 * find_spec - find HW specification info by name
88 * @aio: the AIO device pointer
89 * @name: name of device
90 * @direction: the direction of substream, SNDRV_PCM_STREAM_*
92 * Find hardware specification information from list by device name. This
93 * information is used for telling the difference of SoCs to driver.
95 * Specification list is array of 'struct uniphier_aio_spec' which is defined
96 * in each drivers (see: aio-i2s.c).
98 * Return: The pointer of hardware specification of AIO if successful,
99 * otherwise NULL on error.
101 static const struct uniphier_aio_spec
*find_spec(struct uniphier_aio
*aio
,
105 const struct uniphier_aio_chip_spec
*chip_spec
= aio
->chip
->chip_spec
;
108 for (i
= 0; i
< chip_spec
->num_specs
; i
++) {
109 const struct uniphier_aio_spec
*spec
= &chip_spec
->specs
[i
];
111 if (match_spec(spec
, name
, direction
))
119 * find_divider - find clock divider by frequency
120 * @aio: the AIO device pointer
121 * @pll_id: PLL ID, should be AUD_PLL_XX
122 * @freq: required frequency
124 * Find suitable clock divider by frequency.
126 * Return: The ID of PLL if successful, otherwise negative error value.
128 static int find_divider(struct uniphier_aio
*aio
, int pll_id
, unsigned int freq
)
130 struct uniphier_aio_pll
*pll
;
131 int mul
[] = { 1, 1, 1, 2, };
132 int div
[] = { 2, 3, 1, 3, };
135 if (!is_valid_pll(aio
->chip
, pll_id
))
138 pll
= &aio
->chip
->plls
[pll_id
];
139 for (i
= 0; i
< ARRAY_SIZE(mul
); i
++)
140 if (pll
->freq
* mul
[i
] / div
[i
] == freq
)
146 static int uniphier_aio_set_sysclk(struct snd_soc_dai
*dai
, int clk_id
,
147 unsigned int freq
, int dir
)
149 struct uniphier_aio
*aio
= uniphier_priv(dai
);
150 struct device
*dev
= &aio
->chip
->pdev
->dev
;
151 bool pll_auto
= false;
178 pll_id
= AUD_PLL_APLL
;
181 pll_id
= AUD_PLL_RX0
;
184 pll_id
= AUD_PLL_USB0
;
187 pll_id
= AUD_PLL_HSC0
;
190 dev_err(dev
, "Sysclk(%d) is not supported\n", clk_id
);
195 for (pll_id
= 0; pll_id
< aio
->chip
->num_plls
; pll_id
++) {
196 div_id
= find_divider(aio
, pll_id
, freq
);
198 aio
->plldiv
= div_id
;
202 if (pll_id
== aio
->chip
->num_plls
) {
203 dev_err(dev
, "Sysclk frequency is not supported(%d)\n",
209 if (dir
== SND_SOC_CLOCK_OUT
)
210 aio
->pll_out
= pll_id
;
212 aio
->pll_in
= pll_id
;
217 static int uniphier_aio_set_pll(struct snd_soc_dai
*dai
, int pll_id
,
218 int source
, unsigned int freq_in
,
219 unsigned int freq_out
)
221 struct uniphier_aio
*aio
= uniphier_priv(dai
);
224 if (!is_valid_pll(aio
->chip
, pll_id
))
227 ret
= aio_chip_set_pll(aio
->chip
, pll_id
, freq_out
);
234 static int uniphier_aio_set_fmt(struct snd_soc_dai
*dai
, unsigned int fmt
)
236 struct uniphier_aio
*aio
= uniphier_priv(dai
);
237 struct device
*dev
= &aio
->chip
->pdev
->dev
;
239 switch (fmt
& SND_SOC_DAIFMT_FORMAT_MASK
) {
240 case SND_SOC_DAIFMT_LEFT_J
:
241 case SND_SOC_DAIFMT_RIGHT_J
:
242 case SND_SOC_DAIFMT_I2S
:
243 aio
->fmt
= fmt
& SND_SOC_DAIFMT_FORMAT_MASK
;
246 dev_err(dev
, "Format is not supported(%d)\n",
247 fmt
& SND_SOC_DAIFMT_FORMAT_MASK
);
254 static int uniphier_aio_startup(struct snd_pcm_substream
*substream
,
255 struct snd_soc_dai
*dai
)
257 struct uniphier_aio
*aio
= uniphier_priv(dai
);
258 struct uniphier_aio_sub
*sub
= &aio
->sub
[substream
->stream
];
261 sub
->substream
= substream
;
262 sub
->pass_through
= 0;
263 sub
->use_mmap
= true;
272 static void uniphier_aio_shutdown(struct snd_pcm_substream
*substream
,
273 struct snd_soc_dai
*dai
)
275 struct uniphier_aio
*aio
= uniphier_priv(dai
);
276 struct uniphier_aio_sub
*sub
= &aio
->sub
[substream
->stream
];
278 sub
->substream
= NULL
;
281 static int uniphier_aio_hw_params(struct snd_pcm_substream
*substream
,
282 struct snd_pcm_hw_params
*params
,
283 struct snd_soc_dai
*dai
)
285 struct uniphier_aio
*aio
= uniphier_priv(dai
);
286 struct uniphier_aio_sub
*sub
= &aio
->sub
[substream
->stream
];
287 struct device
*dev
= &aio
->chip
->pdev
->dev
;
290 switch (params_rate(params
)) {
301 dev_err(dev
, "Rate is not supported(%d)\n",
302 params_rate(params
));
305 ret
= snd_soc_dai_set_sysclk(dai
, AUD_CLK_A
,
306 freq
, SND_SOC_CLOCK_OUT
);
310 sub
->params
= *params
;
314 aio_port_set_volume(sub
, sub
->vol
);
320 static int uniphier_aio_hw_free(struct snd_pcm_substream
*substream
,
321 struct snd_soc_dai
*dai
)
323 struct uniphier_aio
*aio
= uniphier_priv(dai
);
324 struct uniphier_aio_sub
*sub
= &aio
->sub
[substream
->stream
];
331 static int uniphier_aio_prepare(struct snd_pcm_substream
*substream
,
332 struct snd_soc_dai
*dai
)
334 struct uniphier_aio
*aio
= uniphier_priv(dai
);
335 struct uniphier_aio_sub
*sub
= &aio
->sub
[substream
->stream
];
338 ret
= aio_port_set_param(sub
, sub
->pass_through
, &sub
->params
);
341 ret
= aio_src_set_param(sub
, &sub
->params
);
344 aio_port_set_enable(sub
, 1);
346 ret
= aio_if_set_param(sub
, sub
->pass_through
);
350 if (sub
->swm
->type
== PORT_TYPE_CONV
) {
351 ret
= aio_srcif_set_param(sub
);
354 ret
= aio_srcch_set_param(sub
);
357 aio_srcch_set_enable(sub
, 1);
363 const struct snd_soc_dai_ops uniphier_aio_i2s_ops
= {
364 .set_sysclk
= uniphier_aio_set_sysclk
,
365 .set_pll
= uniphier_aio_set_pll
,
366 .set_fmt
= uniphier_aio_set_fmt
,
367 .startup
= uniphier_aio_startup
,
368 .shutdown
= uniphier_aio_shutdown
,
369 .hw_params
= uniphier_aio_hw_params
,
370 .hw_free
= uniphier_aio_hw_free
,
371 .prepare
= uniphier_aio_prepare
,
373 EXPORT_SYMBOL_GPL(uniphier_aio_i2s_ops
);
375 const struct snd_soc_dai_ops uniphier_aio_spdif_ops
= {
376 .set_sysclk
= uniphier_aio_set_sysclk
,
377 .set_pll
= uniphier_aio_set_pll
,
378 .startup
= uniphier_aio_startup
,
379 .shutdown
= uniphier_aio_shutdown
,
380 .hw_params
= uniphier_aio_hw_params
,
381 .hw_free
= uniphier_aio_hw_free
,
382 .prepare
= uniphier_aio_prepare
,
384 EXPORT_SYMBOL_GPL(uniphier_aio_spdif_ops
);
386 int uniphier_aio_dai_probe(struct snd_soc_dai
*dai
)
388 struct uniphier_aio
*aio
= uniphier_priv(dai
);
391 for (i
= 0; i
< ARRAY_SIZE(aio
->sub
); i
++) {
392 struct uniphier_aio_sub
*sub
= &aio
->sub
[i
];
393 const struct uniphier_aio_spec
*spec
;
395 spec
= find_spec(aio
, dai
->name
, i
);
399 sub
->swm
= &spec
->swm
;
402 sub
->vol
= AUD_VOL_INIT
;
405 aio_iecout_set_enable(aio
->chip
, true);
406 aio_chip_init(aio
->chip
);
407 aio
->chip
->active
= 1;
411 EXPORT_SYMBOL_GPL(uniphier_aio_dai_probe
);
413 int uniphier_aio_dai_remove(struct snd_soc_dai
*dai
)
415 struct uniphier_aio
*aio
= uniphier_priv(dai
);
417 aio
->chip
->active
= 0;
421 EXPORT_SYMBOL_GPL(uniphier_aio_dai_remove
);
423 int uniphier_aio_dai_suspend(struct snd_soc_dai
*dai
)
425 struct uniphier_aio
*aio
= uniphier_priv(dai
);
427 aio
->chip
->num_wup_aios
--;
428 if (!aio
->chip
->num_wup_aios
) {
429 reset_control_assert(aio
->chip
->rst
);
430 clk_disable_unprepare(aio
->chip
->clk
);
435 EXPORT_SYMBOL_GPL(uniphier_aio_dai_suspend
);
437 int uniphier_aio_dai_resume(struct snd_soc_dai
*dai
)
439 struct uniphier_aio
*aio
= uniphier_priv(dai
);
442 if (!aio
->chip
->active
)
445 if (!aio
->chip
->num_wup_aios
) {
446 ret
= clk_prepare_enable(aio
->chip
->clk
);
450 ret
= reset_control_deassert(aio
->chip
->rst
);
455 aio_iecout_set_enable(aio
->chip
, true);
456 aio_chip_init(aio
->chip
);
458 for (i
= 0; i
< ARRAY_SIZE(aio
->sub
); i
++) {
459 struct uniphier_aio_sub
*sub
= &aio
->sub
[i
];
461 if (!sub
->spec
|| !sub
->substream
)
474 aio
->chip
->num_wup_aios
++;
479 if (!aio
->chip
->num_wup_aios
)
480 reset_control_assert(aio
->chip
->rst
);
482 if (!aio
->chip
->num_wup_aios
)
483 clk_disable_unprepare(aio
->chip
->clk
);
487 EXPORT_SYMBOL_GPL(uniphier_aio_dai_resume
);
489 static int uniphier_aio_vol_info(struct snd_kcontrol
*kcontrol
,
490 struct snd_ctl_elem_info
*uinfo
)
492 uinfo
->type
= SNDRV_CTL_ELEM_TYPE_INTEGER
;
494 uinfo
->value
.integer
.min
= 0;
495 uinfo
->value
.integer
.max
= AUD_VOL_MAX
;
500 static int uniphier_aio_vol_get(struct snd_kcontrol
*kcontrol
,
501 struct snd_ctl_elem_value
*ucontrol
)
503 struct snd_soc_component
*comp
= snd_soc_kcontrol_component(kcontrol
);
504 struct uniphier_aio_chip
*chip
= snd_soc_component_get_drvdata(comp
);
505 struct uniphier_aio_sub
*sub
;
506 int oport_hw
= kcontrol
->private_value
;
508 sub
= find_volume(chip
, oport_hw
);
512 ucontrol
->value
.integer
.value
[0] = sub
->vol
;
517 static int uniphier_aio_vol_put(struct snd_kcontrol
*kcontrol
,
518 struct snd_ctl_elem_value
*ucontrol
)
520 struct snd_soc_component
*comp
= snd_soc_kcontrol_component(kcontrol
);
521 struct uniphier_aio_chip
*chip
= snd_soc_component_get_drvdata(comp
);
522 struct uniphier_aio_sub
*sub
;
523 int oport_hw
= kcontrol
->private_value
;
525 sub
= find_volume(chip
, oport_hw
);
529 if (sub
->vol
== ucontrol
->value
.integer
.value
[0])
531 sub
->vol
= ucontrol
->value
.integer
.value
[0];
533 aio_port_set_volume(sub
, sub
->vol
);
538 static const struct snd_kcontrol_new uniphier_aio_controls
[] = {
540 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
541 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
,
542 .name
= "HPCMOUT1 Volume",
543 .info
= uniphier_aio_vol_info
,
544 .get
= uniphier_aio_vol_get
,
545 .put
= uniphier_aio_vol_put
,
546 .private_value
= AUD_HW_HPCMOUT1
,
549 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
550 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
,
551 .name
= "PCMOUT1 Volume",
552 .info
= uniphier_aio_vol_info
,
553 .get
= uniphier_aio_vol_get
,
554 .put
= uniphier_aio_vol_put
,
555 .private_value
= AUD_HW_PCMOUT1
,
558 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
559 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
,
560 .name
= "PCMOUT2 Volume",
561 .info
= uniphier_aio_vol_info
,
562 .get
= uniphier_aio_vol_get
,
563 .put
= uniphier_aio_vol_put
,
564 .private_value
= AUD_HW_PCMOUT2
,
567 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
568 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
,
569 .name
= "PCMOUT3 Volume",
570 .info
= uniphier_aio_vol_info
,
571 .get
= uniphier_aio_vol_get
,
572 .put
= uniphier_aio_vol_put
,
573 .private_value
= AUD_HW_PCMOUT3
,
576 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
577 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
,
578 .name
= "HIECOUT1 Volume",
579 .info
= uniphier_aio_vol_info
,
580 .get
= uniphier_aio_vol_get
,
581 .put
= uniphier_aio_vol_put
,
582 .private_value
= AUD_HW_HIECOUT1
,
585 .iface
= SNDRV_CTL_ELEM_IFACE_MIXER
,
586 .access
= SNDRV_CTL_ELEM_ACCESS_READWRITE
,
587 .name
= "IECOUT1 Volume",
588 .info
= uniphier_aio_vol_info
,
589 .get
= uniphier_aio_vol_get
,
590 .put
= uniphier_aio_vol_put
,
591 .private_value
= AUD_HW_IECOUT1
,
595 static const struct snd_soc_component_driver uniphier_aio_component
= {
596 .name
= "uniphier-aio",
597 .controls
= uniphier_aio_controls
,
598 .num_controls
= ARRAY_SIZE(uniphier_aio_controls
),
601 int uniphier_aio_probe(struct platform_device
*pdev
)
603 struct uniphier_aio_chip
*chip
;
604 struct device
*dev
= &pdev
->dev
;
607 chip
= devm_kzalloc(dev
, sizeof(*chip
), GFP_KERNEL
);
611 chip
->chip_spec
= of_device_get_match_data(dev
);
612 if (!chip
->chip_spec
)
615 chip
->regmap_sg
= syscon_regmap_lookup_by_phandle(dev
->of_node
,
617 if (IS_ERR(chip
->regmap_sg
)) {
618 if (PTR_ERR(chip
->regmap_sg
) == -EPROBE_DEFER
)
619 return -EPROBE_DEFER
;
620 chip
->regmap_sg
= NULL
;
623 chip
->clk
= devm_clk_get(dev
, "aio");
624 if (IS_ERR(chip
->clk
))
625 return PTR_ERR(chip
->clk
);
627 chip
->rst
= devm_reset_control_get_shared(dev
, "aio");
628 if (IS_ERR(chip
->rst
))
629 return PTR_ERR(chip
->rst
);
631 chip
->num_aios
= chip
->chip_spec
->num_dais
;
632 chip
->num_wup_aios
= chip
->num_aios
;
633 chip
->aios
= devm_kcalloc(dev
,
634 chip
->num_aios
, sizeof(struct uniphier_aio
),
639 chip
->num_plls
= chip
->chip_spec
->num_plls
;
640 chip
->plls
= devm_kcalloc(dev
,
642 sizeof(struct uniphier_aio_pll
),
646 memcpy(chip
->plls
, chip
->chip_spec
->plls
,
647 sizeof(struct uniphier_aio_pll
) * chip
->num_plls
);
649 for (i
= 0; i
< chip
->num_aios
; i
++) {
650 struct uniphier_aio
*aio
= &chip
->aios
[i
];
653 aio
->fmt
= SND_SOC_DAIFMT_I2S
;
655 for (j
= 0; j
< ARRAY_SIZE(aio
->sub
); j
++) {
656 struct uniphier_aio_sub
*sub
= &aio
->sub
[j
];
659 spin_lock_init(&sub
->lock
);
664 platform_set_drvdata(pdev
, chip
);
666 ret
= clk_prepare_enable(chip
->clk
);
670 ret
= reset_control_deassert(chip
->rst
);
674 ret
= devm_snd_soc_register_component(dev
, &uniphier_aio_component
,
675 chip
->chip_spec
->dais
,
676 chip
->chip_spec
->num_dais
);
678 dev_err(dev
, "Register component failed.\n");
682 ret
= uniphier_aiodma_soc_register_platform(pdev
);
684 dev_err(dev
, "Register platform failed.\n");
691 reset_control_assert(chip
->rst
);
694 clk_disable_unprepare(chip
->clk
);
698 EXPORT_SYMBOL_GPL(uniphier_aio_probe
);
700 int uniphier_aio_remove(struct platform_device
*pdev
)
702 struct uniphier_aio_chip
*chip
= platform_get_drvdata(pdev
);
704 reset_control_assert(chip
->rst
);
705 clk_disable_unprepare(chip
->clk
);
709 EXPORT_SYMBOL_GPL(uniphier_aio_remove
);
711 MODULE_AUTHOR("Katsuhiro Suzuki <suzuki.katsuhiro@socionext.com>");
712 MODULE_DESCRIPTION("UniPhier AIO CPU DAI driver.");
713 MODULE_LICENSE("GPL v2");