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