blob: 7b65dda227b95dce2e967edd4398a8352d239689 [file] [log] [blame]
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301/*
2 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/device.h>
17#include <linux/slab.h>
18#include <linux/vmalloc.h>
19#include <linux/kthread.h>
20#include <linux/platform_device.h>
21#include <linux/of.h>
22#include <linux/delay.h>
23#include <linux/sched.h>
24#include <linux/freezer.h>
25#include <sound/soc.h>
26#include <sound/cpe_core.h>
27#include <sound/lsm_params.h>
28#include <sound/pcm_params.h>
29#include <sound/msm-slim-dma.h>
30
31#define SAMPLE_RATE_48KHZ 48000
32#define SAMPLE_RATE_16KHZ 16000
33#define LSM_VOICE_WAKEUP_APP_V2 2
34#define AFE_PORT_ID_1 1
35#define AFE_PORT_ID_3 3
36#define AFE_OUT_PORT_2 2
37#define LISTEN_MIN_NUM_PERIODS 2
38#define LISTEN_MAX_NUM_PERIODS 12
39#define LISTEN_MAX_PERIOD_SIZE 61440
40#define LISTEN_MIN_PERIOD_SIZE 320
41#define LISTEN_MAX_STATUS_PAYLOAD_SIZE 256
42#define MSM_CPE_MAX_CUSTOM_PARAM_SIZE 2048
43
44#define MSM_CPE_LAB_THREAD_TIMEOUT (3 * (HZ/10))
45
46#define MSM_CPE_LSM_GRAB_LOCK(lock, name) \
47{ \
48 pr_debug("%s: %s lock acquire\n", \
49 __func__, name); \
50 mutex_lock(lock); \
51}
52
53#define MSM_CPE_LSM_REL_LOCK(lock, name) \
54{ \
55 pr_debug("%s: %s lock release\n", \
56 __func__, name); \
57 mutex_unlock(lock); \
58}
59
60/* Conventional and unconventional sample rate supported */
61static unsigned int supported_sample_rates[] = {
62 8000, 16000, 48000, 192000, 384000
63};
64
65static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
66 .count = ARRAY_SIZE(supported_sample_rates),
67 .list = supported_sample_rates,
68 .mask = 0,
69};
70
71
72static struct snd_pcm_hardware msm_pcm_hardware_listen = {
73 .info = (SNDRV_PCM_INFO_BLOCK_TRANSFER |
74 SNDRV_PCM_INFO_MMAP_VALID |
75 SNDRV_PCM_INFO_INTERLEAVED |
76 SNDRV_PCM_INFO_PAUSE |
77 SNDRV_PCM_INFO_RESUME),
78 .formats = (SNDRV_PCM_FMTBIT_S16_LE |
79 SNDRV_PCM_FMTBIT_S24_LE |
80 SNDRV_PCM_FMTBIT_S32_LE),
81 .rates = (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_48000 |
82 SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_384000),
83 .rate_min = 16000,
84 .rate_max = 384000,
85 .channels_min = 1,
86 .channels_max = 1,
87 .buffer_bytes_max = LISTEN_MAX_NUM_PERIODS *
88 LISTEN_MAX_PERIOD_SIZE,
89 .period_bytes_min = LISTEN_MIN_PERIOD_SIZE,
90 .period_bytes_max = LISTEN_MAX_PERIOD_SIZE,
91 .periods_min = LISTEN_MIN_NUM_PERIODS,
92 .periods_max = LISTEN_MAX_NUM_PERIODS,
93 .fifo_size = 0,
94};
95
96enum {
97 AFE_CMD_INVALID = 0,
98 AFE_CMD_PORT_START,
99 AFE_CMD_PORT_SUSPEND,
100 AFE_CMD_PORT_RESUME,
101 AFE_CMD_PORT_STOP,
102};
103
104enum cpe_lab_thread_status {
105 MSM_LSM_LAB_THREAD_STOP,
106 MSM_LSM_LAB_THREAD_RUNNING,
107 MSM_LSM_LAB_THREAD_ERROR,
108};
109
110struct cpe_hw_params {
111 u32 sample_rate;
112 u16 sample_size;
113 u32 buf_sz;
114 u32 period_count;
115 u16 channels;
116};
117
118struct cpe_data_pcm_buf {
119 u8 *mem;
120 phys_addr_t phys;
121};
122
123struct cpe_lsm_lab {
124 atomic_t in_count;
125 atomic_t abort_read;
126 u32 dma_write;
127 u32 buf_idx;
128 u32 pcm_size;
129 enum cpe_lab_thread_status thread_status;
130 struct cpe_data_pcm_buf *pcm_buf;
131 wait_queue_head_t period_wait;
132 struct completion comp;
133 struct completion thread_complete;
134};
135
136struct cpe_priv {
137 void *core_handle;
138 struct snd_soc_codec *codec;
139 struct wcd_cpe_lsm_ops lsm_ops;
140 struct wcd_cpe_afe_ops afe_ops;
141 bool afe_mad_ctl;
142 u32 input_port_id;
143};
144
145struct cpe_lsm_data {
146 struct device *dev;
147 struct cpe_lsm_session *lsm_session;
148 struct mutex lsm_api_lock;
149 struct cpe_lsm_lab lab;
150 struct cpe_hw_params hw_params;
151 struct snd_pcm_substream *substream;
152
153 wait_queue_head_t event_wait;
154 atomic_t event_avail;
155 atomic_t event_stop;
156
157 u8 ev_det_status;
158 u8 ev_det_pld_size;
159 u8 *ev_det_payload;
160
161 bool cpe_prepared;
162};
163
164static int msm_cpe_afe_mad_ctl_get(struct snd_kcontrol *kcontrol,
165 struct snd_ctl_elem_value *ucontrol)
166{
167 struct cpe_priv *cpe = kcontrol->private_data;
168
169 ucontrol->value.integer.value[0] = cpe->afe_mad_ctl;
170 return 0;
171}
172
173static int msm_cpe_afe_mad_ctl_put(struct snd_kcontrol *kcontrol,
174 struct snd_ctl_elem_value *ucontrol)
175{
176 struct cpe_priv *cpe = kcontrol->private_data;
177
178 cpe->afe_mad_ctl = ucontrol->value.integer.value[0];
179 return 0;
180}
181
182static struct snd_kcontrol_new msm_cpe_kcontrols[] = {
183 SOC_SINGLE_EXT("CPE AFE MAD Enable", SND_SOC_NOPM, 0, 1, 0,
184 msm_cpe_afe_mad_ctl_get, msm_cpe_afe_mad_ctl_put),
185};
186
187/*
188 * cpe_get_private_data: obtain ASoC platform driver private data
189 * @substream: ASoC substream for which private data to be obtained
190 */
191static struct cpe_priv *cpe_get_private_data(
192 struct snd_pcm_substream *substream)
193{
194 struct snd_soc_pcm_runtime *rtd;
195
196 if (!substream || !substream->private_data) {
197 pr_err("%s: %s is invalid\n",
198 __func__,
199 (!substream) ? "substream" : "private_data");
200 goto err_ret;
201 }
202
203 rtd = substream->private_data;
204
205 if (!rtd || !rtd->platform) {
206 pr_err("%s: %s is invalid\n",
207 __func__,
208 (!rtd) ? "runtime" : "platform");
209 goto err_ret;
210 }
211
212 return snd_soc_platform_get_drvdata(rtd->platform);
213
214err_ret:
215 return NULL;
216}
217
218/*
219 * cpe_get_lsm_data: obtain the lsm session data given the substream
220 * @substream: ASoC substream for which lsm session data to be obtained
221 */
222static struct cpe_lsm_data *cpe_get_lsm_data(
223 struct snd_pcm_substream *substream)
224{
225 struct snd_pcm_runtime *runtime = substream->runtime;
226
227 return runtime->private_data;
228}
229
230static void msm_cpe_process_event_status(void *data,
231 u8 detect_status, u8 size, u8 *payload)
232{
233 struct cpe_lsm_data *lsm_d = data;
234
235 lsm_d->ev_det_status = detect_status;
236 lsm_d->ev_det_pld_size = size;
237
238 lsm_d->ev_det_payload = kzalloc(size, GFP_KERNEL);
239 if (!lsm_d->ev_det_payload)
240 return;
241
242 memcpy(lsm_d->ev_det_payload, payload, size);
243
244 atomic_set(&lsm_d->event_avail, 1);
245 wake_up(&lsm_d->event_wait);
246}
247
248static void msm_cpe_process_event_status_done(struct cpe_lsm_data *lsm_data)
249{
250 kfree(lsm_data->ev_det_payload);
251 lsm_data->ev_det_payload = NULL;
252
253 lsm_data->ev_det_status = 0;
254 lsm_data->ev_det_pld_size = 0;
255}
256
257/*
258 * msm_cpe_afe_port_cntl: Perform the afe port control
259 * @substream: substream for which afe port command to be performed
260 * @core_handle: handle to core
261 * @afe_ops: handle to the afe operations
262 * @afe_cfg: afe port configuration data
263 * @cmd: command to be sent to AFE
264 *
265 */
266static int msm_cpe_afe_port_cntl(
267 struct snd_pcm_substream *substream,
268 void *core_handle,
269 struct wcd_cpe_afe_ops *afe_ops,
270 struct wcd_cpe_afe_port_cfg *afe_cfg,
271 int cmd)
272{
273 struct snd_soc_pcm_runtime *rtd = substream->private_data;
274 int rc = 0;
275
276 if (!afe_cfg->port_id) {
277 /*
278 * It is possible driver can get closed without prepare,
279 * in which case afe ports will not be initialized.
280 */
281 dev_dbg(rtd->dev,
282 "%s: Invalid afe port id\n",
283 __func__);
284 return 0;
285 }
286
287 switch (cmd) {
288 case AFE_CMD_PORT_START:
289 rc = afe_ops->afe_port_start(core_handle, afe_cfg);
290 if (rc != 0)
291 dev_err(rtd->dev,
292 "%s: AFE port start failed\n",
293 __func__);
294 break;
295 case AFE_CMD_PORT_SUSPEND:
296 rc = afe_ops->afe_port_suspend(core_handle, afe_cfg);
297 if (rc != 0)
298 dev_err(rtd->dev,
299 "%s: afe_suspend failed, err = %d\n",
300 __func__, rc);
301 break;
302 case AFE_CMD_PORT_RESUME:
303 rc = afe_ops->afe_port_resume(core_handle, afe_cfg);
304 if (rc != 0)
305 dev_err(rtd->dev,
306 "%s: afe_resume failed, err = %d\n",
307 __func__, rc);
308 break;
309 case AFE_CMD_PORT_STOP:
310 rc = afe_ops->afe_port_stop(core_handle, afe_cfg);
311 if (rc != 0)
312 dev_err(rtd->dev,
313 "%s: afe_stopfailed, err = %d\n",
314 __func__, rc);
315 break;
316 }
317
318 return rc;
319}
320
321static int msm_cpe_lsm_lab_stop(struct snd_pcm_substream *substream)
322{
323 struct snd_soc_pcm_runtime *rtd = substream->private_data;
324 struct cpe_lsm_data *lsm_d = cpe_get_lsm_data(substream);
325 struct cpe_priv *cpe = cpe_get_private_data(substream);
326 struct wcd_cpe_lsm_ops *lsm_ops;
327 struct wcd_cpe_afe_ops *afe_ops;
328 struct cpe_lsm_session *session;
329 struct cpe_lsm_lab *lab_d = &lsm_d->lab;
330 struct msm_slim_dma_data *dma_data = NULL;
331 int rc;
332
333 /*
334 * the caller is not aware of LAB status and will
335 * try to stop lab even if it is already stopped.
336 * return success right away is LAB is already stopped
337 */
338 if (lab_d->thread_status == MSM_LSM_LAB_THREAD_STOP) {
339 dev_dbg(rtd->dev,
340 "%s: lab already stopped\n",
341 __func__);
342 return 0;
343 }
344
345 if (!cpe || !cpe->core_handle) {
346 dev_err(rtd->dev,
347 "%s: Invalid private data\n",
348 __func__);
349 return -EINVAL;
350 }
351
352 if (!lsm_d->lsm_session) {
353 dev_err(rtd->dev,
354 "%s: Invalid session data\n",
355 __func__);
356 return -EINVAL;
357 }
358
359 lsm_ops = &cpe->lsm_ops;
360 afe_ops = &cpe->afe_ops;
361 session = lsm_d->lsm_session;
362 if (rtd->cpu_dai)
363 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai,
364 substream);
365 if (!dma_data || !dma_data->dai_channel_ctl) {
366 dev_err(rtd->dev,
367 "%s: dma_data is not set\n",
368 __func__);
369 return -EINVAL;
370 }
371
372 if (lab_d->thread_status == MSM_LSM_LAB_THREAD_RUNNING) {
373 dev_dbg(rtd->dev, "%s: stopping lab thread\n",
374 __func__);
375 rc = kthread_stop(session->lsm_lab_thread);
376
377 /*
378 * kthread_stop returns EINTR if the thread_fn
379 * was not scheduled before calling kthread_stop.
380 * In this case, we dont need to wait for lab
381 * thread to complete as lab thread will not be
382 * scheduled at all.
383 */
384 if (rc == -EINTR)
385 goto done;
386
387 /* Wait for the lab thread to exit */
388 rc = wait_for_completion_timeout(
389 &lab_d->thread_complete,
390 MSM_CPE_LAB_THREAD_TIMEOUT);
391 if (!rc) {
392 dev_err(rtd->dev,
393 "%s: Wait for lab thread timedout\n",
394 __func__);
395 return -ETIMEDOUT;
396 }
397 }
398
399 rc = lsm_ops->lab_ch_setup(cpe->core_handle,
400 session,
401 WCD_CPE_PRE_DISABLE);
402 if (rc)
403 dev_err(rtd->dev,
404 "%s: PRE ch teardown failed, err = %d\n",
405 __func__, rc);
406 /* continue with teardown even if any intermediate step fails */
407 rc = dma_data->dai_channel_ctl(dma_data, rtd->cpu_dai, false);
408 if (rc)
409 dev_err(rtd->dev,
410 "%s: open data failed %d\n", __func__, rc);
411 dma_data->ph = 0;
412
413 /*
414 * Even though LAB stop failed,
415 * output AFE port needs to be stopped
416 */
417 rc = afe_ops->afe_port_stop(cpe->core_handle,
418 &session->afe_out_port_cfg);
419 if (rc)
420 dev_err(rtd->dev,
421 "%s: AFE out port stop failed, err = %d\n",
422 __func__, rc);
423
424 rc = lsm_ops->lab_ch_setup(cpe->core_handle,
425 session,
426 WCD_CPE_POST_DISABLE);
427 if (rc)
428 dev_err(rtd->dev,
429 "%s: POST ch teardown failed, err = %d\n",
430 __func__, rc);
431
432done:
433 lab_d->thread_status = MSM_LSM_LAB_THREAD_STOP;
434 lab_d->buf_idx = 0;
435 atomic_set(&lab_d->in_count, 0);
436 lab_d->dma_write = 0;
437
438 return 0;
439}
440
441static int msm_cpe_lab_buf_alloc(struct snd_pcm_substream *substream,
442 struct cpe_lsm_session *session,
443 struct msm_slim_dma_data *dma_data)
444{
445 struct snd_soc_pcm_runtime *rtd = substream->private_data;
446 struct cpe_lsm_data *lsm_d = cpe_get_lsm_data(substream);
447 struct cpe_lsm_lab *lab_d = &lsm_d->lab;
448 struct cpe_hw_params *hw_params = &lsm_d->hw_params;
449 struct cpe_data_pcm_buf *pcm_buf = NULL;
450 int rc = 0;
451 int dma_alloc = 0;
452 u32 count = 0;
453 u32 bufsz, bufcnt;
454
455 if (lab_d->pcm_buf &&
456 lab_d->pcm_buf->mem) {
457 dev_dbg(rtd->dev,
458 "%s: LAB buf already allocated\n",
459 __func__);
460 goto exit;
461 }
462
463 bufsz = hw_params->buf_sz;
464 bufcnt = hw_params->period_count;
465
466 dev_dbg(rtd->dev,
467 "%s:Buf Size %d Buf count %d\n",
468 __func__,
469 bufsz, bufcnt);
470
471 pcm_buf = kzalloc(((sizeof(struct cpe_data_pcm_buf)) * bufcnt),
472 GFP_KERNEL);
473 if (!pcm_buf) {
474 rc = -ENOMEM;
475 goto exit;
476 }
477
478 lab_d->pcm_buf = pcm_buf;
479 dma_alloc = bufsz * bufcnt;
480 pcm_buf->mem = NULL;
481 pcm_buf->mem = dma_alloc_coherent(dma_data->sdev->dev.parent,
482 dma_alloc,
483 &(pcm_buf->phys),
484 GFP_KERNEL);
485 if (!pcm_buf->mem) {
486 dev_err(rtd->dev,
487 "%s:DMA alloc failed size = %x\n",
488 __func__, dma_alloc);
489 rc = -ENOMEM;
490 goto fail;
491 }
492
493 count = 0;
494 while (count < bufcnt) {
495 pcm_buf[count].mem = pcm_buf[0].mem + (count * bufsz);
496 pcm_buf[count].phys = pcm_buf[0].phys + (count * bufsz);
497 dev_dbg(rtd->dev,
498 "%s: pcm_buf[%d].mem %pK pcm_buf[%d].phys %pK\n",
499 __func__, count,
500 (void *)pcm_buf[count].mem,
501 count, &(pcm_buf[count].phys));
502 count++;
503 }
504
505 return 0;
506fail:
507 if (pcm_buf) {
508 if (pcm_buf->mem)
509 dma_free_coherent(dma_data->sdev->dev.parent, dma_alloc,
510 pcm_buf->mem, pcm_buf->phys);
511 kfree(pcm_buf);
512 lab_d->pcm_buf = NULL;
513 }
514exit:
515 return rc;
516}
517
518static int msm_cpe_lab_buf_dealloc(struct snd_pcm_substream *substream,
519 struct cpe_lsm_session *session, struct msm_slim_dma_data *dma_data)
520{
521 struct snd_soc_pcm_runtime *rtd = substream->private_data;
522 struct cpe_lsm_data *lsm_d = cpe_get_lsm_data(substream);
523 struct cpe_lsm_lab *lab_d = &lsm_d->lab;
524 struct cpe_hw_params *hw_params = &lsm_d->hw_params;
525 int rc = 0;
526 int dma_alloc = 0;
527 struct cpe_data_pcm_buf *pcm_buf = NULL;
528 int bufsz, bufcnt;
529
530 bufsz = hw_params->buf_sz;
531 bufcnt = hw_params->period_count;
532
533 dev_dbg(rtd->dev,
534 "%s:Buf Size %d Buf count %d\n", __func__,
535 bufsz, bufcnt);
536
537 if (bufcnt <= 0 || bufsz <= 0) {
538 dev_err(rtd->dev,
539 "%s: Invalid params, bufsz = %u, bufcnt = %u\n",
540 __func__, bufsz, bufcnt);
541 return -EINVAL;
542 }
543
544 pcm_buf = lab_d->pcm_buf;
545 dma_alloc = bufsz * bufcnt;
546 if (dma_data && pcm_buf)
547 dma_free_coherent(dma_data->sdev->dev.parent, dma_alloc,
548 pcm_buf->mem, pcm_buf->phys);
549 kfree(pcm_buf);
550 lab_d->pcm_buf = NULL;
551 return rc;
552}
553
554/*
555 * msm_cpe_lab_thread: Initiated on KW detection
556 * @data: lab data
557 *
558 * Start lab thread and call CPE core API for SLIM
559 * read operations.
560 */
561static int msm_cpe_lab_thread(void *data)
562{
563 struct cpe_lsm_data *lsm_d = data;
564 struct cpe_lsm_session *session = lsm_d->lsm_session;
565 struct snd_pcm_substream *substream = lsm_d->substream;
566 struct cpe_lsm_lab *lab_d = &lsm_d->lab;
567 struct cpe_hw_params *hw_params = &lsm_d->hw_params;
568 struct cpe_priv *cpe = cpe_get_private_data(substream);
569 struct wcd_cpe_lsm_ops *lsm_ops;
570 struct wcd_cpe_afe_ops *afe_ops;
571 struct cpe_data_pcm_buf *cur_buf, *next_buf;
572 struct msm_slim_dma_data *dma_data = NULL;
573 struct snd_soc_pcm_runtime *rtd = NULL;
574 bool wait_timedout = false;
575 int rc = 0;
576 u32 done_len = 0;
577 u32 buf_count = 0;
578 u32 prd_cnt;
579
580 allow_signal(SIGKILL);
581 set_current_state(TASK_INTERRUPTIBLE);
582
583 pr_debug("%s: Lab thread start\n", __func__);
584 init_completion(&lab_d->comp);
585
586 if (PCM_RUNTIME_CHECK(substream)) {
587 rc = -EINVAL;
588 goto done;
589 }
590
591 if (!cpe || !cpe->core_handle) {
592 pr_err("%s: Handle to %s is invalid\n",
593 __func__,
594 (!cpe) ? "cpe" : "core");
595 rc = -EINVAL;
596 goto done;
597 }
598
599 rtd = substream->private_data;
600 if (rtd->cpu_dai)
601 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai,
602 substream);
603 if (!dma_data || !dma_data->dai_channel_ctl) {
604 pr_err("%s: dma_data is not set\n", __func__);
605 rc = -EINVAL;
606 goto done;
607 }
608
609 lsm_ops = &cpe->lsm_ops;
610 afe_ops = &cpe->afe_ops;
611
612 rc = lsm_ops->lab_ch_setup(cpe->core_handle,
613 session,
614 WCD_CPE_PRE_ENABLE);
615 if (rc) {
616 dev_err(rtd->dev,
617 "%s: PRE ch setup failed, err = %d\n",
618 __func__, rc);
619 goto done;
620 }
621
622 rc = dma_data->dai_channel_ctl(dma_data, rtd->cpu_dai, true);
623 if (rc) {
624 dev_err(rtd->dev,
625 "%s: open data failed %d\n", __func__, rc);
626 goto done;
627 }
628
629 dev_dbg(rtd->dev, "%s: Established data channel\n",
630 __func__);
631
632 init_waitqueue_head(&lab_d->period_wait);
633 memset(lab_d->pcm_buf[0].mem, 0, lab_d->pcm_size);
634
635 rc = slim_port_xfer(dma_data->sdev, dma_data->ph,
636 lab_d->pcm_buf[0].phys,
637 hw_params->buf_sz, &lab_d->comp);
638 if (rc) {
639 dev_err(rtd->dev,
640 "%s: buf[0] slim_port_xfer failed, err = %d\n",
641 __func__, rc);
642 goto done;
643 }
644
645 rc = slim_port_xfer(dma_data->sdev, dma_data->ph,
646 lab_d->pcm_buf[1].phys,
647 hw_params->buf_sz, &lab_d->comp);
648 if (rc) {
649 dev_err(rtd->dev,
650 "%s: buf[0] slim_port_xfer failed, err = %d\n",
651 __func__, rc);
652 goto done;
653 }
654
655 cur_buf = &lab_d->pcm_buf[0];
656 next_buf = &lab_d->pcm_buf[2];
657 prd_cnt = hw_params->period_count;
658 rc = lsm_ops->lab_ch_setup(cpe->core_handle,
659 session,
660 WCD_CPE_POST_ENABLE);
661 if (rc) {
662 dev_err(rtd->dev,
663 "%s: POST ch setup failed, err = %d\n",
664 __func__, rc);
665 goto done;
666 }
667
668 rc = afe_ops->afe_port_start(cpe->core_handle,
669 &session->afe_out_port_cfg);
670 if (rc) {
671 dev_err(rtd->dev,
672 "%s: AFE out port start failed, err = %d\n",
673 __func__, rc);
674 goto done;
675 }
676
677 while (!kthread_should_stop() &&
678 lab_d->thread_status != MSM_LSM_LAB_THREAD_ERROR) {
679
680 rc = slim_port_xfer(dma_data->sdev, dma_data->ph,
681 next_buf->phys,
682 hw_params->buf_sz, &lab_d->comp);
683 if (rc) {
684 dev_err(rtd->dev,
685 "%s: slim_port_xfer failed, err = %d\n",
686 __func__, rc);
687 lab_d->thread_status = MSM_LSM_LAB_THREAD_ERROR;
688 }
689
690 rc = wait_for_completion_timeout(&lab_d->comp, (2 * HZ/10));
691 if (!rc) {
692 dev_err(rtd->dev,
693 "%s: wait timedout for slim buffer\n",
694 __func__);
695 wait_timedout = true;
696 } else {
697 wait_timedout = false;
698 }
699
700 rc = slim_port_get_xfer_status(dma_data->sdev,
701 dma_data->ph,
702 &cur_buf->phys, &done_len);
703 if (rc ||
704 (!rc && wait_timedout)) {
705 dev_err(rtd->dev,
706 "%s: xfer_status failure, rc = %d, wait_timedout = %s\n",
707 __func__, rc,
708 (wait_timedout ? "true" : "false"));
709 lab_d->thread_status = MSM_LSM_LAB_THREAD_ERROR;
710 }
711
712 if (done_len ||
713 ((!done_len) &&
714 lab_d->thread_status == MSM_LSM_LAB_THREAD_ERROR)) {
715 atomic_inc(&lab_d->in_count);
716 lab_d->dma_write += snd_pcm_lib_period_bytes(substream);
717 snd_pcm_period_elapsed(substream);
718 wake_up(&lab_d->period_wait);
719 buf_count++;
720
721 cur_buf = &lab_d->pcm_buf[buf_count % prd_cnt];
722 next_buf = &lab_d->pcm_buf[(buf_count + 2) % prd_cnt];
723 dev_dbg(rtd->dev,
724 "%s: Cur buf.mem = %pK Next Buf.mem = %pK\n"
725 " buf count = 0x%x\n", __func__,
726 cur_buf->mem, next_buf->mem, buf_count);
727 } else {
728 dev_err(rtd->dev,
729 "%s: SB get status, invalid len = 0x%x\n",
730 __func__, done_len);
731 }
732 done_len = 0;
733 }
734
735done:
736 if (rc)
737 lab_d->thread_status = MSM_LSM_LAB_THREAD_ERROR;
738 pr_debug("%s: Exit lab_thread, exit_status=%d, thread_status=%d\n",
739 __func__, rc, lab_d->thread_status);
740 complete(&lab_d->thread_complete);
741
742 return 0;
743}
744
745/*
746 * msm_cpe_lsm_open: ASoC call to open the stream
747 * @substream: substream that is to be opened
748 *
749 * Create session data for lsm session and open the lsm session
750 * on CPE.
751 */
752static int msm_cpe_lsm_open(struct snd_pcm_substream *substream)
753{
754 struct cpe_lsm_data *lsm_d;
755 struct snd_pcm_runtime *runtime = substream->runtime;
756 struct snd_soc_pcm_runtime *rtd = substream->private_data;
757 struct cpe_priv *cpe = cpe_get_private_data(substream);
758 struct wcd_cpe_lsm_ops *lsm_ops;
759 int rc = 0;
760
761 if (!cpe || !cpe->codec) {
762 dev_err(rtd->dev,
763 "%s: Invalid private data\n",
764 __func__);
765 return -EINVAL;
766 }
767
768 runtime->hw = msm_pcm_hardware_listen;
769
770 rc = snd_pcm_hw_constraint_list(runtime, 0,
771 SNDRV_PCM_HW_PARAM_RATE,
772 &constraints_sample_rates);
773 if (rc < 0) {
774 pr_err("snd_pcm_hw_constraint_list failed rc %d\n", rc);
775 return -EINVAL;
776 }
777
778 /* Ensure that buffer size is a multiple of period size */
779 rc = snd_pcm_hw_constraint_integer(runtime,
780 SNDRV_PCM_HW_PARAM_PERIODS);
781 if (rc < 0) {
782 pr_err("%s: Unable to set pcm_param_periods, rc %d\n",
783 __func__, rc);
784 return -EINVAL;
785 }
786
787 rc = snd_pcm_hw_constraint_minmax(runtime,
788 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
789 LISTEN_MIN_NUM_PERIODS * LISTEN_MIN_PERIOD_SIZE,
790 LISTEN_MAX_NUM_PERIODS * LISTEN_MAX_PERIOD_SIZE);
791 if (rc < 0) {
792 pr_err("%s: Unable to set pcm constraints, rc %d\n",
793 __func__, rc);
794 return -EINVAL;
795 }
796
797 cpe->core_handle = wcd_cpe_get_core_handle(cpe->codec);
798
799 if (!cpe->core_handle) {
800 dev_err(rtd->dev,
801 "%s: Invalid handle to codec core\n",
802 __func__);
803 return -EINVAL;
804 }
805
806 lsm_ops = &cpe->lsm_ops;
807 lsm_d = kzalloc(sizeof(struct cpe_lsm_data), GFP_KERNEL);
808 if (!lsm_d) {
809 dev_err(rtd->dev,
810 "%s: ENOMEM for lsm session, size = %zd\n",
811 __func__, sizeof(struct cpe_lsm_data));
812 rc = -ENOMEM;
813 goto fail_return;
814 }
815 mutex_init(&lsm_d->lsm_api_lock);
816
817 lsm_d->lsm_session = lsm_ops->lsm_alloc_session(cpe->core_handle,
818 lsm_d, msm_cpe_process_event_status);
819 if (!lsm_d->lsm_session) {
820 dev_err(rtd->dev,
821 "%s: session allocation failed",
822 __func__);
823 rc = -EINVAL;
824 goto fail_session_alloc;
825 }
826 /* Explicitly Assign the LAB thread to STOP state */
827 lsm_d->lab.thread_status = MSM_LSM_LAB_THREAD_STOP;
828 lsm_d->lsm_session->started = false;
829 lsm_d->substream = substream;
830 init_waitqueue_head(&lsm_d->lab.period_wait);
831 lsm_d->cpe_prepared = false;
832
833 dev_dbg(rtd->dev, "%s: allocated session with id = %d\n",
834 __func__, lsm_d->lsm_session->id);
835
836
837 rc = lsm_ops->lsm_open_tx(cpe->core_handle, lsm_d->lsm_session,
838 LSM_VOICE_WAKEUP_APP_V2, 16000);
839 if (rc < 0) {
840 dev_err(rtd->dev,
841 "%s: OPEN_TX cmd failed, err = %d\n",
842 __func__, rc);
843 goto fail_open_tx;
844 }
845
846 init_waitqueue_head(&lsm_d->event_wait);
847 atomic_set(&lsm_d->event_avail, 0);
848 atomic_set(&lsm_d->event_stop, 0);
849 runtime->private_data = lsm_d;
850
851 return 0;
852
853fail_open_tx:
854 lsm_ops->lsm_dealloc_session(cpe->core_handle, lsm_d->lsm_session);
855
856fail_session_alloc:
857 mutex_destroy(&lsm_d->lsm_api_lock);
858 kfree(lsm_d);
859fail_return:
860 return rc;
861}
862
863/*
864 * msm_cpe_lsm_close: ASoC call to close/cleanup the stream
865 * @substream: substream that is to be closed
866 *
867 * Deallocate the session and release the AFE port. It is not
868 * required to deregister the sound model as long as we close
869 * the lsm session on CPE.
870 */
871static int msm_cpe_lsm_close(struct snd_pcm_substream *substream)
872{
873 struct snd_pcm_runtime *runtime = substream->runtime;
874 struct snd_soc_pcm_runtime *rtd = substream->private_data;
875 struct cpe_lsm_data *lsm_d = cpe_get_lsm_data(substream);
876 struct cpe_priv *cpe = cpe_get_private_data(substream);
877 struct wcd_cpe_lsm_ops *lsm_ops;
878 struct cpe_lsm_session *session;
879 struct wcd_cpe_afe_ops *afe_ops;
880 struct wcd_cpe_afe_port_cfg *afe_cfg;
881 int rc = 0;
882
883 if (!cpe || !cpe->core_handle) {
884 dev_err(rtd->dev,
885 "%s: Invalid private data\n",
886 __func__);
887 return -EINVAL;
888 }
889
890 if (!lsm_d || !lsm_d->lsm_session) {
891 dev_err(rtd->dev,
892 "%s: Invalid session data\n",
893 __func__);
894 return -EINVAL;
895 }
896
897 lsm_ops = &cpe->lsm_ops;
898 session = lsm_d->lsm_session;
899 afe_ops = &cpe->afe_ops;
900 afe_cfg = &(lsm_d->lsm_session->afe_port_cfg);
901
902 /*
903 * If driver is closed without stopping LAB,
904 * explicitly stop LAB before cleaning up the
905 * driver resources.
906 */
907 rc = msm_cpe_lsm_lab_stop(substream);
908 if (rc) {
909 dev_err(rtd->dev,
910 "%s: Failed to stop lab, error = %d\n",
911 __func__, rc);
912 return rc;
913 }
914
915 rc = msm_cpe_afe_port_cntl(substream,
916 cpe->core_handle,
917 afe_ops, afe_cfg,
918 AFE_CMD_PORT_STOP);
919
920 lsm_d->cpe_prepared = false;
921
922 rc = lsm_ops->lsm_close_tx(cpe->core_handle, session);
923 if (rc != 0) {
924 dev_err(rtd->dev,
925 "%s: lsm_close fail, err = %d\n",
926 __func__, rc);
927 return rc;
928 }
929
930 lsm_ops->lsm_dealloc_session(cpe->core_handle, session);
931 runtime->private_data = NULL;
932 mutex_destroy(&lsm_d->lsm_api_lock);
933 kfree(lsm_d);
934
935 return rc;
936}
937
938static int msm_cpe_lsm_get_conf_levels(
939 struct cpe_lsm_session *session,
940 u8 *conf_levels_ptr)
941{
942 int rc = 0;
943
944 if (session->num_confidence_levels <= 0) {
945 pr_debug("%s: conf_levels (%u), skip set params\n",
946 __func__,
947 session->num_confidence_levels);
948 goto done;
949 }
950
951 session->conf_levels = kzalloc(session->num_confidence_levels,
952 GFP_KERNEL);
953 if (!session->conf_levels) {
954 rc = -ENOMEM;
955 goto done;
956 }
957
958 if (copy_from_user(session->conf_levels,
959 conf_levels_ptr,
960 session->num_confidence_levels)) {
961 pr_err("%s: copy_from_user failed for confidence levels %u\n",
962 __func__, session->num_confidence_levels);
963 kfree(session->conf_levels);
964 session->conf_levels = NULL;
965 rc = -EFAULT;
966 goto done;
967 }
968
969done:
970 return rc;
971}
972
973static int msm_cpe_lsm_validate_out_format(
974 struct snd_pcm_substream *substream,
975 struct snd_lsm_output_format_cfg *cfg)
976{
977 struct snd_soc_pcm_runtime *rtd = substream->private_data;
978 int rc = 0;
979
980 if (!cfg) {
981 dev_err(rtd->dev,
982 "%s: Invalid lsm out cfg\n", __func__);
983 rc = -EINVAL;
984 goto done;
985 }
986
987 if (cfg->format != LSM_OUT_FORMAT_PCM &&
988 cfg->format != LSM_OUT_FORMAT_ADPCM) {
989 dev_err(rtd->dev,
990 "%s: Invalid format %u\n",
991 __func__, cfg->format);
992 rc = -EINVAL;
993 goto done;
994 }
995
996 if (cfg->packing != LSM_OUT_DATA_RAW &&
997 cfg->packing != LSM_OUT_DATA_PACKED) {
998 dev_err(rtd->dev,
999 "%s: Invalid packing method %u\n",
1000 __func__, cfg->packing);
1001 rc = -EINVAL;
1002 goto done;
1003 }
1004
1005 if (cfg->events != LSM_OUT_DATA_EVENTS_DISABLED &&
1006 cfg->events != LSM_OUT_DATA_EVENTS_ENABLED) {
1007 dev_err(rtd->dev,
1008 "%s: Invalid events provided %u\n",
1009 __func__, cfg->events);
1010 rc = -EINVAL;
1011 goto done;
1012 }
1013
1014 if (cfg->mode != LSM_OUT_TRANSFER_MODE_RT &&
1015 cfg->mode != LSM_OUT_TRANSFER_MODE_FTRT) {
1016 dev_err(rtd->dev,
1017 "%s: Invalid transfer mode %u\n",
1018 __func__, cfg->mode);
1019 rc = -EINVAL;
1020 goto done;
1021 }
1022
1023done:
1024 return rc;
1025}
1026
1027/*
1028 * msm_cpe_lsm_ioctl_shared: Shared IOCTL for this platform driver
1029 * @substream: ASoC substream for which the operation is invoked
1030 * @cmd: command for the ioctl
1031 * @arg: argument for the ioctl
1032 *
1033 * Perform dedicated listen functions like register sound model,
1034 * deregister sound model, etc
1035 * Called with lsm_api_lock acquired.
1036 */
1037static int msm_cpe_lsm_ioctl_shared(struct snd_pcm_substream *substream,
1038 unsigned int cmd, void *arg)
1039{
1040 struct snd_lsm_sound_model_v2 snd_model;
1041 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1042 struct cpe_lsm_data *lsm_d = cpe_get_lsm_data(substream);
1043 struct cpe_priv *cpe = cpe_get_private_data(substream);
1044 struct cpe_lsm_session *session;
1045 struct wcd_cpe_lsm_ops *lsm_ops;
1046 struct cpe_lsm_lab *lab_d = &lsm_d->lab;
1047 struct snd_dma_buffer *dma_buf = &substream->dma_buffer;
1048 struct msm_slim_dma_data *dma_data = NULL;
1049 struct snd_lsm_detection_params det_params;
1050 int rc = 0;
1051
1052 if (!cpe || !cpe->core_handle) {
1053 dev_err(rtd->dev,
1054 "%s: Invalid private data\n",
1055 __func__);
1056 return -EINVAL;
1057 }
1058
1059 if (!lsm_d || !lsm_d->lsm_session) {
1060 dev_err(rtd->dev,
1061 "%s: Invalid session data\n",
1062 __func__);
1063 return -EINVAL;
1064 }
1065
1066 session = lsm_d->lsm_session;
1067 lsm_ops = &cpe->lsm_ops;
1068
1069 switch (cmd) {
1070 case SNDRV_LSM_STOP_LAB:
1071 dev_dbg(rtd->dev,
1072 "%s: %s, lab_enable = %d, lab_thread_ststus = %d\n",
1073 __func__, "SNDRV_LSM_STOP_LAB",
1074 session->lab_enable,
1075 lab_d->thread_status);
1076
1077 if (session->lab_enable &&
1078 lab_d->thread_status != MSM_LSM_LAB_THREAD_STOP) {
1079 atomic_inc(&lab_d->abort_read);
1080 wake_up(&lab_d->period_wait);
1081 rc = msm_cpe_lsm_lab_stop(substream);
1082 if (rc) {
1083 dev_err(rtd->dev,
1084 "%s: stop LAB failed, error = %d\n",
1085 __func__, rc);
1086 return rc;
1087 }
1088 } else if (!session->lab_enable) {
1089 dev_dbg(rtd->dev,
1090 "%s: LAB already stopped\n",
1091 __func__);
1092 }
1093
1094 break;
1095
1096 case SNDRV_LSM_LAB_CONTROL:
1097 if (copy_from_user(&session->lab_enable, (void *)arg,
1098 sizeof(u32))) {
1099 dev_err(rtd->dev,
1100 "%s: copy_from_user failed, size %zd\n",
1101 __func__, sizeof(u32));
1102 return -EFAULT;
1103 }
1104
1105 dev_dbg(rtd->dev,
1106 "%s: %s, lab_enable = %d\n",
1107 __func__, "SNDRV_LSM_LAB_CONTROL",
1108 session->lab_enable);
1109 if (rtd->cpu_dai)
1110 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai,
1111 substream);
1112 if (!dma_data || !dma_data->dai_channel_ctl) {
1113 dev_err(rtd->dev,
1114 "%s: dma_data is not set\n", __func__);
1115 return -EINVAL;
1116 }
1117
1118 if (session->lab_enable) {
1119 rc = msm_cpe_lab_buf_alloc(substream,
1120 session, dma_data);
1121 if (rc < 0) {
1122 dev_err(rtd->dev,
1123 "%s: lab buffer alloc failed, err = %d\n",
1124 __func__, rc);
1125 return rc;
1126 }
1127
1128 dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
1129 dma_buf->dev.dev = substream->pcm->card->dev;
1130 dma_buf->private_data = NULL;
1131 dma_buf->area = lab_d->pcm_buf[0].mem;
1132 dma_buf->addr = lab_d->pcm_buf[0].phys;
1133 dma_buf->bytes = (lsm_d->hw_params.buf_sz *
1134 lsm_d->hw_params.period_count);
1135 init_completion(&lab_d->thread_complete);
1136 snd_pcm_set_runtime_buffer(substream,
1137 &substream->dma_buffer);
1138 rc = lsm_ops->lsm_lab_control(cpe->core_handle,
1139 session, true);
1140 if (rc < 0) {
1141 dev_err(rtd->dev,
1142 "%s: Lab Enable Failed rc %d\n",
1143 __func__, rc);
1144 return rc;
1145 }
1146 } else {
1147 /*
1148 * It is possible that lab is still enabled
1149 * when trying to de-allocate the lab buffer.
1150 * Make sure to disable lab before de-allocating
1151 * the lab buffer.
1152 */
1153 rc = msm_cpe_lsm_lab_stop(substream);
1154 if (rc < 0) {
1155 dev_err(rtd->dev,
1156 "%s: LAB stop failed, error = %d\n",
1157 __func__, rc);
1158 return rc;
1159 }
1160 /*
1161 * Buffer has to be de-allocated even if
1162 * lab_control failed.
1163 */
1164 rc = msm_cpe_lab_buf_dealloc(substream,
1165 session, dma_data);
1166 if (rc < 0) {
1167 dev_err(rtd->dev,
1168 "%s: lab buffer free failed, err = %d\n",
1169 __func__, rc);
1170 return rc;
1171 }
1172 }
1173 break;
1174 case SNDRV_LSM_REG_SND_MODEL_V2:
1175 dev_dbg(rtd->dev,
1176 "%s: %s\n",
1177 __func__, "SNDRV_LSM_REG_SND_MODEL_V2");
1178
1179 memcpy(&snd_model, arg,
1180 sizeof(struct snd_lsm_sound_model_v2));
1181
1182 session->num_confidence_levels =
1183 snd_model.num_confidence_levels;
1184 rc = msm_cpe_lsm_get_conf_levels(session,
1185 snd_model.confidence_level);
1186 if (rc) {
1187 dev_err(rtd->dev,
1188 "%s: %s get_conf_levels fail, err = %d\n",
1189 __func__, "SNDRV_LSM_REG_SND_MODEL_V2",
1190 rc);
1191 break;
1192 }
1193
1194 session->snd_model_data = kzalloc(snd_model.data_size,
1195 GFP_KERNEL);
1196 if (!session->snd_model_data) {
1197 kfree(session->conf_levels);
1198 session->conf_levels = NULL;
1199 return -ENOMEM;
1200 }
1201 session->snd_model_size = snd_model.data_size;
1202
1203 if (copy_from_user(session->snd_model_data,
1204 snd_model.data, snd_model.data_size)) {
1205 dev_err(rtd->dev,
1206 "%s: copy_from_user failed for snd_model\n",
1207 __func__);
1208 kfree(session->conf_levels);
1209 kfree(session->snd_model_data);
1210 session->conf_levels = NULL;
1211 session->snd_model_data = NULL;
1212 return -EFAULT;
1213 }
1214
1215 rc = lsm_ops->lsm_shmem_alloc(cpe->core_handle, session,
1216 session->snd_model_size);
1217 if (rc != 0) {
1218 dev_err(rtd->dev,
1219 "%s: shared memory allocation failed, err = %d\n",
1220 __func__, rc);
1221 kfree(session->snd_model_data);
1222 kfree(session->conf_levels);
1223 session->snd_model_data = NULL;
1224 session->conf_levels = NULL;
1225 return rc;
1226 }
1227
1228 rc = lsm_ops->lsm_register_snd_model(cpe->core_handle, session,
1229 snd_model.detection_mode,
1230 snd_model.detect_failure);
1231 if (rc != 0) {
1232 dev_err(rtd->dev,
1233 "%s: snd_model_reg failed, err = %d\n",
1234 __func__, rc);
1235 lsm_ops->lsm_shmem_dealloc(cpe->core_handle, session);
1236 kfree(session->snd_model_data);
1237 kfree(session->conf_levels);
1238 session->snd_model_data = NULL;
1239 session->conf_levels = NULL;
1240 return rc;
1241 }
1242
1243 break;
1244
1245 case SNDRV_LSM_DEREG_SND_MODEL:
1246 dev_dbg(rtd->dev,
1247 "%s: %s\n",
1248 __func__, "SNDRV_LSM_DEREG_SND_MODEL");
1249
1250 if (session->lab_enable) {
1251 /*
1252 * It is possible that lab is still enabled
1253 * when trying to deregister sound model.
1254 * Make sure to disable lab before de-allocating
1255 * the lab buffer.
1256 */
1257 rc = msm_cpe_lsm_lab_stop(substream);
1258 if (rc) {
1259 dev_err(rtd->dev,
1260 "%s: LAB stop failed, error = %d\n",
1261 __func__, rc);
1262 return rc;
1263 }
1264
1265 rc = lsm_ops->lsm_lab_control(cpe->core_handle,
1266 session, false);
1267 if (rc)
1268 dev_err(rtd->dev,
1269 "%s: Lab Disable Failed rc %d\n",
1270 __func__, rc);
1271
1272 dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai,
1273 substream);
1274 if (!dma_data || !dma_data->dai_channel_ctl)
1275 dev_err(rtd->dev,
1276 "%s: dma_data is not set\n", __func__);
1277
1278 /*
1279 * Buffer has to be de-allocated even if
1280 * lab_control failed and/or dma data is invalid.
1281 */
1282 rc = msm_cpe_lab_buf_dealloc(substream,
1283 session, dma_data);
1284 if (rc < 0)
1285 dev_err(rtd->dev,
1286 "%s: lab buffer free failed, err = %d\n",
1287 __func__, rc);
1288 }
1289
1290 rc = lsm_ops->lsm_deregister_snd_model(
1291 cpe->core_handle, session);
1292 if (rc != 0) {
1293 dev_err(rtd->dev,
1294 "%s: snd_model de-reg failed, err = %d\n",
1295 __func__, rc);
1296 return rc;
1297 }
1298
1299 kfree(session->snd_model_data);
1300 kfree(session->conf_levels);
1301 session->snd_model_data = NULL;
1302 session->conf_levels = NULL;
1303
1304 rc = lsm_ops->lsm_shmem_dealloc(cpe->core_handle, session);
1305 if (rc != 0) {
1306 dev_err(rtd->dev,
1307 "%s: LSM shared memory dealloc failed, err = %d\n",
1308 __func__, rc);
1309 return rc;
1310 }
1311
1312 break;
1313
1314 case SNDRV_LSM_EVENT_STATUS:
1315 case SNDRV_LSM_EVENT_STATUS_V3: {
1316 struct snd_lsm_event_status *user;
1317 struct snd_lsm_event_status_v3 *user_v3;
1318
1319 dev_dbg(rtd->dev,
1320 "%s: %s\n",
1321 __func__, "SNDRV_LSM_EVENT_STATUS(_V3)");
1322 if (!arg) {
1323 dev_err(rtd->dev,
1324 "%s: Invalid argument to ioctl %s\n",
1325 __func__,
1326 "SNDRV_LSM_EVENT_STATUS(_V3)");
1327 return -EINVAL;
1328 }
1329
1330 /*
1331 * Release the api lock before wait to allow
1332 * other IOCTLs to be invoked while waiting
1333 * for event
1334 */
1335 MSM_CPE_LSM_REL_LOCK(&lsm_d->lsm_api_lock,
1336 "lsm_api_lock");
1337
1338 rc = wait_event_freezable(lsm_d->event_wait,
1339 (atomic_read(&lsm_d->event_avail) == 1) ||
1340 (atomic_read(&lsm_d->event_stop) == 1));
1341
1342 MSM_CPE_LSM_GRAB_LOCK(&lsm_d->lsm_api_lock,
1343 "lsm_api_lock");
1344
1345 if (!rc) {
1346 if (atomic_read(&lsm_d->event_avail) == 1) {
1347 rc = 0;
1348 atomic_set(&lsm_d->event_avail, 0);
1349
1350 if (cmd == SNDRV_LSM_EVENT_STATUS) {
1351 user = arg;
1352 if (lsm_d->ev_det_pld_size >
1353 user->payload_size) {
1354 dev_err(rtd->dev,
1355 "%s: avail pld_bytes = %u, needed = %u\n",
1356 __func__,
1357 user->payload_size,
1358 lsm_d->ev_det_pld_size);
1359 return -EINVAL;
1360 }
1361
1362 user->status = lsm_d->ev_det_status;
1363 user->payload_size =
1364 lsm_d->ev_det_pld_size;
1365 memcpy(user->payload,
1366 lsm_d->ev_det_payload,
1367 lsm_d->ev_det_pld_size);
1368 } else {
1369 user_v3 = arg;
1370 if (lsm_d->ev_det_pld_size >
1371 user_v3->payload_size) {
1372 dev_err(rtd->dev,
1373 "%s: avail pld_bytes = %u, needed = %u\n",
1374 __func__,
1375 user_v3->payload_size,
1376 lsm_d->ev_det_pld_size);
1377 return -EINVAL;
1378 }
1379 /* event status timestamp not supported
1380 * on CPE mode. Set msw and lsw to 0.
1381 */
1382 user_v3->timestamp_lsw = 0;
1383 user_v3->timestamp_msw = 0;
1384 user_v3->status = lsm_d->ev_det_status;
1385 user_v3->payload_size =
1386 lsm_d->ev_det_pld_size;
1387 memcpy(user_v3->payload,
1388 lsm_d->ev_det_payload,
1389 lsm_d->ev_det_pld_size);
1390 }
1391 } else if (atomic_read(&lsm_d->event_stop) == 1) {
1392 dev_dbg(rtd->dev,
1393 "%s: wait_aborted\n", __func__);
1394 if (cmd == SNDRV_LSM_EVENT_STATUS) {
1395 user = arg;
1396 user->payload_size = 0;
1397 } else {
1398 user_v3 = arg;
1399 user_v3->payload_size = 0;
1400 }
1401 rc = 0;
1402 }
1403 }
1404 }
1405 break;
1406
1407 case SNDRV_LSM_ABORT_EVENT:
1408 dev_dbg(rtd->dev,
1409 "%s: %s\n",
1410 __func__, "SNDRV_LSM_ABORT_EVENT");
1411 atomic_set(&lsm_d->event_stop, 1);
1412 wake_up(&lsm_d->event_wait);
1413 break;
1414
1415 case SNDRV_LSM_START:
1416 dev_dbg(rtd->dev,
1417 "%s: %s\n",
1418 __func__, "SNDRV_LSM_START");
1419 rc = lsm_ops->lsm_start(cpe->core_handle, session);
1420 if (rc != 0) {
1421 dev_err(rtd->dev,
1422 "%s: lsm_start fail, err = %d\n",
1423 __func__, rc);
1424 return rc;
1425 }
1426 session->started = true;
1427 break;
1428
1429 case SNDRV_LSM_STOP:
1430 dev_dbg(rtd->dev,
1431 "%s: %s, lab_enable = %d, lab_thread_status = %d\n",
1432 __func__, "SNDRV_LSM_STOP",
1433 session->lab_enable,
1434 lab_d->thread_status);
1435 if ((session->lab_enable &&
1436 lab_d->thread_status ==
1437 MSM_LSM_LAB_THREAD_RUNNING)) {
1438 /* Explicitly stop LAB */
1439 rc = msm_cpe_lsm_lab_stop(substream);
1440 if (rc) {
1441 dev_err(rtd->dev,
1442 "%s: lab_stop failed, err = %d\n",
1443 __func__, rc);
1444 return rc;
1445 }
1446 }
1447
1448 rc = lsm_ops->lsm_stop(cpe->core_handle, session);
1449 if (rc != 0) {
1450 dev_err(rtd->dev,
1451 "%s: lsm_stop fail err = %d\n",
1452 __func__, rc);
1453
1454 return rc;
1455 }
1456 session->started = false;
1457 break;
1458
1459 case SNDRV_LSM_SET_PARAMS:
1460 memcpy(&det_params, arg,
1461 sizeof(det_params));
1462 if (det_params.num_confidence_levels <= 0) {
1463 dev_err(rtd->dev,
1464 "%s: %s: Invalid confidence levels %u\n",
1465 __func__, "SNDRV_LSM_SET_PARAMS",
1466 det_params.num_confidence_levels);
1467 return -EINVAL;
1468 }
1469
1470 session->num_confidence_levels =
1471 det_params.num_confidence_levels;
1472 rc = msm_cpe_lsm_get_conf_levels(session,
1473 det_params.conf_level);
1474 if (rc) {
1475 dev_err(rtd->dev,
1476 "%s: %s get_conf_levels fail, err = %d\n",
1477 __func__, "SNDRV_LSM_SET_PARAMS",
1478 rc);
1479 break;
1480 }
1481
1482 rc = lsm_ops->lsm_set_data(cpe->core_handle, session,
1483 det_params.detect_mode,
1484 det_params.detect_failure);
1485 if (rc) {
1486 dev_err(rtd->dev,
1487 "%s: lsm_set_data failed, err = %d\n",
1488 __func__, rc);
1489 return rc;
1490 }
1491
1492 kfree(session->conf_levels);
1493 session->conf_levels = NULL;
1494
1495 break;
1496
1497 case SNDRV_LSM_OUT_FORMAT_CFG: {
1498 struct snd_lsm_output_format_cfg u_fmt_cfg;
1499
1500 if (!arg) {
1501 dev_err(rtd->dev,
1502 "%s: Invalid argument to ioctl %s\n",
1503 __func__, "SNDRV_LSM_OUT_FORMAT_CFG");
1504 return -EINVAL;
1505 }
1506
1507 if (copy_from_user(&u_fmt_cfg, arg,
1508 sizeof(u_fmt_cfg))) {
1509 dev_err(rtd->dev,
1510 "%s: copy_from_user failed for out_fmt_cfg\n",
1511 __func__);
1512 return -EFAULT;
1513 }
1514
1515 if (msm_cpe_lsm_validate_out_format(substream,
1516 &u_fmt_cfg))
1517 return -EINVAL;
1518
1519 session->out_fmt_cfg.format = u_fmt_cfg.format;
1520 session->out_fmt_cfg.pack_mode = u_fmt_cfg.packing;
1521 session->out_fmt_cfg.data_path_events =
1522 u_fmt_cfg.events;
1523 session->out_fmt_cfg.transfer_mode = u_fmt_cfg.mode;
1524
1525 rc = lsm_ops->lsm_set_fmt_cfg(cpe->core_handle,
1526 session);
1527 if (rc) {
1528 dev_err(rtd->dev,
1529 "%s: lsm_set_fmt_cfg failed, err = %d\n",
1530 __func__, rc);
1531 return rc;
1532 }
1533 }
1534 break;
1535
1536 case SNDRV_LSM_SET_PORT: {
1537 u32 port_id = cpe->input_port_id;
1538
1539 dev_dbg(rtd->dev, "%s: %s\n", __func__, "SNDRV_LSM_SET_PORT");
1540 rc = lsm_ops->lsm_set_port(cpe->core_handle, session, &port_id);
1541 if (rc) {
1542 dev_err(rtd->dev,
1543 "%s: lsm_set_port failed, err = %d\n",
1544 __func__, rc);
1545 return rc;
1546 }
1547 }
1548 break;
1549
1550 default:
1551 dev_dbg(rtd->dev,
1552 "%s: Default snd_lib_ioctl cmd 0x%x\n",
1553 __func__, cmd);
1554 rc = snd_pcm_lib_ioctl(substream, cmd, arg);
1555 }
1556
1557 return rc;
1558}
1559
1560static int msm_cpe_lsm_lab_start(struct snd_pcm_substream *substream,
1561 u16 event_det_status)
1562{
1563 struct snd_soc_pcm_runtime *rtd;
1564 struct cpe_lsm_data *lsm_d = NULL;
1565 struct cpe_priv *cpe = NULL;
1566 struct cpe_lsm_session *session = NULL;
1567 struct cpe_lsm_lab *lab_d = NULL;
1568 struct cpe_hw_params *hw_params;
1569 struct wcd_cpe_lsm_ops *lsm_ops;
1570 struct wcd_cpe_afe_ops *afe_ops;
1571 struct wcd_cpe_afe_port_cfg *out_port;
1572 int rc;
1573
1574 if (!substream || !substream->private_data) {
1575 pr_err("%s: invalid substream (%pK)\n",
1576 __func__, substream);
1577 return -EINVAL;
1578 }
1579
1580 rtd = substream->private_data;
1581 lsm_d = cpe_get_lsm_data(substream);
1582 cpe = cpe_get_private_data(substream);
1583
1584 if (!cpe || !cpe->core_handle) {
1585 dev_err(rtd->dev,
1586 "%s: Invalid private data\n",
1587 __func__);
1588 return -EINVAL;
1589 }
1590
1591 if (!lsm_d || !lsm_d->lsm_session) {
1592 dev_err(rtd->dev,
1593 "%s: Invalid session data\n",
1594 __func__);
1595 return -EINVAL;
1596 }
1597
1598 session = lsm_d->lsm_session;
1599 lsm_ops = &cpe->lsm_ops;
1600 lab_d = &lsm_d->lab;
1601 afe_ops = &cpe->afe_ops;
1602 hw_params = &lsm_d->hw_params;
1603
1604 if (!session->started) {
1605 dev_dbg(rtd->dev,
1606 "%s: Session is stopped, cannot start LAB\n",
1607 __func__);
1608 return 0;
1609 }
1610
1611 reinit_completion(&lab_d->thread_complete);
1612
1613 if (session->lab_enable &&
1614 event_det_status ==
1615 LSM_VOICE_WAKEUP_STATUS_DETECTED) {
1616 out_port = &session->afe_out_port_cfg;
1617 out_port->port_id = session->afe_out_port_id;
1618 out_port->bit_width = hw_params->sample_size;
1619 out_port->num_channels = hw_params->channels;
1620 out_port->sample_rate = hw_params->sample_rate;
1621 dev_dbg(rtd->dev, "%s: port_id= %u, bit_width= %u, rate= %u\n",
1622 __func__, out_port->port_id, out_port->bit_width,
1623 out_port->sample_rate);
1624
1625 rc = afe_ops->afe_port_cmd_cfg(cpe->core_handle,
1626 out_port);
1627 if (rc) {
1628 dev_err(rtd->dev,
1629 "%s: Failed afe generic config v2, err = %d\n",
1630 __func__, rc);
1631 return rc;
1632 }
1633
1634 atomic_set(&lab_d->abort_read, 0);
1635 dev_dbg(rtd->dev,
1636 "%s: KW detected, scheduling LAB thread\n",
1637 __func__);
1638
1639 /*
1640 * Even though thread might be only scheduled and
1641 * not currently running, mark the internal driver
1642 * status to running so driver can cancel this thread
1643 * if it needs to before the thread gets chance to run.
1644 */
1645 lab_d->thread_status = MSM_LSM_LAB_THREAD_RUNNING;
1646 session->lsm_lab_thread = kthread_run(
1647 msm_cpe_lab_thread,
1648 lsm_d,
1649 "lab_thread");
1650 }
1651
1652 return 0;
1653}
1654
1655static bool msm_cpe_lsm_is_valid_stream(struct snd_pcm_substream *substream,
1656 const char *func)
1657{
1658 struct snd_soc_pcm_runtime *rtd;
1659 struct cpe_lsm_data *lsm_d = NULL;
1660 struct cpe_priv *cpe = NULL;
1661 struct cpe_lsm_session *session = NULL;
1662 struct wcd_cpe_lsm_ops *lsm_ops;
1663
1664 if (!substream || !substream->private_data) {
1665 pr_err("%s: invalid substream (%pK)\n",
1666 func, substream);
1667 return false;
1668 }
1669
1670 rtd = substream->private_data;
1671 lsm_d = cpe_get_lsm_data(substream);
1672 cpe = cpe_get_private_data(substream);
1673
1674 if (!cpe || !cpe->core_handle) {
1675 dev_err(rtd->dev,
1676 "%s: Invalid private data\n",
1677 func);
1678 return false;
1679 }
1680
1681 if (!lsm_d || !lsm_d->lsm_session) {
1682 dev_err(rtd->dev,
1683 "%s: Invalid session data\n",
1684 func);
1685 return false;
1686 }
1687
1688 session = lsm_d->lsm_session;
1689 lsm_ops = &cpe->lsm_ops;
1690
1691 if (!lsm_ops) {
1692 dev_err(rtd->dev,
1693 "%s: Invalid lsm_ops\n", func);
1694 return false;
1695 }
1696
1697 return true;
1698}
1699
1700static int msm_cpe_lsm_set_epd(struct snd_pcm_substream *substream,
1701 struct lsm_params_info *p_info)
1702{
1703 struct snd_soc_pcm_runtime *rtd;
1704 struct cpe_lsm_data *lsm_d = NULL;
1705 struct cpe_priv *cpe = NULL;
1706 struct cpe_lsm_session *session = NULL;
1707 struct wcd_cpe_lsm_ops *lsm_ops;
1708 struct snd_lsm_ep_det_thres epd_thres;
1709 int rc;
1710
1711 if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
1712 return -EINVAL;
1713
1714 rtd = substream->private_data;
1715 lsm_d = cpe_get_lsm_data(substream);
1716 cpe = cpe_get_private_data(substream);
1717 session = lsm_d->lsm_session;
1718 lsm_ops = &cpe->lsm_ops;
1719
1720 if (p_info->param_size != sizeof(epd_thres)) {
1721 dev_err(rtd->dev,
1722 "%s: Invalid param_size %d\n",
1723 __func__, p_info->param_size);
1724 rc = -EINVAL;
1725 goto done;
1726 }
1727
1728 if (copy_from_user(&epd_thres, p_info->param_data,
1729 p_info->param_size)) {
1730 dev_err(rtd->dev,
1731 "%s: copy_from_user failed, size = %d\n",
1732 __func__, p_info->param_size);
1733 rc = -EFAULT;
1734 goto done;
1735 }
1736
1737 rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
1738 session, p_info, &epd_thres,
1739 LSM_ENDPOINT_DETECT_THRESHOLD);
1740 if (unlikely(rc))
1741 dev_err(rtd->dev,
1742 "%s: set_one_param(epd_threshold) failed, rc %d\n",
1743 __func__, rc);
1744done:
1745 return rc;
1746}
1747
1748static int msm_cpe_lsm_set_mode(struct snd_pcm_substream *substream,
1749 struct lsm_params_info *p_info)
1750{
1751 struct snd_soc_pcm_runtime *rtd;
1752 struct cpe_lsm_data *lsm_d = NULL;
1753 struct cpe_priv *cpe = NULL;
1754 struct cpe_lsm_session *session = NULL;
1755 struct wcd_cpe_lsm_ops *lsm_ops;
1756 struct snd_lsm_detect_mode det_mode;
1757 int rc;
1758
1759 if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
1760 return -EINVAL;
1761
1762 rtd = substream->private_data;
1763 lsm_d = cpe_get_lsm_data(substream);
1764 cpe = cpe_get_private_data(substream);
1765 session = lsm_d->lsm_session;
1766 lsm_ops = &cpe->lsm_ops;
1767
1768 if (p_info->param_size != sizeof(det_mode)) {
1769 dev_err(rtd->dev,
1770 "%s: Invalid param_size %d\n",
1771 __func__, p_info->param_size);
1772 rc = -EINVAL;
1773 goto done;
1774 }
1775
1776 if (copy_from_user(&det_mode, p_info->param_data,
1777 p_info->param_size)) {
1778 dev_err(rtd->dev,
1779 "%s: copy_from_user failed, size = %d\n",
1780 __func__, p_info->param_size);
1781 rc = -EFAULT;
1782 goto done;
1783 }
1784
1785 rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
1786 session, p_info, &det_mode,
1787 LSM_OPERATION_MODE);
1788 if (unlikely(rc))
1789 dev_err(rtd->dev,
1790 "%s: set_one_param(epd_threshold) failed, rc %d\n",
1791 __func__, rc);
1792done:
1793 return rc;
1794}
1795
1796static int msm_cpe_lsm_set_gain(struct snd_pcm_substream *substream,
1797 struct lsm_params_info *p_info)
1798{
1799 struct snd_soc_pcm_runtime *rtd;
1800 struct cpe_lsm_data *lsm_d = NULL;
1801 struct cpe_priv *cpe = NULL;
1802 struct cpe_lsm_session *session = NULL;
1803 struct wcd_cpe_lsm_ops *lsm_ops;
1804 struct snd_lsm_gain gain;
1805 int rc;
1806
1807 if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
1808 return -EINVAL;
1809
1810 rtd = substream->private_data;
1811 lsm_d = cpe_get_lsm_data(substream);
1812 cpe = cpe_get_private_data(substream);
1813 session = lsm_d->lsm_session;
1814 lsm_ops = &cpe->lsm_ops;
1815
1816 if (p_info->param_size != sizeof(gain)) {
1817 dev_err(rtd->dev,
1818 "%s: Invalid param_size %d\n",
1819 __func__, p_info->param_size);
1820 rc = -EINVAL;
1821 goto done;
1822 }
1823
1824 if (copy_from_user(&gain, p_info->param_data,
1825 p_info->param_size)) {
1826 dev_err(rtd->dev,
1827 "%s: copy_from_user failed, size = %d\n",
1828 __func__, p_info->param_size);
1829 rc = -EFAULT;
1830 goto done;
1831 }
1832
1833 rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
1834 session, p_info, &gain,
1835 LSM_GAIN);
1836 if (unlikely(rc))
1837 dev_err(rtd->dev,
1838 "%s: set_one_param(epd_threshold) failed, rc %d\n",
1839 __func__, rc);
1840done:
1841 return rc;
1842
1843}
1844
1845static int msm_cpe_lsm_set_conf(struct snd_pcm_substream *substream,
1846 struct lsm_params_info *p_info)
1847{
1848 struct snd_soc_pcm_runtime *rtd;
1849 struct cpe_lsm_data *lsm_d = NULL;
1850 struct cpe_priv *cpe = NULL;
1851 struct cpe_lsm_session *session = NULL;
1852 struct wcd_cpe_lsm_ops *lsm_ops;
1853 int rc;
1854
1855 if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
1856 return -EINVAL;
1857
1858 rtd = substream->private_data;
1859 lsm_d = cpe_get_lsm_data(substream);
1860 cpe = cpe_get_private_data(substream);
1861 session = lsm_d->lsm_session;
1862 lsm_ops = &cpe->lsm_ops;
1863
1864 session->num_confidence_levels =
1865 p_info->param_size;
1866 rc = msm_cpe_lsm_get_conf_levels(session,
1867 p_info->param_data);
1868 if (rc) {
1869 dev_err(rtd->dev,
1870 "%s: get_conf_levels failed, err = %d\n",
1871 __func__, rc);
1872 goto done;
1873 }
1874
1875 rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
1876 session, p_info, NULL,
1877 LSM_MIN_CONFIDENCE_LEVELS);
1878 if (unlikely(rc))
1879 dev_err(rtd->dev,
1880 "%s: set_one_param(conf_levels) failed, rc %d\n",
1881 __func__, rc);
1882done:
1883 return rc;
1884}
1885
1886static int msm_cpe_lsm_reg_model(struct snd_pcm_substream *substream,
1887 struct lsm_params_info *p_info)
1888{
1889 struct snd_soc_pcm_runtime *rtd;
1890 struct cpe_lsm_data *lsm_d = NULL;
1891 struct cpe_priv *cpe = NULL;
1892 struct cpe_lsm_session *session = NULL;
1893 struct wcd_cpe_lsm_ops *lsm_ops;
1894 int rc;
1895 size_t offset;
1896 u8 *snd_model_ptr;
1897
1898 if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
1899 return -EINVAL;
1900
1901 rtd = substream->private_data;
1902 lsm_d = cpe_get_lsm_data(substream);
1903 cpe = cpe_get_private_data(substream);
1904 session = lsm_d->lsm_session;
1905 lsm_ops = &cpe->lsm_ops;
1906
1907 lsm_ops->lsm_get_snd_model_offset(cpe->core_handle,
1908 session, &offset);
1909 /* Check if 'p_info->param_size + offset' crosses U32_MAX. */
1910 if (p_info->param_size > U32_MAX - offset) {
1911 dev_err(rtd->dev,
1912 "%s: Invalid param_size %d\n",
1913 __func__, p_info->param_size);
1914 return -EINVAL;
1915 }
1916 session->snd_model_size = p_info->param_size + offset;
1917
1918 session->snd_model_data = vzalloc(session->snd_model_size);
1919 if (!session->snd_model_data)
1920 return -ENOMEM;
1921
1922 snd_model_ptr = ((u8 *) session->snd_model_data) + offset;
1923
1924 if (copy_from_user(snd_model_ptr,
1925 p_info->param_data, p_info->param_size)) {
1926 dev_err(rtd->dev,
1927 "%s: copy_from_user for snd_model failed\n",
1928 __func__);
1929 rc = -EFAULT;
1930 goto free_snd_model_data;
1931 }
1932
1933 rc = lsm_ops->lsm_shmem_alloc(cpe->core_handle, session,
1934 session->snd_model_size);
1935 if (rc != 0) {
1936 dev_err(rtd->dev,
1937 "%s: shared memory allocation failed, err = %d\n",
1938 __func__, rc);
1939 rc = -EINVAL;
1940 goto free_snd_model_data;
1941 }
1942
1943 rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
1944 session, p_info, NULL,
1945 LSM_REG_SND_MODEL);
1946 if (unlikely(rc)) {
1947 dev_err(rtd->dev,
1948 "%s: set_one_param(snd_model) failed, rc %d\n",
1949 __func__, rc);
1950 goto dealloc_shmem;
1951 }
1952 return 0;
1953
1954dealloc_shmem:
1955 lsm_ops->lsm_shmem_dealloc(cpe->core_handle, session);
1956
1957free_snd_model_data:
1958 vfree(session->snd_model_data);
1959 return rc;
1960}
1961
1962static int msm_cpe_lsm_dereg_model(struct snd_pcm_substream *substream,
1963 struct lsm_params_info *p_info)
1964{
1965 struct snd_soc_pcm_runtime *rtd;
1966 struct cpe_lsm_data *lsm_d = NULL;
1967 struct cpe_priv *cpe = NULL;
1968 struct cpe_lsm_session *session = NULL;
1969 struct wcd_cpe_lsm_ops *lsm_ops;
1970 int rc;
1971
1972 if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
1973 return -EINVAL;
1974
1975 rtd = substream->private_data;
1976 lsm_d = cpe_get_lsm_data(substream);
1977 cpe = cpe_get_private_data(substream);
1978 session = lsm_d->lsm_session;
1979 lsm_ops = &cpe->lsm_ops;
1980
1981 rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
1982 session, p_info, NULL,
1983 LSM_DEREG_SND_MODEL);
1984 if (rc)
1985 dev_err(rtd->dev,
1986 "%s: dereg_snd_model failed\n",
1987 __func__);
1988 return lsm_ops->lsm_shmem_dealloc(cpe->core_handle, session);
1989}
1990
1991static int msm_cpe_lsm_set_custom(struct snd_pcm_substream *substream,
1992 struct lsm_params_info *p_info)
1993{
1994 struct snd_soc_pcm_runtime *rtd;
1995 struct cpe_lsm_data *lsm_d = NULL;
1996 struct cpe_priv *cpe = NULL;
1997 struct cpe_lsm_session *session = NULL;
1998 struct wcd_cpe_lsm_ops *lsm_ops;
1999 u8 *data;
2000 int rc;
2001
2002 if (!msm_cpe_lsm_is_valid_stream(substream, __func__))
2003 return -EINVAL;
2004
2005 rtd = substream->private_data;
2006 lsm_d = cpe_get_lsm_data(substream);
2007 cpe = cpe_get_private_data(substream);
2008 session = lsm_d->lsm_session;
2009 lsm_ops = &cpe->lsm_ops;
2010
2011 if (p_info->param_size > MSM_CPE_MAX_CUSTOM_PARAM_SIZE) {
2012 dev_err(rtd->dev,
2013 "%s: invalid size %d, max allowed %d\n",
2014 __func__, p_info->param_size,
2015 MSM_CPE_MAX_CUSTOM_PARAM_SIZE);
2016 return -EINVAL;
2017 }
2018
2019 data = kzalloc(p_info->param_size, GFP_KERNEL);
2020 if (!data)
2021 return -ENOMEM;
2022
2023 if (copy_from_user(data, p_info->param_data,
2024 p_info->param_size)) {
2025 dev_err(rtd->dev,
2026 "%s: copy_from_user failed for custom params, size = %d\n",
2027 __func__, p_info->param_size);
2028 rc = -EFAULT;
2029 goto err_ret;
2030 }
2031
2032 rc = lsm_ops->lsm_set_one_param(cpe->core_handle,
2033 session, p_info, data,
2034 LSM_CUSTOM_PARAMS);
2035 if (rc)
2036 dev_err(rtd->dev,
2037 "%s: custom_params failed, err = %d\n",
2038 __func__, rc);
2039err_ret:
2040 kfree(data);
2041 return rc;
2042}
2043
2044static int msm_cpe_lsm_process_params(struct snd_pcm_substream *substream,
2045 struct snd_lsm_module_params *p_data,
2046 void *params)
2047{
2048 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2049 struct lsm_params_info *p_info;
2050 int i;
2051 int rc = 0;
2052
2053 p_info = (struct lsm_params_info *) params;
2054
2055 for (i = 0; i < p_data->num_params; i++) {
2056 dev_dbg(rtd->dev,
2057 "%s: param (%d), module_id = 0x%x, param_id = 0x%x, param_size = 0x%x, param_type = 0x%x\n",
2058 __func__, i, p_info->module_id,
2059 p_info->param_id, p_info->param_size,
2060 p_info->param_type);
2061
2062 switch (p_info->param_type) {
2063 case LSM_ENDPOINT_DETECT_THRESHOLD:
2064 rc = msm_cpe_lsm_set_epd(substream, p_info);
2065 break;
2066 case LSM_OPERATION_MODE:
2067 rc = msm_cpe_lsm_set_mode(substream, p_info);
2068 break;
2069 case LSM_GAIN:
2070 rc = msm_cpe_lsm_set_gain(substream, p_info);
2071 break;
2072 case LSM_MIN_CONFIDENCE_LEVELS:
2073 rc = msm_cpe_lsm_set_conf(substream, p_info);
2074 break;
2075 case LSM_REG_SND_MODEL:
2076 rc = msm_cpe_lsm_reg_model(substream, p_info);
2077 break;
2078 case LSM_DEREG_SND_MODEL:
2079 rc = msm_cpe_lsm_dereg_model(substream, p_info);
2080 break;
2081 case LSM_CUSTOM_PARAMS:
2082 rc = msm_cpe_lsm_set_custom(substream, p_info);
2083 break;
2084 default:
2085 dev_err(rtd->dev,
2086 "%s: Invalid param_type %d\n",
2087 __func__, p_info->param_type);
2088 rc = -EINVAL;
2089 break;
2090 }
2091 if (rc) {
2092 pr_err("%s: set_param fail for param_type %d\n",
2093 __func__, p_info->param_type);
2094 return rc;
2095 }
2096
2097 p_info++;
2098 }
2099
2100 return rc;
2101}
2102
2103static int msm_cpe_lsm_ioctl(struct snd_pcm_substream *substream,
2104 unsigned int cmd, void *arg)
2105{
2106 int err = 0;
2107 struct snd_soc_pcm_runtime *rtd;
2108 struct cpe_priv *cpe = NULL;
2109 struct cpe_lsm_data *lsm_d = NULL;
2110 struct cpe_lsm_session *session = NULL;
2111 struct wcd_cpe_lsm_ops *lsm_ops;
2112
2113 if (!substream || !substream->private_data) {
2114 pr_err("%s: invalid substream (%pK)\n",
2115 __func__, substream);
2116 return -EINVAL;
2117 }
2118
2119 rtd = substream->private_data;
2120 lsm_d = cpe_get_lsm_data(substream);
2121 cpe = cpe_get_private_data(substream);
2122
2123 if (!cpe || !cpe->core_handle) {
2124 dev_err(rtd->dev,
2125 "%s: Invalid private data\n",
2126 __func__);
2127 return -EINVAL;
2128 }
2129
2130 if (!lsm_d || !lsm_d->lsm_session) {
2131 dev_err(rtd->dev,
2132 "%s: Invalid session data\n",
2133 __func__);
2134 return -EINVAL;
2135 }
2136
2137 MSM_CPE_LSM_GRAB_LOCK(&lsm_d->lsm_api_lock,
2138 "lsm_api_lock");
2139
2140 session = lsm_d->lsm_session;
2141 lsm_ops = &cpe->lsm_ops;
2142
2143 switch (cmd) {
2144 case SNDRV_LSM_REG_SND_MODEL_V2: {
2145 struct snd_lsm_sound_model_v2 snd_model;
2146
2147 if (session->is_topology_used) {
2148 dev_err(rtd->dev,
2149 "%s: %s: not supported if using topology\n",
2150 __func__, "LSM_REG_SND_MODEL_V2");
2151 err = -EINVAL;
2152 goto done;
2153 }
2154
2155 if (copy_from_user(&snd_model, (void *)arg,
2156 sizeof(struct snd_lsm_sound_model_v2))) {
2157 dev_err(rtd->dev,
2158 "%s: copy from user failed, size %zd\n",
2159 __func__,
2160 sizeof(struct snd_lsm_sound_model_v2));
2161 err = -EFAULT;
2162 goto done;
2163 }
2164
2165 err = msm_cpe_lsm_ioctl_shared(substream, cmd,
2166 &snd_model);
2167 }
2168 break;
2169 case SNDRV_LSM_EVENT_STATUS: {
2170 struct snd_lsm_event_status u_event_status;
2171 struct snd_lsm_event_status *event_status = NULL;
2172 int u_pld_size = 0;
2173
2174 if (copy_from_user(&u_event_status, (void *)arg,
2175 sizeof(struct snd_lsm_event_status))) {
2176 dev_err(rtd->dev,
2177 "%s: event status copy from user failed, size %zd\n",
2178 __func__,
2179 sizeof(struct snd_lsm_event_status));
2180 err = -EFAULT;
2181 goto done;
2182 }
2183
2184 if (u_event_status.payload_size >
2185 LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
2186 dev_err(rtd->dev,
2187 "%s: payload_size %d is invalid, max allowed = %d\n",
2188 __func__, u_event_status.payload_size,
2189 LISTEN_MAX_STATUS_PAYLOAD_SIZE);
2190 err = -EINVAL;
2191 goto done;
2192 }
2193
2194 u_pld_size = sizeof(struct snd_lsm_event_status) +
2195 u_event_status.payload_size;
2196
2197 event_status = kzalloc(u_pld_size, GFP_KERNEL);
2198 if (!event_status) {
2199 err = -ENOMEM;
2200 goto done;
2201 } else {
2202 event_status->payload_size =
2203 u_event_status.payload_size;
2204 err = msm_cpe_lsm_ioctl_shared(substream,
2205 cmd, event_status);
2206 }
2207
2208 if (!err && copy_to_user(arg, event_status, u_pld_size)) {
2209 dev_err(rtd->dev,
2210 "%s: copy to user failed\n",
2211 __func__);
2212 kfree(event_status);
2213 err = -EFAULT;
2214 goto done;
2215 }
2216
2217 msm_cpe_lsm_lab_start(substream, event_status->status);
2218 msm_cpe_process_event_status_done(lsm_d);
2219 kfree(event_status);
2220 }
2221 break;
2222 case SNDRV_LSM_EVENT_STATUS_V3: {
2223 struct snd_lsm_event_status_v3 u_event_status;
2224 struct snd_lsm_event_status_v3 *event_status = NULL;
2225 int u_pld_size = 0;
2226
2227 if (copy_from_user(&u_event_status, (void *)arg,
2228 sizeof(struct snd_lsm_event_status_v3))) {
2229 dev_err(rtd->dev,
2230 "%s: event status copy from user failed, size %zd\n",
2231 __func__,
2232 sizeof(struct snd_lsm_event_status_v3));
2233 err = -EFAULT;
2234 goto done;
2235 }
2236
2237 if (u_event_status.payload_size >
2238 LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
2239 dev_err(rtd->dev,
2240 "%s: payload_size %d is invalid, max allowed = %d\n",
2241 __func__, u_event_status.payload_size,
2242 LISTEN_MAX_STATUS_PAYLOAD_SIZE);
2243 err = -EINVAL;
2244 goto done;
2245 }
2246
2247 u_pld_size = sizeof(struct snd_lsm_event_status_v3) +
2248 u_event_status.payload_size;
2249
2250 event_status = kzalloc(u_pld_size, GFP_KERNEL);
2251 if (!event_status) {
2252 err = -ENOMEM;
2253 goto done;
2254 } else {
2255 event_status->payload_size =
2256 u_event_status.payload_size;
2257 err = msm_cpe_lsm_ioctl_shared(substream,
2258 cmd, event_status);
2259 }
2260
2261 if (!err && copy_to_user(arg, event_status, u_pld_size)) {
2262 dev_err(rtd->dev,
2263 "%s: copy to user failed\n",
2264 __func__);
2265 kfree(event_status);
2266 err = -EFAULT;
2267 goto done;
2268 }
2269
2270 msm_cpe_lsm_lab_start(substream, event_status->status);
2271 msm_cpe_process_event_status_done(lsm_d);
2272 kfree(event_status);
2273 }
2274 break;
2275 case SNDRV_LSM_SET_PARAMS: {
2276 struct snd_lsm_detection_params det_params;
2277
2278 if (session->is_topology_used) {
2279 dev_err(rtd->dev,
2280 "%s: %s: not supported if using topology\n",
2281 __func__, "SNDRV_LSM_SET_PARAMS");
2282 err = -EINVAL;
2283 goto done;
2284 }
2285
2286 if (copy_from_user(&det_params, (void *) arg,
2287 sizeof(det_params))) {
2288 dev_err(rtd->dev,
2289 "%s: %s: copy_from_user failed, size = %zd\n",
2290 __func__, "SNDRV_LSM_SET_PARAMS",
2291 sizeof(det_params));
2292 err = -EFAULT;
2293 goto done;
2294 }
2295
2296 err = msm_cpe_lsm_ioctl_shared(substream, cmd,
2297 &det_params);
2298 }
2299 break;
2300
2301 case SNDRV_LSM_SET_MODULE_PARAMS: {
2302 struct snd_lsm_module_params p_data;
2303 size_t p_size;
2304 u8 *params;
2305
2306 if (!session->is_topology_used) {
2307 dev_err(rtd->dev,
2308 "%s: %s: not supported if not using topology\n",
2309 __func__, "SET_MODULE_PARAMS");
2310 err = -EINVAL;
2311 goto done;
2312 }
2313
2314 if (!arg) {
2315 dev_err(rtd->dev,
2316 "%s: %s: No Param data to set\n",
2317 __func__, "SET_MODULE_PARAMS");
2318 err = -EINVAL;
2319 goto done;
2320 }
2321
2322 if (copy_from_user(&p_data, arg,
2323 sizeof(p_data))) {
2324 dev_err(rtd->dev,
2325 "%s: %s: copy_from_user failed, size = %zd\n",
2326 __func__, "p_data", sizeof(p_data));
2327 err = -EFAULT;
2328 goto done;
2329 }
2330
2331 if (p_data.num_params > LSM_PARAMS_MAX) {
2332 dev_err(rtd->dev,
2333 "%s: %s: Invalid num_params %d\n",
2334 __func__, "SET_MODULE_PARAMS",
2335 p_data.num_params);
2336 err = -EINVAL;
2337 goto done;
2338 }
2339
2340 p_size = p_data.num_params *
2341 sizeof(struct lsm_params_info);
2342
2343 if (p_data.data_size != p_size) {
2344 dev_err(rtd->dev,
2345 "%s: %s: Invalid size %zd\n",
2346 __func__, "SET_MODULE_PARAMS", p_size);
2347
2348 err = -EFAULT;
2349 goto done;
2350 }
2351
2352 params = kzalloc(p_size, GFP_KERNEL);
2353 if (!params) {
2354 err = -ENOMEM;
2355 goto done;
2356 }
2357
2358 if (copy_from_user(params, p_data.params,
2359 p_data.data_size)) {
2360 dev_err(rtd->dev,
2361 "%s: %s: copy_from_user failed, size = %d\n",
2362 __func__, "params", p_data.data_size);
2363 kfree(params);
2364 err = -EFAULT;
2365 goto done;
2366 }
2367
2368 err = msm_cpe_lsm_process_params(substream, &p_data, params);
2369 if (err)
2370 dev_err(rtd->dev,
2371 "%s: %s: Failed to set params, err = %d\n",
2372 __func__, "SET_MODULE_PARAMS", err);
2373 kfree(params);
2374 break;
2375 }
2376 default:
2377 err = msm_cpe_lsm_ioctl_shared(substream, cmd, arg);
2378 break;
2379 }
2380
2381done:
2382 MSM_CPE_LSM_REL_LOCK(&lsm_d->lsm_api_lock,
2383 "lsm_api_lock");
2384 return err;
2385}
2386
2387#ifdef CONFIG_COMPAT
2388struct snd_lsm_sound_model_v2_32 {
2389 compat_uptr_t data;
2390 compat_uptr_t confidence_level;
2391 u32 data_size;
2392 enum lsm_detection_mode detection_mode;
2393 u8 num_confidence_levels;
2394 bool detect_failure;
2395};
2396
2397struct snd_lsm_detection_params_32 {
2398 compat_uptr_t conf_level;
2399 enum lsm_detection_mode detect_mode;
2400 u8 num_confidence_levels;
2401 bool detect_failure;
2402};
2403
2404struct lsm_params_info_32 {
2405 u32 module_id;
2406 u32 param_id;
2407 u32 param_size;
2408 compat_uptr_t param_data;
2409 uint32_t param_type;
2410};
2411
2412struct snd_lsm_module_params_32 {
2413 compat_uptr_t params;
2414 u32 num_params;
2415 u32 data_size;
2416};
2417
2418enum {
2419 SNDRV_LSM_REG_SND_MODEL_V2_32 =
2420 _IOW('U', 0x07, struct snd_lsm_sound_model_v2_32),
2421 SNDRV_LSM_SET_PARAMS32 =
2422 _IOW('U', 0x0A, struct snd_lsm_detection_params_32),
2423 SNDRV_LSM_SET_MODULE_PARAMS_32 =
2424 _IOW('U', 0x0B, struct snd_lsm_module_params_32),
2425};
2426
2427static int msm_cpe_lsm_ioctl_compat(struct snd_pcm_substream *substream,
2428 unsigned int cmd, void *arg)
2429{
2430 int err = 0;
2431 struct snd_soc_pcm_runtime *rtd;
2432 struct cpe_priv *cpe = NULL;
2433 struct cpe_lsm_data *lsm_d = NULL;
2434 struct cpe_lsm_session *session = NULL;
2435 struct wcd_cpe_lsm_ops *lsm_ops;
2436
2437 if (!substream || !substream->private_data) {
2438 pr_err("%s: invalid substream (%pK)\n",
2439 __func__, substream);
2440 return -EINVAL;
2441 }
2442
2443 rtd = substream->private_data;
2444 lsm_d = cpe_get_lsm_data(substream);
2445 cpe = cpe_get_private_data(substream);
2446
2447 if (!cpe || !cpe->core_handle) {
2448 dev_err(rtd->dev,
2449 "%s: Invalid private data\n",
2450 __func__);
2451 return -EINVAL;
2452 }
2453
2454 if (!lsm_d || !lsm_d->lsm_session) {
2455 dev_err(rtd->dev,
2456 "%s: Invalid session data\n",
2457 __func__);
2458 return -EINVAL;
2459 }
2460
2461 MSM_CPE_LSM_GRAB_LOCK(&lsm_d->lsm_api_lock,
2462 "lsm_api_lock");
2463
2464 session = lsm_d->lsm_session;
2465 lsm_ops = &cpe->lsm_ops;
2466
2467 switch (cmd) {
2468 case SNDRV_LSM_REG_SND_MODEL_V2_32: {
2469 struct snd_lsm_sound_model_v2 snd_model;
2470 struct snd_lsm_sound_model_v2_32 snd_model32;
2471
2472 if (session->is_topology_used) {
2473 dev_err(rtd->dev,
2474 "%s: %s: not supported if using topology\n",
2475 __func__, "LSM_REG_SND_MODEL_V2_32");
2476 err = -EINVAL;
2477 goto done;
2478 }
2479
2480 dev_dbg(rtd->dev,
2481 "%s: ioctl %s\n", __func__,
2482 "SNDRV_LSM_REG_SND_MODEL_V2_32");
2483
2484 if (copy_from_user(&snd_model32, (void *)arg,
2485 sizeof(snd_model32))) {
2486 dev_err(rtd->dev,
2487 "%s: copy from user failed, size %zd\n",
2488 __func__,
2489 sizeof(snd_model32));
2490 err = -EFAULT;
2491 goto done;
2492 }
2493
2494 snd_model.data = compat_ptr(snd_model32.data);
2495 snd_model.confidence_level =
2496 compat_ptr(snd_model32.confidence_level);
2497 snd_model.data_size = snd_model32.data_size;
2498 snd_model.detect_failure = snd_model32.detect_failure;
2499 snd_model.num_confidence_levels =
2500 snd_model32.num_confidence_levels;
2501 snd_model.detection_mode = snd_model32.detection_mode;
2502
2503 cmd = SNDRV_LSM_REG_SND_MODEL_V2;
2504 err = msm_cpe_lsm_ioctl_shared(substream, cmd, &snd_model);
2505 if (err)
2506 dev_err(rtd->dev,
2507 "%s: %s failed, error = %d\n",
2508 __func__,
2509 "SNDRV_LSM_REG_SND_MODEL_V2_32",
2510 err);
2511 }
2512 break;
2513 case SNDRV_LSM_EVENT_STATUS: {
2514 struct snd_lsm_event_status *event_status = NULL;
2515 struct snd_lsm_event_status u_event_status32;
2516 struct snd_lsm_event_status *udata_32 = NULL;
2517 int u_pld_size = 0;
2518
2519 dev_dbg(rtd->dev,
2520 "%s: ioctl %s\n", __func__,
2521 "SNDRV_LSM_EVENT_STATUS32");
2522
2523 if (copy_from_user(&u_event_status32, (void *)arg,
2524 sizeof(struct snd_lsm_event_status))) {
2525 dev_err(rtd->dev,
2526 "%s: event status copy from user failed, size %zd\n",
2527 __func__,
2528 sizeof(struct snd_lsm_event_status));
2529 err = -EFAULT;
2530 goto done;
2531 }
2532
2533 if (u_event_status32.payload_size >
2534 LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
2535 dev_err(rtd->dev,
2536 "%s: payload_size %d is invalid, max allowed = %d\n",
2537 __func__, u_event_status32.payload_size,
2538 LISTEN_MAX_STATUS_PAYLOAD_SIZE);
2539 err = -EINVAL;
2540 goto done;
2541 }
2542
2543 u_pld_size = sizeof(struct snd_lsm_event_status) +
2544 u_event_status32.payload_size;
2545 event_status = kzalloc(u_pld_size, GFP_KERNEL);
2546 if (!event_status) {
2547 dev_err(rtd->dev,
2548 "%s: No memory for event status\n",
2549 __func__);
2550 err = -ENOMEM;
2551 goto done;
2552 } else {
2553 event_status->payload_size =
2554 u_event_status32.payload_size;
2555 err = msm_cpe_lsm_ioctl_shared(substream,
2556 cmd, event_status);
2557 if (err)
2558 dev_err(rtd->dev,
2559 "%s: %s failed, error = %d\n",
2560 __func__,
2561 "SNDRV_LSM_EVENT_STATUS32",
2562 err);
2563 }
2564
2565 if (!err) {
2566 udata_32 = kzalloc(u_pld_size, GFP_KERNEL);
2567 if (!udata_32) {
2568 dev_err(rtd->dev,
2569 "%s: nomem for udata\n",
2570 __func__);
2571 err = -EFAULT;
2572 } else {
2573 udata_32->status = event_status->status;
2574 udata_32->payload_size =
2575 event_status->payload_size;
2576 memcpy(udata_32->payload,
2577 event_status->payload,
2578 u_pld_size);
2579 }
2580 }
2581
2582 if (!err && copy_to_user(arg, udata_32,
2583 u_pld_size)) {
2584 dev_err(rtd->dev,
2585 "%s: copy to user failed\n",
2586 __func__);
2587 kfree(event_status);
2588 kfree(udata_32);
2589 err = -EFAULT;
2590 goto done;
2591 }
2592
2593 msm_cpe_lsm_lab_start(substream, event_status->status);
2594 msm_cpe_process_event_status_done(lsm_d);
2595 kfree(event_status);
2596 kfree(udata_32);
2597 }
2598 break;
2599 case SNDRV_LSM_EVENT_STATUS_V3: {
2600 struct snd_lsm_event_status_v3 *event_status = NULL;
2601 struct snd_lsm_event_status_v3 u_event_status32;
2602 struct snd_lsm_event_status_v3 *udata_32 = NULL;
2603 int u_pld_size = 0;
2604
2605 dev_dbg(rtd->dev,
2606 "%s: ioctl %s\n", __func__,
2607 "SNDRV_LSM_EVENT_STATUS_V3_32");
2608
2609 if (copy_from_user(&u_event_status32, (void *)arg,
2610 sizeof(struct snd_lsm_event_status_v3))) {
2611 dev_err(rtd->dev,
2612 "%s: event status copy from user failed, size %zd\n",
2613 __func__,
2614 sizeof(struct snd_lsm_event_status_v3));
2615 err = -EFAULT;
2616 goto done;
2617 }
2618
2619 if (u_event_status32.payload_size >
2620 LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
2621 dev_err(rtd->dev,
2622 "%s: payload_size %d is invalid, max allowed = %d\n",
2623 __func__, u_event_status32.payload_size,
2624 LISTEN_MAX_STATUS_PAYLOAD_SIZE);
2625 err = -EINVAL;
2626 goto done;
2627 }
2628
2629 u_pld_size = sizeof(struct snd_lsm_event_status_v3) +
2630 u_event_status32.payload_size;
2631 event_status = kzalloc(u_pld_size, GFP_KERNEL);
2632 if (!event_status) {
2633 dev_err(rtd->dev,
2634 "%s: No memory for event status\n",
2635 __func__);
2636 err = -ENOMEM;
2637 goto done;
2638 } else {
2639 event_status->payload_size =
2640 u_event_status32.payload_size;
2641 err = msm_cpe_lsm_ioctl_shared(substream,
2642 cmd, event_status);
2643 if (err)
2644 dev_err(rtd->dev,
2645 "%s: %s failed, error = %d\n",
2646 __func__,
2647 "SNDRV_LSM_EVENT_STATUS_V3_32",
2648 err);
2649 }
2650
2651 if (!err) {
2652 udata_32 = kzalloc(u_pld_size, GFP_KERNEL);
2653 if (!udata_32) {
2654 dev_err(rtd->dev,
2655 "%s: nomem for udata\n",
2656 __func__);
2657 err = -EFAULT;
2658 } else {
2659 udata_32->timestamp_lsw =
2660 event_status->timestamp_lsw;
2661 udata_32->timestamp_msw =
2662 event_status->timestamp_msw;
2663 udata_32->status = event_status->status;
2664 udata_32->payload_size =
2665 event_status->payload_size;
2666 memcpy(udata_32->payload,
2667 event_status->payload,
2668 u_pld_size);
2669 }
2670 }
2671
2672 if (!err && copy_to_user(arg, udata_32,
2673 u_pld_size)) {
2674 dev_err(rtd->dev,
2675 "%s: copy to user failed\n",
2676 __func__);
2677 kfree(event_status);
2678 kfree(udata_32);
2679 err = -EFAULT;
2680 goto done;
2681 }
2682
2683 msm_cpe_lsm_lab_start(substream, event_status->status);
2684 msm_cpe_process_event_status_done(lsm_d);
2685 kfree(event_status);
2686 kfree(udata_32);
2687 }
2688 break;
2689 case SNDRV_LSM_SET_PARAMS32: {
2690 struct snd_lsm_detection_params_32 det_params32;
2691 struct snd_lsm_detection_params det_params;
2692
2693 if (session->is_topology_used) {
2694 dev_err(rtd->dev,
2695 "%s: %s: not supported if using topology\n",
2696 __func__, "SNDRV_LSM_SET_PARAMS32");
2697
2698 err = -EINVAL;
2699 goto done;
2700 }
2701
2702 if (copy_from_user(&det_params32, arg,
2703 sizeof(det_params32))) {
2704 err = -EFAULT;
2705 dev_err(rtd->dev,
2706 "%s: %s: copy_from_user failed, size = %zd\n",
2707 __func__, "SNDRV_LSM_SET_PARAMS_32",
2708 sizeof(det_params32));
2709 } else {
2710 det_params.conf_level =
2711 compat_ptr(det_params32.conf_level);
2712 det_params.detect_mode =
2713 det_params32.detect_mode;
2714 det_params.num_confidence_levels =
2715 det_params32.num_confidence_levels;
2716 det_params.detect_failure =
2717 det_params32.detect_failure;
2718 cmd = SNDRV_LSM_SET_PARAMS;
2719 err = msm_cpe_lsm_ioctl_shared(substream, cmd,
2720 &det_params);
2721 if (err)
2722 dev_err(rtd->dev,
2723 "%s: ioctl %s failed\n", __func__,
2724 "SNDRV_LSM_SET_PARAMS");
2725 }
2726
2727 break;
2728 }
2729
2730 case SNDRV_LSM_SET_MODULE_PARAMS_32: {
2731 struct snd_lsm_module_params_32 p_data_32;
2732 struct snd_lsm_module_params p_data;
2733 u8 *params, *params32;
2734 size_t p_size;
2735 struct lsm_params_info_32 *p_info_32;
2736 struct lsm_params_info *p_info;
2737 int i;
2738
2739 if (!session->is_topology_used) {
2740 dev_err(rtd->dev,
2741 "%s: %s: not supported if not using topology\n",
2742 __func__, "SET_MODULE_PARAMS_32");
2743 err = -EINVAL;
2744 goto done;
2745 }
2746
2747 if (copy_from_user(&p_data_32, arg,
2748 sizeof(p_data_32))) {
2749 dev_err(rtd->dev,
2750 "%s: %s: copy_from_user failed, size = %zd\n",
2751 __func__, "SET_MODULE_PARAMS_32",
2752 sizeof(p_data_32));
2753 err = -EFAULT;
2754 goto done;
2755 }
2756
2757 p_data.params = compat_ptr(p_data_32.params);
2758 p_data.num_params = p_data_32.num_params;
2759 p_data.data_size = p_data_32.data_size;
2760
2761 if (p_data.num_params > LSM_PARAMS_MAX) {
2762 dev_err(rtd->dev,
2763 "%s: %s: Invalid num_params %d\n",
2764 __func__, "SET_MODULE_PARAMS_32",
2765 p_data.num_params);
2766 err = -EINVAL;
2767 goto done;
2768 }
2769
2770 if (p_data.data_size !=
2771 (p_data.num_params * sizeof(struct lsm_params_info_32))) {
2772 dev_err(rtd->dev,
2773 "%s: %s: Invalid size %d\n",
2774 __func__, "SET_MODULE_PARAMS_32",
2775 p_data.data_size);
2776 err = -EINVAL;
2777 goto done;
2778 }
2779
2780 p_size = sizeof(struct lsm_params_info_32) *
2781 p_data.num_params;
2782
2783 params32 = kzalloc(p_size, GFP_KERNEL);
2784 if (!params32) {
2785 err = -ENOMEM;
2786 goto done;
2787 }
2788
2789 p_size = sizeof(struct lsm_params_info) * p_data.num_params;
2790 params = kzalloc(p_size, GFP_KERNEL);
2791 if (!params) {
2792 kfree(params32);
2793 err = -ENOMEM;
2794 goto done;
2795 }
2796
2797 if (copy_from_user(params32, p_data.params,
2798 p_data.data_size)) {
2799 dev_err(rtd->dev,
2800 "%s: %s: copy_from_user failed, size = %d\n",
2801 __func__, "params32", p_data.data_size);
2802 kfree(params32);
2803 kfree(params);
2804 err = -EFAULT;
2805 goto done;
2806 }
2807
2808 p_info_32 = (struct lsm_params_info_32 *) params32;
2809 p_info = (struct lsm_params_info *) params;
2810 for (i = 0; i < p_data.num_params; i++) {
2811 p_info->module_id = p_info_32->module_id;
2812 p_info->param_id = p_info_32->param_id;
2813 p_info->param_size = p_info_32->param_size;
2814 p_info->param_data = compat_ptr(p_info_32->param_data);
2815 p_info->param_type = p_info_32->param_type;
2816
2817 p_info_32++;
2818 p_info++;
2819 }
2820
2821 err = msm_cpe_lsm_process_params(substream,
2822 &p_data, params);
2823 if (err)
2824 dev_err(rtd->dev,
2825 "%s: Failed to process params, err = %d\n",
2826 __func__, err);
2827 kfree(params);
2828 kfree(params32);
2829 break;
2830 }
2831 case SNDRV_LSM_REG_SND_MODEL_V2:
2832 case SNDRV_LSM_SET_PARAMS:
2833 case SNDRV_LSM_SET_MODULE_PARAMS:
2834 /*
2835 * In ideal cases, the compat_ioctl should never be called
2836 * with the above unlocked ioctl commands. Print error
2837 * and return error if it does.
2838 */
2839 dev_err(rtd->dev,
2840 "%s: Invalid cmd for compat_ioctl\n",
2841 __func__);
2842 err = -EINVAL;
2843 break;
2844 default:
2845 err = msm_cpe_lsm_ioctl_shared(substream, cmd, arg);
2846 break;
2847 }
2848done:
2849 MSM_CPE_LSM_REL_LOCK(&lsm_d->lsm_api_lock,
2850 "lsm_api_lock");
2851 return err;
2852}
2853
2854#else
2855#define msm_cpe_lsm_ioctl_compat NULL
2856#endif
2857
2858/*
2859 * msm_cpe_lsm_prepare: prepare call from ASoC core for this platform
2860 * @substream: ASoC substream for which the operation is invoked
2861 *
2862 * start the AFE port on CPE associated for this listen session
2863 */
2864static int msm_cpe_lsm_prepare(struct snd_pcm_substream *substream)
2865{
2866 int rc = 0;
2867 struct cpe_priv *cpe = cpe_get_private_data(substream);
2868 struct cpe_lsm_data *lsm_d = cpe_get_lsm_data(substream);
2869 struct snd_soc_pcm_runtime *rtd = substream->private_data;
2870 struct wcd_cpe_afe_ops *afe_ops;
2871 struct wcd_cpe_afe_port_cfg *afe_cfg;
2872 struct cpe_lsm_session *lsm_session;
2873 struct cpe_lsm_lab *lab_d = &lsm_d->lab;
2874 struct snd_pcm_runtime *runtime = substream->runtime;
2875 struct lsm_hw_params lsm_param;
2876 struct wcd_cpe_lsm_ops *lsm_ops;
2877
2878 if (!cpe || !cpe->core_handle) {
2879 dev_err(rtd->dev,
2880 "%s: Invalid private data\n",
2881 __func__);
2882 return -EINVAL;
2883 }
2884
2885 if (!lsm_d || !lsm_d->lsm_session) {
2886 dev_err(rtd->dev,
2887 "%s: Invalid session data\n",
2888 __func__);
2889 return -EINVAL;
2890 }
2891 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
2892 runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
2893 pr_err("%s: XRUN ignore for now\n", __func__);
2894 return 0;
2895 }
2896
2897 lsm_session = lsm_d->lsm_session;
2898 lab_d->pcm_size = snd_pcm_lib_buffer_bytes(substream);
2899
2900 dev_dbg(rtd->dev,
2901 "%s: pcm_size 0x%x", __func__, lab_d->pcm_size);
2902
2903 if (lsm_d->cpe_prepared) {
2904 dev_dbg(rtd->dev, "%s: CPE is alredy prepared\n",
2905 __func__);
2906 return 0;
2907 }
2908
2909 lsm_ops = &cpe->lsm_ops;
2910 afe_ops = &cpe->afe_ops;
2911 afe_cfg = &(lsm_d->lsm_session->afe_port_cfg);
2912
2913 switch (cpe->input_port_id) {
2914 case AFE_PORT_ID_3:
2915 afe_cfg->port_id = AFE_PORT_ID_3;
2916 afe_cfg->bit_width = 16;
2917 afe_cfg->num_channels = 1;
2918 afe_cfg->sample_rate = SAMPLE_RATE_48KHZ;
2919 rc = afe_ops->afe_port_cmd_cfg(cpe->core_handle, afe_cfg);
2920 break;
2921 case AFE_PORT_ID_1:
2922 default:
2923 afe_cfg->port_id = AFE_PORT_ID_1;
2924 afe_cfg->bit_width = 16;
2925 afe_cfg->num_channels = 1;
2926 afe_cfg->sample_rate = SAMPLE_RATE_16KHZ;
2927 rc = afe_ops->afe_set_params(cpe->core_handle,
2928 afe_cfg, cpe->afe_mad_ctl);
2929 break;
2930 }
2931
2932 if (rc != 0) {
2933 dev_err(rtd->dev,
2934 "%s: cpe afe params failed for port = %d, err = %d\n",
2935 __func__, afe_cfg->port_id, rc);
2936 return rc;
2937 }
2938 lsm_param.sample_rate = afe_cfg->sample_rate;
2939 lsm_param.num_chs = afe_cfg->num_channels;
2940 lsm_param.bit_width = afe_cfg->bit_width;
2941 rc = lsm_ops->lsm_set_media_fmt_params(cpe->core_handle, lsm_session,
2942 &lsm_param);
2943 if (rc)
2944 dev_dbg(rtd->dev,
2945 "%s: failed to set lsm media fmt params, err = %d\n",
2946 __func__, rc);
2947
2948 /* Send connect to port (input) */
2949 rc = lsm_ops->lsm_set_port(cpe->core_handle, lsm_session,
2950 &cpe->input_port_id);
2951 if (rc) {
2952 dev_err(rtd->dev,
2953 "%s: Failed to set connect input port, err=%d\n",
2954 __func__, rc);
2955 return rc;
2956 }
2957
2958 if (cpe->input_port_id != 3) {
2959 rc = lsm_ops->lsm_get_afe_out_port_id(cpe->core_handle,
2960 lsm_session);
2961 if (rc != 0) {
2962 dev_err(rtd->dev,
2963 "%s: failed to get port id, err = %d\n",
2964 __func__, rc);
2965 return rc;
2966 }
2967 /* Send connect to port (output) */
2968 rc = lsm_ops->lsm_set_port(cpe->core_handle, lsm_session,
2969 &lsm_session->afe_out_port_id);
2970 if (rc) {
2971 dev_err(rtd->dev,
2972 "%s: Failed to set connect output port, err=%d\n",
2973 __func__, rc);
2974 return rc;
2975 }
2976 }
2977 rc = msm_cpe_afe_port_cntl(substream,
2978 cpe->core_handle,
2979 afe_ops, afe_cfg,
2980 AFE_CMD_PORT_START);
2981 if (rc)
2982 dev_err(rtd->dev,
2983 "%s: cpe_afe_port start failed, err = %d\n",
2984 __func__, rc);
2985 else
2986 lsm_d->cpe_prepared = true;
2987
2988 return rc;
2989}
2990
2991/*
2992 * msm_cpe_lsm_trigger: trigger call from ASoC core for this platform
2993 * @substream: ASoC substream for which the operation is invoked
2994 * @cmd: the trigger command from framework
2995 *
2996 * suspend/resume the AFE port on CPE associated with listen session
2997 */
2998static int msm_cpe_lsm_trigger(struct snd_pcm_substream *substream,
2999 int cmd)
3000{
3001 struct snd_soc_pcm_runtime *rtd = substream->private_data;
3002 struct cpe_priv *cpe = cpe_get_private_data(substream);
3003 struct cpe_lsm_data *lsm_d = cpe_get_lsm_data(substream);
3004 struct wcd_cpe_afe_ops *afe_ops;
3005 struct wcd_cpe_afe_port_cfg *afe_cfg;
3006 int afe_cmd = AFE_CMD_INVALID;
3007 int rc = 0;
3008
3009 if (!cpe || !cpe->core_handle) {
3010 dev_err(rtd->dev,
3011 "%s: Invalid private data\n",
3012 __func__);
3013 return -EINVAL;
3014 }
3015
3016 if (!lsm_d || !lsm_d->lsm_session) {
3017 dev_err(rtd->dev,
3018 "%s: Invalid session data\n",
3019 __func__);
3020 return -EINVAL;
3021 }
3022
3023 afe_ops = &cpe->afe_ops;
3024 afe_cfg = &(lsm_d->lsm_session->afe_port_cfg);
3025
3026 switch (cmd) {
3027 case SNDRV_PCM_TRIGGER_SUSPEND:
3028 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
3029 afe_cmd = AFE_CMD_PORT_SUSPEND;
3030 break;
3031
3032 case SNDRV_PCM_TRIGGER_RESUME:
3033 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
3034 afe_cmd = AFE_CMD_PORT_RESUME;
3035 break;
3036
3037 default:
3038 afe_cmd = AFE_CMD_INVALID;
3039 dev_dbg(rtd->dev,
3040 "%s: unhandled trigger cmd %d\n",
3041 __func__, cmd);
3042 break;
3043 }
3044
3045 if (afe_cmd != AFE_CMD_INVALID)
3046 rc = msm_cpe_afe_port_cntl(substream,
3047 cpe->core_handle,
3048 afe_ops, afe_cfg,
3049 afe_cmd);
3050
3051 return rc;
3052}
3053
3054static int msm_cpe_lsm_hwparams(struct snd_pcm_substream *substream,
3055 struct snd_pcm_hw_params *params)
3056{
3057
3058 struct snd_soc_pcm_runtime *rtd = substream->private_data;
3059 struct cpe_lsm_data *lsm_d = cpe_get_lsm_data(substream);
3060 struct cpe_priv *cpe = cpe_get_private_data(substream);
3061 struct cpe_lsm_session *session = NULL;
3062 struct cpe_hw_params *hw_params = NULL;
3063
3064 if (!cpe || !cpe->core_handle) {
3065 dev_err(rtd->dev,
3066 "%s: Invalid %s\n",
3067 __func__,
3068 (!cpe) ? "cpe" : "core");
3069 return -EINVAL;
3070 }
3071
3072 if (!lsm_d || !lsm_d->lsm_session) {
3073 dev_err(rtd->dev,
3074 "%s: Invalid %s\n",
3075 __func__,
3076 (!lsm_d) ? "priv_data" : "session");
3077 return -EINVAL;
3078 }
3079
3080 session = lsm_d->lsm_session;
3081 hw_params = &lsm_d->hw_params;
3082 hw_params->buf_sz = (params_buffer_bytes(params)
3083 / params_periods(params));
3084 hw_params->period_count = params_periods(params);
3085 hw_params->channels = params_channels(params);
3086 hw_params->sample_rate = params_rate(params);
3087
3088 if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE)
3089 hw_params->sample_size = 16;
3090 else if (params_format(params) ==
3091 SNDRV_PCM_FORMAT_S24_LE)
3092 hw_params->sample_size = 24;
3093 else if (params_format(params) ==
3094 SNDRV_PCM_FORMAT_S32_LE)
3095 hw_params->sample_size = 32;
3096 else {
3097 dev_err(rtd->dev,
3098 "%s: Invalid Format 0x%x\n",
3099 __func__, params_format(params));
3100 return -EINVAL;
3101 }
3102
3103 dev_dbg(rtd->dev,
3104 "%s: Format %d buffer size(bytes) %d period count %d\n"
3105 " Channel %d period in bytes 0x%x Period Size 0x%x rate = %d\n",
3106 __func__, params_format(params), params_buffer_bytes(params),
3107 params_periods(params), params_channels(params),
3108 params_period_bytes(params), params_period_size(params),
3109 params_rate(params));
3110
3111 return 0;
3112}
3113
3114static snd_pcm_uframes_t msm_cpe_lsm_pointer(
3115 struct snd_pcm_substream *substream)
3116{
3117
3118 struct cpe_lsm_data *lsm_d = cpe_get_lsm_data(substream);
3119 struct snd_pcm_runtime *runtime = substream->runtime;
3120 struct snd_soc_pcm_runtime *rtd = substream->private_data;
3121 struct cpe_lsm_session *session;
3122 struct cpe_lsm_lab *lab_d = &lsm_d->lab;
3123
3124 session = lsm_d->lsm_session;
3125 if (lab_d->dma_write >= lab_d->pcm_size)
3126 lab_d->dma_write = 0;
3127 dev_dbg(rtd->dev,
3128 "%s:pcm_dma_pos = %d\n",
3129 __func__, lab_d->dma_write);
3130
3131 return bytes_to_frames(runtime, (lab_d->dma_write));
3132}
3133
3134static int msm_cpe_lsm_copy(struct snd_pcm_substream *substream, int a,
3135 snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
3136{
3137 struct cpe_lsm_data *lsm_d = cpe_get_lsm_data(substream);
3138 struct snd_soc_pcm_runtime *rtd = substream->private_data;
3139 struct snd_pcm_runtime *runtime = substream->runtime;
3140 struct cpe_lsm_session *session;
3141 struct cpe_lsm_lab *lab_d = &lsm_d->lab;
3142 char *pcm_buf;
3143 int fbytes = 0;
3144 int rc = 0;
3145
3146 fbytes = frames_to_bytes(runtime, frames);
3147 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
3148 runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
3149 pr_err("%s: XRUN ignore for now\n", __func__);
3150 return 0;
3151 }
3152 session = lsm_d->lsm_session;
3153
3154 /* Check if buffer reading is already in error state */
3155 if (lab_d->thread_status == MSM_LSM_LAB_THREAD_ERROR) {
3156 dev_err(rtd->dev,
3157 "%s: Bufferring is in error state\n",
3158 __func__);
3159 /*
3160 * Advance the period so there is no wait in case
3161 * read is invoked even after error is propogated
3162 */
3163 atomic_inc(&lab_d->in_count);
3164 lab_d->dma_write += snd_pcm_lib_period_bytes(substream);
3165 snd_pcm_period_elapsed(substream);
3166 return -ENETRESET;
3167 } else if (lab_d->thread_status == MSM_LSM_LAB_THREAD_STOP) {
3168 dev_err(rtd->dev,
3169 "%s: Buferring is in stopped\n",
3170 __func__);
3171 return -EIO;
3172 }
3173
3174 rc = wait_event_timeout(lab_d->period_wait,
3175 (atomic_read(&lab_d->in_count) ||
3176 atomic_read(&lab_d->abort_read)),
3177 (2 * HZ));
3178 if (atomic_read(&lab_d->abort_read)) {
3179 pr_debug("%s: LSM LAB Abort read\n", __func__);
3180 return -EIO;
3181 }
3182 if (lab_d->thread_status != MSM_LSM_LAB_THREAD_RUNNING) {
3183 pr_err("%s: Lab stopped\n", __func__);
3184 return -EIO;
3185 }
3186 if (!rc) {
3187 pr_err("%s:LAB err wait_event_timeout\n", __func__);
3188 rc = -EAGAIN;
3189 goto fail;
3190 }
3191 if (lab_d->buf_idx >= (lsm_d->hw_params.period_count))
3192 lab_d->buf_idx = 0;
3193 pcm_buf = (lab_d->pcm_buf[lab_d->buf_idx].mem);
3194 pr_debug("%s: Buf IDX = 0x%x pcm_buf %pK\n",
3195 __func__, lab_d->buf_idx, pcm_buf);
3196 if (pcm_buf) {
3197 if (copy_to_user(buf, pcm_buf, fbytes)) {
3198 pr_err("Failed to copy buf to user\n");
3199 rc = -EFAULT;
3200 goto fail;
3201 }
3202 }
3203 lab_d->buf_idx++;
3204 atomic_dec(&lab_d->in_count);
3205 return 0;
3206fail:
3207 return rc;
3208}
3209
3210/*
3211 * msm_asoc_cpe_lsm_probe: ASoC framework for lsm platform driver
3212 * @platform: platform registered with ASoC core
3213 *
3214 * Allocate the private data for this platform and obtain the ops for
3215 * lsm and afe modules from underlying driver. Also find the codec
3216 * for this platform as specified by machine driver for ASoC framework.
3217 */
3218static int msm_asoc_cpe_lsm_probe(struct snd_soc_platform *platform)
3219{
3220 struct snd_soc_card *card;
3221 struct snd_soc_pcm_runtime *rtd;
3222 struct snd_soc_codec *codec;
3223 struct cpe_priv *cpe_priv;
3224 const struct snd_kcontrol_new *kcontrol;
3225 bool found_runtime = false;
3226 const char *cpe_dev_id = "qcom,msm-cpe-lsm-id";
3227 u32 port_id = 0;
3228 int ret = 0;
3229
3230 if (!platform || !platform->component.card) {
3231 pr_err("%s: Invalid platform or card\n",
3232 __func__);
3233 return -EINVAL;
3234 }
3235
3236 card = platform->component.card;
3237
3238 /* Match platform to codec */
3239 list_for_each_entry(rtd, &card->rtd_list, list) {
3240 if (!rtd->platform)
3241 continue;
3242 if (!strcmp(rtd->platform->component.name,
3243 platform->component.name)) {
3244 found_runtime = true;
3245 break;
3246 }
3247 }
3248
3249 if (!found_runtime) {
3250 dev_err(platform->dev,
3251 "%s: Failed to find runtime for platform\n",
3252 __func__);
3253 return -EINVAL;
3254 }
3255
3256 ret = of_property_read_u32(platform->dev->of_node, cpe_dev_id,
3257 &port_id);
3258 if (ret) {
3259 dev_dbg(platform->dev,
3260 "%s: missing 0x%x in dt node\n", __func__, port_id);
3261 port_id = 1;
3262 }
3263
3264 codec = rtd->codec;
3265
3266 cpe_priv = kzalloc(sizeof(struct cpe_priv),
3267 GFP_KERNEL);
3268 if (!cpe_priv)
3269 return -ENOMEM;
3270
3271 cpe_priv->codec = codec;
3272 cpe_priv->input_port_id = port_id;
3273 wcd_cpe_get_lsm_ops(&cpe_priv->lsm_ops);
3274 wcd_cpe_get_afe_ops(&cpe_priv->afe_ops);
3275
3276 snd_soc_platform_set_drvdata(platform, cpe_priv);
3277 kcontrol = &msm_cpe_kcontrols[0];
3278 snd_ctl_add(card->snd_card, snd_ctl_new1(kcontrol, cpe_priv));
3279 return 0;
3280}
3281
3282static const struct snd_pcm_ops msm_cpe_lsm_ops = {
3283 .open = msm_cpe_lsm_open,
3284 .close = msm_cpe_lsm_close,
3285 .ioctl = msm_cpe_lsm_ioctl,
3286 .prepare = msm_cpe_lsm_prepare,
3287 .trigger = msm_cpe_lsm_trigger,
3288 .pointer = msm_cpe_lsm_pointer,
3289 .copy = msm_cpe_lsm_copy,
3290 .hw_params = msm_cpe_lsm_hwparams,
3291 .compat_ioctl = msm_cpe_lsm_ioctl_compat,
3292};
3293
3294static struct snd_soc_platform_driver msm_soc_cpe_platform = {
3295 .ops = &msm_cpe_lsm_ops,
3296 .probe = msm_asoc_cpe_lsm_probe,
3297};
3298
3299/*
3300 * msm_cpe_lsm_probe: platform driver probe
3301 * @pdev: platform device
3302 *
3303 * Register the ASoC platform driver with ASoC core
3304 */
3305static int msm_cpe_lsm_probe(struct platform_device *pdev)
3306{
3307
3308 return snd_soc_register_platform(&pdev->dev,
3309 &msm_soc_cpe_platform);
3310}
3311
3312/*
3313 * msm_cpe_lsm_remove: platform driver remove
3314 * @pdev: platform device
3315 *
3316 * Deregister the ASoC platform driver
3317 */
3318static int msm_cpe_lsm_remove(struct platform_device *pdev)
3319{
3320 snd_soc_unregister_platform(&pdev->dev);
3321 return 0;
3322}
3323
3324static const struct of_device_id msm_cpe_lsm_dt_match[] = {
3325 {.compatible = "qcom,msm-cpe-lsm" },
3326 { }
3327};
3328
3329static struct platform_driver msm_cpe_lsm_driver = {
3330 .driver = {
3331 .name = "msm-cpe-lsm",
3332 .owner = THIS_MODULE,
3333 .of_match_table = of_match_ptr(msm_cpe_lsm_dt_match),
3334 },
3335 .probe = msm_cpe_lsm_probe,
3336 .remove = msm_cpe_lsm_remove,
3337};
3338module_platform_driver(msm_cpe_lsm_driver);
3339
3340MODULE_DESCRIPTION("CPE LSM platform driver");
3341MODULE_DEVICE_TABLE(of, msm_cpe_lsm_dt_match);
3342MODULE_LICENSE("GPL v2");