1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun //
3*4882a593Smuzhiyun // Copyright (c) 2020 BayLibre, SAS.
4*4882a593Smuzhiyun // Author: Jerome Brunet <jbrunet@baylibre.com>
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <linux/bitfield.h>
7*4882a593Smuzhiyun #include <linux/clk.h>
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/of_platform.h>
10*4882a593Smuzhiyun #include <linux/regmap.h>
11*4882a593Smuzhiyun #include <linux/reset.h>
12*4882a593Smuzhiyun #include <sound/soc.h>
13*4882a593Smuzhiyun #include <sound/soc-dai.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #include <dt-bindings/sound/meson-aiu.h>
16*4882a593Smuzhiyun #include "aiu.h"
17*4882a593Smuzhiyun #include "aiu-fifo.h"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #define AIU_I2S_MISC_958_SRC_SHIFT 3
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun static const char * const aiu_spdif_encode_sel_texts[] = {
22*4882a593Smuzhiyun "SPDIF", "I2S",
23*4882a593Smuzhiyun };
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun static SOC_ENUM_SINGLE_DECL(aiu_spdif_encode_sel_enum, AIU_I2S_MISC,
26*4882a593Smuzhiyun AIU_I2S_MISC_958_SRC_SHIFT,
27*4882a593Smuzhiyun aiu_spdif_encode_sel_texts);
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun static const struct snd_kcontrol_new aiu_spdif_encode_mux =
30*4882a593Smuzhiyun SOC_DAPM_ENUM("SPDIF Buffer Src", aiu_spdif_encode_sel_enum);
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun static const struct snd_soc_dapm_widget aiu_cpu_dapm_widgets[] = {
33*4882a593Smuzhiyun SND_SOC_DAPM_MUX("SPDIF SRC SEL", SND_SOC_NOPM, 0, 0,
34*4882a593Smuzhiyun &aiu_spdif_encode_mux),
35*4882a593Smuzhiyun };
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun static const struct snd_soc_dapm_route aiu_cpu_dapm_routes[] = {
38*4882a593Smuzhiyun { "I2S Encoder Playback", NULL, "I2S FIFO Playback" },
39*4882a593Smuzhiyun { "SPDIF SRC SEL", "SPDIF", "SPDIF FIFO Playback" },
40*4882a593Smuzhiyun { "SPDIF SRC SEL", "I2S", "I2S FIFO Playback" },
41*4882a593Smuzhiyun { "SPDIF Encoder Playback", NULL, "SPDIF SRC SEL" },
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun
aiu_of_xlate_dai_name(struct snd_soc_component * component,struct of_phandle_args * args,const char ** dai_name,unsigned int component_id)44*4882a593Smuzhiyun int aiu_of_xlate_dai_name(struct snd_soc_component *component,
45*4882a593Smuzhiyun struct of_phandle_args *args,
46*4882a593Smuzhiyun const char **dai_name,
47*4882a593Smuzhiyun unsigned int component_id)
48*4882a593Smuzhiyun {
49*4882a593Smuzhiyun struct snd_soc_dai *dai;
50*4882a593Smuzhiyun int id;
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun if (args->args_count != 2)
53*4882a593Smuzhiyun return -EINVAL;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun if (args->args[0] != component_id)
56*4882a593Smuzhiyun return -EINVAL;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun id = args->args[1];
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun if (id < 0 || id >= component->num_dai)
61*4882a593Smuzhiyun return -EINVAL;
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun for_each_component_dais(component, dai) {
64*4882a593Smuzhiyun if (id == 0)
65*4882a593Smuzhiyun break;
66*4882a593Smuzhiyun id--;
67*4882a593Smuzhiyun }
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun *dai_name = dai->driver->name;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun return 0;
72*4882a593Smuzhiyun }
73*4882a593Smuzhiyun
aiu_cpu_of_xlate_dai_name(struct snd_soc_component * component,struct of_phandle_args * args,const char ** dai_name)74*4882a593Smuzhiyun static int aiu_cpu_of_xlate_dai_name(struct snd_soc_component *component,
75*4882a593Smuzhiyun struct of_phandle_args *args,
76*4882a593Smuzhiyun const char **dai_name)
77*4882a593Smuzhiyun {
78*4882a593Smuzhiyun return aiu_of_xlate_dai_name(component, args, dai_name, AIU_CPU);
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun
aiu_cpu_component_probe(struct snd_soc_component * component)81*4882a593Smuzhiyun static int aiu_cpu_component_probe(struct snd_soc_component *component)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun struct aiu *aiu = snd_soc_component_get_drvdata(component);
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /* Required for the SPDIF Source control operation */
86*4882a593Smuzhiyun return clk_prepare_enable(aiu->i2s.clks[PCLK].clk);
87*4882a593Smuzhiyun }
88*4882a593Smuzhiyun
aiu_cpu_component_remove(struct snd_soc_component * component)89*4882a593Smuzhiyun static void aiu_cpu_component_remove(struct snd_soc_component *component)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun struct aiu *aiu = snd_soc_component_get_drvdata(component);
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun clk_disable_unprepare(aiu->i2s.clks[PCLK].clk);
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun static const struct snd_soc_component_driver aiu_cpu_component = {
97*4882a593Smuzhiyun .name = "AIU CPU",
98*4882a593Smuzhiyun .dapm_widgets = aiu_cpu_dapm_widgets,
99*4882a593Smuzhiyun .num_dapm_widgets = ARRAY_SIZE(aiu_cpu_dapm_widgets),
100*4882a593Smuzhiyun .dapm_routes = aiu_cpu_dapm_routes,
101*4882a593Smuzhiyun .num_dapm_routes = ARRAY_SIZE(aiu_cpu_dapm_routes),
102*4882a593Smuzhiyun .of_xlate_dai_name = aiu_cpu_of_xlate_dai_name,
103*4882a593Smuzhiyun .pointer = aiu_fifo_pointer,
104*4882a593Smuzhiyun .probe = aiu_cpu_component_probe,
105*4882a593Smuzhiyun .remove = aiu_cpu_component_remove,
106*4882a593Smuzhiyun };
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun static struct snd_soc_dai_driver aiu_cpu_dai_drv[] = {
109*4882a593Smuzhiyun [CPU_I2S_FIFO] = {
110*4882a593Smuzhiyun .name = "I2S FIFO",
111*4882a593Smuzhiyun .playback = {
112*4882a593Smuzhiyun .stream_name = "I2S FIFO Playback",
113*4882a593Smuzhiyun .channels_min = 2,
114*4882a593Smuzhiyun .channels_max = 8,
115*4882a593Smuzhiyun .rates = SNDRV_PCM_RATE_CONTINUOUS,
116*4882a593Smuzhiyun .rate_min = 5512,
117*4882a593Smuzhiyun .rate_max = 192000,
118*4882a593Smuzhiyun .formats = AIU_FORMATS,
119*4882a593Smuzhiyun },
120*4882a593Smuzhiyun .ops = &aiu_fifo_i2s_dai_ops,
121*4882a593Smuzhiyun .pcm_new = aiu_fifo_pcm_new,
122*4882a593Smuzhiyun .probe = aiu_fifo_i2s_dai_probe,
123*4882a593Smuzhiyun .remove = aiu_fifo_dai_remove,
124*4882a593Smuzhiyun },
125*4882a593Smuzhiyun [CPU_SPDIF_FIFO] = {
126*4882a593Smuzhiyun .name = "SPDIF FIFO",
127*4882a593Smuzhiyun .playback = {
128*4882a593Smuzhiyun .stream_name = "SPDIF FIFO Playback",
129*4882a593Smuzhiyun .channels_min = 2,
130*4882a593Smuzhiyun .channels_max = 2,
131*4882a593Smuzhiyun .rates = SNDRV_PCM_RATE_CONTINUOUS,
132*4882a593Smuzhiyun .rate_min = 5512,
133*4882a593Smuzhiyun .rate_max = 192000,
134*4882a593Smuzhiyun .formats = AIU_FORMATS,
135*4882a593Smuzhiyun },
136*4882a593Smuzhiyun .ops = &aiu_fifo_spdif_dai_ops,
137*4882a593Smuzhiyun .pcm_new = aiu_fifo_pcm_new,
138*4882a593Smuzhiyun .probe = aiu_fifo_spdif_dai_probe,
139*4882a593Smuzhiyun .remove = aiu_fifo_dai_remove,
140*4882a593Smuzhiyun },
141*4882a593Smuzhiyun [CPU_I2S_ENCODER] = {
142*4882a593Smuzhiyun .name = "I2S Encoder",
143*4882a593Smuzhiyun .playback = {
144*4882a593Smuzhiyun .stream_name = "I2S Encoder Playback",
145*4882a593Smuzhiyun .channels_min = 2,
146*4882a593Smuzhiyun .channels_max = 8,
147*4882a593Smuzhiyun .rates = SNDRV_PCM_RATE_8000_192000,
148*4882a593Smuzhiyun .formats = AIU_FORMATS,
149*4882a593Smuzhiyun },
150*4882a593Smuzhiyun .ops = &aiu_encoder_i2s_dai_ops,
151*4882a593Smuzhiyun },
152*4882a593Smuzhiyun [CPU_SPDIF_ENCODER] = {
153*4882a593Smuzhiyun .name = "SPDIF Encoder",
154*4882a593Smuzhiyun .playback = {
155*4882a593Smuzhiyun .stream_name = "SPDIF Encoder Playback",
156*4882a593Smuzhiyun .channels_min = 2,
157*4882a593Smuzhiyun .channels_max = 2,
158*4882a593Smuzhiyun .rates = (SNDRV_PCM_RATE_32000 |
159*4882a593Smuzhiyun SNDRV_PCM_RATE_44100 |
160*4882a593Smuzhiyun SNDRV_PCM_RATE_48000 |
161*4882a593Smuzhiyun SNDRV_PCM_RATE_88200 |
162*4882a593Smuzhiyun SNDRV_PCM_RATE_96000 |
163*4882a593Smuzhiyun SNDRV_PCM_RATE_176400 |
164*4882a593Smuzhiyun SNDRV_PCM_RATE_192000),
165*4882a593Smuzhiyun .formats = AIU_FORMATS,
166*4882a593Smuzhiyun },
167*4882a593Smuzhiyun .ops = &aiu_encoder_spdif_dai_ops,
168*4882a593Smuzhiyun }
169*4882a593Smuzhiyun };
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun static const struct regmap_config aiu_regmap_cfg = {
172*4882a593Smuzhiyun .reg_bits = 32,
173*4882a593Smuzhiyun .val_bits = 32,
174*4882a593Smuzhiyun .reg_stride = 4,
175*4882a593Smuzhiyun .max_register = 0x2ac,
176*4882a593Smuzhiyun };
177*4882a593Smuzhiyun
aiu_clk_bulk_get(struct device * dev,const char * const * ids,unsigned int num,struct aiu_interface * interface)178*4882a593Smuzhiyun static int aiu_clk_bulk_get(struct device *dev,
179*4882a593Smuzhiyun const char * const *ids,
180*4882a593Smuzhiyun unsigned int num,
181*4882a593Smuzhiyun struct aiu_interface *interface)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun struct clk_bulk_data *clks;
184*4882a593Smuzhiyun int i, ret;
185*4882a593Smuzhiyun
186*4882a593Smuzhiyun clks = devm_kcalloc(dev, num, sizeof(*clks), GFP_KERNEL);
187*4882a593Smuzhiyun if (!clks)
188*4882a593Smuzhiyun return -ENOMEM;
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun for (i = 0; i < num; i++)
191*4882a593Smuzhiyun clks[i].id = ids[i];
192*4882a593Smuzhiyun
193*4882a593Smuzhiyun ret = devm_clk_bulk_get(dev, num, clks);
194*4882a593Smuzhiyun if (ret < 0)
195*4882a593Smuzhiyun return ret;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun interface->clks = clks;
198*4882a593Smuzhiyun interface->clk_num = num;
199*4882a593Smuzhiyun return 0;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun static const char * const aiu_i2s_ids[] = {
203*4882a593Smuzhiyun [PCLK] = "i2s_pclk",
204*4882a593Smuzhiyun [AOCLK] = "i2s_aoclk",
205*4882a593Smuzhiyun [MCLK] = "i2s_mclk",
206*4882a593Smuzhiyun [MIXER] = "i2s_mixer",
207*4882a593Smuzhiyun };
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun static const char * const aiu_spdif_ids[] = {
210*4882a593Smuzhiyun [PCLK] = "spdif_pclk",
211*4882a593Smuzhiyun [AOCLK] = "spdif_aoclk",
212*4882a593Smuzhiyun [MCLK] = "spdif_mclk_sel"
213*4882a593Smuzhiyun };
214*4882a593Smuzhiyun
aiu_clk_get(struct device * dev)215*4882a593Smuzhiyun static int aiu_clk_get(struct device *dev)
216*4882a593Smuzhiyun {
217*4882a593Smuzhiyun struct aiu *aiu = dev_get_drvdata(dev);
218*4882a593Smuzhiyun int ret;
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun aiu->pclk = devm_clk_get(dev, "pclk");
221*4882a593Smuzhiyun if (IS_ERR(aiu->pclk)) {
222*4882a593Smuzhiyun if (PTR_ERR(aiu->pclk) != -EPROBE_DEFER)
223*4882a593Smuzhiyun dev_err(dev, "Can't get the aiu pclk\n");
224*4882a593Smuzhiyun return PTR_ERR(aiu->pclk);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun aiu->spdif_mclk = devm_clk_get(dev, "spdif_mclk");
228*4882a593Smuzhiyun if (IS_ERR(aiu->spdif_mclk)) {
229*4882a593Smuzhiyun if (PTR_ERR(aiu->spdif_mclk) != -EPROBE_DEFER)
230*4882a593Smuzhiyun dev_err(dev, "Can't get the aiu spdif master clock\n");
231*4882a593Smuzhiyun return PTR_ERR(aiu->spdif_mclk);
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun ret = aiu_clk_bulk_get(dev, aiu_i2s_ids, ARRAY_SIZE(aiu_i2s_ids),
235*4882a593Smuzhiyun &aiu->i2s);
236*4882a593Smuzhiyun if (ret) {
237*4882a593Smuzhiyun if (ret != -EPROBE_DEFER)
238*4882a593Smuzhiyun dev_err(dev, "Can't get the i2s clocks\n");
239*4882a593Smuzhiyun return ret;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun
242*4882a593Smuzhiyun ret = aiu_clk_bulk_get(dev, aiu_spdif_ids, ARRAY_SIZE(aiu_spdif_ids),
243*4882a593Smuzhiyun &aiu->spdif);
244*4882a593Smuzhiyun if (ret) {
245*4882a593Smuzhiyun if (ret != -EPROBE_DEFER)
246*4882a593Smuzhiyun dev_err(dev, "Can't get the spdif clocks\n");
247*4882a593Smuzhiyun return ret;
248*4882a593Smuzhiyun }
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun ret = clk_prepare_enable(aiu->pclk);
251*4882a593Smuzhiyun if (ret) {
252*4882a593Smuzhiyun dev_err(dev, "peripheral clock enable failed\n");
253*4882a593Smuzhiyun return ret;
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun ret = devm_add_action_or_reset(dev,
257*4882a593Smuzhiyun (void(*)(void *))clk_disable_unprepare,
258*4882a593Smuzhiyun aiu->pclk);
259*4882a593Smuzhiyun if (ret)
260*4882a593Smuzhiyun dev_err(dev, "failed to add reset action on pclk");
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun return ret;
263*4882a593Smuzhiyun }
264*4882a593Smuzhiyun
aiu_probe(struct platform_device * pdev)265*4882a593Smuzhiyun static int aiu_probe(struct platform_device *pdev)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun struct device *dev = &pdev->dev;
268*4882a593Smuzhiyun void __iomem *regs;
269*4882a593Smuzhiyun struct regmap *map;
270*4882a593Smuzhiyun struct aiu *aiu;
271*4882a593Smuzhiyun int ret;
272*4882a593Smuzhiyun
273*4882a593Smuzhiyun aiu = devm_kzalloc(dev, sizeof(*aiu), GFP_KERNEL);
274*4882a593Smuzhiyun if (!aiu)
275*4882a593Smuzhiyun return -ENOMEM;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun aiu->platform = device_get_match_data(dev);
278*4882a593Smuzhiyun if (!aiu->platform)
279*4882a593Smuzhiyun return -ENODEV;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun platform_set_drvdata(pdev, aiu);
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun ret = device_reset(dev);
284*4882a593Smuzhiyun if (ret) {
285*4882a593Smuzhiyun if (ret != -EPROBE_DEFER)
286*4882a593Smuzhiyun dev_err(dev, "Failed to reset device\n");
287*4882a593Smuzhiyun return ret;
288*4882a593Smuzhiyun }
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun regs = devm_platform_ioremap_resource(pdev, 0);
291*4882a593Smuzhiyun if (IS_ERR(regs))
292*4882a593Smuzhiyun return PTR_ERR(regs);
293*4882a593Smuzhiyun
294*4882a593Smuzhiyun map = devm_regmap_init_mmio(dev, regs, &aiu_regmap_cfg);
295*4882a593Smuzhiyun if (IS_ERR(map)) {
296*4882a593Smuzhiyun dev_err(dev, "failed to init regmap: %ld\n",
297*4882a593Smuzhiyun PTR_ERR(map));
298*4882a593Smuzhiyun return PTR_ERR(map);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun aiu->i2s.irq = platform_get_irq_byname(pdev, "i2s");
302*4882a593Smuzhiyun if (aiu->i2s.irq < 0)
303*4882a593Smuzhiyun return aiu->i2s.irq;
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun aiu->spdif.irq = platform_get_irq_byname(pdev, "spdif");
306*4882a593Smuzhiyun if (aiu->spdif.irq < 0)
307*4882a593Smuzhiyun return aiu->spdif.irq;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun ret = aiu_clk_get(dev);
310*4882a593Smuzhiyun if (ret)
311*4882a593Smuzhiyun return ret;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun /* Register the cpu component of the aiu */
314*4882a593Smuzhiyun ret = snd_soc_register_component(dev, &aiu_cpu_component,
315*4882a593Smuzhiyun aiu_cpu_dai_drv,
316*4882a593Smuzhiyun ARRAY_SIZE(aiu_cpu_dai_drv));
317*4882a593Smuzhiyun if (ret) {
318*4882a593Smuzhiyun dev_err(dev, "Failed to register cpu component\n");
319*4882a593Smuzhiyun return ret;
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun /* Register the hdmi codec control component */
323*4882a593Smuzhiyun ret = aiu_hdmi_ctrl_register_component(dev);
324*4882a593Smuzhiyun if (ret) {
325*4882a593Smuzhiyun dev_err(dev, "Failed to register hdmi control component\n");
326*4882a593Smuzhiyun goto err;
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun /* Register the internal dac control component on gxl */
330*4882a593Smuzhiyun if (aiu->platform->has_acodec) {
331*4882a593Smuzhiyun ret = aiu_acodec_ctrl_register_component(dev);
332*4882a593Smuzhiyun if (ret) {
333*4882a593Smuzhiyun dev_err(dev,
334*4882a593Smuzhiyun "Failed to register acodec control component\n");
335*4882a593Smuzhiyun goto err;
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun return 0;
340*4882a593Smuzhiyun err:
341*4882a593Smuzhiyun snd_soc_unregister_component(dev);
342*4882a593Smuzhiyun return ret;
343*4882a593Smuzhiyun }
344*4882a593Smuzhiyun
aiu_remove(struct platform_device * pdev)345*4882a593Smuzhiyun static int aiu_remove(struct platform_device *pdev)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun snd_soc_unregister_component(&pdev->dev);
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun return 0;
350*4882a593Smuzhiyun }
351*4882a593Smuzhiyun
352*4882a593Smuzhiyun static const struct aiu_platform_data aiu_gxbb_pdata = {
353*4882a593Smuzhiyun .has_acodec = false,
354*4882a593Smuzhiyun .has_clk_ctrl_more_i2s_div = true,
355*4882a593Smuzhiyun };
356*4882a593Smuzhiyun
357*4882a593Smuzhiyun static const struct aiu_platform_data aiu_gxl_pdata = {
358*4882a593Smuzhiyun .has_acodec = true,
359*4882a593Smuzhiyun .has_clk_ctrl_more_i2s_div = true,
360*4882a593Smuzhiyun };
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun static const struct aiu_platform_data aiu_meson8_pdata = {
363*4882a593Smuzhiyun .has_acodec = false,
364*4882a593Smuzhiyun .has_clk_ctrl_more_i2s_div = false,
365*4882a593Smuzhiyun };
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun static const struct of_device_id aiu_of_match[] = {
368*4882a593Smuzhiyun { .compatible = "amlogic,aiu-gxbb", .data = &aiu_gxbb_pdata },
369*4882a593Smuzhiyun { .compatible = "amlogic,aiu-gxl", .data = &aiu_gxl_pdata },
370*4882a593Smuzhiyun { .compatible = "amlogic,aiu-meson8", .data = &aiu_meson8_pdata },
371*4882a593Smuzhiyun { .compatible = "amlogic,aiu-meson8b", .data = &aiu_meson8_pdata },
372*4882a593Smuzhiyun {}
373*4882a593Smuzhiyun };
374*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, aiu_of_match);
375*4882a593Smuzhiyun
376*4882a593Smuzhiyun static struct platform_driver aiu_pdrv = {
377*4882a593Smuzhiyun .probe = aiu_probe,
378*4882a593Smuzhiyun .remove = aiu_remove,
379*4882a593Smuzhiyun .driver = {
380*4882a593Smuzhiyun .name = "meson-aiu",
381*4882a593Smuzhiyun .of_match_table = aiu_of_match,
382*4882a593Smuzhiyun },
383*4882a593Smuzhiyun };
384*4882a593Smuzhiyun module_platform_driver(aiu_pdrv);
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun MODULE_DESCRIPTION("Meson AIU Driver");
387*4882a593Smuzhiyun MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
388*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
389