Lines Matching +full:sun4i +full:- +full:a10 +full:- +full:cpu +full:- +full:clk

1 // SPDX-License-Identifier: GPL-2.0-or-later
5 * Copyright 2015 Maxime Ripard <maxime.ripard@free-electrons.com>
7 * Copyright 2016 Chen-Yu Tsai <wens@csie.org>
19 #include <linux/clk.h>
121 * sun6i shares the same digital control and FIFO registers as sun4i,
330 struct clk *clk_apb;
331 struct clk *clk_module;
347 regmap_field_set_bits(scodec->reg_dac_fifoc,
351 regmap_field_set_bits(scodec->reg_dac_fifoc,
358 regmap_field_clear_bits(scodec->reg_dac_fifoc,
365 regmap_field_set_bits(scodec->reg_adc_fifoc,
372 regmap_field_clear_bits(scodec->reg_adc_fifoc,
380 struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
386 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
395 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
402 return -EINVAL;
412 struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
416 regmap_field_set_bits(scodec->reg_adc_fifoc,
421 regmap_field_update_bits(scodec->reg_adc_fifoc,
430 if (of_device_is_compatible(scodec->dev->of_node,
431 "allwinner,sun4i-a10-codec") ||
432 of_device_is_compatible(scodec->dev->of_node,
433 "allwinner,sun7i-a20-codec")) {
434 regmap_update_bits(scodec->regmap, SUN4I_CODEC_ADC_ACTL,
439 if (of_device_is_compatible(scodec->dev->of_node,
440 "allwinner,sun7i-a20-codec"))
442 regmap_update_bits(scodec->regmap, SUN4I_CODEC_DAC_TUNE,
453 struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
457 regmap_field_set_bits(scodec->reg_dac_fifoc,
461 regmap_field_update_bits(scodec->reg_dac_fifoc,
465 if (substream->runtime->rate > 32000)
472 regmap_field_update_bits(scodec->reg_dac_fifoc,
477 regmap_field_clear_bits(scodec->reg_dac_fifoc,
486 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
560 return -EINVAL;
569 regmap_field_update_bits(scodec->reg_adc_fifoc,
575 regmap_field_set_bits(scodec->reg_adc_fifoc,
578 regmap_field_clear_bits(scodec->reg_adc_fifoc,
582 if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32) {
583 regmap_field_set_bits(scodec->reg_adc_fifoc,
586 regmap_field_clear_bits(scodec->reg_adc_fifoc,
589 scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
591 regmap_field_clear_bits(scodec->reg_adc_fifoc,
595 regmap_field_set_bits(scodec->reg_adc_fifoc,
598 scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
611 regmap_field_update_bits(scodec->reg_dac_fifoc,
621 regmap_field_update_bits(scodec->reg_dac_fifoc,
626 if (hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min == 32) {
627 regmap_field_set_bits(scodec->reg_dac_fifoc,
631 regmap_field_clear_bits(scodec->reg_dac_fifoc,
634 scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
636 regmap_field_clear_bits(scodec->reg_dac_fifoc,
640 regmap_field_set_bits(scodec->reg_dac_fifoc,
643 scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
654 struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
660 return -EINVAL;
662 ret = clk_set_rate(scodec->clk_module, clk_freq);
670 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
682 struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
688 regmap_field_set_bits(scodec->reg_dac_fifoc,
691 return clk_prepare_enable(scodec->clk_module);
698 struct sun4i_codec *scodec = snd_soc_card_get_drvdata(rtd->card);
700 clk_disable_unprepare(scodec->clk_module);
745 /*** sun4i Codec ***/
750 static DECLARE_TLV_DB_SCALE(sun4i_codec_pa_volume_scale, -6300, 100, 1);
751 static DECLARE_TLV_DB_SCALE(sun4i_codec_linein_loopback_gain_scale, -150, 150,
753 static DECLARE_TLV_DB_SCALE(sun4i_codec_linein_preamp_gain_scale, -1200, 300,
755 static DECLARE_TLV_DB_SCALE(sun4i_codec_fmin_loopback_gain_scale, -450, 150,
757 static DECLARE_TLV_DB_SCALE(sun4i_codec_micin_loopback_gain_scale, -450, 150,
884 /* Mic Pre-Amplifiers */
885 SND_SOC_DAPM_PGA("MIC1 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL,
887 SND_SOC_DAPM_PGA("MIC2 Pre-Amplifier", SUN4I_CODEC_ADC_ACTL,
924 { "Right Mixer", "Mic1 Playback Switch", "MIC1 Pre-Amplifier" },
925 { "Right Mixer", "Mic2 Playback Switch", "MIC2 Pre-Amplifier" },
932 { "Left Mixer", "Mic1 Playback Switch", "MIC1 Pre-Amplifier" },
933 { "Left Mixer", "Mic2 Playback Switch", "MIC2 Pre-Amplifier" },
947 { "Left ADC", NULL, "MIC1 Pre-Amplifier" },
948 { "Right ADC", NULL, "MIC1 Pre-Amplifier" },
949 { "MIC1 Pre-Amplifier", NULL, "Mic1"},
953 { "Left ADC", NULL, "MIC2 Pre-Amplifier" },
954 { "Right ADC", NULL, "MIC2 Pre-Amplifier" },
955 { "MIC2 Pre-Amplifier", NULL, "Mic2"},
1081 static const DECLARE_TLV_DB_SCALE(sun6i_codec_dvol_scale, -7308, 116, 0);
1082 static const DECLARE_TLV_DB_SCALE(sun6i_codec_hp_vol_scale, -6300, 100, 1);
1084 -450, 150, 0);
1087 2, 31, TLV_DB_SCALE_ITEM(-4350, 150, 0),
1114 /* Mixer pre-gains */
1377 static const DECLARE_TLV_DB_SCALE(suniv_codec_dvol_scale, -7308, 116, 0);
1378 static const DECLARE_TLV_DB_SCALE(suniv_codec_hp_vol_scale, -6300, 100, 1);
1380 -450, 150, 0);
1540 .name = "sun4i-codec",
1543 .debugfs_prefix = "cpu",
1555 snd_soc_dai_init_dma_data(dai, &scodec->playback_dma_data,
1556 &scodec->capture_dma_data);
1566 .name = "sun4i-codec-cpu-dai",
1596 link->cpus = &dlc[0];
1597 link->codecs = &dlc[1];
1598 link->platforms = &dlc[2];
1600 link->num_cpus = 1;
1601 link->num_codecs = 1;
1602 link->num_platforms = 1;
1604 link->name = "cdc";
1605 link->stream_name = "CDC PCM";
1606 link->codecs->dai_name = "Codec";
1607 link->cpus->dai_name = dev_name(dev);
1608 link->codecs->name = dev_name(dev);
1609 link->platforms->name = dev_name(dev);
1610 link->dai_fmt = SND_SOC_DAIFMT_I2S;
1620 struct sun4i_codec *scodec = snd_soc_card_get_drvdata(w->dapm->card);
1622 gpiod_set_value_cansleep(scodec->gpio_pa,
1652 return ERR_PTR(-ENOMEM);
1654 card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1655 if (!card->dai_link)
1656 return ERR_PTR(-ENOMEM);
1658 card->dev = dev;
1659 card->owner = THIS_MODULE;
1660 card->name = "sun4i-codec";
1661 card->dapm_widgets = sun4i_codec_card_dapm_widgets;
1662 card->num_dapm_widgets = ARRAY_SIZE(sun4i_codec_card_dapm_widgets);
1663 card->dapm_routes = sun4i_codec_card_dapm_routes;
1664 card->num_dapm_routes = ARRAY_SIZE(sun4i_codec_card_dapm_routes);
1685 return ERR_PTR(-ENOMEM);
1687 card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1688 if (!card->dai_link)
1689 return ERR_PTR(-ENOMEM);
1691 card->dev = dev;
1692 card->owner = THIS_MODULE;
1693 card->name = "A31 Audio Codec";
1694 card->dapm_widgets = sun6i_codec_card_dapm_widgets;
1695 card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1696 card->fully_routed = true;
1698 ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1700 dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1731 return ERR_PTR(-ENOMEM);
1733 aux_dev.dlc.of_node = of_parse_phandle(dev->of_node,
1734 "allwinner,codec-analog-controls",
1738 return ERR_PTR(-EINVAL);
1741 card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1742 if (!card->dai_link)
1743 return ERR_PTR(-ENOMEM);
1745 card->dev = dev;
1746 card->owner = THIS_MODULE;
1747 card->name = "A23 Audio Codec";
1748 card->dapm_widgets = sun6i_codec_card_dapm_widgets;
1749 card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1750 card->dapm_routes = sun8i_codec_card_routes;
1751 card->num_dapm_routes = ARRAY_SIZE(sun8i_codec_card_routes);
1752 card->aux_dev = &aux_dev;
1753 card->num_aux_devs = 1;
1754 card->fully_routed = true;
1756 ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1758 dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1770 return ERR_PTR(-ENOMEM);
1772 aux_dev.dlc.of_node = of_parse_phandle(dev->of_node,
1773 "allwinner,codec-analog-controls",
1777 return ERR_PTR(-EINVAL);
1780 card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1781 if (!card->dai_link)
1782 return ERR_PTR(-ENOMEM);
1784 card->dev = dev;
1785 card->owner = THIS_MODULE;
1786 card->name = "H3 Audio Codec";
1787 card->dapm_widgets = sun6i_codec_card_dapm_widgets;
1788 card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1789 card->dapm_routes = sun8i_codec_card_routes;
1790 card->num_dapm_routes = ARRAY_SIZE(sun8i_codec_card_routes);
1791 card->aux_dev = &aux_dev;
1792 card->num_aux_devs = 1;
1793 card->fully_routed = true;
1795 ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1797 dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1809 return ERR_PTR(-ENOMEM);
1811 aux_dev.dlc.of_node = of_parse_phandle(dev->of_node,
1812 "allwinner,codec-analog-controls",
1816 return ERR_PTR(-EINVAL);
1819 card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1820 if (!card->dai_link)
1821 return ERR_PTR(-ENOMEM);
1823 card->dev = dev;
1824 card->owner = THIS_MODULE;
1825 card->name = "V3s Audio Codec";
1826 card->dapm_widgets = sun6i_codec_card_dapm_widgets;
1827 card->num_dapm_widgets = ARRAY_SIZE(sun6i_codec_card_dapm_widgets);
1828 card->dapm_routes = sun8i_codec_card_routes;
1829 card->num_dapm_routes = ARRAY_SIZE(sun8i_codec_card_routes);
1830 card->aux_dev = &aux_dev;
1831 card->num_aux_devs = 1;
1832 card->fully_routed = true;
1834 ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1836 dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
1957 return ERR_PTR(-ENOMEM);
1959 card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
1960 if (!card->dai_link)
1961 return ERR_PTR(-ENOMEM);
1963 card->dai_link->playback_only = true;
1964 card->dai_link->capture_only = false;
1966 card->dev = dev;
1967 card->owner = THIS_MODULE;
1968 card->name = "H616 Audio Codec";
1969 card->driver_name = "sun4i-codec";
1970 card->controls = sun50i_h616_card_controls;
1971 card->num_controls = ARRAY_SIZE(sun50i_h616_card_controls);
1972 card->dapm_widgets = sun50i_h616_codec_card_dapm_widgets;
1973 card->num_dapm_widgets = ARRAY_SIZE(sun50i_h616_codec_card_dapm_widgets);
1974 card->dapm_routes = sun50i_h616_codec_card_routes;
1975 card->num_dapm_routes = ARRAY_SIZE(sun50i_h616_codec_card_routes);
1976 card->fully_routed = true;
1978 ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
1980 dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
2014 return ERR_PTR(-ENOMEM);
2016 card->dai_link = sun4i_codec_create_link(dev, &card->num_links);
2017 if (!card->dai_link)
2018 return ERR_PTR(-ENOMEM);
2020 card->dev = dev;
2021 card->name = "F1C100s Audio Codec";
2022 card->dapm_widgets = suniv_codec_card_dapm_widgets;
2023 card->num_dapm_widgets = ARRAY_SIZE(suniv_codec_card_dapm_widgets);
2024 card->dapm_routes = suniv_codec_card_routes;
2025 card->num_dapm_routes = ARRAY_SIZE(suniv_codec_card_routes);
2026 card->fully_routed = true;
2028 ret = snd_soc_of_parse_audio_routing(card, "allwinner,audio-routing");
2030 dev_warn(dev, "failed to parse audio-routing: %d\n", ret);
2208 .compatible = "allwinner,sun4i-a10-codec",
2212 .compatible = "allwinner,sun6i-a31-codec",
2216 .compatible = "allwinner,sun7i-a20-codec",
2220 .compatible = "allwinner,sun8i-a23-codec",
2224 .compatible = "allwinner,sun8i-h3-codec",
2228 .compatible = "allwinner,sun8i-v3s-codec",
2232 .compatible = "allwinner,sun50i-h616-codec",
2236 .compatible = "allwinner,suniv-f1c100s-codec",
2252 scodec = devm_kzalloc(&pdev->dev, sizeof(*scodec), GFP_KERNEL);
2254 return -ENOMEM;
2256 scodec->dev = &pdev->dev;
2262 quirks = of_device_get_match_data(&pdev->dev);
2264 dev_err(&pdev->dev, "Failed to determine the quirks to use\n");
2265 return -ENODEV;
2268 scodec->regmap = devm_regmap_init_mmio(&pdev->dev, base,
2269 quirks->regmap_config);
2270 if (IS_ERR(scodec->regmap)) {
2271 dev_err(&pdev->dev, "Failed to create our regmap\n");
2272 return PTR_ERR(scodec->regmap);
2276 scodec->clk_apb = devm_clk_get_enabled(&pdev->dev, "apb");
2277 if (IS_ERR(scodec->clk_apb)) {
2278 dev_err(&pdev->dev, "Failed to get the APB clock\n");
2279 return PTR_ERR(scodec->clk_apb);
2282 scodec->clk_module = devm_clk_get(&pdev->dev, "codec");
2283 if (IS_ERR(scodec->clk_module)) {
2284 dev_err(&pdev->dev, "Failed to get the module clock\n");
2285 return PTR_ERR(scodec->clk_module);
2288 if (quirks->has_reset) {
2289 scodec->rst = devm_reset_control_get_exclusive_deasserted(&pdev->dev, NULL);
2290 if (IS_ERR(scodec->rst)) {
2291 dev_err(&pdev->dev, "Failed to get reset control\n");
2292 return PTR_ERR(scodec->rst);
2296 scodec->gpio_pa = devm_gpiod_get_optional(&pdev->dev, "allwinner,pa",
2298 if (IS_ERR(scodec->gpio_pa)) {
2299 ret = PTR_ERR(scodec->gpio_pa);
2300 dev_err_probe(&pdev->dev, ret, "Failed to get pa gpio\n");
2305 scodec->reg_adc_fifoc = devm_regmap_field_alloc(&pdev->dev,
2306 scodec->regmap,
2307 quirks->reg_adc_fifoc);
2308 if (IS_ERR(scodec->reg_adc_fifoc)) {
2309 ret = PTR_ERR(scodec->reg_adc_fifoc);
2310 dev_err(&pdev->dev, "Failed to create regmap fields: %d\n",
2315 scodec->reg_dac_fifoc = devm_regmap_field_alloc(&pdev->dev,
2316 scodec->regmap,
2317 quirks->reg_dac_fifoc);
2318 if (IS_ERR(scodec->reg_dac_fifoc)) {
2319 ret = PTR_ERR(scodec->reg_dac_fifoc);
2320 dev_err(&pdev->dev, "Failed to create regmap fields: %d\n",
2326 scodec->playback_dma_data.addr = res->start + quirks->reg_dac_txdata;
2327 scodec->playback_dma_data.maxburst = quirks->dma_max_burst;
2328 scodec->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
2330 if (!quirks->playback_only) {
2332 scodec->capture_dma_data.addr = res->start +
2333 quirks->reg_adc_rxdata;
2334 scodec->capture_dma_data.maxburst = quirks->dma_max_burst;
2335 scodec->capture_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
2338 ret = devm_snd_soc_register_component(&pdev->dev, quirks->codec,
2341 dev_err(&pdev->dev, "Failed to register our codec\n");
2345 ret = devm_snd_soc_register_component(&pdev->dev,
2349 dev_err(&pdev->dev, "Failed to register our DAI\n");
2353 ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
2355 dev_err(&pdev->dev, "Failed to register against DMAEngine\n");
2359 card = quirks->create_card(&pdev->dev);
2362 dev_err(&pdev->dev, "Failed to create our card\n");
2370 dev_err_probe(&pdev->dev, ret, "Failed to register our card\n");
2386 .name = "sun4i-codec",
2394 MODULE_DESCRIPTION("Allwinner A10 codec driver");
2397 MODULE_AUTHOR("Maxime Ripard <maxime.ripard@free-electrons.com>");
2398 MODULE_AUTHOR("Chen-Yu Tsai <wens@csie.org>");