xref: /linux/sound/soc/generic/simple-card.c (revision 0d456bad36d42d16022be045c8a53ddbb59ee478)
1 /*
2  * ASoC simple sound card support
3  *
4  * Copyright (C) 2012 Renesas Solutions Corp.
5  * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License version 2 as
9  * published by the Free Software Foundation.
10  */
11 
12 #include <linux/platform_device.h>
13 #include <linux/module.h>
14 #include <sound/simple_card.h>
15 
16 #define asoc_simple_get_card_info(p) \
17 	container_of(p->dai_link, struct asoc_simple_card_info, snd_link)
18 
19 static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
20 {
21 	struct asoc_simple_card_info *cinfo = asoc_simple_get_card_info(rtd);
22 	struct asoc_simple_dai_init_info *iinfo = cinfo->init;
23 	struct snd_soc_dai *codec = rtd->codec_dai;
24 	struct snd_soc_dai *cpu = rtd->cpu_dai;
25 	unsigned int cpu_daifmt = iinfo->fmt | iinfo->cpu_daifmt;
26 	unsigned int codec_daifmt = iinfo->fmt | iinfo->codec_daifmt;
27 	int ret;
28 
29 	if (codec_daifmt) {
30 		ret = snd_soc_dai_set_fmt(codec, codec_daifmt);
31 		if (ret < 0)
32 			return ret;
33 	}
34 
35 	if (iinfo->sysclk) {
36 		ret = snd_soc_dai_set_sysclk(codec, 0, iinfo->sysclk, 0);
37 		if (ret < 0)
38 			return ret;
39 	}
40 
41 	if (cpu_daifmt) {
42 		ret = snd_soc_dai_set_fmt(cpu, cpu_daifmt);
43 		if (ret < 0)
44 			return ret;
45 	}
46 
47 	return 0;
48 }
49 
50 static int asoc_simple_card_probe(struct platform_device *pdev)
51 {
52 	struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
53 
54 	if (!cinfo) {
55 		dev_err(&pdev->dev, "no info for asoc-simple-card\n");
56 		return -EINVAL;
57 	}
58 
59 	if (!cinfo->name	||
60 	    !cinfo->card	||
61 	    !cinfo->cpu_dai	||
62 	    !cinfo->codec	||
63 	    !cinfo->platform	||
64 	    !cinfo->codec_dai) {
65 		dev_err(&pdev->dev, "insufficient asoc_simple_card_info settings\n");
66 		return -EINVAL;
67 	}
68 
69 	/*
70 	 * init snd_soc_dai_link
71 	 */
72 	cinfo->snd_link.name		= cinfo->name;
73 	cinfo->snd_link.stream_name	= cinfo->name;
74 	cinfo->snd_link.cpu_dai_name	= cinfo->cpu_dai;
75 	cinfo->snd_link.platform_name	= cinfo->platform;
76 	cinfo->snd_link.codec_name	= cinfo->codec;
77 	cinfo->snd_link.codec_dai_name	= cinfo->codec_dai;
78 
79 	/* enable snd_link.init if cinfo has settings */
80 	if (cinfo->init)
81 		cinfo->snd_link.init	= asoc_simple_card_dai_init;
82 
83 	/*
84 	 * init snd_soc_card
85 	 */
86 	cinfo->snd_card.name		= cinfo->card;
87 	cinfo->snd_card.owner		= THIS_MODULE;
88 	cinfo->snd_card.dai_link	= &cinfo->snd_link;
89 	cinfo->snd_card.num_links	= 1;
90 	cinfo->snd_card.dev		= &pdev->dev;
91 
92 	return snd_soc_register_card(&cinfo->snd_card);
93 }
94 
95 static int asoc_simple_card_remove(struct platform_device *pdev)
96 {
97 	struct asoc_simple_card_info *cinfo = pdev->dev.platform_data;
98 
99 	return snd_soc_unregister_card(&cinfo->snd_card);
100 }
101 
102 static struct platform_driver asoc_simple_card = {
103 	.driver = {
104 		.name	= "asoc-simple-card",
105 	},
106 	.probe		= asoc_simple_card_probe,
107 	.remove		= asoc_simple_card_remove,
108 };
109 
110 module_platform_driver(asoc_simple_card);
111 
112 MODULE_LICENSE("GPL");
113 MODULE_DESCRIPTION("ASoC Simple Sound Card");
114 MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
115