blob: 41aa40765a8d3b3e18c52aaeb3acb5dd2ee73725 [file] [log] [blame]
Kuninori Morimotod5734542018-07-02 06:30:28 +00001// SPDX-License-Identifier: GPL-2.0
2//
3// ASoC simple sound card support
4//
5// Copyright (C) 2012 Renesas Solutions Corp.
6// Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
7
Kuninori Morimotofa558c22013-11-20 15:25:02 +09008#include <linux/clk.h>
Xiubo Li6ff62ee2014-02-14 09:34:36 +08009#include <linux/device.h>
Kuninori Morimotof2390882012-04-08 21:17:50 -070010#include <linux/module.h>
Kuninori Morimotofa558c22013-11-20 15:25:02 +090011#include <linux/of.h>
Kuninori Morimoto42bf0292019-04-04 09:52:52 +090012#include <linux/of_device.h>
Kuninori Morimotof2390882012-04-08 21:17:50 -070013#include <linux/platform_device.h>
Xiubo Lica919fe2014-01-14 12:35:32 +080014#include <linux/string.h>
Kuninori Morimotof2390882012-04-08 21:17:50 -070015#include <sound/simple_card.h>
Xiubo Li6ff62ee2014-02-14 09:34:36 +080016#include <sound/soc-dai.h>
17#include <sound/soc.h>
Kuninori Morimotof2390882012-04-08 21:17:50 -070018
Kuninori Morimoto42bf0292019-04-04 09:52:52 +090019#define DPCM_SELECTABLE 1
20
Kuninori Morimoto44c16af2016-08-08 06:02:07 +000021#define DAI "sound-dai"
22#define CELL "#sound-dai-cells"
Kuninori Morimoto548563f2016-05-31 08:59:01 +000023#define PREFIX "simple-audio-card,"
24
Kuninori Morimoto2d01a842018-12-20 10:47:34 +090025static const struct snd_soc_ops simple_ops = {
Kuninori Morimotof38df5b2019-03-20 13:55:14 +090026 .startup = asoc_simple_startup,
Kuninori Morimoto686911b2019-03-20 13:55:27 +090027 .shutdown = asoc_simple_shutdown,
Kuninori Morimotof48dcbb2019-03-20 13:55:39 +090028 .hw_params = asoc_simple_hw_params,
Andrew Lunn2942a0e2014-05-22 17:31:49 +020029};
30
Kuninori Morimotoad11e592019-03-20 13:56:50 +090031static int asoc_simple_parse_dai(struct device_node *node,
32 struct snd_soc_dai_link_component *dlc,
Kuninori Morimotoad11e592019-03-20 13:56:50 +090033 int *is_single_link)
Kuninori Morimoto8f7f2982019-03-20 13:56:36 +090034{
35 struct of_phandle_args args;
36 int ret;
37
38 if (!node)
39 return 0;
40
41 /*
Kuninori Morimoto8f7f2982019-03-20 13:56:36 +090042 * Get node via "sound-dai = <&phandle port>"
43 * it will be used as xxx_of_node on soc_bind_dai_link()
44 */
45 ret = of_parse_phandle_with_args(node, DAI, CELL, 0, &args);
46 if (ret)
47 return ret;
48
Kuninori Morimoto39c66b62019-09-03 17:15:54 +090049 /*
50 * FIXME
51 *
52 * Here, dlc->dai_name is pointer to CPU/Codec DAI name.
53 * If user unbinded CPU or Codec driver, but not for Sound Card,
54 * dlc->dai_name is keeping unbinded CPU or Codec
55 * driver's pointer.
56 *
57 * If user re-bind CPU or Codec driver again, ALSA SoC will try
58 * to rebind Card via snd_soc_try_rebind_card(), but because of
59 * above reason, it might can't bind Sound Card.
60 * Because Sound Card is pointing to released dai_name pointer.
61 *
62 * To avoid this rebind Card issue,
63 * 1) It needs to alloc memory to keep dai_name eventhough
64 * CPU or Codec driver was unbinded, or
65 * 2) user need to rebind Sound Card everytime
66 * if he unbinded CPU or Codec.
67 */
Kuninori Morimotof1072942019-06-06 13:07:35 +090068 ret = snd_soc_of_get_dai_name(node, &dlc->dai_name);
69 if (ret < 0)
70 return ret;
Kuninori Morimoto8f7f2982019-03-20 13:56:36 +090071
Kuninori Morimotof1072942019-06-06 13:07:35 +090072 dlc->of_node = args.np;
Kuninori Morimoto8f7f2982019-03-20 13:56:36 +090073
74 if (is_single_link)
75 *is_single_link = !args.args_count;
76
77 return 0;
78}
79
Kuninori Morimotocdc44472019-03-18 13:50:08 +090080static void simple_parse_convert(struct device *dev,
81 struct device_node *np,
Kuninori Morimotoad11e592019-03-20 13:56:50 +090082 struct asoc_simple_data *adata)
Kuninori Morimoto7e5e1f82018-12-20 10:46:42 +090083{
84 struct device_node *top = dev->of_node;
85 struct device_node *node = of_get_parent(np);
86
Kuninori Morimotoad11e592019-03-20 13:56:50 +090087 asoc_simple_parse_convert(dev, top, PREFIX, adata);
88 asoc_simple_parse_convert(dev, node, PREFIX, adata);
89 asoc_simple_parse_convert(dev, node, NULL, adata);
90 asoc_simple_parse_convert(dev, np, NULL, adata);
Kuninori Morimoto7e5e1f82018-12-20 10:46:42 +090091
92 of_node_put(node);
93}
94
Kuninori Morimotod708d352019-03-18 13:50:17 +090095static void simple_parse_mclk_fs(struct device_node *top,
96 struct device_node *cpu,
97 struct device_node *codec,
98 struct simple_dai_props *props,
99 char *prefix)
100{
101 struct device_node *node = of_get_parent(cpu);
102 char prop[128];
103
104 snprintf(prop, sizeof(prop), "%smclk-fs", PREFIX);
105 of_property_read_u32(top, prop, &props->mclk_fs);
106
107 snprintf(prop, sizeof(prop), "%smclk-fs", prefix);
108 of_property_read_u32(node, prop, &props->mclk_fs);
109 of_property_read_u32(cpu, prop, &props->mclk_fs);
110 of_property_read_u32(codec, prop, &props->mclk_fs);
111
112 of_node_put(node);
113}
114
Kuninori Morimotoe59289c2019-03-20 13:54:59 +0900115static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv,
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900116 struct device_node *np,
117 struct device_node *codec,
118 struct link_info *li,
119 bool is_top)
Kuninori Morimotoda215352018-12-14 11:35:10 +0900120{
121 struct device *dev = simple_priv_to_dev(priv);
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900122 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
123 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900124 struct asoc_simple_dai *dai;
Kuninori Morimotof1072942019-06-06 13:07:35 +0900125 struct snd_soc_dai_link_component *cpus = dai_link->cpus;
Kuninori Morimotocfc652a2018-12-14 11:35:24 +0900126 struct snd_soc_dai_link_component *codecs = dai_link->codecs;
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900127 struct device_node *top = dev->of_node;
128 struct device_node *node = of_get_parent(np);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900129 char *prefix = "";
130 int ret;
131
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900132 dev_dbg(dev, "link_of DPCM (%pOF)\n", np);
133
134 li->link++;
135
Kuninori Morimotoda215352018-12-14 11:35:10 +0900136 /* For single DAI link & old style of DT node */
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900137 if (is_top)
Kuninori Morimotoda215352018-12-14 11:35:10 +0900138 prefix = PREFIX;
139
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900140 if (li->cpu) {
Kuninori Morimotoda215352018-12-14 11:35:10 +0900141 int is_single_links = 0;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900142
Kuninori Morimoto848704f2019-10-15 11:52:41 +0900143 /* Codec is dummy */
Kuninori Morimotoda215352018-12-14 11:35:10 +0900144 codecs->of_node = NULL;
145 codecs->dai_name = "snd-soc-dummy-dai";
146 codecs->name = "snd-soc-dummy";
147
148 /* FE settings */
149 dai_link->dynamic = 1;
150 dai_link->dpcm_merged_format = 1;
151
152 dai =
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900153 dai_props->cpu_dai = &priv->dais[li->dais++];
Kuninori Morimotoda215352018-12-14 11:35:10 +0900154
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900155 ret = asoc_simple_parse_cpu(np, dai_link, &is_single_links);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900156 if (ret)
Wen Yang724808a2019-07-10 15:25:06 +0800157 goto out_put_node;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900158
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900159 ret = asoc_simple_parse_clk_cpu(dev, np, dai_link, dai);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900160 if (ret < 0)
Wen Yang724808a2019-07-10 15:25:06 +0800161 goto out_put_node;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900162
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900163 ret = asoc_simple_set_dailink_name(dev, dai_link,
164 "fe.%s",
Kuninori Morimotof1072942019-06-06 13:07:35 +0900165 cpus->dai_name);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900166 if (ret < 0)
Wen Yang724808a2019-07-10 15:25:06 +0800167 goto out_put_node;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900168
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900169 asoc_simple_canonicalize_cpu(dai_link, is_single_links);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900170 } else {
171 struct snd_soc_codec_conf *cconf;
172
Kuninori Morimoto848704f2019-10-15 11:52:41 +0900173 /* CPU is dummy */
Kuninori Morimotof1072942019-06-06 13:07:35 +0900174 cpus->of_node = NULL;
175 cpus->dai_name = "snd-soc-dummy-dai";
176 cpus->name = "snd-soc-dummy";
Kuninori Morimotoda215352018-12-14 11:35:10 +0900177
178 /* BE settings */
179 dai_link->no_pcm = 1;
Kuninori Morimoto629f7542019-03-20 13:56:06 +0900180 dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900181
182 dai =
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900183 dai_props->codec_dai = &priv->dais[li->dais++];
Kuninori Morimotoda215352018-12-14 11:35:10 +0900184
185 cconf =
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900186 dai_props->codec_conf = &priv->codec_conf[li->conf++];
Kuninori Morimotoda215352018-12-14 11:35:10 +0900187
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900188 ret = asoc_simple_parse_codec(np, dai_link);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900189 if (ret < 0)
Wen Yang724808a2019-07-10 15:25:06 +0800190 goto out_put_node;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900191
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900192 ret = asoc_simple_parse_clk_codec(dev, np, dai_link, dai);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900193 if (ret < 0)
Wen Yang724808a2019-07-10 15:25:06 +0800194 goto out_put_node;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900195
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900196 ret = asoc_simple_set_dailink_name(dev, dai_link,
197 "be.%s",
198 codecs->dai_name);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900199 if (ret < 0)
Wen Yang724808a2019-07-10 15:25:06 +0800200 goto out_put_node;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900201
202 /* check "prefix" from top node */
Kuninori Morimotocfc652a2018-12-14 11:35:24 +0900203 snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node,
Kuninori Morimotoda215352018-12-14 11:35:10 +0900204 PREFIX "prefix");
Kuninori Morimotocfc652a2018-12-14 11:35:24 +0900205 snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node,
206 "prefix");
207 snd_soc_of_parse_node_prefix(np, cconf, codecs->of_node,
208 "prefix");
Kuninori Morimotoda215352018-12-14 11:35:10 +0900209 }
210
Kuninori Morimotocdc44472019-03-18 13:50:08 +0900211 simple_parse_convert(dev, np, &dai_props->adata);
Kuninori Morimotod708d352019-03-18 13:50:17 +0900212 simple_parse_mclk_fs(top, np, codec, dai_props, prefix);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900213
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900214 asoc_simple_canonicalize_platform(dai_link);
Kuninori Morimotofe7ed4d2019-01-21 16:40:59 +0900215
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900216 ret = asoc_simple_parse_tdm(np, dai);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900217 if (ret)
Wen Yang724808a2019-07-10 15:25:06 +0800218 goto out_put_node;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900219
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900220 ret = asoc_simple_parse_daifmt(dev, node, codec,
221 prefix, &dai_link->dai_fmt);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900222 if (ret < 0)
Wen Yang724808a2019-07-10 15:25:06 +0800223 goto out_put_node;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900224
Pierre-Louis Bossart25612472020-07-07 16:04:37 -0500225 snd_soc_dai_link_set_capabilities(dai_link);
226
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900227 dai_link->ops = &simple_ops;
Kuninori Morimotoad934ca2019-03-20 13:55:52 +0900228 dai_link->init = asoc_simple_dai_init;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900229
Wen Yang724808a2019-07-10 15:25:06 +0800230out_put_node:
231 of_node_put(node);
232 return ret;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900233}
234
Kuninori Morimotoe59289c2019-03-20 13:54:59 +0900235static int simple_dai_link_of(struct asoc_simple_priv *priv,
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900236 struct device_node *np,
237 struct device_node *codec,
238 struct link_info *li,
239 bool is_top)
Jean-Francois Moine6a91a17bd2014-03-20 11:49:55 +0100240{
Kuninori Morimotof531913f2014-09-09 21:37:57 -0700241 struct device *dev = simple_priv_to_dev(priv);
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900242 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link);
243 struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link);
Kuninori Morimoto4fb7f4d2018-12-04 08:19:43 +0000244 struct asoc_simple_dai *cpu_dai;
245 struct asoc_simple_dai *codec_dai;
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900246 struct device_node *top = dev->of_node;
Kuninori Morimoto1b5721b2014-10-27 18:04:52 -0700247 struct device_node *cpu = NULL;
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900248 struct device_node *node = NULL;
Jun Niee0ae2252015-04-29 18:11:07 +0800249 struct device_node *plat = NULL;
Jyri Sarhab3ca11f2014-03-24 12:15:25 +0200250 char prop[128];
251 char *prefix = "";
Kuninori Morimoto44c16af2016-08-08 06:02:07 +0000252 int ret, single_cpu;
Jean-Francois Moine6a91a17bd2014-03-20 11:49:55 +0100253
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900254 cpu = np;
255 node = of_get_parent(np);
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900256 li->link++;
257
258 dev_dbg(dev, "link_of (%pOF)\n", node);
259
Xiubo Li20804372014-09-03 10:23:39 +0800260 /* For single DAI link & old style of DT node */
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900261 if (is_top)
Kuninori Morimoto548563f2016-05-31 08:59:01 +0000262 prefix = PREFIX;
Jean-Francois Moine6a91a17bd2014-03-20 11:49:55 +0100263
Jun Niee0ae2252015-04-29 18:11:07 +0800264 snprintf(prop, sizeof(prop), "%splat", prefix);
265 plat = of_get_child_by_name(node, prop);
266
Kuninori Morimoto4fb7f4d2018-12-04 08:19:43 +0000267 cpu_dai =
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900268 dai_props->cpu_dai = &priv->dais[li->dais++];
Kuninori Morimoto4fb7f4d2018-12-04 08:19:43 +0000269 codec_dai =
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900270 dai_props->codec_dai = &priv->dais[li->dais++];
Kuninori Morimoto4fb7f4d2018-12-04 08:19:43 +0000271
Jon Hunter4819d062019-05-24 09:54:04 +0100272 ret = asoc_simple_parse_daifmt(dev, node, codec,
273 prefix, &dai_link->dai_fmt);
274 if (ret < 0)
275 goto dai_link_of_err;
276
Kuninori Morimotod708d352019-03-18 13:50:17 +0900277 simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix);
Arnaud Pouliquen85a4bfd2015-06-05 10:19:05 +0200278
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900279 ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu);
Kuninori Morimoto44c16af2016-08-08 06:02:07 +0000280 if (ret < 0)
281 goto dai_link_of_err;
282
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900283 ret = asoc_simple_parse_codec(codec, dai_link);
Kuninori Morimoto44c16af2016-08-08 06:02:07 +0000284 if (ret < 0)
285 goto dai_link_of_err;
286
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900287 ret = asoc_simple_parse_platform(plat, dai_link);
Kuninori Morimoto44c16af2016-08-08 06:02:07 +0000288 if (ret < 0)
289 goto dai_link_of_err;
290
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900291 ret = asoc_simple_parse_tdm(cpu, cpu_dai);
Jyri Sarhab3ca11f2014-03-24 12:15:25 +0200292 if (ret < 0)
293 goto dai_link_of_err;
294
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900295 ret = asoc_simple_parse_tdm(codec, codec_dai);
Kuninori Morimoto5fb9cb12016-05-20 09:40:41 +0000296 if (ret < 0)
297 goto dai_link_of_err;
298
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900299 ret = asoc_simple_parse_clk_cpu(dev, cpu, dai_link, cpu_dai);
Kuninori Morimoto28abd992016-07-19 02:53:13 +0000300 if (ret < 0)
301 goto dai_link_of_err;
302
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900303 ret = asoc_simple_parse_clk_codec(dev, codec, dai_link, codec_dai);
Kuninori Morimoto28abd992016-07-19 02:53:13 +0000304 if (ret < 0)
305 goto dai_link_of_err;
306
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900307 ret = asoc_simple_set_dailink_name(dev, dai_link,
308 "%s-%s",
Kuninori Morimotof1072942019-06-06 13:07:35 +0900309 dai_link->cpus->dai_name,
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900310 dai_link->codecs->dai_name);
Kuninori Morimoto2e8d1c72016-07-11 23:57:34 +0000311 if (ret < 0)
Vishal Thanki31f30322015-03-03 18:59:00 +0530312 goto dai_link_of_err;
Vishal Thanki31f30322015-03-03 18:59:00 +0530313
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900314 dai_link->ops = &simple_ops;
Kuninori Morimotoad934ca2019-03-20 13:55:52 +0900315 dai_link->init = asoc_simple_dai_init;
Jyri Sarhab3ca11f2014-03-24 12:15:25 +0200316
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900317 asoc_simple_canonicalize_cpu(dai_link, single_cpu);
318 asoc_simple_canonicalize_platform(dai_link);
Kuninori Morimoto179949b2014-08-27 20:08:06 -0700319
Jyri Sarhab3ca11f2014-03-24 12:15:25 +0200320dai_link_of_err:
Takashi Iwai44662f92019-02-19 16:46:48 +0100321 of_node_put(plat);
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900322 of_node_put(node);
Kuninori Morimoto1b5721b2014-10-27 18:04:52 -0700323
Jean-Francois Moine6a91a17bd2014-03-20 11:49:55 +0100324 return ret;
325}
326
Kuninori Morimoto39af7f72021-03-26 12:26:40 +0900327static int __simple_for_each_link(struct asoc_simple_priv *priv,
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900328 struct link_info *li,
Kuninori Morimotoe59289c2019-03-20 13:54:59 +0900329 int (*func_noml)(struct asoc_simple_priv *priv,
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900330 struct device_node *np,
331 struct device_node *codec,
332 struct link_info *li, bool is_top),
Kuninori Morimotoe59289c2019-03-20 13:54:59 +0900333 int (*func_dpcm)(struct asoc_simple_priv *priv,
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900334 struct device_node *np,
335 struct device_node *codec,
336 struct link_info *li, bool is_top))
337{
338 struct device *dev = simple_priv_to_dev(priv);
339 struct device_node *top = dev->of_node;
340 struct device_node *node;
Kuninori Morimoto42bf0292019-04-04 09:52:52 +0900341 uintptr_t dpcm_selectable = (uintptr_t)of_device_get_match_data(dev);
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900342 bool is_top = 0;
Takashi Iwai0b9c9ed2019-02-19 16:46:49 +0100343 int ret = 0;
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900344
345 /* Check if it has dai-link */
346 node = of_get_child_by_name(top, PREFIX "dai-link");
347 if (!node) {
Daniel Baluta461d8542019-02-16 10:09:42 +0000348 node = of_node_get(top);
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900349 is_top = 1;
350 }
351
352 /* loop for all dai-link */
353 do {
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900354 struct asoc_simple_data adata;
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900355 struct device_node *codec;
Daniel Baluta5525cf02019-12-09 15:53:53 +0200356 struct device_node *plat;
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900357 struct device_node *np;
358 int num = of_get_child_count(node);
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900359
360 /* get codec */
361 codec = of_get_child_by_name(node, is_top ?
362 PREFIX "codec" : "codec");
Takashi Iwai0b9c9ed2019-02-19 16:46:49 +0100363 if (!codec) {
364 ret = -ENODEV;
365 goto error;
366 }
Daniel Baluta5525cf02019-12-09 15:53:53 +0200367 /* get platform */
368 plat = of_get_child_by_name(node, is_top ?
369 PREFIX "plat" : "plat");
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900370
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900371 /* get convert-xxx property */
372 memset(&adata, 0, sizeof(adata));
373 for_each_child_of_node(node, np)
Kuninori Morimotocdc44472019-03-18 13:50:08 +0900374 simple_parse_convert(dev, np, &adata);
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900375
376 /* loop for all CPU/Codec node */
377 for_each_child_of_node(node, np) {
Daniel Baluta5525cf02019-12-09 15:53:53 +0200378 if (plat == np)
379 continue;
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900380 /*
381 * It is DPCM
382 * if it has many CPUs,
383 * or has convert-xxx property
384 */
Kuninori Morimoto42bf0292019-04-04 09:52:52 +0900385 if (dpcm_selectable &&
386 (num > 2 ||
Kuninori Morimoto39af7f72021-03-26 12:26:40 +0900387 adata.convert_rate || adata.convert_channels)) {
388 /*
389 * np
390 * |1(CPU)|0(Codec) li->cpu
391 * CPU |Pass |return
392 * Codec |return|Pass
393 */
394 if (li->cpu != (np == codec))
395 ret = func_dpcm(priv, np, codec, li, is_top);
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900396 /* else normal sound */
Kuninori Morimoto39af7f72021-03-26 12:26:40 +0900397 } else {
398 /*
399 * np
400 * |1(CPU)|0(Codec) li->cpu
401 * CPU |Pass |return
402 * Codec |return|return
403 */
404 if (li->cpu && (np != codec))
405 ret = func_noml(priv, np, codec, li, is_top);
406 }
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900407
Takashi Iwai0b9c9ed2019-02-19 16:46:49 +0100408 if (ret < 0) {
Wen Yang27862d52019-07-10 15:25:07 +0800409 of_node_put(codec);
Takashi Iwai0b9c9ed2019-02-19 16:46:49 +0100410 of_node_put(np);
411 goto error;
412 }
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900413 }
414
Wen Yang27862d52019-07-10 15:25:07 +0800415 of_node_put(codec);
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900416 node = of_get_next_child(top, node);
417 } while (!is_top && node);
418
Takashi Iwai0b9c9ed2019-02-19 16:46:49 +0100419 error:
420 of_node_put(node);
421 return ret;
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900422}
423
Kuninori Morimoto39af7f72021-03-26 12:26:40 +0900424static int simple_for_each_link(struct asoc_simple_priv *priv,
425 struct link_info *li,
426 int (*func_noml)(struct asoc_simple_priv *priv,
427 struct device_node *np,
428 struct device_node *codec,
429 struct link_info *li, bool is_top),
430 int (*func_dpcm)(struct asoc_simple_priv *priv,
431 struct device_node *np,
432 struct device_node *codec,
433 struct link_info *li, bool is_top))
434{
435 int ret;
436 /*
437 * Detect all CPU first, and Detect all Codec 2nd.
438 *
439 * In Normal sound case, all DAIs are detected
440 * as "CPU-Codec".
441 *
442 * In DPCM sound case,
443 * all CPUs are detected as "CPU-dummy", and
444 * all Codecs are detected as "dummy-Codec".
445 * To avoid random sub-device numbering,
446 * detect "dummy-Codec" in last;
447 */
448 for (li->cpu = 1; li->cpu >= 0; li->cpu--) {
449 ret = __simple_for_each_link(priv, li, func_noml, func_dpcm);
450 if (ret < 0)
451 break;
452 }
453
454 return ret;
455}
456
Kuninori Morimotoe59289c2019-03-20 13:54:59 +0900457static int simple_parse_of(struct asoc_simple_priv *priv)
Kuninori Morimotofa558c22013-11-20 15:25:02 +0900458{
Kuninori Morimotof531913f2014-09-09 21:37:57 -0700459 struct device *dev = simple_priv_to_dev(priv);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900460 struct device_node *top = dev->of_node;
Kuninori Morimoto5be50952017-03-15 04:44:00 +0000461 struct snd_soc_card *card = simple_priv_to_card(priv);
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900462 struct link_info li;
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900463 int ret;
Kuninori Morimotofa558c22013-11-20 15:25:02 +0900464
Kuninori Morimotoda215352018-12-14 11:35:10 +0900465 if (!top)
Xiubo Li20804372014-09-03 10:23:39 +0800466 return -EINVAL;
467
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900468 ret = asoc_simple_parse_widgets(card, PREFIX);
Kuninori Morimotofa2760dd2017-06-16 01:39:11 +0000469 if (ret < 0)
Kuninori Morimotoda215352018-12-14 11:35:10 +0900470 return ret;
Xiubo Li9d681f52014-02-08 15:59:53 +0800471
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900472 ret = asoc_simple_parse_routing(card, PREFIX);
Kuninori Morimoto1fdb5d22017-06-15 00:25:17 +0000473 if (ret < 0)
Kuninori Morimotoda215352018-12-14 11:35:10 +0900474 return ret;
Xiubo Lid4c22092013-12-23 12:57:01 +0800475
Paul Cercueil552f2d72019-04-26 04:25:50 +0200476 ret = asoc_simple_parse_pin_switches(card, PREFIX);
477 if (ret < 0)
478 return ret;
479
Xiubo Li20804372014-09-03 10:23:39 +0800480 /* Single/Muti DAI link(s) & New style of DT node */
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900481 memset(&li, 0, sizeof(li));
Kuninori Morimoto39af7f72021-03-26 12:26:40 +0900482 ret = simple_for_each_link(priv, &li,
483 simple_dai_link_of,
484 simple_dai_link_of_dpcm);
485 if (ret < 0)
486 return ret;
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900487
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900488 ret = asoc_simple_parse_card_name(card, PREFIX);
Nikita Yushchenko899a2472016-09-26 12:56:51 +0300489 if (ret < 0)
Kuninori Morimotoda215352018-12-14 11:35:10 +0900490 return ret;
Nikita Yushchenko899a2472016-09-26 12:56:51 +0300491
Stephan Gerholdd9ffff62020-08-01 12:02:56 +0200492 ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs");
Kuninori Morimotoa03b0542016-08-26 03:05:16 +0000493
494 return ret;
Kuninori Morimotofa558c22013-11-20 15:25:02 +0900495}
496
Kuninori Morimotoe59289c2019-03-20 13:54:59 +0900497static int simple_count_noml(struct asoc_simple_priv *priv,
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900498 struct device_node *np,
499 struct device_node *codec,
500 struct link_info *li, bool is_top)
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900501{
Kuninori Morimotoa6e87982021-03-26 12:26:33 +0900502 li->link += 1;
503 li->dais += 2;
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900504
505 return 0;
506}
507
Kuninori Morimotoe59289c2019-03-20 13:54:59 +0900508static int simple_count_dpcm(struct asoc_simple_priv *priv,
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900509 struct device_node *np,
510 struct device_node *codec,
511 struct link_info *li, bool is_top)
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900512{
Kuninori Morimotoa6e87982021-03-26 12:26:33 +0900513 if (li->cpu) {
514 li->link++; /* CPU-dummy */
515 li->dais++;
516 } else {
517 li->link++; /* dummy-Codec */
518 li->dais++;
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900519 li->conf++;
Kuninori Morimotoa6e87982021-03-26 12:26:33 +0900520 }
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900521
522 return 0;
523}
524
Kuninori Morimotoe59289c2019-03-20 13:54:59 +0900525static void simple_get_dais_count(struct asoc_simple_priv *priv,
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900526 struct link_info *li)
Kuninori Morimotoda215352018-12-14 11:35:10 +0900527{
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900528 struct device *dev = simple_priv_to_dev(priv);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900529 struct device_node *top = dev->of_node;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900530
531 /*
532 * link_num : number of links.
533 * CPU-Codec / CPU-dummy / dummy-Codec
534 * dais_num : number of DAIs
535 * ccnf_num : number of codec_conf
536 * same number for "dummy-Codec"
537 *
538 * ex1)
539 * CPU0 --- Codec0 link : 5
540 * CPU1 --- Codec1 dais : 7
541 * CPU2 -/ ccnf : 1
542 * CPU3 --- Codec2
543 *
544 * => 5 links = 2xCPU-Codec + 2xCPU-dummy + 1xdummy-Codec
545 * => 7 DAIs = 4xCPU + 3xCodec
546 * => 1 ccnf = 1xdummy-Codec
547 *
548 * ex2)
549 * CPU0 --- Codec0 link : 5
550 * CPU1 --- Codec1 dais : 6
551 * CPU2 -/ ccnf : 1
552 * CPU3 -/
553 *
554 * => 5 links = 1xCPU-Codec + 3xCPU-dummy + 1xdummy-Codec
555 * => 6 DAIs = 4xCPU + 2xCodec
556 * => 1 ccnf = 1xdummy-Codec
557 *
558 * ex3)
559 * CPU0 --- Codec0 link : 6
560 * CPU1 -/ dais : 6
561 * CPU2 --- Codec1 ccnf : 2
562 * CPU3 -/
563 *
564 * => 6 links = 0xCPU-Codec + 4xCPU-dummy + 2xdummy-Codec
565 * => 6 DAIs = 4xCPU + 2xCodec
566 * => 2 ccnf = 2xdummy-Codec
Kuninori Morimoto7adee602018-12-20 10:46:47 +0900567 *
568 * ex4)
569 * CPU0 --- Codec0 (convert-rate) link : 3
570 * CPU1 --- Codec1 dais : 4
571 * ccnf : 1
572 *
573 * => 3 links = 1xCPU-Codec + 1xCPU-dummy + 1xdummy-Codec
574 * => 4 DAIs = 2xCPU + 2xCodec
575 * => 1 ccnf = 1xdummy-Codec
Kuninori Morimotoda215352018-12-14 11:35:10 +0900576 */
577 if (!top) {
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900578 li->link = 1;
579 li->dais = 2;
580 li->conf = 0;
Kuninori Morimotoda215352018-12-14 11:35:10 +0900581 return;
582 }
583
Kuninori Morimoto39af7f72021-03-26 12:26:40 +0900584 simple_for_each_link(priv, li,
585 simple_count_noml,
586 simple_count_dpcm);
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900587
Kuninori Morimotoc39291a2018-12-20 10:47:28 +0900588 dev_dbg(dev, "link %d, dais %d, ccnf %d\n",
589 li->link, li->dais, li->conf);
Kuninori Morimotoda215352018-12-14 11:35:10 +0900590}
591
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900592static int simple_soc_probe(struct snd_soc_card *card)
Katsuhiro Suzuki8d1bd112018-06-11 17:32:13 +0900593{
Kuninori Morimotoe59289c2019-03-20 13:54:59 +0900594 struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card);
Katsuhiro Suzuki8d1bd112018-06-11 17:32:13 +0900595 int ret;
596
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900597 ret = asoc_simple_init_hp(card, &priv->hp_jack, PREFIX);
Katsuhiro Suzuki8d1bd112018-06-11 17:32:13 +0900598 if (ret < 0)
599 return ret;
600
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900601 ret = asoc_simple_init_mic(card, &priv->mic_jack, PREFIX);
Katsuhiro Suzuki8d1bd112018-06-11 17:32:13 +0900602 if (ret < 0)
603 return ret;
604
605 return 0;
606}
607
Amir Goldsteinb0a821d2019-05-16 13:26:28 +0300608static int asoc_simple_probe(struct platform_device *pdev)
Kuninori Morimotof2390882012-04-08 21:17:50 -0700609{
Kuninori Morimotoe59289c2019-03-20 13:54:59 +0900610 struct asoc_simple_priv *priv;
Kuninori Morimotof89983e2012-12-25 22:52:33 -0800611 struct device *dev = &pdev->dev;
Kuninori Morimotodcee9bfe2017-03-15 04:43:21 +0000612 struct device_node *np = dev->of_node;
Kuninori Morimoto5be50952017-03-15 04:44:00 +0000613 struct snd_soc_card *card;
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900614 struct link_info li;
Kuninori Morimoto65a50562019-03-20 13:56:26 +0900615 int ret;
Kuninori Morimotof2390882012-04-08 21:17:50 -0700616
Xiubo Li0dd4fc32014-09-10 09:59:55 +0800617 /* Allocate the private data and the DAI link array */
Kuninori Morimotob0133d92016-08-26 03:10:25 +0000618 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
Jean-Francois Moineca65b492014-01-15 16:51:52 +0100619 if (!priv)
Xiubo Lica919fe2014-01-14 12:35:32 +0800620 return -ENOMEM;
621
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900622 card = simple_priv_to_card(priv);
623 card->owner = THIS_MODULE;
624 card->dev = dev;
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900625 card->probe = simple_soc_probe;
Kuninori Morimotod947cdf2018-12-20 10:47:23 +0900626
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900627 memset(&li, 0, sizeof(li));
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900628 simple_get_dais_count(priv, &li);
Kuninori Morimoto17029e42018-12-20 10:46:53 +0900629 if (!li.link || !li.dais)
Kuninori Morimotoda215352018-12-14 11:35:10 +0900630 return -EINVAL;
631
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900632 ret = asoc_simple_init_priv(priv, &li);
Kuninori Morimoto65a50562019-03-20 13:56:26 +0900633 if (ret < 0)
634 return ret;
Xiubo Lica919fe2014-01-14 12:35:32 +0800635
Jean-Francois Moine201a0ea2014-01-15 16:51:41 +0100636 if (np && of_device_is_available(np)) {
637
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900638 ret = simple_parse_of(priv);
Xiubo Lica919fe2014-01-14 12:35:32 +0800639 if (ret < 0) {
640 if (ret != -EPROBE_DEFER)
641 dev_err(dev, "parse error %d\n", ret);
Jean-Francois Moinee512e002014-03-11 10:03:40 +0100642 goto err;
Kuninori Morimotofa558c22013-11-20 15:25:02 +0900643 }
Jean-Francois Moine6a91a17bd2014-03-20 11:49:55 +0100644
Kuninori Morimotofa558c22013-11-20 15:25:02 +0900645 } else {
Jean-Francois Moineca65b492014-01-15 16:51:52 +0100646 struct asoc_simple_card_info *cinfo;
Kuninori Morimotof1072942019-06-06 13:07:35 +0900647 struct snd_soc_dai_link_component *cpus;
Kuninori Morimoto710af912018-08-31 03:08:24 +0000648 struct snd_soc_dai_link_component *codecs;
Kuninori Morimotoe58f41e2018-08-31 03:10:33 +0000649 struct snd_soc_dai_link_component *platform;
Kuninori Morimoto65a50562019-03-20 13:56:26 +0900650 struct snd_soc_dai_link *dai_link = priv->dai_link;
651 struct simple_dai_props *dai_props = priv->dai_props;
652
Nathan Chancellor869858f2018-12-13 14:15:20 +0900653 int dai_idx = 0;
Jean-Francois Moineca65b492014-01-15 16:51:52 +0100654
655 cinfo = dev->platform_data;
656 if (!cinfo) {
Xiubo Li34787d0a2014-01-09 17:49:40 +0800657 dev_err(dev, "no info for asoc-simple-card\n");
658 return -EINVAL;
659 }
Kuninori Morimotofa558c22013-11-20 15:25:02 +0900660
Nicolin Chen781cbeb2014-04-24 19:14:00 +0800661 if (!cinfo->name ||
662 !cinfo->codec_dai.name ||
663 !cinfo->codec ||
664 !cinfo->platform ||
Jean-Francois Moine7722f832014-01-15 16:51:33 +0100665 !cinfo->cpu_dai.name) {
666 dev_err(dev, "insufficient asoc_simple_card_info settings\n");
667 return -EINVAL;
668 }
Jean-Francois Moine2bee9912014-01-15 16:51:37 +0100669
Nathan Chancellor869858f2018-12-13 14:15:20 +0900670 dai_props->cpu_dai = &priv->dais[dai_idx++];
671 dai_props->codec_dai = &priv->dais[dai_idx++];
672
Kuninori Morimotof1072942019-06-06 13:07:35 +0900673 cpus = dai_link->cpus;
674 cpus->dai_name = cinfo->cpu_dai.name;
675
Kuninori Morimoto710af912018-08-31 03:08:24 +0000676 codecs = dai_link->codecs;
677 codecs->name = cinfo->codec;
678 codecs->dai_name = cinfo->codec_dai.name;
679
Kuninori Morimoto910fdca2019-01-21 09:32:32 +0900680 platform = dai_link->platforms;
Kuninori Morimotoe58f41e2018-08-31 03:10:33 +0000681 platform->name = cinfo->platform;
682
Kuninori Morimoto5be50952017-03-15 04:44:00 +0000683 card->name = (cinfo->card) ? cinfo->card : cinfo->name;
Jean-Francois Moine5ca8ba42014-01-15 16:51:45 +0100684 dai_link->name = cinfo->name;
685 dai_link->stream_name = cinfo->name;
Lars-Peter Clausen1efb53a2015-03-24 01:07:08 +0000686 dai_link->dai_fmt = cinfo->daifmt;
Kuninori Morimotoad934ca2019-03-20 13:55:52 +0900687 dai_link->init = asoc_simple_dai_init;
Kuninori Morimoto65a50562019-03-20 13:56:26 +0900688 memcpy(dai_props->cpu_dai, &cinfo->cpu_dai,
689 sizeof(*dai_props->cpu_dai));
690 memcpy(dai_props->codec_dai, &cinfo->codec_dai,
691 sizeof(*dai_props->codec_dai));
Kuninori Morimotof2390882012-04-08 21:17:50 -0700692 }
693
Kuninori Morimoto5be50952017-03-15 04:44:00 +0000694 snd_soc_card_set_drvdata(card, priv);
Xiubo Liba194a42014-01-13 17:08:08 +0800695
Kuninori Morimoto0580dde2019-03-20 13:54:42 +0900696 asoc_simple_debug_info(priv);
697
Kuninori Morimoto5be50952017-03-15 04:44:00 +0000698 ret = devm_snd_soc_register_card(dev, card);
Kuninori Morimotoc6d112e2017-05-19 00:57:21 +0000699 if (ret < 0)
700 goto err;
701
702 return 0;
Jean-Francois Moinee512e002014-03-11 10:03:40 +0100703err:
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900704 asoc_simple_clean_reference(card);
Kuninori Morimoto387f5822016-08-26 03:07:59 +0000705
Jean-Francois Moinee512e002014-03-11 10:03:40 +0100706 return ret;
Kuninori Morimotof2390882012-04-08 21:17:50 -0700707}
708
Amir Goldsteinb0a821d2019-05-16 13:26:28 +0300709static int asoc_simple_remove(struct platform_device *pdev)
Xiubo Lie3c4a282014-09-01 14:46:52 +0800710{
Dylan Reid3fe24032014-10-01 14:25:20 -0700711 struct snd_soc_card *card = platform_get_drvdata(pdev);
Dylan Reid3fe24032014-10-01 14:25:20 -0700712
Kuninori Morimotoad11e592019-03-20 13:56:50 +0900713 return asoc_simple_clean_reference(card);
Xiubo Lie3c4a282014-09-01 14:46:52 +0800714}
715
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900716static const struct of_device_id simple_of_match[] = {
Kuninori Morimotofa558c22013-11-20 15:25:02 +0900717 { .compatible = "simple-audio-card", },
Kuninori Morimoto42bf0292019-04-04 09:52:52 +0900718 { .compatible = "simple-scu-audio-card",
719 .data = (void *)DPCM_SELECTABLE },
Kuninori Morimotofa558c22013-11-20 15:25:02 +0900720 {},
721};
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900722MODULE_DEVICE_TABLE(of, simple_of_match);
Kuninori Morimotofa558c22013-11-20 15:25:02 +0900723
Kuninori Morimotof2390882012-04-08 21:17:50 -0700724static struct platform_driver asoc_simple_card = {
725 .driver = {
Nicolin Chen781cbeb2014-04-24 19:14:00 +0800726 .name = "asoc-simple-card",
Peter Ujfalusi7c376712016-05-09 13:38:10 +0300727 .pm = &snd_soc_pm_ops,
Kuninori Morimoto2d01a842018-12-20 10:47:34 +0900728 .of_match_table = simple_of_match,
Kuninori Morimotof2390882012-04-08 21:17:50 -0700729 },
Amir Goldsteinb0a821d2019-05-16 13:26:28 +0300730 .probe = asoc_simple_probe,
731 .remove = asoc_simple_remove,
Kuninori Morimotof2390882012-04-08 21:17:50 -0700732};
733
734module_platform_driver(asoc_simple_card);
735
Fabio Estevamc445be32013-08-23 14:35:17 -0300736MODULE_ALIAS("platform:asoc-simple-card");
Kuninori Morimotoa1dbfd02016-08-26 03:07:28 +0000737MODULE_LICENSE("GPL v2");
Kuninori Morimotof2390882012-04-08 21:17:50 -0700738MODULE_DESCRIPTION("ASoC Simple Sound Card");
739MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");