xref: /OK3568_Linux_fs/kernel/sound/soc/meson/aiu.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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