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