16e3398c6SAndra Danciu // SPDX-License-Identifier: GPL-2.0
26e3398c6SAndra Danciu //
36e3398c6SAndra Danciu // Phytec pcm030 driver for the PSC of the Freescale MPC52xx
46e3398c6SAndra Danciu // configured as AC97 interface
56e3398c6SAndra Danciu //
66e3398c6SAndra Danciu // Copyright 2008 Jon Smirl, Digispeaker
76e3398c6SAndra Danciu // Author: Jon Smirl <jonsmirl@gmail.com>
8a9262c4fSJon Smirl 
9a9262c4fSJon Smirl #include <linux/init.h>
10a9262c4fSJon Smirl #include <linux/module.h>
11a9262c4fSJon Smirl #include <linux/device.h>
12a9262c4fSJon Smirl #include <linux/of_device.h>
13a9262c4fSJon Smirl #include <linux/of_platform.h>
14a9262c4fSJon Smirl 
15a9262c4fSJon Smirl #include <sound/soc.h>
16a9262c4fSJon Smirl 
17a9262c4fSJon Smirl #include "mpc5200_dma.h"
18a9262c4fSJon Smirl 
19afc5e652STakashi Iwai #define DRV_NAME "pcm030-audio-fabric"
20afc5e652STakashi Iwai 
21c912fa91SEric Millbrandt struct pcm030_audio_data {
22c912fa91SEric Millbrandt 	struct snd_soc_card *card;
23c912fa91SEric Millbrandt 	struct platform_device *codec_device;
24c912fa91SEric Millbrandt };
25c912fa91SEric Millbrandt 
2661c29313SKuninori Morimoto SND_SOC_DAILINK_DEFS(analog,
2761c29313SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.0")),
2861c29313SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-hifi")),
2961c29313SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
3061c29313SKuninori Morimoto 
3161c29313SKuninori Morimoto SND_SOC_DAILINK_DEFS(iec958,
3261c29313SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CPU("mpc5200-psc-ac97.1")),
3361c29313SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_CODEC("wm9712-codec", "wm9712-aux")),
3461c29313SKuninori Morimoto 	DAILINK_COMP_ARRAY(COMP_EMPTY()));
3561c29313SKuninori Morimoto 
36a9262c4fSJon Smirl static struct snd_soc_dai_link pcm030_fabric_dai[] = {
37a9262c4fSJon Smirl {
38c73adc74SEric Millbrandt 	.name = "AC97.0",
39a9262c4fSJon Smirl 	.stream_name = "AC97 Analog",
4061c29313SKuninori Morimoto 	SND_SOC_DAILINK_REG(analog),
41a9262c4fSJon Smirl },
42a9262c4fSJon Smirl {
43c73adc74SEric Millbrandt 	.name = "AC97.1",
44a9262c4fSJon Smirl 	.stream_name = "AC97 IEC958",
4561c29313SKuninori Morimoto 	SND_SOC_DAILINK_REG(iec958),
46a9262c4fSJon Smirl },
47a9262c4fSJon Smirl };
48a9262c4fSJon Smirl 
4908401161SEric Millbrandt static struct snd_soc_card pcm030_card = {
504c3c5df0SAxel Lin 	.name = "pcm030",
514c3c5df0SAxel Lin 	.owner = THIS_MODULE,
524c3c5df0SAxel Lin 	.dai_link = pcm030_fabric_dai,
534c3c5df0SAxel Lin 	.num_links = ARRAY_SIZE(pcm030_fabric_dai),
544c3c5df0SAxel Lin };
554c3c5df0SAxel Lin 
pcm030_fabric_probe(struct platform_device * op)5634913fd9SMarkus Pargmann static int pcm030_fabric_probe(struct platform_device *op)
57a9262c4fSJon Smirl {
5808401161SEric Millbrandt 	struct device_node *np = op->dev.of_node;
5908401161SEric Millbrandt 	struct device_node *platform_np;
6008401161SEric Millbrandt 	struct snd_soc_card *card = &pcm030_card;
61c912fa91SEric Millbrandt 	struct pcm030_audio_data *pdata;
627fe072b4SKuninori Morimoto 	struct snd_soc_dai_link *dai_link;
6308401161SEric Millbrandt 	int ret;
6408401161SEric Millbrandt 	int i;
65a9262c4fSJon Smirl 
6671a157e8SGrant Likely 	if (!of_machine_is_compatible("phytec,pcm030"))
67a9262c4fSJon Smirl 		return -ENODEV;
68a9262c4fSJon Smirl 
69c912fa91SEric Millbrandt 	pdata = devm_kzalloc(&op->dev, sizeof(struct pcm030_audio_data),
70c912fa91SEric Millbrandt 			     GFP_KERNEL);
71c912fa91SEric Millbrandt 	if (!pdata)
72c912fa91SEric Millbrandt 		return -ENOMEM;
73c912fa91SEric Millbrandt 
7408401161SEric Millbrandt 	card->dev = &op->dev;
75c912fa91SEric Millbrandt 
76c912fa91SEric Millbrandt 	pdata->card = card;
7708401161SEric Millbrandt 
7808401161SEric Millbrandt 	platform_np = of_parse_phandle(np, "asoc-platform", 0);
7908401161SEric Millbrandt 	if (!platform_np) {
8008401161SEric Millbrandt 		dev_err(&op->dev, "ac97 not registered\n");
81a9262c4fSJon Smirl 		return -ENODEV;
82a9262c4fSJon Smirl 	}
83a9262c4fSJon Smirl 
847fe072b4SKuninori Morimoto 	for_each_card_prelinks(card, i, dai_link)
8561c29313SKuninori Morimoto 		dai_link->platforms->of_node = platform_np;
86a9262c4fSJon Smirl 
87c912fa91SEric Millbrandt 	ret = request_module("snd-soc-wm9712");
88c912fa91SEric Millbrandt 	if (ret)
89c912fa91SEric Millbrandt 		dev_err(&op->dev, "request_module returned: %d\n", ret);
90c912fa91SEric Millbrandt 
91c912fa91SEric Millbrandt 	pdata->codec_device = platform_device_alloc("wm9712-codec", -1);
92c912fa91SEric Millbrandt 	if (!pdata->codec_device)
93c912fa91SEric Millbrandt 		dev_err(&op->dev, "platform_device_alloc() failed\n");
94c912fa91SEric Millbrandt 
95c912fa91SEric Millbrandt 	ret = platform_device_add(pdata->codec_device);
96fb25621dSMiaoqian Lin 	if (ret) {
97c912fa91SEric Millbrandt 		dev_err(&op->dev, "platform_device_add() failed: %d\n", ret);
98fb25621dSMiaoqian Lin 		platform_device_put(pdata->codec_device);
99fb25621dSMiaoqian Lin 	}
100c912fa91SEric Millbrandt 
10108401161SEric Millbrandt 	ret = snd_soc_register_card(card);
102fb25621dSMiaoqian Lin 	if (ret) {
10308401161SEric Millbrandt 		dev_err(&op->dev, "snd_soc_register_card() failed: %d\n", ret);
104679139eaSYang Yingliang 		platform_device_unregister(pdata->codec_device);
105fb25621dSMiaoqian Lin 	}
10608401161SEric Millbrandt 
1076c7ef410SWei Yongjun 	platform_set_drvdata(op, pdata);
10808401161SEric Millbrandt 	return ret;
109fb25621dSMiaoqian Lin 
110a9262c4fSJon Smirl }
111a9262c4fSJon Smirl 
pcm030_fabric_remove(struct platform_device * op)112*b7f036b9SUwe Kleine-König static void pcm030_fabric_remove(struct platform_device *op)
11308401161SEric Millbrandt {
114c912fa91SEric Millbrandt 	struct pcm030_audio_data *pdata = platform_get_drvdata(op);
11508401161SEric Millbrandt 
1161892a991SUwe Kleine-König 	snd_soc_unregister_card(pdata->card);
117c912fa91SEric Millbrandt 	platform_device_unregister(pdata->codec_device);
11808401161SEric Millbrandt }
11908401161SEric Millbrandt 
1206ffa84dfSFabian Frederick static const struct of_device_id pcm030_audio_match[] = {
12108401161SEric Millbrandt 	{ .compatible = "phytec,pcm030-audio-fabric", },
12208401161SEric Millbrandt 	{}
12308401161SEric Millbrandt };
12408401161SEric Millbrandt MODULE_DEVICE_TABLE(of, pcm030_audio_match);
12508401161SEric Millbrandt 
12608401161SEric Millbrandt static struct platform_driver pcm030_fabric_driver = {
12708401161SEric Millbrandt 	.probe		= pcm030_fabric_probe,
128*b7f036b9SUwe Kleine-König 	.remove_new	= pcm030_fabric_remove,
12908401161SEric Millbrandt 	.driver		= {
13008401161SEric Millbrandt 		.name	= DRV_NAME,
13108401161SEric Millbrandt 		.of_match_table    = pcm030_audio_match,
13208401161SEric Millbrandt 	},
13308401161SEric Millbrandt };
13408401161SEric Millbrandt 
13508401161SEric Millbrandt module_platform_driver(pcm030_fabric_driver);
136a9262c4fSJon Smirl 
137a9262c4fSJon Smirl 
138a9262c4fSJon Smirl MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
139a9262c4fSJon Smirl MODULE_DESCRIPTION(DRV_NAME ": mpc5200 pcm030 fabric driver");
140a9262c4fSJon Smirl MODULE_LICENSE("GPL");
141a9262c4fSJon Smirl 
142