18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// Copyright (c) 2020 BayLibre, SAS. 48c2ecf20Sopenharmony_ci// Author: Jerome Brunet <jbrunet@baylibre.com> 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/bitfield.h> 78c2ecf20Sopenharmony_ci#include <linux/clk.h> 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/of_platform.h> 108c2ecf20Sopenharmony_ci#include <linux/regmap.h> 118c2ecf20Sopenharmony_ci#include <linux/reset.h> 128c2ecf20Sopenharmony_ci#include <sound/soc.h> 138c2ecf20Sopenharmony_ci#include <sound/soc-dai.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <dt-bindings/sound/meson-aiu.h> 168c2ecf20Sopenharmony_ci#include "aiu.h" 178c2ecf20Sopenharmony_ci#include "aiu-fifo.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define AIU_I2S_MISC_958_SRC_SHIFT 3 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic const char * const aiu_spdif_encode_sel_texts[] = { 228c2ecf20Sopenharmony_ci "SPDIF", "I2S", 238c2ecf20Sopenharmony_ci}; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(aiu_spdif_encode_sel_enum, AIU_I2S_MISC, 268c2ecf20Sopenharmony_ci AIU_I2S_MISC_958_SRC_SHIFT, 278c2ecf20Sopenharmony_ci aiu_spdif_encode_sel_texts); 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistatic const struct snd_kcontrol_new aiu_spdif_encode_mux = 308c2ecf20Sopenharmony_ci SOC_DAPM_ENUM("SPDIF Buffer Src", aiu_spdif_encode_sel_enum); 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_widget aiu_cpu_dapm_widgets[] = { 338c2ecf20Sopenharmony_ci SND_SOC_DAPM_MUX("SPDIF SRC SEL", SND_SOC_NOPM, 0, 0, 348c2ecf20Sopenharmony_ci &aiu_spdif_encode_mux), 358c2ecf20Sopenharmony_ci}; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic const struct snd_soc_dapm_route aiu_cpu_dapm_routes[] = { 388c2ecf20Sopenharmony_ci { "I2S Encoder Playback", NULL, "I2S FIFO Playback" }, 398c2ecf20Sopenharmony_ci { "SPDIF SRC SEL", "SPDIF", "SPDIF FIFO Playback" }, 408c2ecf20Sopenharmony_ci { "SPDIF SRC SEL", "I2S", "I2S FIFO Playback" }, 418c2ecf20Sopenharmony_ci { "SPDIF Encoder Playback", NULL, "SPDIF SRC SEL" }, 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ciint aiu_of_xlate_dai_name(struct snd_soc_component *component, 458c2ecf20Sopenharmony_ci struct of_phandle_args *args, 468c2ecf20Sopenharmony_ci const char **dai_name, 478c2ecf20Sopenharmony_ci unsigned int component_id) 488c2ecf20Sopenharmony_ci{ 498c2ecf20Sopenharmony_ci struct snd_soc_dai *dai; 508c2ecf20Sopenharmony_ci int id; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci if (args->args_count != 2) 538c2ecf20Sopenharmony_ci return -EINVAL; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci if (args->args[0] != component_id) 568c2ecf20Sopenharmony_ci return -EINVAL; 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci id = args->args[1]; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci if (id < 0 || id >= component->num_dai) 618c2ecf20Sopenharmony_ci return -EINVAL; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci for_each_component_dais(component, dai) { 648c2ecf20Sopenharmony_ci if (id == 0) 658c2ecf20Sopenharmony_ci break; 668c2ecf20Sopenharmony_ci id--; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci *dai_name = dai->driver->name; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci return 0; 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic int aiu_cpu_of_xlate_dai_name(struct snd_soc_component *component, 758c2ecf20Sopenharmony_ci struct of_phandle_args *args, 768c2ecf20Sopenharmony_ci const char **dai_name) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci return aiu_of_xlate_dai_name(component, args, dai_name, AIU_CPU); 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_cistatic int aiu_cpu_component_probe(struct snd_soc_component *component) 828c2ecf20Sopenharmony_ci{ 838c2ecf20Sopenharmony_ci struct aiu *aiu = snd_soc_component_get_drvdata(component); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci /* Required for the SPDIF Source control operation */ 868c2ecf20Sopenharmony_ci return clk_prepare_enable(aiu->i2s.clks[PCLK].clk); 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic void aiu_cpu_component_remove(struct snd_soc_component *component) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci struct aiu *aiu = snd_soc_component_get_drvdata(component); 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci clk_disable_unprepare(aiu->i2s.clks[PCLK].clk); 948c2ecf20Sopenharmony_ci} 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_cistatic const struct snd_soc_component_driver aiu_cpu_component = { 978c2ecf20Sopenharmony_ci .name = "AIU CPU", 988c2ecf20Sopenharmony_ci .dapm_widgets = aiu_cpu_dapm_widgets, 998c2ecf20Sopenharmony_ci .num_dapm_widgets = ARRAY_SIZE(aiu_cpu_dapm_widgets), 1008c2ecf20Sopenharmony_ci .dapm_routes = aiu_cpu_dapm_routes, 1018c2ecf20Sopenharmony_ci .num_dapm_routes = ARRAY_SIZE(aiu_cpu_dapm_routes), 1028c2ecf20Sopenharmony_ci .of_xlate_dai_name = aiu_cpu_of_xlate_dai_name, 1038c2ecf20Sopenharmony_ci .pointer = aiu_fifo_pointer, 1048c2ecf20Sopenharmony_ci .probe = aiu_cpu_component_probe, 1058c2ecf20Sopenharmony_ci .remove = aiu_cpu_component_remove, 1068c2ecf20Sopenharmony_ci}; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver aiu_cpu_dai_drv[] = { 1098c2ecf20Sopenharmony_ci [CPU_I2S_FIFO] = { 1108c2ecf20Sopenharmony_ci .name = "I2S FIFO", 1118c2ecf20Sopenharmony_ci .playback = { 1128c2ecf20Sopenharmony_ci .stream_name = "I2S FIFO Playback", 1138c2ecf20Sopenharmony_ci .channels_min = 2, 1148c2ecf20Sopenharmony_ci .channels_max = 8, 1158c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_CONTINUOUS, 1168c2ecf20Sopenharmony_ci .rate_min = 5512, 1178c2ecf20Sopenharmony_ci .rate_max = 192000, 1188c2ecf20Sopenharmony_ci .formats = AIU_FORMATS, 1198c2ecf20Sopenharmony_ci }, 1208c2ecf20Sopenharmony_ci .ops = &aiu_fifo_i2s_dai_ops, 1218c2ecf20Sopenharmony_ci .pcm_new = aiu_fifo_pcm_new, 1228c2ecf20Sopenharmony_ci .probe = aiu_fifo_i2s_dai_probe, 1238c2ecf20Sopenharmony_ci .remove = aiu_fifo_dai_remove, 1248c2ecf20Sopenharmony_ci }, 1258c2ecf20Sopenharmony_ci [CPU_SPDIF_FIFO] = { 1268c2ecf20Sopenharmony_ci .name = "SPDIF FIFO", 1278c2ecf20Sopenharmony_ci .playback = { 1288c2ecf20Sopenharmony_ci .stream_name = "SPDIF FIFO Playback", 1298c2ecf20Sopenharmony_ci .channels_min = 2, 1308c2ecf20Sopenharmony_ci .channels_max = 2, 1318c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_CONTINUOUS, 1328c2ecf20Sopenharmony_ci .rate_min = 5512, 1338c2ecf20Sopenharmony_ci .rate_max = 192000, 1348c2ecf20Sopenharmony_ci .formats = AIU_FORMATS, 1358c2ecf20Sopenharmony_ci }, 1368c2ecf20Sopenharmony_ci .ops = &aiu_fifo_spdif_dai_ops, 1378c2ecf20Sopenharmony_ci .pcm_new = aiu_fifo_pcm_new, 1388c2ecf20Sopenharmony_ci .probe = aiu_fifo_spdif_dai_probe, 1398c2ecf20Sopenharmony_ci .remove = aiu_fifo_dai_remove, 1408c2ecf20Sopenharmony_ci }, 1418c2ecf20Sopenharmony_ci [CPU_I2S_ENCODER] = { 1428c2ecf20Sopenharmony_ci .name = "I2S Encoder", 1438c2ecf20Sopenharmony_ci .playback = { 1448c2ecf20Sopenharmony_ci .stream_name = "I2S Encoder Playback", 1458c2ecf20Sopenharmony_ci .channels_min = 2, 1468c2ecf20Sopenharmony_ci .channels_max = 8, 1478c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_8000_192000, 1488c2ecf20Sopenharmony_ci .formats = AIU_FORMATS, 1498c2ecf20Sopenharmony_ci }, 1508c2ecf20Sopenharmony_ci .ops = &aiu_encoder_i2s_dai_ops, 1518c2ecf20Sopenharmony_ci }, 1528c2ecf20Sopenharmony_ci [CPU_SPDIF_ENCODER] = { 1538c2ecf20Sopenharmony_ci .name = "SPDIF Encoder", 1548c2ecf20Sopenharmony_ci .playback = { 1558c2ecf20Sopenharmony_ci .stream_name = "SPDIF Encoder Playback", 1568c2ecf20Sopenharmony_ci .channels_min = 2, 1578c2ecf20Sopenharmony_ci .channels_max = 2, 1588c2ecf20Sopenharmony_ci .rates = (SNDRV_PCM_RATE_32000 | 1598c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_44100 | 1608c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_48000 | 1618c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_88200 | 1628c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_96000 | 1638c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_176400 | 1648c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_192000), 1658c2ecf20Sopenharmony_ci .formats = AIU_FORMATS, 1668c2ecf20Sopenharmony_ci }, 1678c2ecf20Sopenharmony_ci .ops = &aiu_encoder_spdif_dai_ops, 1688c2ecf20Sopenharmony_ci } 1698c2ecf20Sopenharmony_ci}; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic const struct regmap_config aiu_regmap_cfg = { 1728c2ecf20Sopenharmony_ci .reg_bits = 32, 1738c2ecf20Sopenharmony_ci .val_bits = 32, 1748c2ecf20Sopenharmony_ci .reg_stride = 4, 1758c2ecf20Sopenharmony_ci .max_register = 0x2ac, 1768c2ecf20Sopenharmony_ci}; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic int aiu_clk_bulk_get(struct device *dev, 1798c2ecf20Sopenharmony_ci const char * const *ids, 1808c2ecf20Sopenharmony_ci unsigned int num, 1818c2ecf20Sopenharmony_ci struct aiu_interface *interface) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci struct clk_bulk_data *clks; 1848c2ecf20Sopenharmony_ci int i, ret; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci clks = devm_kcalloc(dev, num, sizeof(*clks), GFP_KERNEL); 1878c2ecf20Sopenharmony_ci if (!clks) 1888c2ecf20Sopenharmony_ci return -ENOMEM; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) 1918c2ecf20Sopenharmony_ci clks[i].id = ids[i]; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci ret = devm_clk_bulk_get(dev, num, clks); 1948c2ecf20Sopenharmony_ci if (ret < 0) 1958c2ecf20Sopenharmony_ci return ret; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci interface->clks = clks; 1988c2ecf20Sopenharmony_ci interface->clk_num = num; 1998c2ecf20Sopenharmony_ci return 0; 2008c2ecf20Sopenharmony_ci} 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cistatic const char * const aiu_i2s_ids[] = { 2038c2ecf20Sopenharmony_ci [PCLK] = "i2s_pclk", 2048c2ecf20Sopenharmony_ci [AOCLK] = "i2s_aoclk", 2058c2ecf20Sopenharmony_ci [MCLK] = "i2s_mclk", 2068c2ecf20Sopenharmony_ci [MIXER] = "i2s_mixer", 2078c2ecf20Sopenharmony_ci}; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_cistatic const char * const aiu_spdif_ids[] = { 2108c2ecf20Sopenharmony_ci [PCLK] = "spdif_pclk", 2118c2ecf20Sopenharmony_ci [AOCLK] = "spdif_aoclk", 2128c2ecf20Sopenharmony_ci [MCLK] = "spdif_mclk_sel" 2138c2ecf20Sopenharmony_ci}; 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int aiu_clk_get(struct device *dev) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci struct aiu *aiu = dev_get_drvdata(dev); 2188c2ecf20Sopenharmony_ci int ret; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci aiu->pclk = devm_clk_get(dev, "pclk"); 2218c2ecf20Sopenharmony_ci if (IS_ERR(aiu->pclk)) { 2228c2ecf20Sopenharmony_ci if (PTR_ERR(aiu->pclk) != -EPROBE_DEFER) 2238c2ecf20Sopenharmony_ci dev_err(dev, "Can't get the aiu pclk\n"); 2248c2ecf20Sopenharmony_ci return PTR_ERR(aiu->pclk); 2258c2ecf20Sopenharmony_ci } 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci aiu->spdif_mclk = devm_clk_get(dev, "spdif_mclk"); 2288c2ecf20Sopenharmony_ci if (IS_ERR(aiu->spdif_mclk)) { 2298c2ecf20Sopenharmony_ci if (PTR_ERR(aiu->spdif_mclk) != -EPROBE_DEFER) 2308c2ecf20Sopenharmony_ci dev_err(dev, "Can't get the aiu spdif master clock\n"); 2318c2ecf20Sopenharmony_ci return PTR_ERR(aiu->spdif_mclk); 2328c2ecf20Sopenharmony_ci } 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci ret = aiu_clk_bulk_get(dev, aiu_i2s_ids, ARRAY_SIZE(aiu_i2s_ids), 2358c2ecf20Sopenharmony_ci &aiu->i2s); 2368c2ecf20Sopenharmony_ci if (ret) { 2378c2ecf20Sopenharmony_ci if (ret != -EPROBE_DEFER) 2388c2ecf20Sopenharmony_ci dev_err(dev, "Can't get the i2s clocks\n"); 2398c2ecf20Sopenharmony_ci return ret; 2408c2ecf20Sopenharmony_ci } 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci ret = aiu_clk_bulk_get(dev, aiu_spdif_ids, ARRAY_SIZE(aiu_spdif_ids), 2438c2ecf20Sopenharmony_ci &aiu->spdif); 2448c2ecf20Sopenharmony_ci if (ret) { 2458c2ecf20Sopenharmony_ci if (ret != -EPROBE_DEFER) 2468c2ecf20Sopenharmony_ci dev_err(dev, "Can't get the spdif clocks\n"); 2478c2ecf20Sopenharmony_ci return ret; 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci ret = clk_prepare_enable(aiu->pclk); 2518c2ecf20Sopenharmony_ci if (ret) { 2528c2ecf20Sopenharmony_ci dev_err(dev, "peripheral clock enable failed\n"); 2538c2ecf20Sopenharmony_ci return ret; 2548c2ecf20Sopenharmony_ci } 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci ret = devm_add_action_or_reset(dev, 2578c2ecf20Sopenharmony_ci (void(*)(void *))clk_disable_unprepare, 2588c2ecf20Sopenharmony_ci aiu->pclk); 2598c2ecf20Sopenharmony_ci if (ret) 2608c2ecf20Sopenharmony_ci dev_err(dev, "failed to add reset action on pclk"); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci return ret; 2638c2ecf20Sopenharmony_ci} 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_cistatic int aiu_probe(struct platform_device *pdev) 2668c2ecf20Sopenharmony_ci{ 2678c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 2688c2ecf20Sopenharmony_ci void __iomem *regs; 2698c2ecf20Sopenharmony_ci struct regmap *map; 2708c2ecf20Sopenharmony_ci struct aiu *aiu; 2718c2ecf20Sopenharmony_ci int ret; 2728c2ecf20Sopenharmony_ci 2738c2ecf20Sopenharmony_ci aiu = devm_kzalloc(dev, sizeof(*aiu), GFP_KERNEL); 2748c2ecf20Sopenharmony_ci if (!aiu) 2758c2ecf20Sopenharmony_ci return -ENOMEM; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci aiu->platform = device_get_match_data(dev); 2788c2ecf20Sopenharmony_ci if (!aiu->platform) 2798c2ecf20Sopenharmony_ci return -ENODEV; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, aiu); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci ret = device_reset(dev); 2848c2ecf20Sopenharmony_ci if (ret) { 2858c2ecf20Sopenharmony_ci if (ret != -EPROBE_DEFER) 2868c2ecf20Sopenharmony_ci dev_err(dev, "Failed to reset device\n"); 2878c2ecf20Sopenharmony_ci return ret; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci regs = devm_platform_ioremap_resource(pdev, 0); 2918c2ecf20Sopenharmony_ci if (IS_ERR(regs)) 2928c2ecf20Sopenharmony_ci return PTR_ERR(regs); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci map = devm_regmap_init_mmio(dev, regs, &aiu_regmap_cfg); 2958c2ecf20Sopenharmony_ci if (IS_ERR(map)) { 2968c2ecf20Sopenharmony_ci dev_err(dev, "failed to init regmap: %ld\n", 2978c2ecf20Sopenharmony_ci PTR_ERR(map)); 2988c2ecf20Sopenharmony_ci return PTR_ERR(map); 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci aiu->i2s.irq = platform_get_irq_byname(pdev, "i2s"); 3028c2ecf20Sopenharmony_ci if (aiu->i2s.irq < 0) 3038c2ecf20Sopenharmony_ci return aiu->i2s.irq; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci aiu->spdif.irq = platform_get_irq_byname(pdev, "spdif"); 3068c2ecf20Sopenharmony_ci if (aiu->spdif.irq < 0) 3078c2ecf20Sopenharmony_ci return aiu->spdif.irq; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci ret = aiu_clk_get(dev); 3108c2ecf20Sopenharmony_ci if (ret) 3118c2ecf20Sopenharmony_ci return ret; 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci /* Register the cpu component of the aiu */ 3148c2ecf20Sopenharmony_ci ret = snd_soc_register_component(dev, &aiu_cpu_component, 3158c2ecf20Sopenharmony_ci aiu_cpu_dai_drv, 3168c2ecf20Sopenharmony_ci ARRAY_SIZE(aiu_cpu_dai_drv)); 3178c2ecf20Sopenharmony_ci if (ret) { 3188c2ecf20Sopenharmony_ci dev_err(dev, "Failed to register cpu component\n"); 3198c2ecf20Sopenharmony_ci return ret; 3208c2ecf20Sopenharmony_ci } 3218c2ecf20Sopenharmony_ci 3228c2ecf20Sopenharmony_ci /* Register the hdmi codec control component */ 3238c2ecf20Sopenharmony_ci ret = aiu_hdmi_ctrl_register_component(dev); 3248c2ecf20Sopenharmony_ci if (ret) { 3258c2ecf20Sopenharmony_ci dev_err(dev, "Failed to register hdmi control component\n"); 3268c2ecf20Sopenharmony_ci goto err; 3278c2ecf20Sopenharmony_ci } 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci /* Register the internal dac control component on gxl */ 3308c2ecf20Sopenharmony_ci if (aiu->platform->has_acodec) { 3318c2ecf20Sopenharmony_ci ret = aiu_acodec_ctrl_register_component(dev); 3328c2ecf20Sopenharmony_ci if (ret) { 3338c2ecf20Sopenharmony_ci dev_err(dev, 3348c2ecf20Sopenharmony_ci "Failed to register acodec control component\n"); 3358c2ecf20Sopenharmony_ci goto err; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci return 0; 3408c2ecf20Sopenharmony_cierr: 3418c2ecf20Sopenharmony_ci snd_soc_unregister_component(dev); 3428c2ecf20Sopenharmony_ci return ret; 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cistatic int aiu_remove(struct platform_device *pdev) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci snd_soc_unregister_component(&pdev->dev); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci return 0; 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistatic const struct aiu_platform_data aiu_gxbb_pdata = { 3538c2ecf20Sopenharmony_ci .has_acodec = false, 3548c2ecf20Sopenharmony_ci .has_clk_ctrl_more_i2s_div = true, 3558c2ecf20Sopenharmony_ci}; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_cistatic const struct aiu_platform_data aiu_gxl_pdata = { 3588c2ecf20Sopenharmony_ci .has_acodec = true, 3598c2ecf20Sopenharmony_ci .has_clk_ctrl_more_i2s_div = true, 3608c2ecf20Sopenharmony_ci}; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_cistatic const struct aiu_platform_data aiu_meson8_pdata = { 3638c2ecf20Sopenharmony_ci .has_acodec = false, 3648c2ecf20Sopenharmony_ci .has_clk_ctrl_more_i2s_div = false, 3658c2ecf20Sopenharmony_ci}; 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_cistatic const struct of_device_id aiu_of_match[] = { 3688c2ecf20Sopenharmony_ci { .compatible = "amlogic,aiu-gxbb", .data = &aiu_gxbb_pdata }, 3698c2ecf20Sopenharmony_ci { .compatible = "amlogic,aiu-gxl", .data = &aiu_gxl_pdata }, 3708c2ecf20Sopenharmony_ci { .compatible = "amlogic,aiu-meson8", .data = &aiu_meson8_pdata }, 3718c2ecf20Sopenharmony_ci { .compatible = "amlogic,aiu-meson8b", .data = &aiu_meson8_pdata }, 3728c2ecf20Sopenharmony_ci {} 3738c2ecf20Sopenharmony_ci}; 3748c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, aiu_of_match); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistatic struct platform_driver aiu_pdrv = { 3778c2ecf20Sopenharmony_ci .probe = aiu_probe, 3788c2ecf20Sopenharmony_ci .remove = aiu_remove, 3798c2ecf20Sopenharmony_ci .driver = { 3808c2ecf20Sopenharmony_ci .name = "meson-aiu", 3818c2ecf20Sopenharmony_ci .of_match_table = aiu_of_match, 3828c2ecf20Sopenharmony_ci }, 3838c2ecf20Sopenharmony_ci}; 3848c2ecf20Sopenharmony_cimodule_platform_driver(aiu_pdrv); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Meson AIU Driver"); 3878c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); 3888c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 389