blob: b2fdf70f5a7e53c776523273e47798030cc0a7ab [file] [log] [blame]
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001/*
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +05302 * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
Banajit Goswami0530e2f2016-12-09 21:34:37 -08003 *
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#include <linux/init.h>
14#include <linux/err.h>
15#include <linux/module.h>
16#include <linux/time.h>
17#include <linux/wait.h>
18#include <linux/platform_device.h>
19#include <linux/slab.h>
20#include <linux/dma-mapping.h>
21#include <linux/of.h>
22#include <linux/msm_audio_ion.h>
23#include <linux/freezer.h>
24#include <sound/core.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27#include <sound/pcm.h>
28#include <sound/timer.h>
29#include <sound/initval.h>
30#include <sound/control.h>
31#include <sound/q6lsm.h>
32#include <sound/lsm_params.h>
33#include <sound/pcm_params.h>
34#include "msm-pcm-routing-v2.h"
35
36#define CAPTURE_MIN_NUM_PERIODS 2
37#define CAPTURE_MAX_NUM_PERIODS 8
38#define CAPTURE_MAX_PERIOD_SIZE 4096
39#define CAPTURE_MIN_PERIOD_SIZE 320
40#define LISTEN_MAX_STATUS_PAYLOAD_SIZE 256
41
42#define LAB_BUFFER_ALLOC 1
43#define LAB_BUFFER_DEALLOC 0
44
45static struct snd_pcm_hardware msm_pcm_hardware_capture = {
46 .info = (SNDRV_PCM_INFO_MMAP |
47 SNDRV_PCM_INFO_BLOCK_TRANSFER |
48 SNDRV_PCM_INFO_INTERLEAVED |
49 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
50 .formats = SNDRV_PCM_FMTBIT_S16_LE,
51 .rates = SNDRV_PCM_RATE_16000,
52 .rate_min = 16000,
53 .rate_max = 16000,
54 .channels_min = 1,
55 .channels_max = 1,
56 .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS *
57 CAPTURE_MAX_PERIOD_SIZE,
58 .period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
59 .period_bytes_max = CAPTURE_MAX_PERIOD_SIZE,
60 .periods_min = CAPTURE_MIN_NUM_PERIODS,
61 .periods_max = CAPTURE_MAX_NUM_PERIODS,
62 .fifo_size = 0,
63};
64
65/* Conventional and unconventional sample rate supported */
66static unsigned int supported_sample_rates[] = {
67 16000,
68};
69
70static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
71 .count = ARRAY_SIZE(supported_sample_rates),
72 .list = supported_sample_rates,
73 .mask = 0,
74};
75
76struct lsm_priv {
77 struct snd_pcm_substream *substream;
78 struct lsm_client *lsm_client;
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +053079 struct snd_lsm_event_status_v3 *event_status;
Banajit Goswami0530e2f2016-12-09 21:34:37 -080080 spinlock_t event_lock;
81 wait_queue_head_t event_wait;
82 unsigned long event_avail;
83 atomic_t event_wait_stop;
84 atomic_t buf_count;
85 atomic_t read_abort;
86 wait_queue_head_t period_wait;
87 int appl_cnt;
88 int dma_write;
89};
90
Revathi Uddaraju1803e362016-10-19 14:12:00 +053091enum { /* lsm session states */
92 IDLE = 0,
93 RUNNING,
94};
95
Banajit Goswami0530e2f2016-12-09 21:34:37 -080096static int msm_lsm_queue_lab_buffer(struct lsm_priv *prtd, int i)
97{
98 int rc = 0;
99 struct lsm_cmd_read cmd_read;
100 struct snd_soc_pcm_runtime *rtd;
101
102 if (!prtd || !prtd->lsm_client) {
103 pr_err("%s: Invalid params prtd %pK lsm client %pK\n",
104 __func__, prtd, ((!prtd) ? NULL : prtd->lsm_client));
105 return -EINVAL;
106 }
107 if (!prtd->substream || !prtd->substream->private_data) {
108 pr_err("%s: Invalid %s\n", __func__,
109 (!prtd->substream) ? "substream" : "private_data");
110 return -EINVAL;
111 }
112 rtd = prtd->substream->private_data;
113
114 if (!prtd->lsm_client->lab_buffer ||
115 i >= prtd->lsm_client->hw_params.period_count) {
116 dev_err(rtd->dev,
117 "%s: Lab buffer not setup %pK incorrect index %d period count %d\n",
118 __func__, prtd->lsm_client->lab_buffer, i,
119 prtd->lsm_client->hw_params.period_count);
120 return -EINVAL;
121 }
122 cmd_read.buf_addr_lsw =
123 lower_32_bits(prtd->lsm_client->lab_buffer[i].phys);
124 cmd_read.buf_addr_msw =
125 msm_audio_populate_upper_32_bits(
126 prtd->lsm_client->lab_buffer[i].phys);
127 cmd_read.buf_size = prtd->lsm_client->lab_buffer[i].size;
128 cmd_read.mem_map_handle =
129 prtd->lsm_client->lab_buffer[i].mem_map_handle;
130 rc = q6lsm_read(prtd->lsm_client, &cmd_read);
131 if (rc)
132 dev_err(rtd->dev,
133 "%s: error in queuing the lab buffer rc %d\n",
134 __func__, rc);
135 return rc;
136}
137
138static int lsm_lab_buffer_sanity(struct lsm_priv *prtd,
139 struct lsm_cmd_read_done *read_done, int *index)
140{
141 int i = 0, rc = -EINVAL;
142 struct snd_soc_pcm_runtime *rtd;
143
144 if (!prtd || !read_done || !index) {
145 pr_err("%s: Invalid params prtd %pK read_done %pK index %pK\n",
146 __func__, prtd, read_done, index);
147 return -EINVAL;
148 }
149
150 if (!prtd->substream || !prtd->substream->private_data) {
151 pr_err("%s: Invalid %s\n", __func__,
152 (!prtd->substream) ? "substream" : "private_data");
153 return -EINVAL;
154 }
155 rtd = prtd->substream->private_data;
156
157 if (!prtd->lsm_client->lab_enable || !prtd->lsm_client->lab_buffer) {
158 dev_err(rtd->dev,
159 "%s: Lab not enabled %d invalid lab buffer %pK\n",
160 __func__, prtd->lsm_client->lab_enable,
161 prtd->lsm_client->lab_buffer);
162 return -EINVAL;
163 }
164 for (i = 0; i < prtd->lsm_client->hw_params.period_count; i++) {
165 if ((lower_32_bits(prtd->lsm_client->lab_buffer[i].phys) ==
166 read_done->buf_addr_lsw) &&
167 (msm_audio_populate_upper_32_bits
168 (prtd->lsm_client->lab_buffer[i].phys) ==
169 read_done->buf_addr_msw) &&
170 (prtd->lsm_client->lab_buffer[i].mem_map_handle ==
171 read_done->mem_map_handle)) {
172 dev_dbg(rtd->dev,
173 "%s: Buffer found %pK memmap handle %d\n",
174 __func__, &prtd->lsm_client->lab_buffer[i].phys,
175 prtd->lsm_client->lab_buffer[i].mem_map_handle);
176 if (read_done->total_size >
177 prtd->lsm_client->lab_buffer[i].size) {
178 dev_err(rtd->dev,
179 "%s: Size mismatch call back size %d actual size %zd\n",
180 __func__, read_done->total_size,
181 prtd->lsm_client->lab_buffer[i].size);
182 rc = -EINVAL;
183 break;
184 } else {
185 *index = i;
186 rc = 0;
187 break;
188 }
189 }
190 }
191 return rc;
192}
193
194static void lsm_event_handler(uint32_t opcode, uint32_t token,
195 void *payload, void *priv)
196{
197 unsigned long flags;
198 struct lsm_priv *prtd = priv;
199 struct snd_pcm_substream *substream = prtd->substream;
200 struct snd_soc_pcm_runtime *rtd;
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530201 struct snd_lsm_event_status_v3 *temp;
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800202 uint16_t status = 0;
203 uint16_t payload_size = 0;
204 uint16_t index = 0;
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530205 uint32_t event_ts_lsw = 0;
206 uint32_t event_ts_msw = 0;
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800207
208 if (!substream || !substream->private_data) {
209 pr_err("%s: Invalid %s\n", __func__,
210 (!substream) ? "substream" : "private_data");
211 return;
212 }
213 rtd = substream->private_data;
214
215 switch (opcode) {
216 case LSM_DATA_EVENT_READ_DONE: {
217 int rc;
218 struct lsm_cmd_read_done *read_done = payload;
219 int buf_index = 0;
220
221 if (prtd->lsm_client->session != token ||
222 !read_done) {
223 dev_err(rtd->dev,
224 "%s: EVENT_READ_DONE invalid callback, session %d callback %d payload %pK",
225 __func__, prtd->lsm_client->session,
226 token, read_done);
227 return;
228 }
229 if (atomic_read(&prtd->read_abort)) {
230 dev_dbg(rtd->dev,
231 "%s: read abort set skip data\n", __func__);
232 return;
233 }
234 if (!lsm_lab_buffer_sanity(prtd, read_done, &buf_index)) {
235 dev_dbg(rtd->dev,
236 "%s: process read done index %d\n",
237 __func__, buf_index);
238 if (buf_index >=
239 prtd->lsm_client->hw_params.period_count) {
240 dev_err(rtd->dev,
241 "%s: Invalid index %d buf_index max cnt %d\n",
242 __func__, buf_index,
243 prtd->lsm_client->hw_params.period_count);
244 return;
245 }
246 prtd->dma_write += read_done->total_size;
247 atomic_inc(&prtd->buf_count);
248 snd_pcm_period_elapsed(substream);
249 wake_up(&prtd->period_wait);
250 /* queue the next period buffer */
251 buf_index = (buf_index + 1) %
252 prtd->lsm_client->hw_params.period_count;
253 rc = msm_lsm_queue_lab_buffer(prtd, buf_index);
254 if (rc)
255 dev_err(rtd->dev,
256 "%s: error in queuing the lab buffer rc %d\n",
257 __func__, rc);
258 } else
259 dev_err(rtd->dev, "%s: Invalid lab buffer returned by dsp\n",
260 __func__);
261 break;
262 }
263
264 case LSM_SESSION_EVENT_DETECTION_STATUS:
265 status = (uint16_t)((uint8_t *)payload)[0];
266 payload_size = (uint16_t)((uint8_t *)payload)[2];
267 index = 4;
268 dev_dbg(rtd->dev,
269 "%s: event detect status = %d payload size = %d\n",
270 __func__, status, payload_size);
271 break;
272
273 case LSM_SESSION_EVENT_DETECTION_STATUS_V2:
274 status = (uint16_t)((uint8_t *)payload)[0];
275 payload_size = (uint16_t)((uint8_t *)payload)[1];
276 index = 2;
277 dev_dbg(rtd->dev,
278 "%s: event detect status = %d payload size = %d\n",
279 __func__, status, payload_size);
280 break;
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530281
282 case LSM_SESSION_EVENT_DETECTION_STATUS_V3:
283 event_ts_lsw = ((uint32_t *)payload)[0];
284 event_ts_msw = ((uint32_t *)payload)[1];
285 status = (uint16_t)((uint8_t *)payload)[8];
286 payload_size = (uint16_t)((uint8_t *)payload)[9];
287 index = 10;
288 dev_dbg(rtd->dev,
289 "%s: ts_msw = %u, ts_lsw = %u, event detect status = %d payload size = %d\n",
290 __func__, event_ts_msw, event_ts_lsw, status,
291 payload_size);
292 break;
293
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800294 default:
295 break;
296 }
297
298 if (opcode == LSM_SESSION_EVENT_DETECTION_STATUS ||
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530299 opcode == LSM_SESSION_EVENT_DETECTION_STATUS_V2 ||
300 opcode == LSM_SESSION_EVENT_DETECTION_STATUS_V3) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800301 spin_lock_irqsave(&prtd->event_lock, flags);
302 temp = krealloc(prtd->event_status,
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530303 sizeof(struct snd_lsm_event_status_v3) +
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800304 payload_size, GFP_ATOMIC);
305 if (!temp) {
306 dev_err(rtd->dev, "%s: no memory for event status\n",
307 __func__);
308 return;
309 }
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530310 /*
311 * event status timestamp will be non-zero and valid if
312 * opcode is LSM_SESSION_EVENT_DETECTION_STATUS_V3
313 */
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800314 prtd->event_status = temp;
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530315 prtd->event_status->timestamp_lsw = event_ts_lsw;
316 prtd->event_status->timestamp_msw = event_ts_msw;
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800317 prtd->event_status->status = status;
318 prtd->event_status->payload_size = payload_size;
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530319
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800320 if (likely(prtd->event_status)) {
321 memcpy(prtd->event_status->payload,
322 &((uint8_t *)payload)[index],
323 payload_size);
324 prtd->event_avail = 1;
325 spin_unlock_irqrestore(&prtd->event_lock, flags);
326 wake_up(&prtd->event_wait);
327 } else {
328 spin_unlock_irqrestore(&prtd->event_lock, flags);
329 dev_err(rtd->dev,
330 "%s: Couldn't allocate %d bytes of memory\n",
331 __func__, payload_size);
332 }
333 if (substream->timer_running)
334 snd_timer_interrupt(substream->timer, 1);
335 }
336}
337
338static int msm_lsm_lab_buffer_alloc(struct lsm_priv *lsm, int alloc)
339{
340 int ret = 0;
341 struct snd_dma_buffer *dma_buf = NULL;
342
343 if (!lsm) {
344 pr_err("%s: Invalid param lsm %pK\n", __func__, lsm);
345 return -EINVAL;
346 }
347 if (alloc) {
348 if (!lsm->substream) {
349 pr_err("%s: substream is NULL\n", __func__);
350 return -EINVAL;
351 }
352 ret = q6lsm_lab_buffer_alloc(lsm->lsm_client, alloc);
353 if (ret) {
354 pr_err("%s: alloc lab buffer failed ret %d\n",
355 __func__, ret);
356 goto exit;
357 }
358 dma_buf = &lsm->substream->dma_buffer;
359 dma_buf->dev.type = SNDRV_DMA_TYPE_DEV;
360 dma_buf->dev.dev = lsm->substream->pcm->card->dev;
361 dma_buf->private_data = NULL;
362 dma_buf->area = lsm->lsm_client->lab_buffer[0].data;
363 dma_buf->addr = lsm->lsm_client->lab_buffer[0].phys;
364 dma_buf->bytes = lsm->lsm_client->hw_params.buf_sz *
365 lsm->lsm_client->hw_params.period_count;
366 snd_pcm_set_runtime_buffer(lsm->substream, dma_buf);
367 } else {
368 ret = q6lsm_lab_buffer_alloc(lsm->lsm_client, alloc);
369 if (ret)
370 pr_err("%s: free lab buffer failed ret %d\n",
371 __func__, ret);
372 kfree(lsm->lsm_client->lab_buffer);
373 lsm->lsm_client->lab_buffer = NULL;
374 }
375exit:
376 return ret;
377}
378
379static int msm_lsm_get_conf_levels(struct lsm_client *client,
380 u8 *conf_levels_ptr)
381{
382 int rc = 0;
383
384 if (client->num_confidence_levels == 0) {
385 pr_debug("%s: no confidence levels provided\n",
386 __func__);
387 client->confidence_levels = NULL;
388 goto done;
389 }
390
391 client->confidence_levels =
392 kzalloc((sizeof(uint8_t) * client->num_confidence_levels),
393 GFP_KERNEL);
394 if (!client->confidence_levels) {
395 pr_err("%s: No memory for confidence\n"
396 "levels num of level from user = %d\n",
397 __func__, client->num_confidence_levels);
398 rc = -ENOMEM;
399 goto done;
400 }
401
402 if (copy_from_user(client->confidence_levels,
403 conf_levels_ptr,
404 client->num_confidence_levels)) {
405 pr_err("%s: copy from user failed, size = %d\n",
406 __func__, client->num_confidence_levels);
407 rc = -EFAULT;
408 goto copy_err;
409 }
410
411 return rc;
412
413copy_err:
414 kfree(client->confidence_levels);
415 client->confidence_levels = NULL;
416done:
417 return rc;
418
419}
420
421static int msm_lsm_set_epd(struct snd_pcm_substream *substream,
422 struct lsm_params_info *p_info)
423{
424 struct snd_pcm_runtime *runtime = substream->runtime;
425 struct lsm_priv *prtd = runtime->private_data;
426 struct snd_soc_pcm_runtime *rtd = substream->private_data;
427 int rc = 0;
428 struct snd_lsm_ep_det_thres epd_th;
429
430 if (p_info->param_size != sizeof(epd_th)) {
431 dev_err(rtd->dev,
432 "%s: Invalid param_size %d\n",
433 __func__, p_info->param_size);
434 rc = -EINVAL;
435 goto done;
436 }
437
438 if (copy_from_user(&epd_th, p_info->param_data,
439 p_info->param_size)) {
440 dev_err(rtd->dev,
441 "%s: copy_from_user failed, size = %d\n",
442 __func__, p_info->param_size);
443 rc = -EFAULT;
444 goto done;
445 }
446
447 rc = q6lsm_set_one_param(prtd->lsm_client, p_info,
448 &epd_th, LSM_ENDPOINT_DETECT_THRESHOLD);
449 if (rc)
450 dev_err(rtd->dev,
451 "%s: Failed to set epd param, err = %d\n",
452 __func__, rc);
453done:
454 return rc;
455}
456
457static int msm_lsm_set_mode(struct snd_pcm_substream *substream,
458 struct lsm_params_info *p_info)
459{
460 struct snd_pcm_runtime *runtime = substream->runtime;
461 struct lsm_priv *prtd = runtime->private_data;
462 struct snd_soc_pcm_runtime *rtd = substream->private_data;
463 struct snd_lsm_detect_mode mode;
464 int rc = 0;
465
466 if (p_info->param_size != sizeof(mode)) {
467 dev_err(rtd->dev,
468 "%s: Invalid param_size %d\n",
469 __func__, p_info->param_size);
470 rc = -EINVAL;
471 goto done;
472 }
473
474 if (copy_from_user(&mode, p_info->param_data,
475 sizeof(mode))) {
476 dev_err(rtd->dev,
477 "%s: copy_from_user failed, size = %zd\n",
478 __func__, sizeof(mode));
479 rc = -EFAULT;
480 goto done;
481 }
482
483 rc = q6lsm_set_one_param(prtd->lsm_client, p_info,
484 &mode, LSM_OPERATION_MODE);
485 if (rc)
486 dev_err(rtd->dev,
487 "%s: Failed to set det_mode param, err = %d\n",
488 __func__, rc);
489done:
490 return rc;
491}
492
493static int msm_lsm_set_gain(struct snd_pcm_substream *substream,
494 struct lsm_params_info *p_info)
495{
496 struct snd_pcm_runtime *runtime = substream->runtime;
497 struct lsm_priv *prtd = runtime->private_data;
498 struct snd_soc_pcm_runtime *rtd = substream->private_data;
499 struct snd_lsm_gain gain;
500 int rc = 0;
501
502 if (p_info->param_size != sizeof(gain)) {
503 dev_err(rtd->dev,
504 "%s: Invalid param_size %d\n",
505 __func__, p_info->param_size);
506 rc = -EINVAL;
507 goto done;
508 }
509
510 if (copy_from_user(&gain, p_info->param_data,
511 sizeof(gain))) {
512 dev_err(rtd->dev,
513 "%s: copy_from_user failed, size = %zd\n",
514 __func__, sizeof(gain));
515 rc = -EFAULT;
516 goto done;
517 }
518
519 rc = q6lsm_set_one_param(prtd->lsm_client, p_info,
520 &gain, LSM_GAIN);
521 if (rc)
522 dev_err(rtd->dev,
523 "%s: Failed to set det_mode param, err = %d\n",
524 __func__, rc);
525done:
526 return rc;
527}
528
529static int msm_lsm_set_conf(struct snd_pcm_substream *substream,
530 struct lsm_params_info *p_info)
531{
532 struct snd_pcm_runtime *runtime = substream->runtime;
533 struct lsm_priv *prtd = runtime->private_data;
534 struct snd_soc_pcm_runtime *rtd = substream->private_data;
535 int rc = 0;
536
537 if (p_info->param_size > MAX_NUM_CONFIDENCE) {
538 dev_err(rtd->dev,
539 "%s: invalid confidence levels %d\n",
540 __func__, p_info->param_size);
541 return -EINVAL;
542 }
543
544 prtd->lsm_client->num_confidence_levels =
545 p_info->param_size;
546 rc = msm_lsm_get_conf_levels(prtd->lsm_client,
547 p_info->param_data);
548 if (rc) {
549 dev_err(rtd->dev,
550 "%s: get_conf_levels failed, err = %d\n",
551 __func__, rc);
552 return rc;
553 }
554
555 rc = q6lsm_set_one_param(prtd->lsm_client, p_info,
556 prtd->lsm_client->confidence_levels,
557 LSM_MIN_CONFIDENCE_LEVELS);
558 if (rc)
559 dev_err(rtd->dev,
560 "%s: Failed to set min_conf_levels, err = %d\n",
561 __func__, rc);
562
563 return rc;
564}
565
566static int msm_lsm_reg_model(struct snd_pcm_substream *substream,
567 struct lsm_params_info *p_info)
568{
569 struct snd_pcm_runtime *runtime = substream->runtime;
570 struct lsm_priv *prtd = runtime->private_data;
571 struct snd_soc_pcm_runtime *rtd = substream->private_data;
572 int rc = 0;
573 u8 *snd_model_ptr;
574 size_t offset;
575
576 rc = q6lsm_snd_model_buf_alloc(prtd->lsm_client,
577 p_info->param_size,
578 true);
579 if (rc) {
580 dev_err(rtd->dev,
581 "%s: snd_model buf alloc failed, size = %d\n",
582 __func__, p_info->param_size);
583 return rc;
584 }
585
586 q6lsm_sm_set_param_data(prtd->lsm_client, p_info, &offset);
587
588 /*
589 * For set_param, advance the sound model data with the
590 * number of bytes required by param_data.
591 */
592 snd_model_ptr = ((u8 *) prtd->lsm_client->sound_model.data) + offset;
593
594 if (copy_from_user(snd_model_ptr,
595 p_info->param_data, p_info->param_size)) {
596 dev_err(rtd->dev,
597 "%s: copy_from_user for snd_model failed, size = %d\n",
598 __func__, p_info->param_size);
599 rc = -EFAULT;
600 goto err_copy;
601 }
602 rc = q6lsm_set_one_param(prtd->lsm_client, p_info, NULL,
603 LSM_REG_SND_MODEL);
604 if (rc) {
605 dev_err(rtd->dev,
606 "%s: Failed to set sound_model, err = %d\n",
607 __func__, rc);
608 goto err_copy;
609 }
610 return rc;
611
612err_copy:
613 q6lsm_snd_model_buf_free(prtd->lsm_client);
614 return rc;
615}
616
617static int msm_lsm_dereg_model(struct snd_pcm_substream *substream,
618 struct lsm_params_info *p_info)
619{
620 struct snd_pcm_runtime *runtime = substream->runtime;
621 struct lsm_priv *prtd = runtime->private_data;
622 struct snd_soc_pcm_runtime *rtd = substream->private_data;
623 int rc = 0;
624
625 rc = q6lsm_set_one_param(prtd->lsm_client, p_info,
626 NULL, LSM_DEREG_SND_MODEL);
627 if (rc)
628 dev_err(rtd->dev,
629 "%s: Failed to set det_mode param, err = %d\n",
630 __func__, rc);
631
632 q6lsm_snd_model_buf_free(prtd->lsm_client);
633
634 return rc;
635}
636
637static int msm_lsm_set_custom(struct snd_pcm_substream *substream,
638 struct lsm_params_info *p_info)
639{
640 struct snd_pcm_runtime *runtime = substream->runtime;
641 struct lsm_priv *prtd = runtime->private_data;
642 struct snd_soc_pcm_runtime *rtd = substream->private_data;
643 u8 *data;
644 int rc = 0;
645
646 data = kzalloc(p_info->param_size, GFP_KERNEL);
647 if (!data)
648 return -ENOMEM;
649
650 if (copy_from_user(data, p_info->param_data,
651 p_info->param_size)) {
652 dev_err(rtd->dev,
653 "%s: copy_from_user failed for custom params, size = %d\n",
654 __func__, p_info->param_size);
655 rc = -EFAULT;
656 goto err_ret;
657 }
658
659 rc = q6lsm_set_one_param(prtd->lsm_client, p_info,
660 data, LSM_CUSTOM_PARAMS);
661 if (rc)
662 dev_err(rtd->dev,
663 "%s: Failed to set custom param, err = %d\n",
664 __func__, rc);
665
666err_ret:
667 kfree(data);
668 return rc;
669}
670
Revathi Uddaraju1803e362016-10-19 14:12:00 +0530671static int msm_lsm_set_poll_enable(struct snd_pcm_substream *substream,
672 struct lsm_params_info *p_info)
673{
674 struct snd_pcm_runtime *runtime = substream->runtime;
675 struct lsm_priv *prtd = runtime->private_data;
676 struct snd_soc_pcm_runtime *rtd = substream->private_data;
677 struct snd_lsm_poll_enable poll_enable;
678 int rc = 0;
679
680 if (p_info->param_size != sizeof(poll_enable)) {
681 dev_err(rtd->dev,
682 "%s: Invalid param_size %d\n",
683 __func__, p_info->param_size);
684 rc = -EINVAL;
685 goto done;
686 }
687
688 if (copy_from_user(&poll_enable, p_info->param_data,
689 sizeof(poll_enable))) {
690 dev_err(rtd->dev,
691 "%s: copy_from_user failed, size = %zd\n",
692 __func__, sizeof(poll_enable));
693 rc = -EFAULT;
694 goto done;
695 }
696
697 if (prtd->lsm_client->poll_enable == poll_enable.poll_en) {
698 dev_dbg(rtd->dev,
699 "%s: Polling for session %d already %s\n",
700 __func__, prtd->lsm_client->session,
701 (poll_enable.poll_en ? "enabled" : "disabled"));
702 rc = 0;
703 goto done;
704 }
705
706 rc = q6lsm_set_one_param(prtd->lsm_client, p_info,
707 &poll_enable, LSM_POLLING_ENABLE);
708 if (!rc) {
709 prtd->lsm_client->poll_enable = poll_enable.poll_en;
710 } else {
711 dev_err(rtd->dev,
712 "%s: Failed to set poll enable, err = %d\n",
713 __func__, rc);
714 }
715done:
716 return rc;
717}
718
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800719static int msm_lsm_process_params(struct snd_pcm_substream *substream,
720 struct snd_lsm_module_params *p_data,
721 void *params)
722{
723 struct snd_soc_pcm_runtime *rtd = substream->private_data;
724 struct lsm_params_info *p_info;
725 int i;
726 int rc = 0;
727
728 p_info = (struct lsm_params_info *) params;
729
730 for (i = 0; i < p_data->num_params; i++) {
731 dev_dbg(rtd->dev,
732 "%s: param (%d), module_id = 0x%x, param_id = 0x%x, param_size = 0x%x, param_type = 0x%x\n",
733 __func__, i, p_info->module_id,
734 p_info->param_id, p_info->param_size,
735 p_info->param_type);
736
737 switch (p_info->param_type) {
738 case LSM_ENDPOINT_DETECT_THRESHOLD:
739 rc = msm_lsm_set_epd(substream, p_info);
740 break;
741 case LSM_OPERATION_MODE:
742 rc = msm_lsm_set_mode(substream, p_info);
743 break;
744 case LSM_GAIN:
745 rc = msm_lsm_set_gain(substream, p_info);
746 break;
747 case LSM_MIN_CONFIDENCE_LEVELS:
748 rc = msm_lsm_set_conf(substream, p_info);
749 break;
750 case LSM_REG_SND_MODEL:
751 rc = msm_lsm_reg_model(substream, p_info);
752 break;
753 case LSM_DEREG_SND_MODEL:
754 rc = msm_lsm_dereg_model(substream, p_info);
755 break;
756 case LSM_CUSTOM_PARAMS:
757 rc = msm_lsm_set_custom(substream, p_info);
758 break;
Revathi Uddaraju1803e362016-10-19 14:12:00 +0530759 case LSM_POLLING_ENABLE:
760 rc = msm_lsm_set_poll_enable(substream, p_info);
761 break;
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800762 default:
763 dev_err(rtd->dev,
764 "%s: Invalid param_type %d\n",
765 __func__, p_info->param_type);
766 rc = -EINVAL;
767 break;
768 }
769 if (rc) {
770 pr_err("%s: set_param fail for param_type %d\n",
771 __func__, p_info->param_type);
772 return rc;
773 }
774
775 p_info++;
776 }
777
778 return rc;
779}
780
781static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
782 unsigned int cmd, void *arg)
783{
784 struct snd_soc_pcm_runtime *rtd;
785 unsigned long flags;
786 int ret;
787 struct snd_lsm_sound_model_v2 snd_model_v2;
788 struct snd_lsm_session_data session_data;
789 int rc = 0;
790 int xchg = 0;
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800791 struct snd_pcm_runtime *runtime;
792 struct lsm_priv *prtd;
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800793 struct snd_lsm_detection_params det_params;
794 uint8_t *confidence_level = NULL;
795
796 if (!substream || !substream->private_data) {
797 pr_err("%s: Invalid %s\n", __func__,
798 (!substream) ? "substream" : "private_data");
799 return -EINVAL;
800 }
801
802 runtime = substream->runtime;
803 prtd = runtime->private_data;
804 rtd = substream->private_data;
805
806 switch (cmd) {
807 case SNDRV_LSM_SET_SESSION_DATA:
808 dev_dbg(rtd->dev, "%s: set session data\n", __func__);
Bhalchandra Gajare930739e2016-12-15 16:43:45 -0800809 if (copy_from_user(&session_data, arg,
810 sizeof(session_data))) {
811 dev_err(rtd->dev, "%s: %s: copy_from_user failed\n",
812 __func__, "LSM_SET_SESSION_DATA");
813 return -EFAULT;
814 }
815
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800816 if (session_data.app_id != LSM_VOICE_WAKEUP_APP_ID_V2) {
817 dev_err(rtd->dev,
818 "%s:Invalid App id %d for Listen client\n",
819 __func__, session_data.app_id);
820 rc = -EINVAL;
821 break;
822 }
823
824 prtd->lsm_client->app_id = session_data.app_id;
825 ret = q6lsm_open(prtd->lsm_client,
826 prtd->lsm_client->app_id);
827 if (ret < 0) {
828 dev_err(rtd->dev,
829 "%s: lsm open failed, %d\n",
830 __func__, ret);
831 return ret;
832 }
833 prtd->lsm_client->opened = true;
834 dev_dbg(rtd->dev, "%s: Session_ID = %d, APP ID = %d\n",
835 __func__,
836 prtd->lsm_client->session,
837 prtd->lsm_client->app_id);
838 break;
839 case SNDRV_LSM_REG_SND_MODEL_V2:
840 dev_dbg(rtd->dev, "%s: Registering sound model V2\n",
841 __func__);
842 memcpy(&snd_model_v2, arg,
843 sizeof(struct snd_lsm_sound_model_v2));
844 if (snd_model_v2.num_confidence_levels >
845 MAX_NUM_CONFIDENCE) {
846 dev_err(rtd->dev,
847 "%s: Invalid conf_levels = %d, maximum allowed = %d\n",
848 __func__, snd_model_v2.num_confidence_levels,
849 MAX_NUM_CONFIDENCE);
850 rc = -EINVAL;
851 break;
852 }
853 rc = q6lsm_snd_model_buf_alloc(prtd->lsm_client,
854 snd_model_v2.data_size, false);
855 if (rc) {
856 dev_err(rtd->dev,
857 "%s: q6lsm buffer alloc failed V2, size %d\n",
858 __func__, snd_model_v2.data_size);
859 break;
860 }
861 if (copy_from_user(prtd->lsm_client->sound_model.data,
862 snd_model_v2.data, snd_model_v2.data_size)) {
863 dev_err(rtd->dev,
864 "%s: copy from user data failed\n"
865 "data %pK size %d\n", __func__,
866 snd_model_v2.data, snd_model_v2.data_size);
867 q6lsm_snd_model_buf_free(prtd->lsm_client);
868 rc = -EFAULT;
869 break;
870 }
871
872 dev_dbg(rtd->dev, "SND Model Magic no byte[0] %x,\n"
873 "byte[1] %x, byte[2] %x byte[3] %x\n",
874 snd_model_v2.data[0], snd_model_v2.data[1],
875 snd_model_v2.data[2], snd_model_v2.data[3]);
876 prtd->lsm_client->num_confidence_levels =
877 snd_model_v2.num_confidence_levels;
878
879 rc = msm_lsm_get_conf_levels(prtd->lsm_client,
880 snd_model_v2.confidence_level);
881 if (rc) {
882 dev_err(rtd->dev,
883 "%s: get_conf_levels failed, err = %d\n",
884 __func__, rc);
885 break;
886 }
887
888 rc = q6lsm_register_sound_model(prtd->lsm_client,
889 snd_model_v2.detection_mode,
890 snd_model_v2.detect_failure);
891 if (rc < 0) {
892 dev_err(rtd->dev,
893 "%s: Register snd Model v2 failed =%d\n",
894 __func__, rc);
895 kfree(confidence_level);
896 q6lsm_snd_model_buf_free(prtd->lsm_client);
897 }
898
899 kfree(prtd->lsm_client->confidence_levels);
900 prtd->lsm_client->confidence_levels = NULL;
901 break;
902
903 case SNDRV_LSM_SET_PARAMS:
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800904 dev_dbg(rtd->dev, "%s: set_params\n", __func__);
905 memcpy(&det_params, arg,
906 sizeof(det_params));
907 if (det_params.num_confidence_levels >
908 MAX_NUM_CONFIDENCE) {
909 rc = -EINVAL;
910 break;
911 }
912
913 prtd->lsm_client->num_confidence_levels =
914 det_params.num_confidence_levels;
915
916 rc = msm_lsm_get_conf_levels(prtd->lsm_client,
917 det_params.conf_level);
918 if (rc) {
919 dev_err(rtd->dev,
920 "%s: Failed to get conf_levels, err = %d\n",
921 __func__, rc);
922 break;
923 }
924
925 rc = q6lsm_set_data(prtd->lsm_client,
926 det_params.detect_mode,
927 det_params.detect_failure);
928 if (rc)
929 dev_err(rtd->dev,
930 "%s: Failed to set params, err = %d\n",
931 __func__, rc);
932
933 kfree(prtd->lsm_client->confidence_levels);
934 prtd->lsm_client->confidence_levels = NULL;
935
936 break;
937
938 case SNDRV_LSM_DEREG_SND_MODEL:
939 dev_dbg(rtd->dev, "%s: Deregistering sound model\n",
940 __func__);
941 rc = q6lsm_deregister_sound_model(prtd->lsm_client);
942 if (rc)
943 dev_err(rtd->dev,
944 "%s: Sound model de-register failed, err = %d\n",
945 __func__, rc);
946 break;
947
948 case SNDRV_LSM_EVENT_STATUS:
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530949 case SNDRV_LSM_EVENT_STATUS_V3: {
950 uint32_t ts_lsw, ts_msw;
951 uint16_t status = 0, payload_size = 0;
952
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800953 dev_dbg(rtd->dev, "%s: Get event status\n", __func__);
954 atomic_set(&prtd->event_wait_stop, 0);
955 rc = wait_event_freezable(prtd->event_wait,
956 (cmpxchg(&prtd->event_avail, 1, 0) ||
957 (xchg = atomic_cmpxchg(&prtd->event_wait_stop,
958 1, 0))));
959 dev_dbg(rtd->dev, "%s: wait_event_freezable %d event_wait_stop %d\n",
960 __func__, rc, xchg);
961 if (!rc && !xchg) {
962 dev_dbg(rtd->dev, "%s: New event available %ld\n",
963 __func__, prtd->event_avail);
964 spin_lock_irqsave(&prtd->event_lock, flags);
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530965
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800966 if (prtd->event_status) {
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530967 payload_size = prtd->event_status->payload_size;
968 ts_lsw = prtd->event_status->timestamp_lsw;
969 ts_msw = prtd->event_status->timestamp_msw;
970 status = prtd->event_status->status;
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800971 spin_unlock_irqrestore(&prtd->event_lock,
972 flags);
973 } else {
974 spin_unlock_irqrestore(&prtd->event_lock,
975 flags);
976 rc = -EINVAL;
977 dev_err(rtd->dev,
978 "%s: prtd->event_status is NULL\n",
979 __func__);
980 break;
981 }
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +0530982
983 if (cmd == SNDRV_LSM_EVENT_STATUS) {
984 struct snd_lsm_event_status *user = arg;
985
986 if (user->payload_size < payload_size) {
987 dev_dbg(rtd->dev,
988 "%s: provided %d bytes isn't enough, needs %d bytes\n",
989 __func__, user->payload_size,
990 payload_size);
991 rc = -ENOMEM;
992 } else {
993 user->status = status;
994 user->payload_size = payload_size;
995 memcpy(user->payload,
996 prtd->event_status->payload,
997 payload_size);
998 }
Banajit Goswami0530e2f2016-12-09 21:34:37 -0800999 } else {
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +05301000 struct snd_lsm_event_status_v3 *user_v3 = arg;
1001
1002 if (user_v3->payload_size < payload_size) {
1003 dev_dbg(rtd->dev,
1004 "%s: provided %d bytes isn't enough, needs %d bytes\n",
1005 __func__, user_v3->payload_size,
1006 payload_size);
1007 rc = -ENOMEM;
1008 } else {
1009 user_v3->timestamp_lsw = ts_lsw;
1010 user_v3->timestamp_msw = ts_msw;
1011 user_v3->status = status;
1012 user_v3->payload_size = payload_size;
1013 memcpy(user_v3->payload,
1014 prtd->event_status->payload,
1015 payload_size);
1016 }
1017 }
1018 if (!rc) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001019 if (prtd->lsm_client->lab_enable
1020 && !prtd->lsm_client->lab_started
1021 && prtd->event_status->status ==
1022 LSM_VOICE_WAKEUP_STATUS_DETECTED) {
1023 atomic_set(&prtd->read_abort, 0);
1024 atomic_set(&prtd->buf_count, 0);
1025 prtd->appl_cnt = 0;
1026 prtd->dma_write = 0;
1027 rc = msm_lsm_queue_lab_buffer(prtd,
1028 0);
1029 if (rc)
1030 dev_err(rtd->dev,
1031 "%s: Queue buffer failed for lab rc = %d\n",
1032 __func__, rc);
1033 else
1034 prtd->lsm_client->lab_started
1035 = true;
1036 }
1037 }
1038 } else if (xchg) {
1039 dev_dbg(rtd->dev, "%s: Wait aborted\n", __func__);
1040 rc = 0;
1041 }
1042 break;
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +05301043 }
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001044
1045 case SNDRV_LSM_ABORT_EVENT:
1046 dev_dbg(rtd->dev, "%s: Aborting event status wait\n",
1047 __func__);
1048 atomic_set(&prtd->event_wait_stop, 1);
1049 wake_up(&prtd->event_wait);
1050 break;
1051
1052 case SNDRV_LSM_START:
1053 dev_dbg(rtd->dev, "%s: Starting LSM client session\n",
1054 __func__);
1055 if (!prtd->lsm_client->started) {
1056 ret = q6lsm_start(prtd->lsm_client, true);
1057 if (!ret) {
1058 prtd->lsm_client->started = true;
1059 dev_dbg(rtd->dev, "%s: LSM client session started\n",
1060 __func__);
1061 }
1062 }
1063 break;
1064
1065 case SNDRV_LSM_STOP: {
1066 dev_dbg(rtd->dev,
1067 "%s: Stopping LSM client session\n",
1068 __func__);
1069 if (prtd->lsm_client->started) {
1070 if (prtd->lsm_client->lab_enable) {
1071 atomic_set(&prtd->read_abort, 1);
1072 if (prtd->lsm_client->lab_started) {
1073 ret = q6lsm_stop_lab(prtd->lsm_client);
1074 if (ret)
1075 dev_err(rtd->dev,
1076 "%s: stop lab failed ret %d\n",
1077 __func__, ret);
1078 prtd->lsm_client->lab_started = false;
1079 }
1080 }
1081 ret = q6lsm_stop(prtd->lsm_client, true);
1082 if (!ret)
1083 dev_dbg(rtd->dev,
1084 "%s: LSM client session stopped %d\n",
1085 __func__, ret);
1086 prtd->lsm_client->started = false;
1087 }
1088 break;
1089 }
1090 case SNDRV_LSM_LAB_CONTROL: {
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001091 u32 enable;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001092
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001093 if (copy_from_user(&enable, arg, sizeof(enable))) {
1094 dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n",
1095 __func__, "LSM_LAB_CONTROL");
1096 return -EFAULT;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001097 }
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001098
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001099 dev_dbg(rtd->dev, "%s: ioctl %s, enable = %d\n",
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001100 __func__, "SNDRV_LSM_LAB_CONTROL", enable);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001101 if (!prtd->lsm_client->started) {
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001102 if (prtd->lsm_client->lab_enable == enable) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001103 dev_dbg(rtd->dev,
1104 "%s: Lab for session %d already %s\n",
1105 __func__, prtd->lsm_client->session,
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001106 enable ? "enabled" : "disabled");
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001107 rc = 0;
1108 break;
1109 }
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001110 rc = q6lsm_lab_control(prtd->lsm_client, enable);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001111 if (rc) {
1112 dev_err(rtd->dev,
1113 "%s: ioctl %s failed rc %d to %s lab for session %d\n",
1114 __func__, "SNDRV_LAB_CONTROL", rc,
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001115 enable ? "enable" : "disable",
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001116 prtd->lsm_client->session);
1117 } else {
1118 rc = msm_lsm_lab_buffer_alloc(prtd,
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001119 enable ? LAB_BUFFER_ALLOC
1120 : LAB_BUFFER_DEALLOC);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001121 if (rc)
1122 dev_err(rtd->dev,
1123 "%s: msm_lsm_lab_buffer_alloc failed rc %d for %s",
1124 __func__, rc,
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001125 enable ? "ALLOC" : "DEALLOC");
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001126 if (!rc)
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001127 prtd->lsm_client->lab_enable = enable;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001128 }
1129 } else {
1130 dev_err(rtd->dev, "%s: ioctl %s issued after start",
1131 __func__, "SNDRV_LSM_LAB_CONTROL");
1132 rc = -EINVAL;
1133 }
1134 break;
1135 }
1136 case SNDRV_LSM_STOP_LAB:
1137 dev_dbg(rtd->dev, "%s: stopping LAB\n", __func__);
1138 if (prtd->lsm_client->lab_enable &&
1139 prtd->lsm_client->lab_started) {
1140 atomic_set(&prtd->read_abort, 1);
1141 rc = q6lsm_stop_lab(prtd->lsm_client);
1142 if (rc)
1143 dev_err(rtd->dev,
1144 "%s: Lab stop failed for session %d rc %d\n",
1145 __func__,
1146 prtd->lsm_client->session, rc);
1147 prtd->lsm_client->lab_started = false;
1148 }
1149 break;
Revathi Uddaraju1803e362016-10-19 14:12:00 +05301150
1151 case SNDRV_LSM_SET_PORT:
1152 dev_dbg(rtd->dev, "%s: set LSM port\n", __func__);
1153 rc = q6lsm_set_port_connected(prtd->lsm_client);
1154 break;
1155
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +05301156 case SNDRV_LSM_SET_FWK_MODE_CONFIG: {
1157 u32 *mode = NULL;
1158
1159 if (!arg) {
1160 dev_err(rtd->dev,
1161 "%s: Invalid param arg for ioctl %s session %d\n",
1162 __func__, "SNDRV_LSM_SET_FWK_MODE_CONFIG",
1163 prtd->lsm_client->session);
1164 rc = -EINVAL;
1165 break;
1166 }
1167 mode = (u32 *)arg;
1168 if (prtd->lsm_client->event_mode == *mode) {
1169 dev_dbg(rtd->dev,
1170 "%s: mode for %d already set to %d\n",
1171 __func__, prtd->lsm_client->session, *mode);
1172 rc = 0;
1173 } else {
1174 dev_dbg(rtd->dev, "%s: Event mode = %d\n",
1175 __func__, *mode);
1176 rc = q6lsm_set_fwk_mode_cfg(prtd->lsm_client, *mode);
1177 if (!rc)
1178 prtd->lsm_client->event_mode = *mode;
1179 else
1180 dev_err(rtd->dev,
1181 "%s: set event mode failed %d\n",
1182 __func__, rc);
1183 }
1184 break;
1185 }
1186
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001187 default:
1188 dev_dbg(rtd->dev,
1189 "%s: Falling into default snd_lib_ioctl cmd 0x%x\n",
1190 __func__, cmd);
1191 rc = snd_pcm_lib_ioctl(substream, cmd, arg);
1192 break;
1193 }
1194
1195 if (!rc)
1196 dev_dbg(rtd->dev, "%s: leave (%d)\n",
1197 __func__, rc);
1198 else
1199 dev_err(rtd->dev, "%s: cmd 0x%x failed %d\n",
1200 __func__, cmd, rc);
1201
1202 return rc;
1203}
1204#ifdef CONFIG_COMPAT
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +05301205
1206struct snd_lsm_event_status32 {
1207 u16 status;
1208 u16 payload_size;
1209 u8 payload[0];
1210};
1211
1212struct snd_lsm_event_status_v3_32 {
1213 u32 timestamp_lsw;
1214 u32 timestamp_msw;
1215 u16 status;
1216 u16 payload_size;
1217 u8 payload[0];
1218};
1219
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001220struct snd_lsm_sound_model_v2_32 {
1221 compat_uptr_t data;
1222 compat_uptr_t confidence_level;
1223 u32 data_size;
1224 enum lsm_detection_mode detection_mode;
1225 u8 num_confidence_levels;
1226 bool detect_failure;
1227};
1228
1229struct snd_lsm_detection_params_32 {
1230 compat_uptr_t conf_level;
1231 enum lsm_detection_mode detect_mode;
1232 u8 num_confidence_levels;
1233 bool detect_failure;
1234};
1235
1236struct lsm_params_info_32 {
1237 u32 module_id;
1238 u32 param_id;
1239 u32 param_size;
1240 compat_uptr_t param_data;
Chaithanya Krishna Bacharaju3f134072016-02-29 14:13:02 +05301241 uint32_t param_type;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001242};
1243
1244struct snd_lsm_module_params_32 {
1245 compat_uptr_t params;
1246 u32 num_params;
1247 u32 data_size;
1248};
1249
1250enum {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001251 SNDRV_LSM_REG_SND_MODEL_V2_32 =
1252 _IOW('U', 0x07, struct snd_lsm_sound_model_v2_32),
1253 SNDRV_LSM_SET_PARAMS_32 =
1254 _IOW('U', 0x0A, struct snd_lsm_detection_params_32),
1255 SNDRV_LSM_SET_MODULE_PARAMS_32 =
1256 _IOW('U', 0x0B, struct snd_lsm_module_params_32),
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +05301257 SNDRV_LSM_EVENT_STATUS_V3_32 =
1258 _IOW('U', 0x0F, struct snd_lsm_event_status_v3_32),
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001259};
1260
1261static int msm_lsm_ioctl_compat(struct snd_pcm_substream *substream,
1262 unsigned int cmd, void __user *arg)
1263{
1264 struct snd_pcm_runtime *runtime;
1265 struct lsm_priv *prtd;
1266 struct snd_soc_pcm_runtime *rtd;
1267 int err = 0;
1268 u32 size = 0;
1269
1270 if (PCM_RUNTIME_CHECK(substream))
1271 return -ENXIO;
1272
1273 if (!substream || !substream->private_data) {
1274 pr_err("%s: Invalid %s\n", __func__,
1275 (!substream) ? "substream" : "private_data");
1276 return -EINVAL;
1277 }
1278 runtime = substream->runtime;
1279 rtd = substream->private_data;
1280 prtd = runtime->private_data;
1281
1282 switch (cmd) {
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001283 case SNDRV_LSM_EVENT_STATUS: {
1284 struct snd_lsm_event_status *user = NULL, userarg32;
1285 struct snd_lsm_event_status *user32 = NULL;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001286
1287 if (copy_from_user(&userarg32, arg, sizeof(userarg32))) {
1288 dev_err(rtd->dev, "%s: err copyuser ioctl %s\n",
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001289 __func__, "SNDRV_LSM_EVENT_STATUS");
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001290 return -EFAULT;
1291 }
1292
1293 if (userarg32.payload_size >
1294 LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
1295 pr_err("%s: payload_size %d is invalid, max allowed = %d\n",
1296 __func__, userarg32.payload_size,
1297 LISTEN_MAX_STATUS_PAYLOAD_SIZE);
1298 return -EINVAL;
1299 }
1300
1301 size = sizeof(*user) + userarg32.payload_size;
1302 user = kmalloc(size, GFP_KERNEL);
1303 if (!user) {
1304 dev_err(rtd->dev,
1305 "%s: Allocation failed event status size %d\n",
1306 __func__, size);
1307 return -EFAULT;
1308 } else {
1309 cmd = SNDRV_LSM_EVENT_STATUS;
1310 user->payload_size = userarg32.payload_size;
1311 err = msm_lsm_ioctl_shared(substream, cmd, user);
1312 }
1313
1314 /* Update size with actual payload size */
1315 size = sizeof(userarg32) + user->payload_size;
1316 if (!err && !access_ok(VERIFY_WRITE, arg, size)) {
1317 dev_err(rtd->dev,
1318 "%s: write verify failed size %d\n",
1319 __func__, size);
1320 err = -EFAULT;
1321 }
1322 if (!err) {
1323 user32 = kmalloc(size, GFP_KERNEL);
1324 if (!user32) {
1325 dev_err(rtd->dev,
1326 "%s: Allocation event user status size %d\n",
1327 __func__, size);
1328 err = -EFAULT;
1329 } else {
1330 user32->status = user->status;
1331 user32->payload_size = user->payload_size;
1332 memcpy(user32->payload,
1333 user->payload, user32->payload_size);
1334 }
1335 }
1336 if (!err && (copy_to_user(arg, user32, size))) {
1337 dev_err(rtd->dev, "%s: failed to copy payload %d",
1338 __func__, size);
1339 err = -EFAULT;
1340 }
1341 kfree(user);
1342 kfree(user32);
1343 if (err)
1344 dev_err(rtd->dev, "%s: lsmevent failed %d",
1345 __func__, err);
1346 break;
1347 }
1348
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +05301349 case SNDRV_LSM_EVENT_STATUS_V3_32: {
1350 struct snd_lsm_event_status_v3_32 userarg32, *user32 = NULL;
1351 struct snd_lsm_event_status_v3 *user = NULL;
1352
1353 if (copy_from_user(&userarg32, arg, sizeof(userarg32))) {
1354 dev_err(rtd->dev, "%s: err copyuser ioctl %s\n",
1355 __func__, "SNDRV_LSM_EVENT_STATUS_V3_32");
1356 return -EFAULT;
1357 }
1358
1359 if (userarg32.payload_size >
1360 LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
1361 pr_err("%s: payload_size %d is invalid, max allowed = %d\n",
1362 __func__, userarg32.payload_size,
1363 LISTEN_MAX_STATUS_PAYLOAD_SIZE);
1364 return -EINVAL;
1365 }
1366
1367 size = sizeof(*user) + userarg32.payload_size;
1368 user = kmalloc(size, GFP_KERNEL);
1369 if (!user) {
1370 dev_err(rtd->dev,
1371 "%s: Allocation failed event status size %d\n",
1372 __func__, size);
1373 return -EFAULT;
1374 }
1375 cmd = SNDRV_LSM_EVENT_STATUS_V3;
1376 user->payload_size = userarg32.payload_size;
1377 err = msm_lsm_ioctl_shared(substream, cmd, user);
1378
1379 /* Update size with actual payload size */
1380 size = sizeof(userarg32) + user->payload_size;
1381 if (!err && !access_ok(VERIFY_WRITE, arg, size)) {
1382 dev_err(rtd->dev,
1383 "%s: write verify failed size %d\n",
1384 __func__, size);
1385 err = -EFAULT;
1386 }
1387 if (!err) {
1388 user32 = kmalloc(size, GFP_KERNEL);
1389 if (!user32) {
1390 dev_err(rtd->dev,
1391 "%s: Allocation event user status size %d\n",
1392 __func__, size);
1393 err = -EFAULT;
1394 } else {
1395 user32->timestamp_lsw = user->timestamp_lsw;
1396 user32->timestamp_msw = user->timestamp_msw;
1397 user32->status = user->status;
1398 user32->payload_size = user->payload_size;
1399 memcpy(user32->payload,
1400 user->payload, user32->payload_size);
1401 }
1402 }
1403 if (!err && (copy_to_user(arg, user32, size))) {
1404 dev_err(rtd->dev, "%s: failed to copy payload %d",
1405 __func__, size);
1406 err = -EFAULT;
1407 }
1408 kfree(user);
1409 kfree(user32);
1410 if (err)
1411 dev_err(rtd->dev, "%s: lsmevent failed %d",
1412 __func__, err);
1413 break;
1414 }
1415
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001416 case SNDRV_LSM_REG_SND_MODEL_V2_32: {
1417 struct snd_lsm_sound_model_v2_32 snd_modelv232;
1418 struct snd_lsm_sound_model_v2 snd_modelv2;
1419
1420 if (prtd->lsm_client->use_topology) {
1421 dev_err(rtd->dev,
1422 "%s: %s: not supported if using topology\n",
1423 __func__, "REG_SND_MODEL_V2");
1424 return -EINVAL;
1425 }
1426
1427 if (copy_from_user(&snd_modelv232, arg,
1428 sizeof(snd_modelv232))) {
1429 err = -EFAULT;
1430 dev_err(rtd->dev,
1431 "%s: copy user failed, size %zd %s\n",
1432 __func__,
1433 sizeof(struct snd_lsm_sound_model_v2_32),
1434 "SNDRV_LSM_REG_SND_MODEL_V2_32");
1435 } else {
1436 snd_modelv2.confidence_level =
1437 compat_ptr(snd_modelv232.confidence_level);
1438 snd_modelv2.data = compat_ptr(snd_modelv232.data);
1439 snd_modelv2.data_size = snd_modelv232.data_size;
1440 snd_modelv2.detect_failure =
1441 snd_modelv232.detect_failure;
1442 snd_modelv2.detection_mode =
1443 snd_modelv232.detection_mode;
1444 snd_modelv2.num_confidence_levels =
1445 snd_modelv232.num_confidence_levels;
1446 cmd = SNDRV_LSM_REG_SND_MODEL_V2;
1447 err = msm_lsm_ioctl_shared(substream, cmd,
1448 &snd_modelv2);
1449 if (err)
1450 dev_err(rtd->dev,
1451 "%s: ioctl %s failed\n", __func__,
1452 "SNDDRV_LSM_REG_SND_MODEL_V2_32");
1453 }
1454 break;
1455 }
1456
1457 case SNDRV_LSM_SET_PARAMS_32:{
1458 struct snd_lsm_detection_params_32 det_params32;
1459 struct snd_lsm_detection_params det_params;
1460
1461 if (prtd->lsm_client->use_topology) {
1462 dev_err(rtd->dev,
1463 "%s: %s: not supported if using topology\n",
1464 __func__, "SET_PARAMS_32");
1465 return -EINVAL;
1466 }
1467
1468 if (copy_from_user(&det_params32, arg,
1469 sizeof(det_params32))) {
1470 err = -EFAULT;
1471 dev_err(rtd->dev,
1472 "%s: %s: copy_from_user failed, size = %zd\n",
1473 __func__, "SNDRV_LSM_SET_PARAMS_32",
1474 sizeof(det_params32));
1475 } else {
1476 det_params.conf_level =
1477 compat_ptr(det_params32.conf_level);
1478 det_params.detect_mode =
1479 det_params32.detect_mode;
1480 det_params.num_confidence_levels =
1481 det_params32.num_confidence_levels;
1482 det_params.detect_failure =
1483 det_params32.detect_failure;
1484 cmd = SNDRV_LSM_SET_PARAMS;
1485 err = msm_lsm_ioctl_shared(substream, cmd,
1486 &det_params);
1487 if (err)
1488 dev_err(rtd->dev,
1489 "%s: ioctl %s failed\n", __func__,
1490 "SNDRV_LSM_SET_PARAMS");
1491 }
1492 break;
1493 }
1494
1495 case SNDRV_LSM_SET_MODULE_PARAMS_32: {
1496 struct snd_lsm_module_params_32 p_data_32;
1497 struct snd_lsm_module_params p_data;
1498 u8 *params, *params32;
1499 size_t p_size;
1500 struct lsm_params_info_32 *p_info_32;
1501 struct lsm_params_info *p_info;
1502 int i;
1503
1504 if (!prtd->lsm_client->use_topology) {
1505 dev_err(rtd->dev,
1506 "%s: %s: not supported if not using topology\n",
1507 __func__, "SET_MODULE_PARAMS_32");
1508 return -EINVAL;
1509 }
1510
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001511 if (copy_from_user(&p_data_32, arg,
1512 sizeof(p_data_32))) {
1513 dev_err(rtd->dev,
1514 "%s: %s: copy_from_user failed, size = %zd\n",
1515 __func__, "SET_MODULE_PARAMS_32",
1516 sizeof(p_data_32));
1517 return -EFAULT;
1518 }
1519
1520 p_data.params = compat_ptr(p_data_32.params);
1521 p_data.num_params = p_data_32.num_params;
1522 p_data.data_size = p_data_32.data_size;
1523
1524 if (p_data.num_params > LSM_PARAMS_MAX) {
1525 dev_err(rtd->dev,
1526 "%s: %s: Invalid num_params %d\n",
1527 __func__, "SET_MODULE_PARAMS_32",
1528 p_data.num_params);
1529 return -EINVAL;
1530 }
1531
1532 if (p_data.data_size !=
1533 (p_data.num_params * sizeof(struct lsm_params_info_32))) {
1534 dev_err(rtd->dev,
1535 "%s: %s: Invalid size %d\n",
1536 __func__, "SET_MODULE_PARAMS_32",
1537 p_data.data_size);
1538 return -EINVAL;
1539 }
1540
1541 p_size = sizeof(struct lsm_params_info_32) *
1542 p_data.num_params;
1543
1544 params32 = kzalloc(p_size, GFP_KERNEL);
1545 if (!params32)
1546 return -ENOMEM;
1547
1548 p_size = sizeof(struct lsm_params_info) * p_data.num_params;
1549 params = kzalloc(p_size, GFP_KERNEL);
1550 if (!params) {
1551 dev_err(rtd->dev,
1552 "%s: no memory for params, size = %zd\n",
1553 __func__, p_size);
1554 kfree(params32);
1555 return -ENOMEM;
1556 }
1557
1558 if (copy_from_user(params32, p_data.params,
1559 p_data.data_size)) {
1560 dev_err(rtd->dev,
1561 "%s: %s: copy_from_user failed, size = %d\n",
1562 __func__, "params32", p_data.data_size);
1563 kfree(params32);
1564 kfree(params);
1565 return -EFAULT;
1566 }
1567
1568 p_info_32 = (struct lsm_params_info_32 *) params32;
1569 p_info = (struct lsm_params_info *) params;
1570 for (i = 0; i < p_data.num_params; i++) {
1571 p_info->module_id = p_info_32->module_id;
1572 p_info->param_id = p_info_32->param_id;
1573 p_info->param_size = p_info_32->param_size;
1574 p_info->param_data = compat_ptr(p_info_32->param_data);
1575 p_info->param_type = p_info_32->param_type;
1576
1577 p_info_32++;
1578 p_info++;
1579 }
1580
1581 err = msm_lsm_process_params(substream,
1582 &p_data, params);
1583 if (err)
1584 dev_err(rtd->dev,
1585 "%s: Failed to process params, err = %d\n",
1586 __func__, err);
1587 kfree(params);
1588 kfree(params32);
1589 break;
1590 }
Bhalchandra Gajare930739e2016-12-15 16:43:45 -08001591 case SNDRV_LSM_REG_SND_MODEL_V2:
1592 case SNDRV_LSM_SET_PARAMS:
1593 case SNDRV_LSM_SET_MODULE_PARAMS:
1594 /*
1595 * In ideal cases, the compat_ioctl should never be called
1596 * with the above unlocked ioctl commands. Print error
1597 * and return error if it does.
1598 */
1599 dev_err(rtd->dev,
1600 "%s: Invalid cmd for compat_ioctl\n",
1601 __func__);
1602 err = -EINVAL;
1603 break;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001604 default:
1605 err = msm_lsm_ioctl_shared(substream, cmd, arg);
1606 break;
1607 }
1608 return err;
1609}
1610#else
1611#define msm_lsm_ioctl_compat NULL
1612#endif
1613
1614static int msm_lsm_ioctl(struct snd_pcm_substream *substream,
1615 unsigned int cmd, void *arg)
1616{
1617 int err = 0;
1618 u32 size = 0;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001619 struct snd_pcm_runtime *runtime;
1620 struct snd_soc_pcm_runtime *rtd;
1621 struct lsm_priv *prtd;
1622
1623 if (!substream || !substream->private_data) {
1624 pr_err("%s: Invalid %s\n", __func__,
1625 (!substream) ? "substream" : "private_data");
1626 return -EINVAL;
1627 }
1628 runtime = substream->runtime;
1629 prtd = runtime->private_data;
1630 rtd = substream->private_data;
1631
1632 switch (cmd) {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001633 case SNDRV_LSM_REG_SND_MODEL_V2: {
1634 struct snd_lsm_sound_model_v2 snd_model_v2;
1635
1636 if (prtd->lsm_client->use_topology) {
1637 dev_err(rtd->dev,
1638 "%s: %s: not supported if using topology\n",
1639 __func__, "REG_SND_MODEL_V2");
1640 return -EINVAL;
1641 }
1642
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001643 if (copy_from_user(&snd_model_v2, arg, sizeof(snd_model_v2))) {
1644 err = -EFAULT;
1645 dev_err(rtd->dev,
1646 "%s: copy from user failed, size %zd\n",
1647 __func__,
1648 sizeof(struct snd_lsm_sound_model_v2));
1649 }
1650 if (!err)
1651 err = msm_lsm_ioctl_shared(substream, cmd,
1652 &snd_model_v2);
1653 if (err)
1654 dev_err(rtd->dev,
1655 "%s REG_SND_MODEL failed err %d\n",
1656 __func__, err);
1657 return err;
1658 }
1659 break;
1660 case SNDRV_LSM_SET_PARAMS: {
1661 struct snd_lsm_detection_params det_params;
1662
1663 if (prtd->lsm_client->use_topology) {
1664 dev_err(rtd->dev,
1665 "%s: %s: not supported if using topology\n",
1666 __func__, "SET_PARAMS");
1667 return -EINVAL;
1668 }
1669
1670 pr_debug("%s: SNDRV_LSM_SET_PARAMS\n", __func__);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001671
1672 if (copy_from_user(&det_params, arg,
1673 sizeof(det_params))) {
1674 dev_err(rtd->dev,
1675 "%s: %s: copy_from_user failed, size %zd\n",
1676 __func__, "SNDRV_LSM_SET_PARAMS",
1677 sizeof(det_params));
1678 err = -EFAULT;
1679 }
1680
1681 if (!err)
1682 err = msm_lsm_ioctl_shared(substream, cmd,
1683 &det_params);
1684 else
1685 dev_err(rtd->dev,
1686 "%s: LSM_SET_PARAMS failed, err %d\n",
1687 __func__, err);
1688 return err;
1689 }
1690
1691 case SNDRV_LSM_SET_MODULE_PARAMS: {
1692 struct snd_lsm_module_params p_data;
1693 size_t p_size;
1694 u8 *params;
1695
1696 if (!prtd->lsm_client->use_topology) {
1697 dev_err(rtd->dev,
1698 "%s: %s: not supported if not using topology\n",
1699 __func__, "SET_MODULE_PARAMS");
1700 return -EINVAL;
1701 }
1702
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001703 if (copy_from_user(&p_data, arg,
1704 sizeof(p_data))) {
1705 dev_err(rtd->dev,
1706 "%s: %s: copy_from_user failed, size = %zd\n",
1707 __func__, "p_data", sizeof(p_data));
1708 return -EFAULT;
1709 }
1710
1711 if (p_data.num_params > LSM_PARAMS_MAX) {
1712 dev_err(rtd->dev,
1713 "%s: %s: Invalid num_params %d\n",
1714 __func__, "SET_MODULE_PARAMS",
1715 p_data.num_params);
1716 return -EINVAL;
1717 }
1718
1719 p_size = p_data.num_params *
1720 sizeof(struct lsm_params_info);
1721
1722 if (p_data.data_size != p_size) {
1723 dev_err(rtd->dev,
1724 "%s: %s: Invalid size %zd\n",
1725 __func__, "SET_MODULE_PARAMS", p_size);
1726
1727 return -EFAULT;
1728 }
1729
1730 params = kzalloc(p_size, GFP_KERNEL);
1731 if (!params)
1732 return -ENOMEM;
1733
1734 if (copy_from_user(params, p_data.params,
1735 p_data.data_size)) {
1736 dev_err(rtd->dev,
1737 "%s: %s: copy_from_user failed, size = %d\n",
1738 __func__, "params", p_data.data_size);
1739 kfree(params);
1740 return -EFAULT;
1741 }
1742
1743 err = msm_lsm_process_params(substream, &p_data, params);
1744 if (err)
1745 dev_err(rtd->dev,
1746 "%s: %s: Failed to set params, err = %d\n",
1747 __func__, "SET_MODULE_PARAMS", err);
1748 kfree(params);
1749 break;
1750 }
1751
1752 case SNDRV_LSM_EVENT_STATUS: {
1753 struct snd_lsm_event_status *user = NULL, userarg;
1754
1755 dev_dbg(rtd->dev,
1756 "%s: SNDRV_LSM_EVENT_STATUS\n", __func__);
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001757 if (copy_from_user(&userarg, arg, sizeof(userarg))) {
1758 dev_err(rtd->dev,
1759 "%s: err copyuser event_status\n",
1760 __func__);
1761 return -EFAULT;
1762 }
1763
1764 if (userarg.payload_size >
1765 LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
1766 pr_err("%s: payload_size %d is invalid, max allowed = %d\n",
1767 __func__, userarg.payload_size,
1768 LISTEN_MAX_STATUS_PAYLOAD_SIZE);
1769 return -EINVAL;
1770 }
1771
1772 size = sizeof(struct snd_lsm_event_status) +
1773 userarg.payload_size;
1774 user = kmalloc(size, GFP_KERNEL);
1775 if (!user) {
1776 dev_err(rtd->dev,
1777 "%s: Allocation failed event status size %d\n",
1778 __func__, size);
1779 return -EFAULT;
1780 }
1781 user->payload_size = userarg.payload_size;
1782 err = msm_lsm_ioctl_shared(substream, cmd, user);
1783
1784 /* Update size with actual payload size */
1785 size = sizeof(*user) + user->payload_size;
1786 if (!err && !access_ok(VERIFY_WRITE, arg, size)) {
1787 dev_err(rtd->dev,
1788 "%s: write verify failed size %d\n",
1789 __func__, size);
1790 err = -EFAULT;
1791 }
1792 if (!err && (copy_to_user(arg, user, size))) {
1793 dev_err(rtd->dev,
1794 "%s: failed to copy payload %d",
1795 __func__, size);
1796 err = -EFAULT;
1797 }
1798 kfree(user);
1799 if (err)
1800 dev_err(rtd->dev,
1801 "%s: lsmevent failed %d", __func__, err);
1802 return err;
1803 }
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +05301804
1805 case SNDRV_LSM_EVENT_STATUS_V3: {
1806 struct snd_lsm_event_status_v3 *user = NULL;
1807 struct snd_lsm_event_status_v3 userarg;
1808
1809 dev_dbg(rtd->dev,
1810 "%s: SNDRV_LSM_EVENT_STATUS_V3\n", __func__);
1811 if (!arg) {
1812 dev_err(rtd->dev,
1813 "%s: Invalid params event_status_v3\n",
1814 __func__);
1815 return -EINVAL;
1816 }
1817 if (copy_from_user(&userarg, arg, sizeof(userarg))) {
1818 dev_err(rtd->dev,
1819 "%s: err copyuser event_status_v3\n",
1820 __func__);
1821 return -EFAULT;
1822 }
1823
1824 if (userarg.payload_size >
1825 LISTEN_MAX_STATUS_PAYLOAD_SIZE) {
1826 pr_err("%s: payload_size %d is invalid, max allowed = %d\n",
1827 __func__, userarg.payload_size,
1828 LISTEN_MAX_STATUS_PAYLOAD_SIZE);
1829 return -EINVAL;
1830 }
1831
1832 size = sizeof(struct snd_lsm_event_status_v3) +
1833 userarg.payload_size;
1834 user = kmalloc(size, GFP_KERNEL);
1835 if (!user) {
1836 dev_err(rtd->dev,
1837 "%s: Allocation failed event status size %d\n",
1838 __func__, size);
1839 return -EFAULT;
1840 }
1841 user->payload_size = userarg.payload_size;
1842 err = msm_lsm_ioctl_shared(substream, cmd, user);
1843
1844 /* Update size with actual payload size */
1845 size = sizeof(*user) + user->payload_size;
1846 if (!err && !access_ok(VERIFY_WRITE, arg, size)) {
1847 dev_err(rtd->dev,
1848 "%s: write verify failed size %d\n",
1849 __func__, size);
1850 err = -EFAULT;
1851 }
1852 if (!err && (copy_to_user(arg, user, size))) {
1853 dev_err(rtd->dev,
1854 "%s: failed to copy payload %d",
1855 __func__, size);
1856 err = -EFAULT;
1857 }
1858 kfree(user);
1859 if (err)
1860 dev_err(rtd->dev,
1861 "%s: lsm_event_v3 failed %d", __func__, err);
1862 break;
1863 }
1864
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001865 default:
1866 err = msm_lsm_ioctl_shared(substream, cmd, arg);
1867 break;
1868 }
1869 return err;
1870}
1871
1872static int msm_lsm_open(struct snd_pcm_substream *substream)
1873{
1874 struct snd_pcm_runtime *runtime = substream->runtime;
1875 struct lsm_priv *prtd;
1876 int ret = 0;
1877
1878 pr_debug("%s\n", __func__);
1879 prtd = kzalloc(sizeof(struct lsm_priv), GFP_KERNEL);
1880 if (!prtd) {
1881 pr_err("%s: Failed to allocate memory for lsm_priv\n",
1882 __func__);
1883 return -ENOMEM;
1884 }
1885 spin_lock_init(&prtd->event_lock);
1886 init_waitqueue_head(&prtd->event_wait);
1887 init_waitqueue_head(&prtd->period_wait);
1888 prtd->substream = substream;
1889 runtime->private_data = prtd;
1890 runtime->hw = msm_pcm_hardware_capture;
1891
1892 ret = snd_pcm_hw_constraint_list(runtime, 0,
1893 SNDRV_PCM_HW_PARAM_RATE,
1894 &constraints_sample_rates);
1895 if (ret < 0)
1896 pr_info("%s: snd_pcm_hw_constraint_list failed ret %d\n",
1897 __func__, ret);
1898 /* Ensure that buffer size is a multiple of period size */
1899 ret = snd_pcm_hw_constraint_integer(runtime,
1900 SNDRV_PCM_HW_PARAM_PERIODS);
1901 if (ret < 0)
1902 pr_info("%s: snd_pcm_hw_constraint_integer failed ret %d\n",
1903 __func__, ret);
1904
1905 ret = snd_pcm_hw_constraint_minmax(runtime,
1906 SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
1907 CAPTURE_MIN_NUM_PERIODS * CAPTURE_MIN_PERIOD_SIZE,
1908 CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE);
1909 if (ret < 0)
1910 pr_info("%s: constraint for buffer bytes min max ret = %d\n",
1911 __func__, ret);
1912 ret = snd_pcm_hw_constraint_step(runtime, 0,
1913 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
1914 if (ret < 0) {
1915 pr_info("%s: constraint for period bytes step ret = %d\n",
1916 __func__, ret);
1917 }
1918 ret = snd_pcm_hw_constraint_step(runtime, 0,
1919 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
1920 if (ret < 0)
1921 pr_info("%s: constraint for buffer bytes step ret = %d\n",
1922 __func__, ret);
1923 prtd->lsm_client = q6lsm_client_alloc(
1924 (lsm_app_cb)lsm_event_handler, prtd);
1925 if (!prtd->lsm_client) {
1926 pr_err("%s: Could not allocate memory\n", __func__);
1927 kfree(prtd);
1928 runtime->private_data = NULL;
1929 return -ENOMEM;
1930 }
1931 prtd->lsm_client->opened = false;
Revathi Uddaraju1803e362016-10-19 14:12:00 +05301932 prtd->lsm_client->session_state = IDLE;
1933 prtd->lsm_client->poll_enable = true;
1934 prtd->lsm_client->perf_mode = 0;
Chaithanya Krishna Bacharaju997bb562016-07-21 10:08:32 +05301935 prtd->lsm_client->event_mode = LSM_EVENT_NON_TIME_STAMP_MODE;
Revathi Uddaraju1803e362016-10-19 14:12:00 +05301936
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001937 return 0;
1938}
1939
1940static int msm_lsm_prepare(struct snd_pcm_substream *substream)
1941{
1942 struct snd_pcm_runtime *runtime = substream->runtime;
1943 struct lsm_priv *prtd = runtime->private_data;
1944 struct snd_soc_pcm_runtime *rtd;
Revathi Uddaraju1803e362016-10-19 14:12:00 +05301945 int ret = 0;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001946
1947 if (!substream->private_data) {
1948 pr_err("%s: Invalid private_data", __func__);
1949 return -EINVAL;
1950 }
1951
1952 rtd = prtd->substream->private_data;
1953
1954 if (!prtd->lsm_client) {
1955 dev_err(rtd->dev,
1956 "%s: LSM client data ptr is NULL\n", __func__);
1957 return -EINVAL;
1958 }
Revathi Uddaraju1803e362016-10-19 14:12:00 +05301959
1960 if (prtd->lsm_client->session_state == IDLE) {
1961 ret = msm_pcm_routing_reg_phy_compr_stream(
1962 rtd->dai_link->id,
1963 prtd->lsm_client->perf_mode,
1964 prtd->lsm_client->session,
1965 SNDRV_PCM_STREAM_CAPTURE,
1966 LISTEN);
1967 if (ret) {
1968 dev_err(rtd->dev,
1969 "%s: register phy compr stream failed %d\n",
1970 __func__, ret);
1971 return ret;
1972 }
1973 }
1974
1975 prtd->lsm_client->session_state = RUNNING;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001976 prtd->lsm_client->started = false;
1977 runtime->private_data = prtd;
Revathi Uddaraju1803e362016-10-19 14:12:00 +05301978 return ret;
Banajit Goswami0530e2f2016-12-09 21:34:37 -08001979}
1980
1981static int msm_lsm_close(struct snd_pcm_substream *substream)
1982{
1983 unsigned long flags;
1984 struct snd_pcm_runtime *runtime = substream->runtime;
1985 struct lsm_priv *prtd = runtime->private_data;
1986 struct snd_soc_pcm_runtime *rtd;
1987 int ret = 0;
1988
1989 if (!substream->private_data) {
1990 pr_err("%s: Invalid private_data", __func__);
1991 return -EINVAL;
1992 }
1993 if (!prtd || !prtd->lsm_client) {
1994 pr_err("%s: No LSM session active\n", __func__);
1995 return -EINVAL;
1996 }
1997 rtd = substream->private_data;
1998
1999 dev_dbg(rtd->dev, "%s\n", __func__);
2000 if (prtd->lsm_client->started) {
2001 ret = q6lsm_stop(prtd->lsm_client, true);
2002 if (ret)
2003 dev_err(rtd->dev,
2004 "%s: session stop failed, err = %d\n",
2005 __func__, ret);
2006 else
2007 dev_dbg(rtd->dev,
2008 "%s: LSM client session stopped %d\n",
2009 __func__, ret);
2010
2011 /*
2012 * Go Ahead and try de-register sound model,
2013 * even if stop failed
2014 */
2015 prtd->lsm_client->started = false;
2016
2017 ret = q6lsm_deregister_sound_model(prtd->lsm_client);
2018 if (ret)
2019 dev_err(rtd->dev,
2020 "%s: dereg_snd_model failed, err = %d\n",
2021 __func__, ret);
2022 else
2023 dev_dbg(rtd->dev, "%s: dereg_snd_model successful\n",
2024 __func__);
2025 }
2026
Revathi Uddaraju1803e362016-10-19 14:12:00 +05302027 msm_pcm_routing_dereg_phy_stream(rtd->dai_link->id,
2028 SNDRV_PCM_STREAM_CAPTURE);
2029
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002030 if (prtd->lsm_client->opened) {
2031 q6lsm_close(prtd->lsm_client);
2032 prtd->lsm_client->opened = false;
2033 }
2034 q6lsm_client_free(prtd->lsm_client);
2035
2036 spin_lock_irqsave(&prtd->event_lock, flags);
2037 kfree(prtd->event_status);
2038 prtd->event_status = NULL;
2039 spin_unlock_irqrestore(&prtd->event_lock, flags);
2040 kfree(prtd);
2041 runtime->private_data = NULL;
2042
2043 return 0;
2044}
2045
2046static int msm_lsm_hw_params(struct snd_pcm_substream *substream,
2047 struct snd_pcm_hw_params *params)
2048{
2049 struct snd_pcm_runtime *runtime = substream->runtime;
2050 struct lsm_priv *prtd = runtime->private_data;
2051 struct lsm_lab_hw_params *hw_params = NULL;
2052 struct snd_soc_pcm_runtime *rtd;
2053
2054 if (!substream->private_data) {
2055 pr_err("%s: Invalid private_data", __func__);
2056 return -EINVAL;
2057 }
2058 rtd = substream->private_data;
2059
2060 if (!prtd || !params) {
2061 dev_err(rtd->dev,
2062 "%s: invalid params prtd %pK params %pK",
2063 __func__, prtd, params);
2064 return -EINVAL;
2065 }
2066 hw_params = &prtd->lsm_client->hw_params;
2067 hw_params->sample_rate = params_rate(params);
2068 hw_params->sample_size =
2069 (params_format(params) == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 0;
2070 hw_params->period_count = params_periods(params);
2071 if (hw_params->sample_rate != 16000 || hw_params->sample_size != 16 ||
2072 hw_params->period_count == 0) {
2073 dev_err(rtd->dev,
2074 "%s: Invalid params sample rate %d sample size %d period count %d",
2075 __func__, hw_params->sample_rate,
2076 hw_params->sample_size,
2077 hw_params->period_count);
2078 return -EINVAL;
2079 }
2080 hw_params->buf_sz = params_buffer_bytes(params) /
2081 hw_params->period_count;
2082 dev_dbg(rtd->dev,
2083 "%s: sample rate %d sample size %d buffer size %d period count %d\n",
2084 __func__, hw_params->sample_rate, hw_params->sample_size,
2085 hw_params->buf_sz, hw_params->period_count);
2086 return 0;
2087}
2088
2089static snd_pcm_uframes_t msm_lsm_pcm_pointer(
2090 struct snd_pcm_substream *substream)
2091{
2092 struct snd_pcm_runtime *runtime = substream->runtime;
2093 struct lsm_priv *prtd = runtime->private_data;
2094 struct snd_soc_pcm_runtime *rtd;
2095
2096 if (!substream->private_data) {
2097 pr_err("%s: Invalid private_data", __func__);
2098 return -EINVAL;
2099 }
2100 rtd = substream->private_data;
2101
2102 if (!prtd) {
2103 dev_err(rtd->dev,
2104 "%s: Invalid param %pK\n", __func__, prtd);
2105 return 0;
2106 }
2107
2108 if (prtd->dma_write >= snd_pcm_lib_buffer_bytes(substream))
2109 prtd->dma_write = 0;
2110 dev_dbg(rtd->dev,
2111 "%s: dma post = %d\n", __func__, prtd->dma_write);
2112 return bytes_to_frames(runtime, prtd->dma_write);
2113}
2114
2115static int msm_lsm_pcm_copy(struct snd_pcm_substream *substream, int ch,
2116 snd_pcm_uframes_t hwoff, void __user *buf, snd_pcm_uframes_t frames)
2117{
2118 struct snd_pcm_runtime *runtime = substream->runtime;
2119 struct lsm_priv *prtd = runtime->private_data;
2120 char *pcm_buf = NULL;
2121 int fbytes = 0, rc = 0;
2122 struct snd_soc_pcm_runtime *rtd;
2123
2124 if (!substream->private_data) {
2125 pr_err("%s: Invalid private_data", __func__);
2126 return -EINVAL;
2127 }
2128 rtd = substream->private_data;
2129
2130 if (!prtd) {
2131 dev_err(rtd->dev,
2132 "%s: Invalid param %pK\n", __func__, prtd);
2133 return -EINVAL;
2134 }
2135
2136 fbytes = frames_to_bytes(runtime, frames);
2137 if (runtime->status->state == SNDRV_PCM_STATE_XRUN ||
2138 runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
2139 dev_err(rtd->dev,
2140 "%s: runtime state incorrect %d", __func__,
2141 runtime->status->state);
2142 return 0;
2143 }
2144 rc = wait_event_timeout(prtd->period_wait,
2145 (atomic_read(&prtd->buf_count) |
2146 atomic_read(&prtd->read_abort)), (2 * HZ));
2147 if (!rc) {
2148 dev_err(rtd->dev,
2149 "%s: timeout for read retry\n", __func__);
2150 return -EAGAIN;
2151 }
2152 if (atomic_read(&prtd->read_abort)) {
2153 dev_err(rtd->dev,
2154 "%s: Read abort received\n", __func__);
2155 return -EIO;
2156 }
2157 prtd->appl_cnt = prtd->appl_cnt %
2158 prtd->lsm_client->hw_params.period_count;
2159 pcm_buf = prtd->lsm_client->lab_buffer[prtd->appl_cnt].data;
2160 dev_dbg(rtd->dev,
2161 "%s: copy the pcm data size %d\n",
2162 __func__, fbytes);
2163 if (pcm_buf) {
2164 if (copy_to_user(buf, pcm_buf, fbytes)) {
2165 dev_err(rtd->dev,
2166 "%s: failed to copy bytes %d\n",
2167 __func__, fbytes);
2168 return -EINVAL;
2169 }
2170 } else {
2171 dev_err(rtd->dev,
2172 "%s: Invalid pcm buffer\n", __func__);
2173 return -EINVAL;
2174 }
2175 prtd->appl_cnt = (prtd->appl_cnt + 1) %
2176 prtd->lsm_client->hw_params.period_count;
2177 atomic_dec(&prtd->buf_count);
2178 return 0;
2179}
2180
Banajit Goswami95da2cb2016-12-15 22:07:55 -08002181static const struct snd_pcm_ops msm_lsm_ops = {
Banajit Goswami0530e2f2016-12-09 21:34:37 -08002182 .open = msm_lsm_open,
2183 .close = msm_lsm_close,
2184 .ioctl = msm_lsm_ioctl,
2185 .prepare = msm_lsm_prepare,
2186 .compat_ioctl = msm_lsm_ioctl_compat,
2187 .hw_params = msm_lsm_hw_params,
2188 .copy = msm_lsm_pcm_copy,
2189 .pointer = msm_lsm_pcm_pointer,
2190};
2191
2192static int msm_asoc_lsm_new(struct snd_soc_pcm_runtime *rtd)
2193{
2194 struct snd_card *card = rtd->card->snd_card;
2195
2196 if (!card->dev->coherent_dma_mask)
2197 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
2198
2199 return 0;
2200}
2201
2202static int msm_asoc_lsm_probe(struct snd_soc_platform *platform)
2203{
2204 pr_debug("enter %s\n", __func__);
2205
2206 return 0;
2207}
2208
2209static struct snd_soc_platform_driver msm_soc_platform = {
2210 .ops = &msm_lsm_ops,
2211 .pcm_new = msm_asoc_lsm_new,
2212 .probe = msm_asoc_lsm_probe,
2213};
2214
2215static int msm_lsm_probe(struct platform_device *pdev)
2216{
2217
2218 return snd_soc_register_platform(&pdev->dev, &msm_soc_platform);
2219}
2220
2221static int msm_lsm_remove(struct platform_device *pdev)
2222{
2223 snd_soc_unregister_platform(&pdev->dev);
2224
2225 return 0;
2226}
2227
2228static const struct of_device_id msm_lsm_client_dt_match[] = {
2229 {.compatible = "qcom,msm-lsm-client" },
2230 { }
2231};
2232
2233static struct platform_driver msm_lsm_driver = {
2234 .driver = {
2235 .name = "msm-lsm-client",
2236 .owner = THIS_MODULE,
2237 .of_match_table = of_match_ptr(msm_lsm_client_dt_match),
2238 },
2239 .probe = msm_lsm_probe,
2240 .remove = msm_lsm_remove,
2241};
2242
2243static int __init msm_soc_platform_init(void)
2244{
2245 return platform_driver_register(&msm_lsm_driver);
2246}
2247module_init(msm_soc_platform_init);
2248
2249static void __exit msm_soc_platform_exit(void)
2250{
2251 platform_driver_unregister(&msm_lsm_driver);
2252}
2253module_exit(msm_soc_platform_exit);
2254
2255MODULE_DESCRIPTION("LSM client platform driver");
2256MODULE_DEVICE_TABLE(of, msm_lsm_client_dt_match);
2257MODULE_LICENSE("GPL v2");