blob: c8b6b77366311d2f9b5bada9489700b67b5ff562 [file] [log] [blame]
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301/* Copyright (c) 2013-2014, 2017 The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#include <linux/init.h>
13#include <linux/module.h>
14#include <linux/device.h>
15#include <linux/of_device.h>
16#include <linux/platform_device.h>
17#include <sound/core.h>
18#include <sound/pcm.h>
19#include <sound/soc.h>
20
21enum {
22 STUB_RX,
23 STUB_TX,
24 STUB_1_RX,
25 STUB_1_TX,
26 STUB_DTMF_TX,
27 STUB_HOST_RX_CAPTURE_TX,
28 STUB_HOST_RX_PLAYBACK_RX,
29 STUB_HOST_TX_CAPTURE_TX,
30 STUB_HOST_TX_PLAYBACK_RX,
31};
32
33static int msm_dai_stub_set_channel_map(struct snd_soc_dai *dai,
34 unsigned int tx_num, unsigned int *tx_slot,
35 unsigned int rx_num, unsigned int *rx_slot)
36{
37 pr_debug("%s:\n", __func__);
38
39 return 0;
40}
41
42static struct snd_soc_dai_ops msm_dai_stub_ops = {
43 .set_channel_map = msm_dai_stub_set_channel_map,
44};
45
46static int msm_dai_stub_add_route(struct snd_soc_dai *dai)
47{
48 struct snd_soc_dapm_route intercon;
49 struct snd_soc_dapm_context *dapm;
50
51 if (!dai || !dai->driver) {
52 pr_err("%s Invalid params\n", __func__);
53 return -EINVAL;
54 }
55 dapm = snd_soc_component_get_dapm(dai->component);
56 memset(&intercon, 0, sizeof(intercon));
57 if (dai->driver->playback.stream_name &&
58 dai->driver->playback.aif_name) {
59 dev_dbg(dai->dev, "%s add route for widget %s",
60 __func__, dai->driver->playback.stream_name);
61 intercon.source = dai->driver->playback.aif_name;
62 intercon.sink = dai->driver->playback.stream_name;
63 dev_dbg(dai->dev, "%s src %s sink %s\n",
64 __func__, intercon.source, intercon.sink);
65 snd_soc_dapm_add_routes(dapm, &intercon, 1);
66 }
67 if (dai->driver->capture.stream_name &&
68 dai->driver->capture.aif_name) {
69 dev_dbg(dai->dev, "%s add route for widget %s",
70 __func__, dai->driver->capture.stream_name);
71 intercon.sink = dai->driver->capture.aif_name;
72 intercon.source = dai->driver->capture.stream_name;
73 dev_dbg(dai->dev, "%s src %s sink %s\n",
74 __func__, intercon.source, intercon.sink);
75 snd_soc_dapm_add_routes(dapm, &intercon, 1);
76 }
77 return 0;
78}
79
80static int msm_dai_stub_dai_probe(struct snd_soc_dai *dai)
81{
82 return msm_dai_stub_add_route(dai);
83}
84
85static int msm_dai_stub_dai_remove(struct snd_soc_dai *dai)
86{
87 pr_debug("%s:\n", __func__);
88 return 0;
89}
90
91static struct snd_soc_dai_driver msm_dai_stub_dai_rx = {
92 .playback = {
93 .stream_name = "Stub Playback",
94 .aif_name = "STUB_RX",
95 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
96 SNDRV_PCM_RATE_16000,
97 .formats = SNDRV_PCM_FMTBIT_S16_LE,
98 .channels_min = 1,
99 .channels_max = 2,
100 .rate_min = 8000,
101 .rate_max = 48000,
102 },
103 .ops = &msm_dai_stub_ops,
104 .probe = &msm_dai_stub_dai_probe,
105 .remove = &msm_dai_stub_dai_remove,
106};
107
108static struct snd_soc_dai_driver msm_dai_stub_dai_tx[] = {
109 {
110 .capture = {
111 .stream_name = "Stub Capture",
112 .aif_name = "STUB_TX",
113 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
114 SNDRV_PCM_RATE_16000,
115 .formats = SNDRV_PCM_FMTBIT_S16_LE,
116 .channels_min = 1,
117 .channels_max = 2,
118 .rate_min = 8000,
119 .rate_max = 48000,
120 },
121 .ops = &msm_dai_stub_ops,
122 .probe = &msm_dai_stub_dai_probe,
123 .remove = &msm_dai_stub_dai_remove,
124 },
125 {
126 .capture = {
127 .stream_name = "Stub1 Capture",
128 .aif_name = "STUB_1_TX",
129 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
130 SNDRV_PCM_RATE_16000,
131 .formats = SNDRV_PCM_FMTBIT_S16_LE,
132 .channels_min = 1,
133 .channels_max = 2,
134 .rate_min = 8000,
135 .rate_max = 48000,
136 },
137 .ops = &msm_dai_stub_ops,
138 .probe = &msm_dai_stub_dai_probe,
139 .remove = &msm_dai_stub_dai_remove,
140 }
141};
142
143static struct snd_soc_dai_driver msm_dai_stub_dtmf_tx_dai = {
144 .capture = {
145 .stream_name = "DTMF TX",
146 .aif_name = "STUB_DTMF_TX",
147 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
148 SNDRV_PCM_RATE_16000,
149 .formats = SNDRV_PCM_FMTBIT_S16_LE,
150 .channels_min = 1,
151 .channels_max = 2,
152 .rate_min = 8000,
153 .rate_max = 48000,
154 },
155 .ops = &msm_dai_stub_ops,
156 .probe = &msm_dai_stub_dai_probe,
157 .remove = &msm_dai_stub_dai_remove,
158};
159
160static struct snd_soc_dai_driver msm_dai_stub_host_capture_tx_dai[] = {
161 {
162 .capture = {
163 .stream_name = "CS-VOICE HOST RX CAPTURE",
164 .aif_name = "STUB_HOST_RX_CAPTURE_TX",
165 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
166 SNDRV_PCM_RATE_16000,
167 .formats = SNDRV_PCM_FMTBIT_S16_LE,
168 .channels_min = 1,
169 .channels_max = 2,
170 .rate_min = 8000,
171 .rate_max = 48000,
172 },
173 .ops = &msm_dai_stub_ops,
174 .probe = &msm_dai_stub_dai_probe,
175 .remove = &msm_dai_stub_dai_remove,
176 },
177 {
178 .capture = {
179 .stream_name = "CS-VOICE HOST TX CAPTURE",
180 .aif_name = "STUB_HOST_TX_CAPTURE_TX",
181 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
182 SNDRV_PCM_RATE_16000,
183 .formats = SNDRV_PCM_FMTBIT_S16_LE,
184 .channels_min = 1,
185 .channels_max = 2,
186 .rate_min = 8000,
187 .rate_max = 48000,
188 },
189 .ops = &msm_dai_stub_ops,
190 .probe = &msm_dai_stub_dai_probe,
191 .remove = &msm_dai_stub_dai_remove,
192 },
193};
194
195static struct snd_soc_dai_driver msm_dai_stub_host_playback_rx_dai[] = {
196 {
197 .playback = {
198 .stream_name = "CS-VOICE HOST RX PLAYBACK",
199 .aif_name = "STUB_HOST_RX_PLAYBACK_RX",
200 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
201 SNDRV_PCM_RATE_16000,
202 .formats = SNDRV_PCM_FMTBIT_S16_LE,
203 .channels_min = 1,
204 .channels_max = 2,
205 .rate_min = 8000,
206 .rate_max = 48000,
207 },
208 .ops = &msm_dai_stub_ops,
209 .probe = &msm_dai_stub_dai_probe,
210 .remove = &msm_dai_stub_dai_remove,
211 },
212 {
213 .playback = {
214 .stream_name = "CS-VOICE HOST TX PLAYBACK",
215 .aif_name = "STUB_HOST_TX_PLAYBACK_RX",
216 .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 |
217 SNDRV_PCM_RATE_16000,
218 .formats = SNDRV_PCM_FMTBIT_S16_LE,
219 .channels_min = 1,
220 .channels_max = 2,
221 .rate_min = 8000,
222 .rate_max = 48000,
223 },
224 .ops = &msm_dai_stub_ops,
225 .probe = &msm_dai_stub_dai_probe,
226 .remove = &msm_dai_stub_dai_remove,
227 },
228};
229
230static const struct snd_soc_component_driver msm_dai_stub_component = {
231 .name = "msm-dai-stub-dev",
232};
233
234static int msm_dai_stub_dev_probe(struct platform_device *pdev)
235{
236 int rc, id = -1;
237 const char *stub_dev_id = "qcom,msm-dai-stub-dev-id";
238
239 rc = of_property_read_u32(pdev->dev.of_node, stub_dev_id, &id);
240 if (rc) {
241 dev_err(&pdev->dev,
242 "%s: missing %s in dt node\n", __func__, stub_dev_id);
243 return rc;
244 }
245
246 pdev->id = id;
247
248 pr_debug("%s: dev name %s, id:%d\n", __func__,
249 dev_name(&pdev->dev), pdev->id);
250
251 switch (id) {
252 case STUB_RX:
253 rc = snd_soc_register_component(&pdev->dev,
254 &msm_dai_stub_component, &msm_dai_stub_dai_rx, 1);
255 break;
256 case STUB_TX:
257 rc = snd_soc_register_component(&pdev->dev,
258 &msm_dai_stub_component, &msm_dai_stub_dai_tx[0], 1);
259 break;
260 case STUB_1_TX:
261 rc = snd_soc_register_component(&pdev->dev,
262 &msm_dai_stub_component, &msm_dai_stub_dai_tx[1], 1);
263 break;
264 case STUB_DTMF_TX:
265 rc = snd_soc_register_component(&pdev->dev,
266 &msm_dai_stub_component,
267 &msm_dai_stub_dtmf_tx_dai, 1);
268 break;
269 case STUB_HOST_RX_CAPTURE_TX:
270 rc = snd_soc_register_component(&pdev->dev,
271 &msm_dai_stub_component,
272 &msm_dai_stub_host_capture_tx_dai[0], 1);
273 break;
274 case STUB_HOST_TX_CAPTURE_TX:
275 rc = snd_soc_register_component(&pdev->dev,
276 &msm_dai_stub_component,
277 &msm_dai_stub_host_capture_tx_dai[1], 1);
278 break;
279 case STUB_HOST_RX_PLAYBACK_RX:
280 rc = snd_soc_register_component(&pdev->dev,
281 &msm_dai_stub_component,
282 &msm_dai_stub_host_playback_rx_dai[0], 1);
283 break;
284 case STUB_HOST_TX_PLAYBACK_RX:
285 rc = snd_soc_register_component(&pdev->dev,
286 &msm_dai_stub_component,
287 &msm_dai_stub_host_playback_rx_dai[1], 1);
288 break;
289 }
290
291 return rc;
292}
293
294static int msm_dai_stub_dev_remove(struct platform_device *pdev)
295{
296 snd_soc_unregister_component(&pdev->dev);
297 return 0;
298}
299
300static const struct of_device_id msm_dai_stub_dev_dt_match[] = {
301 { .compatible = "qcom,msm-dai-stub-dev", },
302 { }
303};
304MODULE_DEVICE_TABLE(of, msm_dai_stub_dev_dt_match);
305
306static struct platform_driver msm_dai_stub_dev = {
307 .probe = msm_dai_stub_dev_probe,
308 .remove = msm_dai_stub_dev_remove,
309 .driver = {
310 .name = "msm-dai-stub-dev",
311 .owner = THIS_MODULE,
312 .of_match_table = msm_dai_stub_dev_dt_match,
313 },
314};
315
316static int msm_dai_stub_probe(struct platform_device *pdev)
317{
318 int rc = 0;
319
320 dev_dbg(&pdev->dev, "dev name %s\n", dev_name(&pdev->dev));
321
322 rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
323 if (rc) {
324 dev_err(&pdev->dev, "%s: failed to add child nodes, rc=%d\n",
325 __func__, rc);
326 } else
327 dev_dbg(&pdev->dev, "%s: added child node\n", __func__);
328
329 return rc;
330}
331
332static int msm_dai_stub_remove(struct platform_device *pdev)
333{
334 pr_debug("%s:\n", __func__);
335
336 return 0;
337}
338
339static const struct of_device_id msm_dai_stub_dt_match[] = {
340 {.compatible = "qcom,msm-dai-stub"},
341 {}
342};
343
344MODULE_DEVICE_TABLE(of, msm_dai_stub_dt_match);
345
346
347static struct platform_driver msm_dai_stub_driver = {
348 .probe = msm_dai_stub_probe,
349 .remove = msm_dai_stub_remove,
350 .driver = {
351 .name = "msm-dai-stub",
352 .owner = THIS_MODULE,
353 .of_match_table = msm_dai_stub_dt_match,
354 },
355};
356
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530357int __init msm_dai_stub_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530358{
359 int rc = 0;
360
361 pr_debug("%s:\n", __func__);
362
363 rc = platform_driver_register(&msm_dai_stub_driver);
364 if (rc) {
365 pr_err("%s: fail to register dai q6 driver", __func__);
366 goto fail;
367 }
368
369 rc = platform_driver_register(&msm_dai_stub_dev);
370 if (rc) {
371 pr_err("%s: fail to register dai q6 dev driver", __func__);
372 goto dai_stub_dev_fail;
373 }
374 return rc;
375
376dai_stub_dev_fail:
377 platform_driver_unregister(&msm_dai_stub_driver);
378fail:
379 return rc;
380}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530381
Asish Bhattacharya5faacb32017-12-04 17:23:15 +0530382void msm_dai_stub_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530383{
384 pr_debug("%s:\n", __func__);
385
386 platform_driver_unregister(&msm_dai_stub_dev);
387 platform_driver_unregister(&msm_dai_stub_driver);
388}
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530389
390/* Module information */
391MODULE_DESCRIPTION("MSM Stub DSP DAI driver");
392MODULE_LICENSE("GPL v2");