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