ASoC: simple-scu-card: remove unused definitions
[deliverable/linux.git] / sound / soc / generic / simple-scu-card.c
CommitLineData
415f1cb2 1/*
53e682b6 2 * ASoC simple SCU sound card support
415f1cb2
KM
3 *
4 * Copyright (C) 2015 Renesas Solutions Corp.
5 * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
6 *
7 * based on ${LINUX}/sound/soc/generic/simple-card.c
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13#include <linux/clk.h>
14#include <linux/device.h>
15#include <linux/module.h>
16#include <linux/of.h>
17#include <linux/of_device.h>
18#include <linux/platform_device.h>
19#include <linux/string.h>
20#include <sound/jack.h>
21#include <sound/soc.h>
22#include <sound/soc-dai.h>
d6a4a9a4 23#include <sound/simple_card_utils.h>
415f1cb2 24
53e682b6 25static const struct of_device_id asoc_simple_card_of_match[] = {
b7419dd7 26 { .compatible = "renesas,rsrc-card", },
64df0e68 27 { .compatible = "simple-scu-audio-card", },
415f1cb2
KM
28 {},
29};
53e682b6 30MODULE_DEVICE_TABLE(of, asoc_simple_card_of_match);
415f1cb2 31
53e682b6 32struct asoc_simple_card_priv {
415f1cb2 33 struct snd_soc_card snd_card;
415f1cb2 34 struct snd_soc_codec_conf codec_conf;
303c3be4 35 struct asoc_simple_dai *dai_props;
3433bf07 36 struct snd_soc_dai_link *dai_link;
af7e2be9 37 u32 convert_rate;
f90432fc 38 u32 convert_channels;
415f1cb2
KM
39};
40
53e682b6
KM
41#define simple_priv_to_dev(priv) ((priv)->snd_card.dev)
42#define simple_priv_to_link(priv, i) ((priv)->snd_card.dai_link + (i))
43#define simple_priv_to_props(priv, i) ((priv)->dai_props + (i))
415f1cb2 44
5bbf3866
KM
45#define DAI "sound-dai"
46#define CELL "#sound-dai-cells"
64df0e68 47#define PREFIX "simple-audio-card,"
5bbf3866 48
53e682b6 49static int asoc_simple_card_startup(struct snd_pcm_substream *substream)
415f1cb2
KM
50{
51 struct snd_soc_pcm_runtime *rtd = substream->private_data;
53e682b6 52 struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
303c3be4 53 struct asoc_simple_dai *dai_props =
53e682b6 54 simple_priv_to_props(priv, rtd->num);
415f1cb2 55
04700027 56 return clk_prepare_enable(dai_props->clk);
415f1cb2
KM
57}
58
53e682b6 59static void asoc_simple_card_shutdown(struct snd_pcm_substream *substream)
415f1cb2
KM
60{
61 struct snd_soc_pcm_runtime *rtd = substream->private_data;
53e682b6 62 struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
303c3be4 63 struct asoc_simple_dai *dai_props =
53e682b6 64 simple_priv_to_props(priv, rtd->num);
415f1cb2 65
04700027 66 clk_disable_unprepare(dai_props->clk);
415f1cb2
KM
67}
68
53e682b6
KM
69static struct snd_soc_ops asoc_simple_card_ops = {
70 .startup = asoc_simple_card_startup,
71 .shutdown = asoc_simple_card_shutdown,
415f1cb2
KM
72};
73
53e682b6 74static int asoc_simple_card_dai_init(struct snd_soc_pcm_runtime *rtd)
415f1cb2 75{
53e682b6 76 struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
04700027
KM
77 struct snd_soc_dai *dai;
78 struct snd_soc_dai_link *dai_link;
303c3be4 79 struct asoc_simple_dai *dai_props;
1a497983 80 int num = rtd->num;
415f1cb2 81
53e682b6
KM
82 dai_link = simple_priv_to_link(priv, num);
83 dai_props = simple_priv_to_props(priv, num);
04700027
KM
84 dai = dai_link->dynamic ?
85 rtd->cpu_dai :
86 rtd->codec_dai;
87
600ee208 88 return asoc_simple_card_init_dai(dai, dai_props);
415f1cb2
KM
89}
90
53e682b6 91static int asoc_simple_card_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
af7e2be9
KM
92 struct snd_pcm_hw_params *params)
93{
53e682b6 94 struct asoc_simple_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
af7e2be9
KM
95 struct snd_interval *rate = hw_param_interval(params,
96 SNDRV_PCM_HW_PARAM_RATE);
f90432fc
KM
97 struct snd_interval *channels = hw_param_interval(params,
98 SNDRV_PCM_HW_PARAM_CHANNELS);
af7e2be9 99
f90432fc
KM
100 if (priv->convert_rate)
101 rate->min =
102 rate->max = priv->convert_rate;
af7e2be9 103
f90432fc
KM
104 if (priv->convert_channels)
105 channels->min =
106 channels->max = priv->convert_channels;
af7e2be9
KM
107
108 return 0;
109}
110
53e682b6
KM
111static int asoc_simple_card_parse_links(struct device_node *np,
112 struct asoc_simple_card_priv *priv,
113 int idx, bool is_fe)
415f1cb2 114{
53e682b6
KM
115 struct device *dev = simple_priv_to_dev(priv);
116 struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, idx);
117 struct asoc_simple_dai *dai_props = simple_priv_to_props(priv, idx);
415f1cb2
KM
118 int ret;
119
6dad9758
KM
120 /* Parse TDM slot */
121 ret = snd_soc_of_parse_tdm_slot(np,
122 &dai_props->tx_slot_mask,
123 &dai_props->rx_slot_mask,
124 &dai_props->slots,
125 &dai_props->slot_width);
126 if (ret)
127 return ret;
128
04700027 129 if (is_fe) {
27b01081
KM
130 int is_single_links = 0;
131
04700027
KM
132 /* BE is dummy */
133 dai_link->codec_of_node = NULL;
134 dai_link->codec_dai_name = "snd-soc-dummy-dai";
135 dai_link->codec_name = "snd-soc-dummy";
136
137 /* FE settings */
138 dai_link->dynamic = 1;
139 dai_link->dpcm_merged_format = 1;
5bbf3866
KM
140
141 ret = asoc_simple_card_parse_cpu(np, dai_link, DAI, CELL,
142 &is_single_links);
143 if (ret)
575f1f92 144 return ret;
04700027 145
c9a235da
KM
146 ret = asoc_simple_card_parse_clk_cpu(np, dai_link, dai_props);
147 if (ret < 0)
148 return ret;
149
8a99a6bd
KM
150 ret = asoc_simple_card_set_dailink_name(dev, dai_link,
151 "fe.%s",
152 dai_link->cpu_dai_name);
153 if (ret < 0)
154 return ret;
04700027 155
27b01081 156 asoc_simple_card_canonicalize_cpu(dai_link, is_single_links);
04700027 157 } else {
04700027
KM
158 /* FE is dummy */
159 dai_link->cpu_of_node = NULL;
160 dai_link->cpu_dai_name = "snd-soc-dummy-dai";
161 dai_link->cpu_name = "snd-soc-dummy";
415f1cb2 162
04700027
KM
163 /* BE settings */
164 dai_link->no_pcm = 1;
53e682b6 165 dai_link->be_hw_params_fixup = asoc_simple_card_be_hw_params_fixup;
5bbf3866
KM
166
167 ret = asoc_simple_card_parse_codec(np, dai_link, DAI, CELL);
575f1f92
KM
168 if (ret < 0)
169 return ret;
04700027 170
c9a235da
KM
171 ret = asoc_simple_card_parse_clk_codec(np, dai_link, dai_props);
172 if (ret < 0)
173 return ret;
174
8a99a6bd
KM
175 ret = asoc_simple_card_set_dailink_name(dev, dai_link,
176 "be.%s",
177 dai_link->codec_dai_name);
178 if (ret < 0)
179 return ret;
180
64df0e68
KM
181 snd_soc_of_parse_audio_prefix(&priv->snd_card,
182 &priv->codec_conf,
183 dai_link->codec_of_node,
184 PREFIX "prefix");
415f1cb2
KM
185 }
186
a09f383e
KM
187 ret = asoc_simple_card_canonicalize_dailink(dai_link);
188 if (ret < 0)
189 return ret;
190
04700027
KM
191 dai_link->dpcm_playback = 1;
192 dai_link->dpcm_capture = 1;
53e682b6
KM
193 dai_link->ops = &asoc_simple_card_ops;
194 dai_link->init = asoc_simple_card_dai_init;
04700027 195
04700027 196 dev_dbg(dev, "\t%s / %04x / %d\n",
8a99a6bd 197 dai_link->name,
ae638b72 198 dai_link->dai_fmt,
04700027 199 dai_props->sysclk);
415f1cb2 200
c9a235da 201 return 0;
415f1cb2
KM
202}
203
53e682b6
KM
204static int asoc_simple_card_dai_link_of(struct device_node *node,
205 struct asoc_simple_card_priv *priv)
af998f85 206{
53e682b6 207 struct device *dev = simple_priv_to_dev(priv);
af998f85
KM
208 struct snd_soc_dai_link *dai_link;
209 struct device_node *np;
210 unsigned int daifmt = 0;
211 int ret, i;
212 bool is_fe;
213
214 /* find 1st codec */
215 i = 0;
216 for_each_child_of_node(node, np) {
53e682b6 217 dai_link = simple_priv_to_link(priv, i);
af998f85 218
64df0e68 219 if (strcmp(np->name, PREFIX "codec") == 0) {
d6a4a9a4 220 ret = asoc_simple_card_parse_daifmt(dev, node, np,
64df0e68 221 PREFIX, &daifmt);
af998f85
KM
222 if (ret < 0)
223 return ret;
224 break;
225 }
226 i++;
227 }
228
229 i = 0;
230 for_each_child_of_node(node, np) {
53e682b6 231 dai_link = simple_priv_to_link(priv, i);
af998f85
KM
232 dai_link->dai_fmt = daifmt;
233
234 is_fe = false;
64df0e68 235 if (strcmp(np->name, PREFIX "cpu") == 0)
af998f85
KM
236 is_fe = true;
237
53e682b6 238 ret = asoc_simple_card_parse_links(np, priv, i, is_fe);
af998f85
KM
239 if (ret < 0)
240 return ret;
241 i++;
242 }
243
244 return 0;
245}
246
53e682b6
KM
247static int asoc_simple_card_parse_of(struct device_node *node,
248 struct asoc_simple_card_priv *priv,
3c7e64dd 249 struct device *dev)
415f1cb2 250{
303c3be4 251 struct asoc_simple_dai *props;
3433bf07 252 struct snd_soc_dai_link *links;
415f1cb2 253 int ret;
af998f85 254 int num;
415f1cb2
KM
255
256 if (!node)
257 return -EINVAL;
258
3433bf07
KM
259 num = of_get_child_count(node);
260 props = devm_kzalloc(dev, sizeof(*props) * num, GFP_KERNEL);
261 links = devm_kzalloc(dev, sizeof(*links) * num, GFP_KERNEL);
262 if (!props || !links)
263 return -ENOMEM;
264
265 priv->dai_props = props;
266 priv->dai_link = links;
3433bf07 267
3c7e64dd
KM
268 /* Init snd_soc_card */
269 priv->snd_card.owner = THIS_MODULE;
270 priv->snd_card.dev = dev;
271 priv->snd_card.dai_link = priv->dai_link;
3433bf07 272 priv->snd_card.num_links = num;
3c7e64dd
KM
273 priv->snd_card.codec_conf = &priv->codec_conf;
274 priv->snd_card.num_configs = 1;
b7419dd7 275
64df0e68
KM
276 ret = snd_soc_of_parse_audio_routing(&priv->snd_card, PREFIX "routing");
277 if (ret < 0)
278 return ret;
415f1cb2 279
af7e2be9 280 /* sampling rate convert */
64df0e68 281 of_property_read_u32(node, PREFIX "convert-rate", &priv->convert_rate);
af7e2be9 282
f90432fc 283 /* channels transfer */
64df0e68 284 of_property_read_u32(node, PREFIX "convert-channels", &priv->convert_channels);
415f1cb2 285
53e682b6 286 ret = asoc_simple_card_dai_link_of(node, priv);
af998f85
KM
287 if (ret < 0)
288 return ret;
415f1cb2 289
64df0e68 290 ret = asoc_simple_card_parse_card_name(&priv->snd_card, PREFIX);
53ae918f
KM
291 if (ret < 0)
292 return ret;
415f1cb2 293
64df0e68
KM
294 dev_dbg(dev, "New card: %s\n",
295 priv->snd_card.name ? priv->snd_card.name : "");
296 dev_dbg(dev, "convert_rate %d\n", priv->convert_rate);
297 dev_dbg(dev, "convert_channels %d\n", priv->convert_channels);
298
415f1cb2
KM
299 return 0;
300}
301
53e682b6 302static int asoc_simple_card_probe(struct platform_device *pdev)
415f1cb2 303{
53e682b6 304 struct asoc_simple_card_priv *priv;
415f1cb2
KM
305 struct device_node *np = pdev->dev.of_node;
306 struct device *dev = &pdev->dev;
307 int ret;
308
309 /* Allocate the private data */
310 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
311 if (!priv)
312 return -ENOMEM;
313
53e682b6 314 ret = asoc_simple_card_parse_of(np, priv, dev);
415f1cb2
KM
315 if (ret < 0) {
316 if (ret != -EPROBE_DEFER)
317 dev_err(dev, "parse error %d\n", ret);
318 goto err;
319 }
320
321 snd_soc_card_set_drvdata(&priv->snd_card, priv);
322
323 ret = devm_snd_soc_register_card(&pdev->dev, &priv->snd_card);
324 if (ret >= 0)
325 return ret;
326err:
239486ba 327 asoc_simple_card_clean_reference(&priv->snd_card);
415f1cb2
KM
328
329 return ret;
330}
331
53e682b6 332static int asoc_simple_card_remove(struct platform_device *pdev)
415f1cb2
KM
333{
334 struct snd_soc_card *card = platform_get_drvdata(pdev);
335
239486ba 336 return asoc_simple_card_clean_reference(card);
415f1cb2
KM
337}
338
53e682b6 339static struct platform_driver asoc_simple_card = {
415f1cb2 340 .driver = {
64df0e68 341 .name = "simple-scu-audio-card",
53e682b6 342 .of_match_table = asoc_simple_card_of_match,
415f1cb2 343 },
53e682b6
KM
344 .probe = asoc_simple_card_probe,
345 .remove = asoc_simple_card_remove,
415f1cb2
KM
346};
347
53e682b6 348module_platform_driver(asoc_simple_card);
415f1cb2 349
53e682b6 350MODULE_ALIAS("platform:asoc-simple-scu-card");
415f1cb2 351MODULE_LICENSE("GPL");
53e682b6 352MODULE_DESCRIPTION("ASoC Simple SCU Sound Card");
415f1cb2 353MODULE_AUTHOR("Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>");
This page took 0.224619 seconds and 5 git commands to generate.