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