xref: /kernel/linux/linux-6.6/sound/soc/meson/aiu.c (revision 62306a36)
162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci//
362306a36Sopenharmony_ci// Copyright (c) 2020 BayLibre, SAS.
462306a36Sopenharmony_ci// Author: Jerome Brunet <jbrunet@baylibre.com>
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/bitfield.h>
762306a36Sopenharmony_ci#include <linux/clk.h>
862306a36Sopenharmony_ci#include <linux/module.h>
962306a36Sopenharmony_ci#include <linux/of_platform.h>
1062306a36Sopenharmony_ci#include <linux/regmap.h>
1162306a36Sopenharmony_ci#include <linux/reset.h>
1262306a36Sopenharmony_ci#include <sound/soc.h>
1362306a36Sopenharmony_ci#include <sound/soc-dai.h>
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <dt-bindings/sound/meson-aiu.h>
1662306a36Sopenharmony_ci#include "aiu.h"
1762306a36Sopenharmony_ci#include "aiu-fifo.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#define AIU_I2S_MISC_958_SRC_SHIFT 3
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic const char * const aiu_spdif_encode_sel_texts[] = {
2262306a36Sopenharmony_ci	"SPDIF", "I2S",
2362306a36Sopenharmony_ci};
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_cistatic SOC_ENUM_SINGLE_DECL(aiu_spdif_encode_sel_enum, AIU_I2S_MISC,
2662306a36Sopenharmony_ci			    AIU_I2S_MISC_958_SRC_SHIFT,
2762306a36Sopenharmony_ci			    aiu_spdif_encode_sel_texts);
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic const struct snd_kcontrol_new aiu_spdif_encode_mux =
3062306a36Sopenharmony_ci	SOC_DAPM_ENUM("SPDIF Buffer Src", aiu_spdif_encode_sel_enum);
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_cistatic const struct snd_soc_dapm_widget aiu_cpu_dapm_widgets[] = {
3362306a36Sopenharmony_ci	SND_SOC_DAPM_MUX("SPDIF SRC SEL", SND_SOC_NOPM, 0, 0,
3462306a36Sopenharmony_ci			 &aiu_spdif_encode_mux),
3562306a36Sopenharmony_ci};
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic const struct snd_soc_dapm_route aiu_cpu_dapm_routes[] = {
3862306a36Sopenharmony_ci	{ "I2S Encoder Playback", NULL, "I2S FIFO Playback" },
3962306a36Sopenharmony_ci	{ "SPDIF SRC SEL", "SPDIF", "SPDIF FIFO Playback" },
4062306a36Sopenharmony_ci	{ "SPDIF SRC SEL", "I2S", "I2S FIFO Playback" },
4162306a36Sopenharmony_ci	{ "SPDIF Encoder Playback", NULL, "SPDIF SRC SEL" },
4262306a36Sopenharmony_ci};
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ciint aiu_of_xlate_dai_name(struct snd_soc_component *component,
4562306a36Sopenharmony_ci			  const struct of_phandle_args *args,
4662306a36Sopenharmony_ci			  const char **dai_name,
4762306a36Sopenharmony_ci			  unsigned int component_id)
4862306a36Sopenharmony_ci{
4962306a36Sopenharmony_ci	struct snd_soc_dai *dai;
5062306a36Sopenharmony_ci	int id;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	if (args->args_count != 2)
5362306a36Sopenharmony_ci		return -EINVAL;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	if (args->args[0] != component_id)
5662306a36Sopenharmony_ci		return -EINVAL;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	id = args->args[1];
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	if (id < 0 || id >= component->num_dai)
6162306a36Sopenharmony_ci		return -EINVAL;
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	for_each_component_dais(component, dai) {
6462306a36Sopenharmony_ci		if (id == 0)
6562306a36Sopenharmony_ci			break;
6662306a36Sopenharmony_ci		id--;
6762306a36Sopenharmony_ci	}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	*dai_name = dai->driver->name;
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	return 0;
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistatic int aiu_cpu_of_xlate_dai_name(struct snd_soc_component *component,
7562306a36Sopenharmony_ci				     const struct of_phandle_args *args,
7662306a36Sopenharmony_ci				     const char **dai_name)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	return aiu_of_xlate_dai_name(component, args, dai_name, AIU_CPU);
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistatic int aiu_cpu_component_probe(struct snd_soc_component *component)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	struct aiu *aiu = snd_soc_component_get_drvdata(component);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	/* Required for the SPDIF Source control operation */
8662306a36Sopenharmony_ci	return clk_prepare_enable(aiu->i2s.clks[PCLK].clk);
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic void aiu_cpu_component_remove(struct snd_soc_component *component)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	struct aiu *aiu = snd_soc_component_get_drvdata(component);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	clk_disable_unprepare(aiu->i2s.clks[PCLK].clk);
9462306a36Sopenharmony_ci}
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_cistatic const struct snd_soc_component_driver aiu_cpu_component = {
9762306a36Sopenharmony_ci	.name			= "AIU CPU",
9862306a36Sopenharmony_ci	.dapm_widgets		= aiu_cpu_dapm_widgets,
9962306a36Sopenharmony_ci	.num_dapm_widgets	= ARRAY_SIZE(aiu_cpu_dapm_widgets),
10062306a36Sopenharmony_ci	.dapm_routes		= aiu_cpu_dapm_routes,
10162306a36Sopenharmony_ci	.num_dapm_routes	= ARRAY_SIZE(aiu_cpu_dapm_routes),
10262306a36Sopenharmony_ci	.of_xlate_dai_name	= aiu_cpu_of_xlate_dai_name,
10362306a36Sopenharmony_ci	.pointer		= aiu_fifo_pointer,
10462306a36Sopenharmony_ci	.probe			= aiu_cpu_component_probe,
10562306a36Sopenharmony_ci	.remove			= aiu_cpu_component_remove,
10662306a36Sopenharmony_ci#ifdef CONFIG_DEBUG_FS
10762306a36Sopenharmony_ci	.debugfs_prefix		= "cpu",
10862306a36Sopenharmony_ci#endif
10962306a36Sopenharmony_ci};
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic struct snd_soc_dai_driver aiu_cpu_dai_drv[] = {
11262306a36Sopenharmony_ci	[CPU_I2S_FIFO] = {
11362306a36Sopenharmony_ci		.name = "I2S FIFO",
11462306a36Sopenharmony_ci		.playback = {
11562306a36Sopenharmony_ci			.stream_name	= "I2S FIFO Playback",
11662306a36Sopenharmony_ci			.channels_min	= 2,
11762306a36Sopenharmony_ci			.channels_max	= 8,
11862306a36Sopenharmony_ci			.rates		= SNDRV_PCM_RATE_CONTINUOUS,
11962306a36Sopenharmony_ci			.rate_min	= 5512,
12062306a36Sopenharmony_ci			.rate_max	= 192000,
12162306a36Sopenharmony_ci			.formats	= AIU_FORMATS,
12262306a36Sopenharmony_ci		},
12362306a36Sopenharmony_ci		.ops		= &aiu_fifo_i2s_dai_ops,
12462306a36Sopenharmony_ci	},
12562306a36Sopenharmony_ci	[CPU_SPDIF_FIFO] = {
12662306a36Sopenharmony_ci		.name = "SPDIF FIFO",
12762306a36Sopenharmony_ci		.playback = {
12862306a36Sopenharmony_ci			.stream_name	= "SPDIF FIFO Playback",
12962306a36Sopenharmony_ci			.channels_min	= 2,
13062306a36Sopenharmony_ci			.channels_max	= 2,
13162306a36Sopenharmony_ci			.rates		= SNDRV_PCM_RATE_CONTINUOUS,
13262306a36Sopenharmony_ci			.rate_min	= 5512,
13362306a36Sopenharmony_ci			.rate_max	= 192000,
13462306a36Sopenharmony_ci			.formats	= AIU_FORMATS,
13562306a36Sopenharmony_ci		},
13662306a36Sopenharmony_ci		.ops		= &aiu_fifo_spdif_dai_ops,
13762306a36Sopenharmony_ci	},
13862306a36Sopenharmony_ci	[CPU_I2S_ENCODER] = {
13962306a36Sopenharmony_ci		.name = "I2S Encoder",
14062306a36Sopenharmony_ci		.playback = {
14162306a36Sopenharmony_ci			.stream_name = "I2S Encoder Playback",
14262306a36Sopenharmony_ci			.channels_min = 2,
14362306a36Sopenharmony_ci			.channels_max = 8,
14462306a36Sopenharmony_ci			.rates = SNDRV_PCM_RATE_8000_192000,
14562306a36Sopenharmony_ci			.formats = AIU_FORMATS,
14662306a36Sopenharmony_ci		},
14762306a36Sopenharmony_ci		.ops = &aiu_encoder_i2s_dai_ops,
14862306a36Sopenharmony_ci	},
14962306a36Sopenharmony_ci	[CPU_SPDIF_ENCODER] = {
15062306a36Sopenharmony_ci		.name = "SPDIF Encoder",
15162306a36Sopenharmony_ci		.playback = {
15262306a36Sopenharmony_ci			.stream_name = "SPDIF Encoder Playback",
15362306a36Sopenharmony_ci			.channels_min = 2,
15462306a36Sopenharmony_ci			.channels_max = 2,
15562306a36Sopenharmony_ci			.rates = (SNDRV_PCM_RATE_32000  |
15662306a36Sopenharmony_ci				  SNDRV_PCM_RATE_44100  |
15762306a36Sopenharmony_ci				  SNDRV_PCM_RATE_48000  |
15862306a36Sopenharmony_ci				  SNDRV_PCM_RATE_88200  |
15962306a36Sopenharmony_ci				  SNDRV_PCM_RATE_96000  |
16062306a36Sopenharmony_ci				  SNDRV_PCM_RATE_176400 |
16162306a36Sopenharmony_ci				  SNDRV_PCM_RATE_192000),
16262306a36Sopenharmony_ci			.formats = AIU_FORMATS,
16362306a36Sopenharmony_ci		},
16462306a36Sopenharmony_ci		.ops = &aiu_encoder_spdif_dai_ops,
16562306a36Sopenharmony_ci	}
16662306a36Sopenharmony_ci};
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic const struct regmap_config aiu_regmap_cfg = {
16962306a36Sopenharmony_ci	.reg_bits	= 32,
17062306a36Sopenharmony_ci	.val_bits	= 32,
17162306a36Sopenharmony_ci	.reg_stride	= 4,
17262306a36Sopenharmony_ci	.max_register	= 0x2ac,
17362306a36Sopenharmony_ci};
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_cistatic int aiu_clk_bulk_get(struct device *dev,
17662306a36Sopenharmony_ci			    const char * const *ids,
17762306a36Sopenharmony_ci			    unsigned int num,
17862306a36Sopenharmony_ci			    struct aiu_interface *interface)
17962306a36Sopenharmony_ci{
18062306a36Sopenharmony_ci	struct clk_bulk_data *clks;
18162306a36Sopenharmony_ci	int i, ret;
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci	clks = devm_kcalloc(dev, num, sizeof(*clks), GFP_KERNEL);
18462306a36Sopenharmony_ci	if (!clks)
18562306a36Sopenharmony_ci		return -ENOMEM;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	for (i = 0; i < num; i++)
18862306a36Sopenharmony_ci		clks[i].id = ids[i];
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	ret = devm_clk_bulk_get(dev, num, clks);
19162306a36Sopenharmony_ci	if (ret < 0)
19262306a36Sopenharmony_ci		return ret;
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci	interface->clks = clks;
19562306a36Sopenharmony_ci	interface->clk_num = num;
19662306a36Sopenharmony_ci	return 0;
19762306a36Sopenharmony_ci}
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_cistatic const char * const aiu_i2s_ids[] = {
20062306a36Sopenharmony_ci	[PCLK]	= "i2s_pclk",
20162306a36Sopenharmony_ci	[AOCLK]	= "i2s_aoclk",
20262306a36Sopenharmony_ci	[MCLK]	= "i2s_mclk",
20362306a36Sopenharmony_ci	[MIXER]	= "i2s_mixer",
20462306a36Sopenharmony_ci};
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_cistatic const char * const aiu_spdif_ids[] = {
20762306a36Sopenharmony_ci	[PCLK]	= "spdif_pclk",
20862306a36Sopenharmony_ci	[AOCLK]	= "spdif_aoclk",
20962306a36Sopenharmony_ci	[MCLK]	= "spdif_mclk_sel"
21062306a36Sopenharmony_ci};
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_cistatic int aiu_clk_get(struct device *dev)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	struct aiu *aiu = dev_get_drvdata(dev);
21562306a36Sopenharmony_ci	struct clk *pclk;
21662306a36Sopenharmony_ci	int ret;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	pclk = devm_clk_get_enabled(dev, "pclk");
21962306a36Sopenharmony_ci	if (IS_ERR(pclk))
22062306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(pclk), "Can't get the aiu pclk\n");
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ci	aiu->spdif_mclk = devm_clk_get(dev, "spdif_mclk");
22362306a36Sopenharmony_ci	if (IS_ERR(aiu->spdif_mclk))
22462306a36Sopenharmony_ci		return dev_err_probe(dev, PTR_ERR(aiu->spdif_mclk),
22562306a36Sopenharmony_ci				     "Can't get the aiu spdif master clock\n");
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	ret = aiu_clk_bulk_get(dev, aiu_i2s_ids, ARRAY_SIZE(aiu_i2s_ids),
22862306a36Sopenharmony_ci			       &aiu->i2s);
22962306a36Sopenharmony_ci	if (ret)
23062306a36Sopenharmony_ci		return dev_err_probe(dev, ret, "Can't get the i2s clocks\n");
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	ret = aiu_clk_bulk_get(dev, aiu_spdif_ids, ARRAY_SIZE(aiu_spdif_ids),
23362306a36Sopenharmony_ci			       &aiu->spdif);
23462306a36Sopenharmony_ci	if (ret)
23562306a36Sopenharmony_ci		return dev_err_probe(dev, ret, "Can't get the spdif clocks\n");
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	return ret;
23862306a36Sopenharmony_ci}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_cistatic int aiu_probe(struct platform_device *pdev)
24162306a36Sopenharmony_ci{
24262306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
24362306a36Sopenharmony_ci	void __iomem *regs;
24462306a36Sopenharmony_ci	struct regmap *map;
24562306a36Sopenharmony_ci	struct aiu *aiu;
24662306a36Sopenharmony_ci	int ret;
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	aiu = devm_kzalloc(dev, sizeof(*aiu), GFP_KERNEL);
24962306a36Sopenharmony_ci	if (!aiu)
25062306a36Sopenharmony_ci		return -ENOMEM;
25162306a36Sopenharmony_ci
25262306a36Sopenharmony_ci	aiu->platform = device_get_match_data(dev);
25362306a36Sopenharmony_ci	if (!aiu->platform)
25462306a36Sopenharmony_ci		return -ENODEV;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	platform_set_drvdata(pdev, aiu);
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	ret = device_reset(dev);
25962306a36Sopenharmony_ci	if (ret)
26062306a36Sopenharmony_ci		return dev_err_probe(dev, ret, "Failed to reset device\n");
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	regs = devm_platform_ioremap_resource(pdev, 0);
26362306a36Sopenharmony_ci	if (IS_ERR(regs))
26462306a36Sopenharmony_ci		return PTR_ERR(regs);
26562306a36Sopenharmony_ci
26662306a36Sopenharmony_ci	map = devm_regmap_init_mmio(dev, regs, &aiu_regmap_cfg);
26762306a36Sopenharmony_ci	if (IS_ERR(map)) {
26862306a36Sopenharmony_ci		dev_err(dev, "failed to init regmap: %ld\n",
26962306a36Sopenharmony_ci			PTR_ERR(map));
27062306a36Sopenharmony_ci		return PTR_ERR(map);
27162306a36Sopenharmony_ci	}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_ci	aiu->i2s.irq = platform_get_irq_byname(pdev, "i2s");
27462306a36Sopenharmony_ci	if (aiu->i2s.irq < 0)
27562306a36Sopenharmony_ci		return aiu->i2s.irq;
27662306a36Sopenharmony_ci
27762306a36Sopenharmony_ci	aiu->spdif.irq = platform_get_irq_byname(pdev, "spdif");
27862306a36Sopenharmony_ci	if (aiu->spdif.irq < 0)
27962306a36Sopenharmony_ci		return aiu->spdif.irq;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	ret = aiu_clk_get(dev);
28262306a36Sopenharmony_ci	if (ret)
28362306a36Sopenharmony_ci		return ret;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	/* Register the cpu component of the aiu */
28662306a36Sopenharmony_ci	ret = snd_soc_register_component(dev, &aiu_cpu_component,
28762306a36Sopenharmony_ci					 aiu_cpu_dai_drv,
28862306a36Sopenharmony_ci					 ARRAY_SIZE(aiu_cpu_dai_drv));
28962306a36Sopenharmony_ci	if (ret) {
29062306a36Sopenharmony_ci		dev_err(dev, "Failed to register cpu component\n");
29162306a36Sopenharmony_ci		return ret;
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci	/* Register the hdmi codec control component */
29562306a36Sopenharmony_ci	ret = aiu_hdmi_ctrl_register_component(dev);
29662306a36Sopenharmony_ci	if (ret) {
29762306a36Sopenharmony_ci		dev_err(dev, "Failed to register hdmi control component\n");
29862306a36Sopenharmony_ci		goto err;
29962306a36Sopenharmony_ci	}
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_ci	/* Register the internal dac control component on gxl */
30262306a36Sopenharmony_ci	if (aiu->platform->has_acodec) {
30362306a36Sopenharmony_ci		ret = aiu_acodec_ctrl_register_component(dev);
30462306a36Sopenharmony_ci		if (ret) {
30562306a36Sopenharmony_ci			dev_err(dev,
30662306a36Sopenharmony_ci			    "Failed to register acodec control component\n");
30762306a36Sopenharmony_ci			goto err;
30862306a36Sopenharmony_ci		}
30962306a36Sopenharmony_ci	}
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	return 0;
31262306a36Sopenharmony_cierr:
31362306a36Sopenharmony_ci	snd_soc_unregister_component(dev);
31462306a36Sopenharmony_ci	return ret;
31562306a36Sopenharmony_ci}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cistatic void aiu_remove(struct platform_device *pdev)
31862306a36Sopenharmony_ci{
31962306a36Sopenharmony_ci	snd_soc_unregister_component(&pdev->dev);
32062306a36Sopenharmony_ci}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_cistatic const struct aiu_platform_data aiu_gxbb_pdata = {
32362306a36Sopenharmony_ci	.has_acodec = false,
32462306a36Sopenharmony_ci	.has_clk_ctrl_more_i2s_div = true,
32562306a36Sopenharmony_ci};
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cistatic const struct aiu_platform_data aiu_gxl_pdata = {
32862306a36Sopenharmony_ci	.has_acodec = true,
32962306a36Sopenharmony_ci	.has_clk_ctrl_more_i2s_div = true,
33062306a36Sopenharmony_ci};
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_cistatic const struct aiu_platform_data aiu_meson8_pdata = {
33362306a36Sopenharmony_ci	.has_acodec = false,
33462306a36Sopenharmony_ci	.has_clk_ctrl_more_i2s_div = false,
33562306a36Sopenharmony_ci};
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_cistatic const struct of_device_id aiu_of_match[] = {
33862306a36Sopenharmony_ci	{ .compatible = "amlogic,aiu-gxbb", .data = &aiu_gxbb_pdata },
33962306a36Sopenharmony_ci	{ .compatible = "amlogic,aiu-gxl", .data = &aiu_gxl_pdata },
34062306a36Sopenharmony_ci	{ .compatible = "amlogic,aiu-meson8", .data = &aiu_meson8_pdata },
34162306a36Sopenharmony_ci	{ .compatible = "amlogic,aiu-meson8b", .data = &aiu_meson8_pdata },
34262306a36Sopenharmony_ci	{}
34362306a36Sopenharmony_ci};
34462306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, aiu_of_match);
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_cistatic struct platform_driver aiu_pdrv = {
34762306a36Sopenharmony_ci	.probe = aiu_probe,
34862306a36Sopenharmony_ci	.remove_new = aiu_remove,
34962306a36Sopenharmony_ci	.driver = {
35062306a36Sopenharmony_ci		.name = "meson-aiu",
35162306a36Sopenharmony_ci		.of_match_table = aiu_of_match,
35262306a36Sopenharmony_ci	},
35362306a36Sopenharmony_ci};
35462306a36Sopenharmony_cimodule_platform_driver(aiu_pdrv);
35562306a36Sopenharmony_ci
35662306a36Sopenharmony_ciMODULE_DESCRIPTION("Meson AIU Driver");
35762306a36Sopenharmony_ciMODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
35862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
359