16ae9ca9cSJerome Brunet // SPDX-License-Identifier: GPL-2.0 26ae9ca9cSJerome Brunet // 36ae9ca9cSJerome Brunet // Copyright (c) 2020 BayLibre, SAS. 46ae9ca9cSJerome Brunet // Author: Jerome Brunet <jbrunet@baylibre.com> 56ae9ca9cSJerome Brunet 66ae9ca9cSJerome Brunet #include <linux/bitfield.h> 76ae9ca9cSJerome Brunet #include <linux/clk.h> 86ae9ca9cSJerome Brunet #include <linux/module.h> 96ae9ca9cSJerome Brunet #include <linux/of_platform.h> 106ae9ca9cSJerome Brunet #include <linux/regmap.h> 116ae9ca9cSJerome Brunet #include <linux/reset.h> 126ae9ca9cSJerome Brunet #include <sound/soc.h> 136ae9ca9cSJerome Brunet #include <sound/soc-dai.h> 146ae9ca9cSJerome Brunet 156ae9ca9cSJerome Brunet #include <dt-bindings/sound/meson-aiu.h> 166ae9ca9cSJerome Brunet #include "aiu.h" 176ae9ca9cSJerome Brunet #include "aiu-fifo.h" 186ae9ca9cSJerome Brunet 196ae9ca9cSJerome Brunet #define AIU_I2S_MISC_958_SRC_SHIFT 3 206ae9ca9cSJerome Brunet 216ae9ca9cSJerome Brunet static const char * const aiu_spdif_encode_sel_texts[] = { 226ae9ca9cSJerome Brunet "SPDIF", "I2S", 236ae9ca9cSJerome Brunet }; 246ae9ca9cSJerome Brunet 256ae9ca9cSJerome Brunet static SOC_ENUM_SINGLE_DECL(aiu_spdif_encode_sel_enum, AIU_I2S_MISC, 266ae9ca9cSJerome Brunet AIU_I2S_MISC_958_SRC_SHIFT, 276ae9ca9cSJerome Brunet aiu_spdif_encode_sel_texts); 286ae9ca9cSJerome Brunet 296ae9ca9cSJerome Brunet static const struct snd_kcontrol_new aiu_spdif_encode_mux = 306ae9ca9cSJerome Brunet SOC_DAPM_ENUM("SPDIF Buffer Src", aiu_spdif_encode_sel_enum); 316ae9ca9cSJerome Brunet 326ae9ca9cSJerome Brunet static const struct snd_soc_dapm_widget aiu_cpu_dapm_widgets[] = { 336ae9ca9cSJerome Brunet SND_SOC_DAPM_MUX("SPDIF SRC SEL", SND_SOC_NOPM, 0, 0, 346ae9ca9cSJerome Brunet &aiu_spdif_encode_mux), 356ae9ca9cSJerome Brunet }; 366ae9ca9cSJerome Brunet 376ae9ca9cSJerome Brunet static const struct snd_soc_dapm_route aiu_cpu_dapm_routes[] = { 386ae9ca9cSJerome Brunet { "I2S Encoder Playback", NULL, "I2S FIFO Playback" }, 396ae9ca9cSJerome Brunet { "SPDIF SRC SEL", "SPDIF", "SPDIF FIFO Playback" }, 406ae9ca9cSJerome Brunet { "SPDIF SRC SEL", "I2S", "I2S FIFO Playback" }, 416ae9ca9cSJerome Brunet { "SPDIF Encoder Playback", NULL, "SPDIF SRC SEL" }, 426ae9ca9cSJerome Brunet }; 436ae9ca9cSJerome Brunet 446ae9ca9cSJerome Brunet int aiu_of_xlate_dai_name(struct snd_soc_component *component, 45*933f98beSKrzysztof Kozlowski const struct of_phandle_args *args, 466ae9ca9cSJerome Brunet const char **dai_name, 476ae9ca9cSJerome Brunet unsigned int component_id) 486ae9ca9cSJerome Brunet { 496ae9ca9cSJerome Brunet struct snd_soc_dai *dai; 506ae9ca9cSJerome Brunet int id; 516ae9ca9cSJerome Brunet 526ae9ca9cSJerome Brunet if (args->args_count != 2) 536ae9ca9cSJerome Brunet return -EINVAL; 546ae9ca9cSJerome Brunet 556ae9ca9cSJerome Brunet if (args->args[0] != component_id) 566ae9ca9cSJerome Brunet return -EINVAL; 576ae9ca9cSJerome Brunet 586ae9ca9cSJerome Brunet id = args->args[1]; 596ae9ca9cSJerome Brunet 606ae9ca9cSJerome Brunet if (id < 0 || id >= component->num_dai) 616ae9ca9cSJerome Brunet return -EINVAL; 626ae9ca9cSJerome Brunet 636ae9ca9cSJerome Brunet for_each_component_dais(component, dai) { 646ae9ca9cSJerome Brunet if (id == 0) 656ae9ca9cSJerome Brunet break; 666ae9ca9cSJerome Brunet id--; 676ae9ca9cSJerome Brunet } 686ae9ca9cSJerome Brunet 696ae9ca9cSJerome Brunet *dai_name = dai->driver->name; 706ae9ca9cSJerome Brunet 716ae9ca9cSJerome Brunet return 0; 726ae9ca9cSJerome Brunet } 736ae9ca9cSJerome Brunet 746ae9ca9cSJerome Brunet static int aiu_cpu_of_xlate_dai_name(struct snd_soc_component *component, 75*933f98beSKrzysztof Kozlowski const struct of_phandle_args *args, 766ae9ca9cSJerome Brunet const char **dai_name) 776ae9ca9cSJerome Brunet { 786ae9ca9cSJerome Brunet return aiu_of_xlate_dai_name(component, args, dai_name, AIU_CPU); 796ae9ca9cSJerome Brunet } 806ae9ca9cSJerome Brunet 816ae9ca9cSJerome Brunet static int aiu_cpu_component_probe(struct snd_soc_component *component) 826ae9ca9cSJerome Brunet { 836ae9ca9cSJerome Brunet struct aiu *aiu = snd_soc_component_get_drvdata(component); 846ae9ca9cSJerome Brunet 856ae9ca9cSJerome Brunet /* Required for the SPDIF Source control operation */ 866ae9ca9cSJerome Brunet return clk_prepare_enable(aiu->i2s.clks[PCLK].clk); 876ae9ca9cSJerome Brunet } 886ae9ca9cSJerome Brunet 896ae9ca9cSJerome Brunet static void aiu_cpu_component_remove(struct snd_soc_component *component) 906ae9ca9cSJerome Brunet { 916ae9ca9cSJerome Brunet struct aiu *aiu = snd_soc_component_get_drvdata(component); 926ae9ca9cSJerome Brunet 936ae9ca9cSJerome Brunet clk_disable_unprepare(aiu->i2s.clks[PCLK].clk); 946ae9ca9cSJerome Brunet } 956ae9ca9cSJerome Brunet 966ae9ca9cSJerome Brunet static const struct snd_soc_component_driver aiu_cpu_component = { 976ae9ca9cSJerome Brunet .name = "AIU CPU", 986ae9ca9cSJerome Brunet .dapm_widgets = aiu_cpu_dapm_widgets, 996ae9ca9cSJerome Brunet .num_dapm_widgets = ARRAY_SIZE(aiu_cpu_dapm_widgets), 1006ae9ca9cSJerome Brunet .dapm_routes = aiu_cpu_dapm_routes, 1016ae9ca9cSJerome Brunet .num_dapm_routes = ARRAY_SIZE(aiu_cpu_dapm_routes), 1026ae9ca9cSJerome Brunet .of_xlate_dai_name = aiu_cpu_of_xlate_dai_name, 1036ae9ca9cSJerome Brunet .pointer = aiu_fifo_pointer, 1046ae9ca9cSJerome Brunet .probe = aiu_cpu_component_probe, 1056ae9ca9cSJerome Brunet .remove = aiu_cpu_component_remove, 1066ae9ca9cSJerome Brunet }; 1076ae9ca9cSJerome Brunet 1086ae9ca9cSJerome Brunet static struct snd_soc_dai_driver aiu_cpu_dai_drv[] = { 1096ae9ca9cSJerome Brunet [CPU_I2S_FIFO] = { 1106ae9ca9cSJerome Brunet .name = "I2S FIFO", 1116ae9ca9cSJerome Brunet .playback = { 1126ae9ca9cSJerome Brunet .stream_name = "I2S FIFO Playback", 1136ae9ca9cSJerome Brunet .channels_min = 2, 1146ae9ca9cSJerome Brunet .channels_max = 8, 1156ae9ca9cSJerome Brunet .rates = SNDRV_PCM_RATE_CONTINUOUS, 1166ae9ca9cSJerome Brunet .rate_min = 5512, 1176ae9ca9cSJerome Brunet .rate_max = 192000, 1186ae9ca9cSJerome Brunet .formats = AIU_FORMATS, 1196ae9ca9cSJerome Brunet }, 1206ae9ca9cSJerome Brunet .ops = &aiu_fifo_i2s_dai_ops, 1216ae9ca9cSJerome Brunet .pcm_new = aiu_fifo_pcm_new, 1226ae9ca9cSJerome Brunet .probe = aiu_fifo_i2s_dai_probe, 1236ae9ca9cSJerome Brunet .remove = aiu_fifo_dai_remove, 1246ae9ca9cSJerome Brunet }, 1256ae9ca9cSJerome Brunet [CPU_SPDIF_FIFO] = { 1266ae9ca9cSJerome Brunet .name = "SPDIF FIFO", 1276ae9ca9cSJerome Brunet .playback = { 1286ae9ca9cSJerome Brunet .stream_name = "SPDIF FIFO Playback", 1296ae9ca9cSJerome Brunet .channels_min = 2, 1306ae9ca9cSJerome Brunet .channels_max = 2, 1316ae9ca9cSJerome Brunet .rates = SNDRV_PCM_RATE_CONTINUOUS, 1326ae9ca9cSJerome Brunet .rate_min = 5512, 1336ae9ca9cSJerome Brunet .rate_max = 192000, 1346ae9ca9cSJerome Brunet .formats = AIU_FORMATS, 1356ae9ca9cSJerome Brunet }, 1366ae9ca9cSJerome Brunet .ops = &aiu_fifo_spdif_dai_ops, 1376ae9ca9cSJerome Brunet .pcm_new = aiu_fifo_pcm_new, 1386ae9ca9cSJerome Brunet .probe = aiu_fifo_spdif_dai_probe, 1396ae9ca9cSJerome Brunet .remove = aiu_fifo_dai_remove, 1406ae9ca9cSJerome Brunet }, 1416ae9ca9cSJerome Brunet [CPU_I2S_ENCODER] = { 1426ae9ca9cSJerome Brunet .name = "I2S Encoder", 1436ae9ca9cSJerome Brunet .playback = { 1446ae9ca9cSJerome Brunet .stream_name = "I2S Encoder Playback", 1456ae9ca9cSJerome Brunet .channels_min = 2, 1466ae9ca9cSJerome Brunet .channels_max = 8, 1476ae9ca9cSJerome Brunet .rates = SNDRV_PCM_RATE_8000_192000, 1486ae9ca9cSJerome Brunet .formats = AIU_FORMATS, 1496ae9ca9cSJerome Brunet }, 1506ae9ca9cSJerome Brunet .ops = &aiu_encoder_i2s_dai_ops, 1516ae9ca9cSJerome Brunet }, 1526ae9ca9cSJerome Brunet [CPU_SPDIF_ENCODER] = { 1536ae9ca9cSJerome Brunet .name = "SPDIF Encoder", 1546ae9ca9cSJerome Brunet .playback = { 1556ae9ca9cSJerome Brunet .stream_name = "SPDIF Encoder Playback", 1566ae9ca9cSJerome Brunet .channels_min = 2, 1576ae9ca9cSJerome Brunet .channels_max = 2, 1586ae9ca9cSJerome Brunet .rates = (SNDRV_PCM_RATE_32000 | 1596ae9ca9cSJerome Brunet SNDRV_PCM_RATE_44100 | 1606ae9ca9cSJerome Brunet SNDRV_PCM_RATE_48000 | 1616ae9ca9cSJerome Brunet SNDRV_PCM_RATE_88200 | 1626ae9ca9cSJerome Brunet SNDRV_PCM_RATE_96000 | 1636ae9ca9cSJerome Brunet SNDRV_PCM_RATE_176400 | 1646ae9ca9cSJerome Brunet SNDRV_PCM_RATE_192000), 1656ae9ca9cSJerome Brunet .formats = AIU_FORMATS, 1666ae9ca9cSJerome Brunet }, 1676ae9ca9cSJerome Brunet .ops = &aiu_encoder_spdif_dai_ops, 1686ae9ca9cSJerome Brunet } 1696ae9ca9cSJerome Brunet }; 1706ae9ca9cSJerome Brunet 1716ae9ca9cSJerome Brunet static const struct regmap_config aiu_regmap_cfg = { 1726ae9ca9cSJerome Brunet .reg_bits = 32, 1736ae9ca9cSJerome Brunet .val_bits = 32, 1746ae9ca9cSJerome Brunet .reg_stride = 4, 1756ae9ca9cSJerome Brunet .max_register = 0x2ac, 1766ae9ca9cSJerome Brunet }; 1776ae9ca9cSJerome Brunet 1786ae9ca9cSJerome Brunet static int aiu_clk_bulk_get(struct device *dev, 1796ae9ca9cSJerome Brunet const char * const *ids, 1806ae9ca9cSJerome Brunet unsigned int num, 1816ae9ca9cSJerome Brunet struct aiu_interface *interface) 1826ae9ca9cSJerome Brunet { 1836ae9ca9cSJerome Brunet struct clk_bulk_data *clks; 1846ae9ca9cSJerome Brunet int i, ret; 1856ae9ca9cSJerome Brunet 186269f0017SJerome Brunet clks = devm_kcalloc(dev, num, sizeof(*clks), GFP_KERNEL); 1876ae9ca9cSJerome Brunet if (!clks) 1886ae9ca9cSJerome Brunet return -ENOMEM; 1896ae9ca9cSJerome Brunet 1906ae9ca9cSJerome Brunet for (i = 0; i < num; i++) 1916ae9ca9cSJerome Brunet clks[i].id = ids[i]; 1926ae9ca9cSJerome Brunet 1936ae9ca9cSJerome Brunet ret = devm_clk_bulk_get(dev, num, clks); 1946ae9ca9cSJerome Brunet if (ret < 0) 1956ae9ca9cSJerome Brunet return ret; 1966ae9ca9cSJerome Brunet 1976ae9ca9cSJerome Brunet interface->clks = clks; 1986ae9ca9cSJerome Brunet interface->clk_num = num; 1996ae9ca9cSJerome Brunet return 0; 2006ae9ca9cSJerome Brunet } 2016ae9ca9cSJerome Brunet 2026ae9ca9cSJerome Brunet static const char * const aiu_i2s_ids[] = { 2036ae9ca9cSJerome Brunet [PCLK] = "i2s_pclk", 2046ae9ca9cSJerome Brunet [AOCLK] = "i2s_aoclk", 2056ae9ca9cSJerome Brunet [MCLK] = "i2s_mclk", 2066ae9ca9cSJerome Brunet [MIXER] = "i2s_mixer", 2076ae9ca9cSJerome Brunet }; 2086ae9ca9cSJerome Brunet 2096ae9ca9cSJerome Brunet static const char * const aiu_spdif_ids[] = { 2106ae9ca9cSJerome Brunet [PCLK] = "spdif_pclk", 2116ae9ca9cSJerome Brunet [AOCLK] = "spdif_aoclk", 2126ae9ca9cSJerome Brunet [MCLK] = "spdif_mclk_sel" 2136ae9ca9cSJerome Brunet }; 2146ae9ca9cSJerome Brunet 2156ae9ca9cSJerome Brunet static int aiu_clk_get(struct device *dev) 2166ae9ca9cSJerome Brunet { 2176ae9ca9cSJerome Brunet struct aiu *aiu = dev_get_drvdata(dev); 2186ae9ca9cSJerome Brunet int ret; 2196ae9ca9cSJerome Brunet 2206ae9ca9cSJerome Brunet aiu->pclk = devm_clk_get(dev, "pclk"); 2216ae9ca9cSJerome Brunet if (IS_ERR(aiu->pclk)) { 2226ae9ca9cSJerome Brunet if (PTR_ERR(aiu->pclk) != -EPROBE_DEFER) 2236ae9ca9cSJerome Brunet dev_err(dev, "Can't get the aiu pclk\n"); 2246ae9ca9cSJerome Brunet return PTR_ERR(aiu->pclk); 2256ae9ca9cSJerome Brunet } 2266ae9ca9cSJerome Brunet 2276ae9ca9cSJerome Brunet aiu->spdif_mclk = devm_clk_get(dev, "spdif_mclk"); 2286ae9ca9cSJerome Brunet if (IS_ERR(aiu->spdif_mclk)) { 2296ae9ca9cSJerome Brunet if (PTR_ERR(aiu->spdif_mclk) != -EPROBE_DEFER) 2306ae9ca9cSJerome Brunet dev_err(dev, "Can't get the aiu spdif master clock\n"); 2316ae9ca9cSJerome Brunet return PTR_ERR(aiu->spdif_mclk); 2326ae9ca9cSJerome Brunet } 2336ae9ca9cSJerome Brunet 2346ae9ca9cSJerome Brunet ret = aiu_clk_bulk_get(dev, aiu_i2s_ids, ARRAY_SIZE(aiu_i2s_ids), 2356ae9ca9cSJerome Brunet &aiu->i2s); 2366ae9ca9cSJerome Brunet if (ret) { 2376ae9ca9cSJerome Brunet if (ret != -EPROBE_DEFER) 2386ae9ca9cSJerome Brunet dev_err(dev, "Can't get the i2s clocks\n"); 2396ae9ca9cSJerome Brunet return ret; 2406ae9ca9cSJerome Brunet } 2416ae9ca9cSJerome Brunet 2426ae9ca9cSJerome Brunet ret = aiu_clk_bulk_get(dev, aiu_spdif_ids, ARRAY_SIZE(aiu_spdif_ids), 2436ae9ca9cSJerome Brunet &aiu->spdif); 2446ae9ca9cSJerome Brunet if (ret) { 2456ae9ca9cSJerome Brunet if (ret != -EPROBE_DEFER) 2466ae9ca9cSJerome Brunet dev_err(dev, "Can't get the spdif clocks\n"); 2476ae9ca9cSJerome Brunet return ret; 2486ae9ca9cSJerome Brunet } 2496ae9ca9cSJerome Brunet 2506ae9ca9cSJerome Brunet ret = clk_prepare_enable(aiu->pclk); 2516ae9ca9cSJerome Brunet if (ret) { 2526ae9ca9cSJerome Brunet dev_err(dev, "peripheral clock enable failed\n"); 2536ae9ca9cSJerome Brunet return ret; 2546ae9ca9cSJerome Brunet } 2556ae9ca9cSJerome Brunet 2566ae9ca9cSJerome Brunet ret = devm_add_action_or_reset(dev, 2576ae9ca9cSJerome Brunet (void(*)(void *))clk_disable_unprepare, 2586ae9ca9cSJerome Brunet aiu->pclk); 2596ae9ca9cSJerome Brunet if (ret) 2606ae9ca9cSJerome Brunet dev_err(dev, "failed to add reset action on pclk"); 2616ae9ca9cSJerome Brunet 2626ae9ca9cSJerome Brunet return ret; 2636ae9ca9cSJerome Brunet } 2646ae9ca9cSJerome Brunet 2656ae9ca9cSJerome Brunet static int aiu_probe(struct platform_device *pdev) 2666ae9ca9cSJerome Brunet { 2676ae9ca9cSJerome Brunet struct device *dev = &pdev->dev; 2686ae9ca9cSJerome Brunet void __iomem *regs; 2696ae9ca9cSJerome Brunet struct regmap *map; 2706ae9ca9cSJerome Brunet struct aiu *aiu; 2716ae9ca9cSJerome Brunet int ret; 2726ae9ca9cSJerome Brunet 2736ae9ca9cSJerome Brunet aiu = devm_kzalloc(dev, sizeof(*aiu), GFP_KERNEL); 2746ae9ca9cSJerome Brunet if (!aiu) 2756ae9ca9cSJerome Brunet return -ENOMEM; 276edc76180SMartin Blumenstingl 277edc76180SMartin Blumenstingl aiu->platform = device_get_match_data(dev); 278edc76180SMartin Blumenstingl if (!aiu->platform) 279edc76180SMartin Blumenstingl return -ENODEV; 280edc76180SMartin Blumenstingl 2816ae9ca9cSJerome Brunet platform_set_drvdata(pdev, aiu); 2826ae9ca9cSJerome Brunet 2836ae9ca9cSJerome Brunet ret = device_reset(dev); 2846ae9ca9cSJerome Brunet if (ret) { 2856ae9ca9cSJerome Brunet if (ret != -EPROBE_DEFER) 2866ae9ca9cSJerome Brunet dev_err(dev, "Failed to reset device\n"); 2876ae9ca9cSJerome Brunet return ret; 2886ae9ca9cSJerome Brunet } 2896ae9ca9cSJerome Brunet 2906ae9ca9cSJerome Brunet regs = devm_platform_ioremap_resource(pdev, 0); 2916ae9ca9cSJerome Brunet if (IS_ERR(regs)) 2926ae9ca9cSJerome Brunet return PTR_ERR(regs); 2936ae9ca9cSJerome Brunet 2946ae9ca9cSJerome Brunet map = devm_regmap_init_mmio(dev, regs, &aiu_regmap_cfg); 2956ae9ca9cSJerome Brunet if (IS_ERR(map)) { 2966ae9ca9cSJerome Brunet dev_err(dev, "failed to init regmap: %ld\n", 2976ae9ca9cSJerome Brunet PTR_ERR(map)); 2986ae9ca9cSJerome Brunet return PTR_ERR(map); 2996ae9ca9cSJerome Brunet } 3006ae9ca9cSJerome Brunet 3016ae9ca9cSJerome Brunet aiu->i2s.irq = platform_get_irq_byname(pdev, "i2s"); 3026e700f06SJerome Brunet if (aiu->i2s.irq < 0) 3036ae9ca9cSJerome Brunet return aiu->i2s.irq; 3046ae9ca9cSJerome Brunet 3056ae9ca9cSJerome Brunet aiu->spdif.irq = platform_get_irq_byname(pdev, "spdif"); 3066e700f06SJerome Brunet if (aiu->spdif.irq < 0) 3076ae9ca9cSJerome Brunet return aiu->spdif.irq; 3086ae9ca9cSJerome Brunet 3096ae9ca9cSJerome Brunet ret = aiu_clk_get(dev); 3106ae9ca9cSJerome Brunet if (ret) 3116ae9ca9cSJerome Brunet return ret; 3126ae9ca9cSJerome Brunet 3136ae9ca9cSJerome Brunet /* Register the cpu component of the aiu */ 3146ae9ca9cSJerome Brunet ret = snd_soc_register_component(dev, &aiu_cpu_component, 3156ae9ca9cSJerome Brunet aiu_cpu_dai_drv, 3166ae9ca9cSJerome Brunet ARRAY_SIZE(aiu_cpu_dai_drv)); 317b82b734cSJerome Brunet if (ret) { 3186ae9ca9cSJerome Brunet dev_err(dev, "Failed to register cpu component\n"); 319b82b734cSJerome Brunet return ret; 320b82b734cSJerome Brunet } 3216ae9ca9cSJerome Brunet 322b82b734cSJerome Brunet /* Register the hdmi codec control component */ 323b82b734cSJerome Brunet ret = aiu_hdmi_ctrl_register_component(dev); 324b82b734cSJerome Brunet if (ret) { 325b82b734cSJerome Brunet dev_err(dev, "Failed to register hdmi control component\n"); 326b82b734cSJerome Brunet goto err; 327b82b734cSJerome Brunet } 328b82b734cSJerome Brunet 32965816025SJerome Brunet /* Register the internal dac control component on gxl */ 330edc76180SMartin Blumenstingl if (aiu->platform->has_acodec) { 33165816025SJerome Brunet ret = aiu_acodec_ctrl_register_component(dev); 33265816025SJerome Brunet if (ret) { 33365816025SJerome Brunet dev_err(dev, 33465816025SJerome Brunet "Failed to register acodec control component\n"); 33565816025SJerome Brunet goto err; 33665816025SJerome Brunet } 33765816025SJerome Brunet } 33865816025SJerome Brunet 339b82b734cSJerome Brunet return 0; 340b82b734cSJerome Brunet err: 341b82b734cSJerome Brunet snd_soc_unregister_component(dev); 3426ae9ca9cSJerome Brunet return ret; 3436ae9ca9cSJerome Brunet } 3446ae9ca9cSJerome Brunet 3456ae9ca9cSJerome Brunet static int aiu_remove(struct platform_device *pdev) 3466ae9ca9cSJerome Brunet { 3476ae9ca9cSJerome Brunet snd_soc_unregister_component(&pdev->dev); 3486ae9ca9cSJerome Brunet 3496ae9ca9cSJerome Brunet return 0; 3506ae9ca9cSJerome Brunet } 3516ae9ca9cSJerome Brunet 352edc76180SMartin Blumenstingl static const struct aiu_platform_data aiu_gxbb_pdata = { 353edc76180SMartin Blumenstingl .has_acodec = false, 3543e25c445SMartin Blumenstingl .has_clk_ctrl_more_i2s_div = true, 355edc76180SMartin Blumenstingl }; 356edc76180SMartin Blumenstingl 357edc76180SMartin Blumenstingl static const struct aiu_platform_data aiu_gxl_pdata = { 358edc76180SMartin Blumenstingl .has_acodec = true, 3593e25c445SMartin Blumenstingl .has_clk_ctrl_more_i2s_div = true, 3603e25c445SMartin Blumenstingl }; 3613e25c445SMartin Blumenstingl 3623e25c445SMartin Blumenstingl static const struct aiu_platform_data aiu_meson8_pdata = { 3633e25c445SMartin Blumenstingl .has_acodec = false, 3643e25c445SMartin Blumenstingl .has_clk_ctrl_more_i2s_div = false, 365edc76180SMartin Blumenstingl }; 366edc76180SMartin Blumenstingl 3676ae9ca9cSJerome Brunet static const struct of_device_id aiu_of_match[] = { 368edc76180SMartin Blumenstingl { .compatible = "amlogic,aiu-gxbb", .data = &aiu_gxbb_pdata }, 369edc76180SMartin Blumenstingl { .compatible = "amlogic,aiu-gxl", .data = &aiu_gxl_pdata }, 3703e25c445SMartin Blumenstingl { .compatible = "amlogic,aiu-meson8", .data = &aiu_meson8_pdata }, 3713e25c445SMartin Blumenstingl { .compatible = "amlogic,aiu-meson8b", .data = &aiu_meson8_pdata }, 3726ae9ca9cSJerome Brunet {} 3736ae9ca9cSJerome Brunet }; 3746ae9ca9cSJerome Brunet MODULE_DEVICE_TABLE(of, aiu_of_match); 3756ae9ca9cSJerome Brunet 3766ae9ca9cSJerome Brunet static struct platform_driver aiu_pdrv = { 3776ae9ca9cSJerome Brunet .probe = aiu_probe, 3786ae9ca9cSJerome Brunet .remove = aiu_remove, 3796ae9ca9cSJerome Brunet .driver = { 3806ae9ca9cSJerome Brunet .name = "meson-aiu", 3816ae9ca9cSJerome Brunet .of_match_table = aiu_of_match, 3826ae9ca9cSJerome Brunet }, 3836ae9ca9cSJerome Brunet }; 3846ae9ca9cSJerome Brunet module_platform_driver(aiu_pdrv); 3856ae9ca9cSJerome Brunet 3866ae9ca9cSJerome Brunet MODULE_DESCRIPTION("Meson AIU Driver"); 3876ae9ca9cSJerome Brunet MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>"); 3886ae9ca9cSJerome Brunet MODULE_LICENSE("GPL v2"); 389