blob: d03f24c42eeb1974c3a26e3e98eed02cca890077 [file] [log] [blame]
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301/*
pavanc34c1d6d2018-06-06 12:13:17 +05302 * Copyright (c) 2013-2018, Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05303 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13#include <linux/fs.h>
14#include <linux/mutex.h>
15#include <linux/wait.h>
16#include <linux/miscdevice.h>
17#include <linux/uaccess.h>
18#include <linux/sched.h>
19#include <linux/miscdevice.h>
20#include <linux/delay.h>
21#include <linux/spinlock.h>
22#include <linux/slab.h>
23#include <linux/debugfs.h>
24#include <linux/time.h>
25#include <linux/atomic.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053026#include <sound/lsm_params.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053027#include <asm/ioctls.h>
28#include <linux/memory.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053029#include <dsp/msm_audio_ion.h>
30#include <dsp/apr_audio-v2.h>
31#include <dsp/q6core.h>
32#include <dsp/q6lsm.h>
33#include <dsp/q6afe-v2.h>
34#include <dsp/audio_cal_utils.h>
35#include "adsp_err.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053036
37#define APR_TIMEOUT (5 * HZ)
38#define LSM_ALIGN_BOUNDARY 512
39#define LSM_SAMPLE_RATE 16000
40#define QLSM_PARAM_ID_MINOR_VERSION 1
41#define QLSM_PARAM_ID_MINOR_VERSION_2 2
42
43static int lsm_afe_port;
44
45enum {
46 LSM_CUSTOM_TOP_IDX,
47 LSM_TOP_IDX,
48 LSM_CAL_IDX,
49 LSM_MAX_CAL_IDX
50};
51
52enum {
53 CMD_STATE_CLEARED = 0,
54 CMD_STATE_WAIT_RESP = 1,
55};
56
57enum {
58 LSM_INVALID_SESSION_ID = 0,
59 LSM_MIN_SESSION_ID = 1,
60 LSM_MAX_SESSION_ID = 8,
61 LSM_CONTROL_SESSION = 0x0F,
62};
63
64#define CHECK_SESSION(x) (x < LSM_MIN_SESSION_ID || x > LSM_MAX_SESSION_ID)
65struct lsm_common {
66 void *apr;
67 atomic_t apr_users;
68 struct lsm_client common_client[LSM_MAX_SESSION_ID + 1];
69
70 int set_custom_topology;
71 struct cal_type_data *cal_data[LSM_MAX_CAL_IDX];
72
73 struct mutex apr_lock;
74};
75
76struct lsm_module_param_ids {
77 uint32_t module_id;
78 uint32_t param_id;
79};
80
81static struct lsm_common lsm_common;
82/*
83 * mmap_handle_p can point either client->sound_model.mem_map_handle or
84 * lsm_common.mmap_handle_for_cal.
85 * mmap_lock must be held while accessing this.
86 */
87static spinlock_t mmap_lock;
88static uint32_t *mmap_handle_p;
89
90static spinlock_t lsm_session_lock;
91static struct lsm_client *lsm_session[LSM_MAX_SESSION_ID + 1];
92
93static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv);
94static int q6lsm_send_cal(struct lsm_client *client, u32 set_params_opcode);
95static int q6lsm_memory_map_regions(struct lsm_client *client,
96 dma_addr_t dma_addr_p, uint32_t dma_buf_sz,
97 uint32_t *mmap_p);
98static int q6lsm_memory_unmap_regions(struct lsm_client *client,
99 uint32_t handle);
100
101static void q6lsm_set_param_hdr_info(
102 struct lsm_set_params_hdr *param_hdr,
103 u32 payload_size, u32 addr_lsw, u32 addr_msw,
104 u32 mmap_handle)
105{
106 param_hdr->data_payload_size = payload_size;
107 param_hdr->data_payload_addr_lsw = addr_lsw;
108 param_hdr->data_payload_addr_msw = addr_msw;
109 param_hdr->mem_map_handle = mmap_handle;
110}
111
112static void q6lsm_set_param_common(
113 struct lsm_param_payload_common *common,
114 struct lsm_module_param_ids *ids,
115 u32 param_size, u32 set_param_version)
116{
117 common->module_id = ids->module_id;
118 common->param_id = ids->param_id;
119
120 switch (set_param_version) {
121 case LSM_SESSION_CMD_SET_PARAMS_V2:
122 common->p_size.param_size = param_size;
123 break;
124 case LSM_SESSION_CMD_SET_PARAMS:
125 default:
126 common->p_size.sr.param_size =
127 (u16) param_size;
128 common->p_size.sr.reserved = 0;
129 break;
130 }
131}
132
133static int q6lsm_callback(struct apr_client_data *data, void *priv)
134{
135 struct lsm_client *client = (struct lsm_client *)priv;
136 uint32_t token;
137 uint32_t *payload;
138
139 if (!client || !data) {
140 pr_err("%s: client %pK data %pK\n",
141 __func__, client, data);
142 WARN_ON(1);
143 return -EINVAL;
144 }
145
146 if (data->opcode == RESET_EVENTS) {
147 pr_debug("%s: SSR event received 0x%x, event 0x%x, proc 0x%x\n",
148 __func__, data->opcode, data->reset_event,
149 data->reset_proc);
150
Xiaoyu Yefb90eb62017-10-10 12:26:08 -0700151 apr_reset(client->apr);
152 client->apr = NULL;
153 atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
154 wake_up(&client->cmd_wait);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530155 cal_utils_clear_cal_block_q6maps(LSM_MAX_CAL_IDX,
156 lsm_common.cal_data);
157 mutex_lock(&lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]->lock);
158 lsm_common.set_custom_topology = 1;
159 mutex_unlock(&lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]->lock);
160 return 0;
161 }
162
163 payload = data->payload;
164 pr_debug("%s: Session %d opcode 0x%x token 0x%x payload size %d\n"
165 "payload [0] = 0x%x\n", __func__, client->session,
166 data->opcode, data->token, data->payload_size, payload[0]);
167 if (data->opcode == LSM_DATA_EVENT_READ_DONE) {
168 struct lsm_cmd_read_done read_done;
169
170 token = data->token;
171 if (data->payload_size > sizeof(read_done)) {
172 pr_err("%s: read done error payload size %d expected size %zd\n",
173 __func__, data->payload_size,
174 sizeof(read_done));
175 return -EINVAL;
176 }
177 pr_debug("%s: opcode %x status %x lsw %x msw %x mem_map handle %x\n",
178 __func__, data->opcode, payload[0], payload[1],
179 payload[2], payload[3]);
180 read_done.status = payload[0];
181 read_done.buf_addr_lsw = payload[1];
182 read_done.buf_addr_msw = payload[2];
183 read_done.mem_map_handle = payload[3];
184 read_done.total_size = payload[4];
185 read_done.offset = payload[5];
186 if (client->cb)
187 client->cb(data->opcode, data->token,
188 (void *)&read_done,
189 client->priv);
190 return 0;
191 } else if (data->opcode == APR_BASIC_RSP_RESULT) {
192 token = data->token;
193 switch (payload[0]) {
194 case LSM_SESSION_CMD_START:
195 case LSM_SESSION_CMD_STOP:
196 case LSM_SESSION_CMD_SET_PARAMS:
197 case LSM_SESSION_CMD_OPEN_TX:
198 case LSM_SESSION_CMD_CLOSE_TX:
199 case LSM_SESSION_CMD_REGISTER_SOUND_MODEL:
200 case LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL:
201 case LSM_SESSION_CMD_SHARED_MEM_UNMAP_REGIONS:
202 case LSM_SESSION_CMD_EOB:
203 case LSM_SESSION_CMD_READ:
204 case LSM_SESSION_CMD_OPEN_TX_V2:
205 case LSM_CMD_ADD_TOPOLOGIES:
206 case LSM_SESSION_CMD_SET_PARAMS_V2:
207 if (token != client->session &&
208 payload[0] !=
209 LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL) {
210 pr_err("%s: Invalid session %d receivced expected %d\n",
211 __func__, token, client->session);
212 return -EINVAL;
213 }
214 client->cmd_err_code = payload[1];
215 if (client->cmd_err_code)
216 pr_err("%s: cmd 0x%x failed status %d\n",
217 __func__, payload[0], client->cmd_err_code);
218 if (atomic_cmpxchg(&client->cmd_state,
219 CMD_STATE_WAIT_RESP,
220 CMD_STATE_CLEARED) ==
221 CMD_STATE_WAIT_RESP)
222 wake_up(&client->cmd_wait);
223 break;
224 default:
225 pr_debug("%s: Unknown command 0x%x\n",
226 __func__, payload[0]);
227 break;
228 }
229 return 0;
230 }
231
232 if (client->cb)
233 client->cb(data->opcode, data->token, data->payload,
234 client->priv);
235
236 return 0;
237}
238
239static int q6lsm_session_alloc(struct lsm_client *client)
240{
241 unsigned long flags;
242 int n, ret = -ENOMEM;
243
244 spin_lock_irqsave(&lsm_session_lock, flags);
245 for (n = LSM_MIN_SESSION_ID; n <= LSM_MAX_SESSION_ID; n++) {
246 if (!lsm_session[n]) {
247 lsm_session[n] = client;
248 ret = n;
249 break;
250 }
251 }
252 spin_unlock_irqrestore(&lsm_session_lock, flags);
253 pr_debug("%s: Alloc Session %d", __func__, n);
254 return ret;
255}
256
257static void q6lsm_session_free(struct lsm_client *client)
258{
259 unsigned long flags;
260
261 pr_debug("%s: Freeing session ID %d\n", __func__, client->session);
262 spin_lock_irqsave(&lsm_session_lock, flags);
263 lsm_session[client->session] = LSM_INVALID_SESSION_ID;
264 spin_unlock_irqrestore(&lsm_session_lock, flags);
265 client->session = LSM_INVALID_SESSION_ID;
266}
267
268static void *q6lsm_mmap_apr_reg(void)
269{
270 if (atomic_inc_return(&lsm_common.apr_users) == 1) {
271 lsm_common.apr =
272 apr_register("ADSP", "LSM", q6lsm_mmapcallback,
273 0x0FFFFFFFF, &lsm_common);
274 if (!lsm_common.apr) {
275 pr_debug("%s: Unable to register APR LSM common port\n",
276 __func__);
277 atomic_dec(&lsm_common.apr_users);
278 }
279 }
280 return lsm_common.apr;
281}
282
283static int q6lsm_mmap_apr_dereg(void)
284{
285 if (atomic_read(&lsm_common.apr_users) <= 0) {
286 WARN("%s: APR common port already closed\n", __func__);
287 } else {
288 if (atomic_dec_return(&lsm_common.apr_users) == 0) {
289 apr_deregister(lsm_common.apr);
290 pr_debug("%s: APR De-Register common port\n", __func__);
291 }
292 }
293 return 0;
294}
295
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530296/**
297 * q6lsm_client_alloc -
298 * Allocate session for LSM client
299 *
300 * @cb: callback fn
301 * @priv: private data
302 *
303 * Returns LSM client handle on success or NULL on failure
304 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530305struct lsm_client *q6lsm_client_alloc(lsm_app_cb cb, void *priv)
306{
307 struct lsm_client *client;
308 int n;
309
310 client = kzalloc(sizeof(struct lsm_client), GFP_KERNEL);
311 if (!client)
312 return NULL;
313 n = q6lsm_session_alloc(client);
314 if (n <= 0) {
315 kfree(client);
316 return NULL;
317 }
318 client->session = n;
319 client->cb = cb;
320 client->priv = priv;
321 if (CHECK_SESSION(client->session)) {
322 pr_err("%s: Client session %d\n",
323 __func__, client->session);
324 kfree(client);
325 return NULL;
326 }
pavanc34c1d6d2018-06-06 12:13:17 +0530327
328 init_waitqueue_head(&client->cmd_wait);
329 mutex_init(&client->cmd_lock);
330 atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
331
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530332 pr_debug("%s: Client Session %d\n", __func__, client->session);
333 client->apr = apr_register("ADSP", "LSM", q6lsm_callback,
334 ((client->session) << 8 | client->session),
335 client);
336
337 if (client->apr == NULL) {
338 pr_err("%s: Registration with APR failed\n", __func__);
339 goto fail;
340 }
341
342 pr_debug("%s: Registering the common port with APR\n", __func__);
343 client->mmap_apr = q6lsm_mmap_apr_reg();
344 if (!client->mmap_apr) {
345 pr_err("%s: APR registration failed\n", __func__);
346 goto fail;
347 }
348
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530349 pr_debug("%s: New client allocated\n", __func__);
350 return client;
351fail:
352 q6lsm_client_free(client);
353 return NULL;
354}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530355EXPORT_SYMBOL(q6lsm_client_alloc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530356
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530357/**
358 * q6lsm_client_free -
359 * Performs LSM client free
360 *
361 * @client: LSM client handle
362 *
363 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530364void q6lsm_client_free(struct lsm_client *client)
365{
366 if (!client)
367 return;
368 if (CHECK_SESSION(client->session)) {
369 pr_err("%s: Invalid Session %d\n", __func__, client->session);
370 return;
371 }
372 apr_deregister(client->apr);
373 client->mmap_apr = NULL;
374 q6lsm_session_free(client);
375 q6lsm_mmap_apr_dereg();
376 mutex_destroy(&client->cmd_lock);
377 kfree(client);
378 client = NULL;
379}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530380EXPORT_SYMBOL(q6lsm_client_free);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530381
382/*
383 * q6lsm_apr_send_pkt : If wait == true, hold mutex to prevent from preempting
384 * other thread's wait.
385 * If mmap_handle_p != NULL, disable irq and spin lock to
386 * protect mmap_handle_p
387 */
388static int q6lsm_apr_send_pkt(struct lsm_client *client, void *handle,
389 void *data, bool wait, uint32_t *mmap_p)
390{
391 int ret;
392 unsigned long flags = 0;
393 struct apr_hdr *msg_hdr = (struct apr_hdr *) data;
394
Xiaoyu Yefb90eb62017-10-10 12:26:08 -0700395 if (!handle) {
396 pr_err("%s: handle is NULL\n", __func__);
397 return -EINVAL;
398 }
399
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530400 pr_debug("%s: enter wait %d\n", __func__, wait);
401 if (wait)
402 mutex_lock(&lsm_common.apr_lock);
403 if (mmap_p) {
404 WARN_ON(!wait);
405 spin_lock_irqsave(&mmap_lock, flags);
406 mmap_handle_p = mmap_p;
407 }
408 atomic_set(&client->cmd_state, CMD_STATE_WAIT_RESP);
409 client->cmd_err_code = 0;
410 ret = apr_send_pkt(handle, data);
411 if (mmap_p)
412 spin_unlock_irqrestore(&mmap_lock, flags);
413
414 if (ret < 0) {
415 pr_err("%s: apr_send_pkt failed %d\n", __func__, ret);
416 } else if (wait) {
417 ret = wait_event_timeout(client->cmd_wait,
418 (atomic_read(&client->cmd_state) ==
419 CMD_STATE_CLEARED),
420 APR_TIMEOUT);
421 if (likely(ret)) {
422 /* q6 returned error */
423 if (client->cmd_err_code) {
424 pr_err("%s: DSP returned error[%s]\n",
425 __func__, adsp_err_get_err_str(
426 client->cmd_err_code));
427 ret = adsp_err_get_lnx_err_code(
428 client->cmd_err_code);
429 } else {
430 ret = 0;
431 }
432 } else {
433 pr_err("%s: wait timedout, apr_opcode = 0x%x, size = %d\n",
434 __func__, msg_hdr->opcode, msg_hdr->pkt_size);
435 /* ret = 0 means wait timed out */
436 ret = -ETIMEDOUT;
437 }
438 } else {
439 ret = 0;
440 }
441 if (wait)
442 mutex_unlock(&lsm_common.apr_lock);
443
444 pr_debug("%s: leave ret %d\n", __func__, ret);
445 return ret;
446}
447
448static void q6lsm_add_hdr(struct lsm_client *client, struct apr_hdr *hdr,
449 uint32_t pkt_size, bool cmd_flg)
450{
451 pr_debug("%s: pkt_size %d cmd_flg %d session %d\n", __func__,
452 pkt_size, cmd_flg, client->session);
453 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
454 APR_HDR_LEN(sizeof(struct apr_hdr)),
455 APR_PKT_VER);
456 hdr->src_svc = APR_SVC_LSM;
457 hdr->src_domain = APR_DOMAIN_APPS;
458 hdr->dest_svc = APR_SVC_LSM;
459 hdr->dest_domain = APR_DOMAIN_ADSP;
460 hdr->src_port = ((client->session << 8) & 0xFF00) | client->session;
461 hdr->dest_port = ((client->session << 8) & 0xFF00) | client->session;
462 hdr->pkt_size = pkt_size;
463 if (cmd_flg)
464 hdr->token = client->session;
465}
466
467
468static int q6lsm_send_custom_topologies(struct lsm_client *client)
469{
470 int rc;
471 struct cal_block_data *cal_block = NULL;
472 struct lsm_custom_topologies cstm_top;
473
474 if (lsm_common.cal_data[LSM_CUSTOM_TOP_IDX] == NULL) {
475 pr_err("%s: LSM_CUSTOM_TOP_IDX invalid\n", __func__);
476 rc = -EINVAL;
477 goto done;
478 }
479
480 lsm_common.set_custom_topology = 0;
481
482 mutex_lock(&lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]->lock);
483 cal_block = cal_utils_get_only_cal_block(
484 lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]);
485 if (!cal_block) {
486 pr_err("%s: Cal block for LSM_CUSTOM_TOP_IDX not found\n",
487 __func__);
488 rc = -EINVAL;
489 goto unlock;
490 }
491
492 if (cal_block->cal_data.size <= 0) {
493 pr_err("%s: Invalid size for LSM_CUSTOM_TOP %zd\n",
494 __func__, cal_block->cal_data.size);
495 rc = -EINVAL;
496 goto unlock;
497 }
498
499 memset(&cstm_top, 0, sizeof(cstm_top));
500 /* Map the memory for out-of-band data */
501 rc = q6lsm_memory_map_regions(client, cal_block->cal_data.paddr,
502 cal_block->map_data.map_size,
503 &cal_block->map_data.q6map_handle);
504 if (rc < 0) {
505 pr_err("%s: Failed to map custom topologied, err = %d\n",
506 __func__, rc);
507 goto unlock;
508 }
509
510 q6lsm_add_hdr(client, &cstm_top.hdr,
511 sizeof(cstm_top), true);
512 cstm_top.hdr.opcode = LSM_CMD_ADD_TOPOLOGIES;
513
514 /*
515 * For ADD_TOPOLOGIES, the dest_port should be 0
516 * Note that source port cannot be zero as it is used
517 * to route the response to a specific client registered
518 * on APR
519 */
520 cstm_top.hdr.dest_port = 0;
521
522 cstm_top.data_payload_addr_lsw =
523 lower_32_bits(cal_block->cal_data.paddr);
524 cstm_top.data_payload_addr_msw =
525 msm_audio_populate_upper_32_bits(
526 cal_block->cal_data.paddr);
527 cstm_top.mem_map_handle = cal_block->map_data.q6map_handle;
528 cstm_top.buffer_size = cal_block->cal_data.size;
529
530 rc = q6lsm_apr_send_pkt(client, client->apr,
531 &cstm_top, true, NULL);
532 if (rc)
533 pr_err("%s: Failed to add custom top, err = %d\n",
534 __func__, rc);
535 /* go ahead and unmap even if custom top failed */
536 rc = q6lsm_memory_unmap_regions(client,
537 cal_block->map_data.q6map_handle);
538 if (rc) {
539 pr_err("%s: Failed to unmap, err = %d\n",
540 __func__, rc);
541 /* Even if mem unmap failed, treat the cmd as success */
542 rc = 0;
543 }
544
545unlock:
546 mutex_unlock(&lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]->lock);
547done:
548 return rc;
549}
550
551static int q6lsm_do_open_v2(struct lsm_client *client,
552 uint16_t app_id)
553{
554 int rc;
555 struct cal_block_data *cal_block = NULL;
556 struct audio_cal_info_lsm_top *lsm_top;
557 struct lsm_stream_cmd_open_tx_v2 open_v2;
558
559 if (lsm_common.cal_data[LSM_TOP_IDX] == NULL) {
560 pr_err("%s: LSM_TOP_IDX invalid\n", __func__);
561 rc = -EINVAL;
562 goto done;
563 }
564
565 mutex_lock(&lsm_common.cal_data[LSM_TOP_IDX]->lock);
566 cal_block = cal_utils_get_only_cal_block(
567 lsm_common.cal_data[LSM_TOP_IDX]);
568 if (!cal_block) {
569 pr_err("%s: Cal block for LSM_TOP_IDX not found\n",
570 __func__);
571 rc = -EINVAL;
572 goto unlock;
573 }
574
575 lsm_top = (struct audio_cal_info_lsm_top *)
576 cal_block->cal_info;
577 if (!lsm_top) {
578 pr_err("%s: cal_info for LSM_TOP_IDX not found\n",
579 __func__);
580 rc = -EINVAL;
581 goto unlock;
582 }
583
584 pr_debug("%s: topology_id = 0x%x, acdb_id = 0x%x, app_type = 0x%x\n",
585 __func__, lsm_top->topology, lsm_top->acdb_id,
586 lsm_top->app_type);
587
588 if (lsm_top->topology == 0) {
589 pr_err("%s: toplogy id not sent for app_type 0x%x\n",
590 __func__, lsm_top->app_type);
591 rc = -EINVAL;
592 goto unlock;
593 }
594
595 client->app_id = lsm_top->app_type;
596 memset(&open_v2, 0, sizeof(open_v2));
597 q6lsm_add_hdr(client, &open_v2.hdr,
598 sizeof(open_v2), true);
599 open_v2.topology_id = lsm_top->topology;
600 open_v2.hdr.opcode = LSM_SESSION_CMD_OPEN_TX_V2;
601
602 rc = q6lsm_apr_send_pkt(client, client->apr,
603 &open_v2, true, NULL);
604 if (rc)
605 pr_err("%s: open_v2 failed, err = %d\n",
606 __func__, rc);
607 else
608 client->use_topology = true;
609unlock:
610 mutex_unlock(&lsm_common.cal_data[LSM_TOP_IDX]->lock);
611done:
612 return rc;
613
614}
615
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530616/**
617 * q6lsm_sm_set_param_data -
618 * Update sound model param data
619 *
620 * @client: LSM client handle
621 * @p_info: param info
622 * @offset: pointer to retrieve size
623 *
624 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530625void q6lsm_sm_set_param_data(struct lsm_client *client,
626 struct lsm_params_info *p_info,
627 size_t *offset)
628{
629 struct lsm_param_payload_common *param;
630
631 param = (struct lsm_param_payload_common *)
632 client->sound_model.data;
633 param->module_id = p_info->module_id;
634 param->param_id = p_info->param_id;
635 param->p_size.param_size = client->sound_model.size;
636 *offset = sizeof(*param);
637}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530638EXPORT_SYMBOL(q6lsm_sm_set_param_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530639
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530640/**
641 * q6lsm_open -
642 * command to open LSM session
643 *
644 * @client: LSM client handle
645 * @app_id: App ID for LSM
646 *
647 * Returns 0 on success or error on failure
648 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530649int q6lsm_open(struct lsm_client *client, uint16_t app_id)
650{
651 int rc = 0;
652 struct lsm_stream_cmd_open_tx open;
653
654 /* Add Custom topologies if needed */
655 if (lsm_common.set_custom_topology) {
656 rc = q6lsm_send_custom_topologies(client);
657 if (rc)
658 pr_err("%s: Failed to send cust_top, err = %d\n",
659 __func__, rc);
660 }
661
662 /* Try to open with topology first */
663 rc = q6lsm_do_open_v2(client, app_id);
664 if (!rc)
665 /* open_v2 was successful */
666 goto done;
667
668 pr_debug("%s: try without topology\n",
669 __func__);
670
671 memset(&open, 0, sizeof(open));
672 q6lsm_add_hdr(client, &open.hdr, sizeof(open), true);
673 switch (client->app_id) {
674 case LSM_VOICE_WAKEUP_APP_ID_V2:
675 open.app_id = client->app_id;
676 break;
677 default:
678 pr_err("%s: default err 0x%x\n", __func__, client->app_id);
679 rc = -EINVAL;
680 break;
681 }
682
683 open.sampling_rate = LSM_SAMPLE_RATE;
684 open.hdr.opcode = LSM_SESSION_CMD_OPEN_TX;
685 rc = q6lsm_apr_send_pkt(client, client->apr,
686 &open, true, NULL);
687 if (rc)
688 pr_err("%s: Open failed opcode 0x%x, rc %d\n",
689 __func__, open.hdr.opcode, rc);
690 else
691 client->use_topology = false;
692done:
693 pr_debug("%s: leave %d\n", __func__, rc);
694 return rc;
695}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530696EXPORT_SYMBOL(q6lsm_open);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530697
698static int q6lsm_send_confidence_levels(
699 struct lsm_client *client,
700 struct lsm_module_param_ids *ids,
701 u32 set_param_opcode)
702{
703 u8 *packet;
704 size_t pkt_size;
705 struct lsm_cmd_set_params_conf *conf_params;
706 struct apr_hdr *msg_hdr;
707 struct lsm_param_min_confidence_levels *cfl;
708 uint8_t i = 0;
709 uint8_t padd_size = 0;
710 u8 *conf_levels;
711 int rc;
712 u32 payload_size, param_size;
713
714 padd_size = (4 - (client->num_confidence_levels % 4)) - 1;
715 pkt_size = sizeof(*conf_params) + padd_size +
716 client->num_confidence_levels;
717
718 packet = kzalloc(pkt_size, GFP_KERNEL);
719 if (!packet)
720 return -ENOMEM;
721
722 conf_params = (struct lsm_cmd_set_params_conf *) packet;
723 conf_levels = (u8 *) (packet + sizeof(*conf_params));
724 msg_hdr = &conf_params->msg_hdr;
725 q6lsm_add_hdr(client, msg_hdr,
726 pkt_size, true);
727 msg_hdr->opcode = set_param_opcode;
728 payload_size = pkt_size - sizeof(*msg_hdr) -
729 sizeof(conf_params->params_hdr);
730 q6lsm_set_param_hdr_info(&conf_params->params_hdr,
731 payload_size, 0, 0, 0);
732 cfl = &conf_params->conf_payload;
733 param_size = ((sizeof(uint8_t) + padd_size +
734 client->num_confidence_levels)) *
735 sizeof(uint8_t);
736 q6lsm_set_param_common(&cfl->common, ids,
737 param_size, set_param_opcode);
738 cfl->num_confidence_levels = client->num_confidence_levels;
739
740 pr_debug("%s: CMD PARAM SIZE = %d\n",
741 __func__, param_size);
742 pr_debug("%s: Num conf_level = %d\n",
743 __func__, client->num_confidence_levels);
744
745 memcpy(conf_levels, client->confidence_levels,
746 client->num_confidence_levels);
747 for (i = 0; i < client->num_confidence_levels; i++)
748 pr_debug("%s: Confidence_level[%d] = %d\n",
749 __func__, i, conf_levels[i]);
750
751 rc = q6lsm_apr_send_pkt(client, client->apr,
752 packet, true, NULL);
753 if (rc)
754 pr_err("%s: confidence_levels cmd failed, err = %d\n",
755 __func__, rc);
756 kfree(packet);
757 return rc;
758}
759
760static int q6lsm_send_param_opmode(struct lsm_client *client,
761 struct lsm_module_param_ids *opmode_ids,
762 u32 set_param_opcode)
763{
764 int rc;
765 struct lsm_cmd_set_params_opmode opmode_params;
766 struct apr_hdr *msg_hdr;
767
768 struct lsm_param_op_mode *op_mode;
769 u32 data_payload_size, param_size;
770
771 msg_hdr = &opmode_params.msg_hdr;
772 q6lsm_add_hdr(client, msg_hdr,
773 sizeof(opmode_params), true);
774 msg_hdr->opcode = set_param_opcode;
775 data_payload_size = sizeof(opmode_params) -
776 sizeof(*msg_hdr) -
777 sizeof(opmode_params.params_hdr);
778 q6lsm_set_param_hdr_info(&opmode_params.params_hdr,
779 data_payload_size, 0, 0, 0);
780 op_mode = &opmode_params.op_mode;
781
782
783 param_size = sizeof(struct lsm_param_op_mode) -
784 sizeof(op_mode->common);
785 q6lsm_set_param_common(&op_mode->common,
786 opmode_ids, param_size,
787 set_param_opcode);
788 op_mode->minor_version = QLSM_PARAM_ID_MINOR_VERSION;
789 op_mode->mode = client->mode;
790 op_mode->reserved = 0;
791 pr_debug("%s: mode = 0x%x", __func__, op_mode->mode);
792
793 rc = q6lsm_apr_send_pkt(client, client->apr,
794 &opmode_params, true, NULL);
795 if (rc)
796 pr_err("%s: Failed set_params opcode 0x%x, rc %d\n",
797 __func__, msg_hdr->opcode, rc);
798
799 pr_debug("%s: leave %d\n", __func__, rc);
800 return rc;
801}
802
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530803/**
804 * set_lsm_port -
805 * Update LSM AFE port
806 *
807 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530808void set_lsm_port(int lsm_port)
809{
810 lsm_afe_port = lsm_port;
811}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530812EXPORT_SYMBOL(set_lsm_port);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530813
814int get_lsm_port(void)
815{
816 return lsm_afe_port;
817}
818
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530819/**
820 * q6lsm_set_port_connected -
821 * command to set LSM port connected
822 *
823 * @client: LSM client handle
824 *
825 * Returns 0 on success or error on failure
826 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530827int q6lsm_set_port_connected(struct lsm_client *client)
828{
829 int rc;
830 struct lsm_cmd_set_connectport connectport;
831 struct lsm_module_param_ids connectport_ids;
832 struct apr_hdr *msg_hdr;
833 struct lsm_param_connect_to_port *connect_to_port;
834 u32 data_payload_size, param_size, set_param_opcode;
835
836 if (client->use_topology) {
837 set_param_opcode = LSM_SESSION_CMD_SET_PARAMS_V2;
838 connectport_ids.module_id = LSM_MODULE_ID_FRAMEWORK;
839 connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT;
840 } else {
841 set_param_opcode = LSM_SESSION_CMD_SET_PARAMS;
842 connectport_ids.module_id = LSM_MODULE_ID_VOICE_WAKEUP;
843 connectport_ids.param_id = LSM_PARAM_ID_CONNECT_TO_PORT;
844 }
845 client->connect_to_port = get_lsm_port();
846
847 msg_hdr = &connectport.msg_hdr;
848 q6lsm_add_hdr(client, msg_hdr,
849 sizeof(connectport), true);
850 msg_hdr->opcode = set_param_opcode;
851 data_payload_size = sizeof(connectport) -
852 sizeof(*msg_hdr) -
853 sizeof(connectport.params_hdr);
854 q6lsm_set_param_hdr_info(&connectport.params_hdr,
855 data_payload_size, 0, 0, 0);
856 connect_to_port = &connectport.connect_to_port;
857
858 param_size = (sizeof(struct lsm_param_connect_to_port) -
859 sizeof(connect_to_port->common));
860 q6lsm_set_param_common(&connect_to_port->common,
861 &connectport_ids, param_size,
862 set_param_opcode);
863 connect_to_port->minor_version = QLSM_PARAM_ID_MINOR_VERSION;
864 connect_to_port->port_id = client->connect_to_port;
865 connect_to_port->reserved = 0;
866 pr_debug("%s: port= %d", __func__, connect_to_port->port_id);
867
868 rc = q6lsm_apr_send_pkt(client, client->apr,
869 &connectport, true, NULL);
870 if (rc)
871 pr_err("%s: Failed set_params opcode 0x%x, rc %d\n",
872 __func__, msg_hdr->opcode, rc);
873
874 return rc;
875}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530876EXPORT_SYMBOL(q6lsm_set_port_connected);
877
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530878static int q6lsm_send_param_polling_enable(struct lsm_client *client,
879 bool poll_en,
880 struct lsm_module_param_ids *poll_enable_ids,
881 u32 set_param_opcode)
882{
883 int rc = 0;
884 struct lsm_cmd_poll_enable cmd;
885 struct apr_hdr *msg_hdr;
886 struct lsm_param_poll_enable *poll_enable;
887 u32 data_payload_size, param_size;
888
889 msg_hdr = &cmd.msg_hdr;
890 q6lsm_add_hdr(client, msg_hdr,
891 sizeof(struct lsm_cmd_poll_enable), true);
892 msg_hdr->opcode = set_param_opcode;
893 data_payload_size = sizeof(struct lsm_cmd_poll_enable) -
894 sizeof(struct apr_hdr) -
895 sizeof(struct lsm_set_params_hdr);
896 q6lsm_set_param_hdr_info(&cmd.params_hdr,
897 data_payload_size, 0, 0, 0);
898 poll_enable = &cmd.poll_enable;
899
900 param_size = (sizeof(struct lsm_param_poll_enable) -
901 sizeof(poll_enable->common));
902 q6lsm_set_param_common(&poll_enable->common,
903 poll_enable_ids, param_size,
904 set_param_opcode);
905 poll_enable->minor_version = QLSM_PARAM_ID_MINOR_VERSION;
906 poll_enable->polling_enable = (poll_en) ? 1 : 0;
907 pr_debug("%s: poll enable= %d", __func__, poll_enable->polling_enable);
908
909 rc = q6lsm_apr_send_pkt(client, client->apr,
910 &cmd, true, NULL);
911 if (rc)
912 pr_err("%s: Failed set_params opcode 0x%x, rc %d\n",
913 __func__, msg_hdr->opcode, rc);
914
915 return rc;
916}
917
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530918/**
919 * q6lsm_set_fwk_mode_cfg -
920 * command to set LSM fwk mode cfg
921 *
922 * @client: LSM client handle
923 * @event_mode: mode for fwk cfg
924 *
925 * Returns 0 on success or error on failure
926 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530927int q6lsm_set_fwk_mode_cfg(struct lsm_client *client,
928 uint32_t event_mode)
929{
930 int rc = 0;
931 struct lsm_cmd_set_fwk_mode_cfg cmd;
932 struct lsm_module_param_ids fwk_mode_cfg_ids;
933 struct apr_hdr *msg_hdr;
934 struct lsm_param_fwk_mode_cfg *fwk_mode_cfg;
935 u32 data_payload_size, param_size, set_param_opcode;
936
937 if (client->use_topology) {
938 set_param_opcode = LSM_SESSION_CMD_SET_PARAMS_V2;
939 fwk_mode_cfg_ids.module_id = LSM_MODULE_ID_FRAMEWORK;
940 fwk_mode_cfg_ids.param_id = LSM_PARAM_ID_FWK_MODE_CONFIG;
941 } else {
942 pr_debug("%s: Ignore sending event mode\n", __func__);
943 return rc;
944 }
945
946 msg_hdr = &cmd.msg_hdr;
947 q6lsm_add_hdr(client, msg_hdr,
948 sizeof(struct lsm_cmd_set_fwk_mode_cfg), true);
949 msg_hdr->opcode = set_param_opcode;
950 data_payload_size = sizeof(struct lsm_cmd_set_fwk_mode_cfg) -
951 sizeof(struct apr_hdr) -
952 sizeof(struct lsm_set_params_hdr);
953 q6lsm_set_param_hdr_info(&cmd.params_hdr,
954 data_payload_size, 0, 0, 0);
955 fwk_mode_cfg = &cmd.fwk_mode_cfg;
956
957 param_size = (sizeof(struct lsm_param_fwk_mode_cfg) -
958 sizeof(fwk_mode_cfg->common));
959 q6lsm_set_param_common(&fwk_mode_cfg->common,
960 &fwk_mode_cfg_ids, param_size,
961 set_param_opcode);
962
963 fwk_mode_cfg->minor_version = QLSM_PARAM_ID_MINOR_VERSION;
964 fwk_mode_cfg->mode = event_mode;
965 pr_debug("%s: mode = %d\n", __func__, fwk_mode_cfg->mode);
966
967 rc = q6lsm_apr_send_pkt(client, client->apr,
968 &cmd, true, NULL);
969 if (rc)
970 pr_err("%s: Failed set_params opcode 0x%x, rc %d\n",
971 __func__, msg_hdr->opcode, rc);
972 return rc;
973}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +0530974EXPORT_SYMBOL(q6lsm_set_fwk_mode_cfg);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530975
976static int q6lsm_arrange_mch_map(struct lsm_param_media_fmt *media_fmt,
977 int channel_count)
978{
979 int rc = 0;
980
981 memset(media_fmt->channel_mapping, 0, LSM_MAX_NUM_CHANNELS);
982
983 switch (channel_count) {
984 case 1:
985 media_fmt->channel_mapping[0] = PCM_CHANNEL_FC;
986 break;
987 case 2:
988 media_fmt->channel_mapping[0] = PCM_CHANNEL_FL;
989 media_fmt->channel_mapping[1] = PCM_CHANNEL_FR;
990 break;
991 case 3:
992 media_fmt->channel_mapping[0] = PCM_CHANNEL_FL;
993 media_fmt->channel_mapping[1] = PCM_CHANNEL_FR;
994 media_fmt->channel_mapping[2] = PCM_CHANNEL_FC;
995 break;
996 case 4:
997 media_fmt->channel_mapping[0] = PCM_CHANNEL_FL;
998 media_fmt->channel_mapping[1] = PCM_CHANNEL_FR;
999 media_fmt->channel_mapping[2] = PCM_CHANNEL_LS;
1000 media_fmt->channel_mapping[3] = PCM_CHANNEL_RS;
1001 break;
1002 default:
1003 pr_err("%s: invalid num_chan %d\n", __func__, channel_count);
1004 rc = -EINVAL;
1005 break;
1006 }
1007 return rc;
1008}
1009
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301010/**
1011 * q6lsm_set_media_fmt_params -
1012 * command to set LSM media fmt params
1013 *
1014 * @client: LSM client handle
1015 *
1016 * Returns 0 on success or error on failure
1017 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301018int q6lsm_set_media_fmt_params(struct lsm_client *client)
1019{
1020 int rc = 0;
1021 struct lsm_cmd_set_media_fmt cmd;
1022 struct lsm_module_param_ids media_fmt_ids;
1023 struct apr_hdr *msg_hdr;
1024 struct lsm_param_media_fmt *media_fmt;
1025 u32 data_payload_size, param_size, set_param_opcode;
1026 struct lsm_hw_params param = client->hw_params;
1027
1028 if (client->use_topology) {
1029 set_param_opcode = LSM_SESSION_CMD_SET_PARAMS_V2;
1030 media_fmt_ids.module_id = LSM_MODULE_ID_FRAMEWORK;
1031 media_fmt_ids.param_id = LSM_PARAM_ID_MEDIA_FMT;
1032 } else {
1033 pr_debug("%s: Ignore sending media format\n", __func__);
1034 goto err_ret;
1035 }
1036
1037 msg_hdr = &cmd.msg_hdr;
1038 q6lsm_add_hdr(client, msg_hdr,
1039 sizeof(struct lsm_cmd_set_media_fmt), true);
1040 msg_hdr->opcode = set_param_opcode;
1041 data_payload_size = sizeof(struct lsm_cmd_set_media_fmt) -
1042 sizeof(struct apr_hdr) -
1043 sizeof(struct lsm_set_params_hdr);
1044 q6lsm_set_param_hdr_info(&cmd.params_hdr,
1045 data_payload_size, 0, 0, 0);
1046 media_fmt = &cmd.media_fmt;
1047
1048 param_size = (sizeof(struct lsm_param_media_fmt) -
1049 sizeof(media_fmt->common));
1050 q6lsm_set_param_common(&media_fmt->common,
1051 &media_fmt_ids, param_size,
1052 set_param_opcode);
1053
1054 media_fmt->minor_version = QLSM_PARAM_ID_MINOR_VERSION_2;
1055 media_fmt->sample_rate = param.sample_rate;
1056 media_fmt->num_channels = param.num_chs;
1057 media_fmt->bit_width = param.sample_size;
1058
1059 rc = q6lsm_arrange_mch_map(media_fmt, media_fmt->num_channels);
1060 if (rc)
1061 goto err_ret;
1062
1063 pr_debug("%s: sample rate= %d, channels %d bit width %d\n",
1064 __func__, media_fmt->sample_rate, media_fmt->num_channels,
1065 media_fmt->bit_width);
1066
1067 rc = q6lsm_apr_send_pkt(client, client->apr,
1068 &cmd, true, NULL);
1069 if (rc)
1070 pr_err("%s: Failed set_params opcode 0x%x, rc %d\n",
1071 __func__, msg_hdr->opcode, rc);
1072err_ret:
1073 return rc;
1074}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301075EXPORT_SYMBOL(q6lsm_set_media_fmt_params);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301076
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301077/**
1078 * q6lsm_set_data -
1079 * Command to set LSM data
1080 *
1081 * @client: LSM client handle
1082 * @mode: LSM detection mode value
1083 * @detectfailure: flag for detect failure
1084 *
1085 * Returns 0 on success or error on failure
1086 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301087int q6lsm_set_data(struct lsm_client *client,
1088 enum lsm_detection_mode mode,
1089 bool detectfailure)
1090{
1091 int rc = 0;
1092 struct lsm_module_param_ids opmode_ids;
1093 struct lsm_module_param_ids conf_levels_ids;
1094
1095 if (!client->confidence_levels) {
1096 /*
1097 * It is possible that confidence levels are
1098 * not provided. This is not a error condition.
1099 * Return gracefully without any error
1100 */
1101 pr_debug("%s: no conf levels to set\n",
1102 __func__);
1103 return rc;
1104 }
1105
1106 if (mode == LSM_MODE_KEYWORD_ONLY_DETECTION) {
1107 client->mode = 0x01;
1108 } else if (mode == LSM_MODE_USER_KEYWORD_DETECTION) {
1109 client->mode = 0x03;
1110 } else {
1111 pr_err("%s: Incorrect detection mode %d\n", __func__, mode);
1112 rc = -EINVAL;
1113 goto err_ret;
1114 }
1115 client->mode |= detectfailure << 2;
1116
1117 opmode_ids.module_id = LSM_MODULE_ID_VOICE_WAKEUP;
1118 opmode_ids.param_id = LSM_PARAM_ID_OPERATION_MODE;
1119
1120 rc = q6lsm_send_param_opmode(client, &opmode_ids,
1121 LSM_SESSION_CMD_SET_PARAMS);
1122 if (rc) {
1123 pr_err("%s: Failed to set lsm config params %d\n",
1124 __func__, rc);
1125 goto err_ret;
1126 }
1127
1128 conf_levels_ids.module_id = LSM_MODULE_ID_VOICE_WAKEUP;
1129 conf_levels_ids.param_id = LSM_PARAM_ID_MIN_CONFIDENCE_LEVELS;
1130
1131 rc = q6lsm_send_confidence_levels(client, &conf_levels_ids,
1132 LSM_SESSION_CMD_SET_PARAMS);
1133 if (rc) {
1134 pr_err("%s: Failed to send conf_levels, err = %d\n",
1135 __func__, rc);
1136 goto err_ret;
1137 }
1138
1139 rc = q6lsm_send_cal(client, LSM_SESSION_CMD_SET_PARAMS);
1140 if (rc) {
1141 pr_err("%s: Failed to send calibration data %d\n",
1142 __func__, rc);
1143 goto err_ret;
1144 }
1145
1146err_ret:
1147 return rc;
1148}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301149EXPORT_SYMBOL(q6lsm_set_data);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301150
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301151/**
1152 * q6lsm_register_sound_model -
1153 * Register LSM snd model
1154 *
1155 * @client: LSM client handle
1156 *
1157 * Returns 0 on success or error on failure
1158 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301159int q6lsm_register_sound_model(struct lsm_client *client,
1160 enum lsm_detection_mode mode,
1161 bool detectfailure)
1162{
1163 int rc;
1164 struct lsm_cmd_reg_snd_model cmd;
1165
1166 memset(&cmd, 0, sizeof(cmd));
1167 rc = q6lsm_set_data(client, mode, detectfailure);
1168 if (rc) {
1169 pr_err("%s: Failed to set lsm data, err = %d\n",
1170 __func__, rc);
1171 return rc;
1172 }
1173
1174 q6lsm_add_hdr(client, &cmd.hdr, sizeof(cmd), true);
1175 cmd.hdr.opcode = LSM_SESSION_CMD_REGISTER_SOUND_MODEL;
1176 cmd.model_addr_lsw = lower_32_bits(client->sound_model.phys);
1177 cmd.model_addr_msw = msm_audio_populate_upper_32_bits(
1178 client->sound_model.phys);
1179 cmd.model_size = client->sound_model.size;
1180 /* read updated mem_map_handle by q6lsm_mmapcallback */
1181 rmb();
1182 cmd.mem_map_handle = client->sound_model.mem_map_handle;
1183
1184 pr_debug("%s: addr %pK, size %d, handle 0x%x\n", __func__,
1185 &client->sound_model.phys, cmd.model_size, cmd.mem_map_handle);
1186 rc = q6lsm_apr_send_pkt(client, client->apr, &cmd, true, NULL);
1187 if (rc)
1188 pr_err("%s: Failed cmd op[0x%x]rc[%d]\n", __func__,
1189 cmd.hdr.opcode, rc);
1190 else
1191 pr_debug("%s: Register sound model succeeded\n", __func__);
1192
1193 return rc;
1194}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301195EXPORT_SYMBOL(q6lsm_register_sound_model);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301196
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301197/**
1198 * q6lsm_deregister_sound_model -
1199 * De-register LSM snd model
1200 *
1201 * @client: LSM client handle
1202 *
1203 * Returns 0 on success or error on failure
1204 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301205int q6lsm_deregister_sound_model(struct lsm_client *client)
1206{
1207 int rc;
1208 struct lsm_cmd_reg_snd_model cmd;
1209
1210 if (!client) {
1211 pr_err("APR handle NULL\n");
1212 return -EINVAL;
1213 }
1214 if (!client->apr) {
1215 pr_err("APR client handle NULL\n");
1216 return -EINVAL;
1217 }
1218
1219 if (CHECK_SESSION(client->session)) {
1220 pr_err("%s: session[%d]", __func__, client->session);
1221 return -EINVAL;
1222 }
1223
1224 memset(&cmd, 0, sizeof(cmd));
1225 q6lsm_add_hdr(client, &cmd.hdr, sizeof(cmd.hdr), false);
1226 cmd.hdr.opcode = LSM_SESSION_CMD_DEREGISTER_SOUND_MODEL;
1227
1228 rc = q6lsm_apr_send_pkt(client, client->apr, &cmd.hdr, true, NULL);
1229 if (rc) {
1230 pr_err("%s: Failed cmd opcode 0x%x, rc %d\n", __func__,
1231 cmd.hdr.opcode, rc);
1232 } else {
1233 pr_debug("%s: Deregister sound model succeeded\n", __func__);
1234 }
1235
1236 q6lsm_snd_model_buf_free(client);
1237
1238 return rc;
1239}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301240EXPORT_SYMBOL(q6lsm_deregister_sound_model);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301241
1242static void q6lsm_add_mmaphdr(struct lsm_client *client, struct apr_hdr *hdr,
1243 u32 pkt_size, u32 cmd_flg, u32 token)
1244{
1245 pr_debug("%s: pkt size=%d cmd_flg=%d session=%d\n", __func__, pkt_size,
1246 cmd_flg, client->session);
1247 hdr->hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
1248 APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
1249 hdr->src_port = 0x00;
1250 hdr->dest_port = client->session;
1251 if (cmd_flg)
1252 hdr->token = token;
1253 hdr->pkt_size = pkt_size;
1254}
1255
1256static int q6lsm_memory_map_regions(struct lsm_client *client,
1257 dma_addr_t dma_addr_p, uint32_t dma_buf_sz,
1258 uint32_t *mmap_p)
1259{
1260 struct avs_cmd_shared_mem_map_regions *mmap_regions = NULL;
1261 struct avs_shared_map_region_payload *mregions = NULL;
1262 void *mmap_region_cmd = NULL;
1263 void *payload = NULL;
1264 int rc;
1265 int cmd_size = 0;
1266
1267 pr_debug("%s: dma_addr_p 0x%pK, dma_buf_sz %d, mmap_p 0x%pK, session %d\n",
1268 __func__, &dma_addr_p, dma_buf_sz, mmap_p,
1269 client->session);
1270 if (CHECK_SESSION(client->session)) {
1271 pr_err("%s: session[%d]", __func__, client->session);
1272 return -EINVAL;
1273 }
1274 cmd_size = sizeof(struct avs_cmd_shared_mem_map_regions) +
1275 sizeof(struct avs_shared_map_region_payload);
1276
1277 mmap_region_cmd = kzalloc(cmd_size, GFP_KERNEL);
1278 if (!mmap_region_cmd)
1279 return -ENOMEM;
1280
1281 mmap_regions = (struct avs_cmd_shared_mem_map_regions *)mmap_region_cmd;
1282 q6lsm_add_mmaphdr(client, &mmap_regions->hdr, cmd_size, true,
1283 (client->session << 8));
1284
1285 mmap_regions->hdr.opcode = LSM_SESSION_CMD_SHARED_MEM_MAP_REGIONS;
1286 mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
1287 mmap_regions->num_regions = 1;
1288 mmap_regions->property_flag = 0x00;
1289 payload = ((u8 *)mmap_region_cmd +
1290 sizeof(struct avs_cmd_shared_mem_map_regions));
1291 mregions = (struct avs_shared_map_region_payload *)payload;
1292
1293 mregions->shm_addr_lsw = lower_32_bits(dma_addr_p);
1294 mregions->shm_addr_msw = msm_audio_populate_upper_32_bits(dma_addr_p);
1295 mregions->mem_size_bytes = dma_buf_sz;
1296
1297 rc = q6lsm_apr_send_pkt(client, client->mmap_apr, mmap_region_cmd,
1298 true, mmap_p);
1299 if (rc)
1300 pr_err("%s: Failed mmap_regions opcode 0x%x, rc %d\n",
1301 __func__, mmap_regions->hdr.opcode, rc);
1302
1303 pr_debug("%s: leave %d\n", __func__, rc);
1304 kfree(mmap_region_cmd);
1305 return rc;
1306}
1307
1308static int q6lsm_memory_unmap_regions(struct lsm_client *client,
1309 uint32_t handle)
1310{
1311 struct avs_cmd_shared_mem_unmap_regions unmap;
1312 int rc = 0;
1313 int cmd_size = 0;
1314
1315 if (CHECK_SESSION(client->session)) {
1316 pr_err("%s: session[%d]", __func__, client->session);
1317 return -EINVAL;
1318 }
1319 cmd_size = sizeof(struct avs_cmd_shared_mem_unmap_regions);
1320 q6lsm_add_mmaphdr(client, &unmap.hdr, cmd_size,
1321 true, (client->session << 8));
1322 unmap.hdr.opcode = LSM_SESSION_CMD_SHARED_MEM_UNMAP_REGIONS;
1323 unmap.mem_map_handle = handle;
1324
1325 pr_debug("%s: unmap handle 0x%x\n", __func__, unmap.mem_map_handle);
1326 rc = q6lsm_apr_send_pkt(client, client->mmap_apr, &unmap, true,
1327 NULL);
1328 if (rc)
1329 pr_err("%s: Failed mmap_regions opcode 0x%x rc %d\n",
1330 __func__, unmap.hdr.opcode, rc);
1331
1332 return rc;
1333}
1334
1335static int q6lsm_send_cal(struct lsm_client *client,
1336 u32 set_params_opcode)
1337{
1338 int rc = 0;
1339 struct lsm_cmd_set_params params;
1340 struct lsm_set_params_hdr *params_hdr = &params.param_hdr;
1341 struct apr_hdr *msg_hdr = &params.msg_hdr;
1342 struct cal_block_data *cal_block = NULL;
1343
1344 pr_debug("%s: Session id %d\n", __func__, client->session);
1345 if (CHECK_SESSION(client->session)) {
1346 pr_err("%s: session[%d]", __func__, client->session);
1347 return -EINVAL;
1348 }
1349
1350 if (lsm_common.cal_data[LSM_CAL_IDX] == NULL)
1351 goto done;
1352
1353 mutex_lock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
1354 cal_block = cal_utils_get_only_cal_block(
1355 lsm_common.cal_data[LSM_CAL_IDX]);
1356
1357 if (!cal_block || cal_block->cal_data.size <= 0) {
1358 pr_debug("%s: No cal to send!\n", __func__);
1359 goto unlock;
1360 }
1361
1362 if (cal_block->cal_data.size != client->lsm_cal_size) {
1363 pr_err("%s: Cal size %zd doesn't match lsm cal size %d\n",
1364 __func__, cal_block->cal_data.size,
1365 client->lsm_cal_size);
1366 rc = -EINVAL;
1367 goto unlock;
1368 }
1369 /* Cache mmap address, only map once or if new addr */
1370 lsm_common.common_client[client->session].session = client->session;
1371 q6lsm_add_hdr(client, msg_hdr, sizeof(params), true);
1372 msg_hdr->opcode = set_params_opcode;
1373 q6lsm_set_param_hdr_info(params_hdr,
1374 cal_block->cal_data.size,
1375 lower_32_bits(client->lsm_cal_phy_addr),
1376 msm_audio_populate_upper_32_bits(
1377 client->lsm_cal_phy_addr),
1378 client->sound_model.mem_map_handle);
1379
1380 pr_debug("%s: Cal Size = %zd", __func__,
1381 cal_block->cal_data.size);
1382 rc = q6lsm_apr_send_pkt(client, client->apr, &params, true, NULL);
1383 if (rc)
1384 pr_err("%s: Failed set_params opcode 0x%x, rc %d\n",
1385 __func__, msg_hdr->opcode, rc);
1386unlock:
1387 mutex_unlock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
1388done:
1389 return rc;
1390}
1391
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301392/**
1393 * q6lsm_snd_model_buf_free -
1394 * Free memory for LSM snd model
1395 *
1396 * @client: LSM client handle
1397 *
1398 * Returns 0 on success or error on failure
1399 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301400int q6lsm_snd_model_buf_free(struct lsm_client *client)
1401{
1402 int rc;
1403
1404 pr_debug("%s: Session id %d\n", __func__, client->session);
1405 if (CHECK_SESSION(client->session)) {
1406 pr_err("%s: session[%d]", __func__, client->session);
1407 return -EINVAL;
1408 }
1409
1410 mutex_lock(&client->cmd_lock);
1411 rc = q6lsm_memory_unmap_regions(client,
1412 client->sound_model.mem_map_handle);
1413 if (rc)
1414 pr_err("%s: CMD Memory_unmap_regions failed %d\n",
1415 __func__, rc);
1416
1417 if (client->sound_model.data) {
1418 msm_audio_ion_free(client->sound_model.client,
1419 client->sound_model.handle);
1420 client->sound_model.client = NULL;
1421 client->sound_model.handle = NULL;
1422 client->sound_model.data = NULL;
1423 client->sound_model.phys = 0;
1424 client->lsm_cal_phy_addr = 0;
1425 client->lsm_cal_size = 0;
1426 }
1427 mutex_unlock(&client->cmd_lock);
1428 return rc;
1429}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301430EXPORT_SYMBOL(q6lsm_snd_model_buf_free);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301431
1432static struct lsm_client *q6lsm_get_lsm_client(int session_id)
1433{
1434 unsigned long flags;
1435 struct lsm_client *client = NULL;
1436
1437 spin_lock_irqsave(&lsm_session_lock, flags);
1438 if (session_id < LSM_MIN_SESSION_ID || session_id > LSM_MAX_SESSION_ID)
1439 pr_err("%s: Invalid session %d\n", __func__, session_id);
1440 else if (!lsm_session[session_id])
1441 pr_err("%s: Not an active session %d\n", __func__, session_id);
1442 else
1443 client = lsm_session[session_id];
1444 spin_unlock_irqrestore(&lsm_session_lock, flags);
1445 return client;
1446}
1447
1448/*
1449 * q6lsm_mmapcallback : atomic context
1450 */
1451static int q6lsm_mmapcallback(struct apr_client_data *data, void *priv)
1452{
1453 unsigned long flags;
1454 uint32_t command;
1455 uint32_t retcode;
1456 uint32_t sid;
1457 const uint32_t *payload = data->payload;
1458 struct lsm_client *client = NULL;
1459
1460 if (data->opcode == RESET_EVENTS) {
1461 sid = (data->token >> 8) & 0x0F;
1462 pr_debug("%s: SSR event received 0x%x, event 0x%x,\n"
1463 "proc 0x%x SID 0x%x\n", __func__, data->opcode,
1464 data->reset_event, data->reset_proc, sid);
Xiaoyu Yefb90eb62017-10-10 12:26:08 -07001465
1466 apr_reset(lsm_common.apr);
1467 lsm_common.apr = NULL;
1468 atomic_set(&lsm_common.apr_users, 0);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301469 lsm_common.common_client[sid].lsm_cal_phy_addr = 0;
1470 cal_utils_clear_cal_block_q6maps(LSM_MAX_CAL_IDX,
1471 lsm_common.cal_data);
1472 lsm_common.set_custom_topology = 1;
1473 return 0;
1474 }
1475
1476 command = payload[0];
1477 retcode = payload[1];
1478 sid = (data->token >> 8) & 0x0F;
1479 pr_debug("%s: opcode 0x%x command 0x%x return code 0x%x SID 0x%x\n",
1480 __func__, data->opcode, command, retcode, sid);
1481 client = q6lsm_get_lsm_client(sid);
1482 if (!client) {
1483 pr_debug("%s: Session %d already freed\n", __func__, sid);
1484 return 0;
1485 }
1486
1487 switch (data->opcode) {
1488 case LSM_SESSION_CMDRSP_SHARED_MEM_MAP_REGIONS:
1489 if (atomic_read(&client->cmd_state) == CMD_STATE_WAIT_RESP) {
1490 spin_lock_irqsave(&mmap_lock, flags);
1491 *mmap_handle_p = command;
1492 /* spin_unlock_irqrestore implies barrier */
1493 spin_unlock_irqrestore(&mmap_lock, flags);
1494 atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
1495 wake_up(&client->cmd_wait);
1496 }
1497 break;
1498 case APR_BASIC_RSP_RESULT:
1499 switch (command) {
1500 case LSM_SESSION_CMD_SHARED_MEM_UNMAP_REGIONS:
1501 atomic_set(&client->cmd_state, CMD_STATE_CLEARED);
1502 wake_up(&client->cmd_wait);
1503 break;
1504 case LSM_SESSION_CMD_SHARED_MEM_MAP_REGIONS:
1505 if (retcode != 0) {
1506 /* error state, signal to stop waiting */
1507 if (atomic_read(&client->cmd_state) ==
1508 CMD_STATE_WAIT_RESP) {
1509 spin_lock_irqsave(&mmap_lock, flags);
1510 /* implies barrier */
1511 spin_unlock_irqrestore(&mmap_lock,
1512 flags);
1513 atomic_set(&client->cmd_state,
1514 CMD_STATE_CLEARED);
1515 wake_up(&client->cmd_wait);
1516 }
1517 }
1518 break;
1519 default:
1520 pr_warn("%s: Unexpected command 0x%x\n", __func__,
1521 command);
1522 }
1523 /* fallthrough */
1524 default:
1525 pr_debug("%s: command 0x%x return code 0x%x opcode 0x%x\n",
1526 __func__, command, retcode, data->opcode);
1527 break;
1528 }
1529 if (client->cb)
1530 client->cb(data->opcode, data->token,
1531 data->payload, client->priv);
1532 return 0;
1533}
1534
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301535/**
1536 * q6lsm_snd_model_buf_alloc -
1537 * Allocate memory for LSM snd model
1538 *
1539 * @client: LSM client handle
1540 * @len: size of sound model
1541 * @allocate_module_data: flag to allocate for set_param payload
1542 *
1543 * Returns 0 on success or error on failure
1544 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301545int q6lsm_snd_model_buf_alloc(struct lsm_client *client, size_t len,
1546 bool allocate_module_data)
1547{
1548 int rc = -EINVAL;
1549 struct cal_block_data *cal_block = NULL;
1550
1551 size_t pad_zero = 0, total_mem = 0;
1552
1553 if (!client || len <= LSM_ALIGN_BOUNDARY)
1554 return rc;
1555
1556 mutex_lock(&client->cmd_lock);
1557
1558 mutex_lock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
1559 cal_block = cal_utils_get_only_cal_block(
1560 lsm_common.cal_data[LSM_CAL_IDX]);
1561 if (cal_block == NULL)
1562 goto fail;
1563
1564 pr_debug("%s:Snd Model len = %zd cal size %zd phys addr %pK", __func__,
1565 len, cal_block->cal_data.size,
1566 &cal_block->cal_data.paddr);
1567 if (!cal_block->cal_data.paddr) {
1568 pr_err("%s: No LSM calibration set for session", __func__);
1569 rc = -EINVAL;
1570 goto fail;
1571 }
1572 if (!client->sound_model.data) {
1573
1574 /*
1575 * if sound module is sent as set_param
1576 * Then memory needs to be allocated for
1577 * set_param payload as well.
1578 */
1579 if (allocate_module_data)
1580 len += sizeof(struct lsm_param_payload_common);
1581
1582 client->sound_model.size = len;
1583 pad_zero = (LSM_ALIGN_BOUNDARY -
1584 (len % LSM_ALIGN_BOUNDARY));
1585 if ((len > SIZE_MAX - pad_zero) ||
1586 (len + pad_zero >
1587 SIZE_MAX - cal_block->cal_data.size)) {
1588 pr_err("%s: invalid allocation size, len = %zd, pad_zero =%zd, cal_size = %zd\n",
1589 __func__, len, pad_zero,
1590 cal_block->cal_data.size);
1591 rc = -EINVAL;
1592 goto fail;
1593 }
1594
1595 total_mem = PAGE_ALIGN(pad_zero + len +
1596 cal_block->cal_data.size);
1597 pr_debug("%s: Pad zeros sound model %zd Total mem %zd\n",
1598 __func__, pad_zero, total_mem);
1599 rc = msm_audio_ion_alloc("lsm_client",
1600 &client->sound_model.client,
1601 &client->sound_model.handle,
1602 total_mem,
1603 &client->sound_model.phys,
1604 &len,
1605 &client->sound_model.data);
1606 if (rc) {
1607 pr_err("%s: Audio ION alloc is failed, rc = %d\n",
1608 __func__, rc);
1609 goto fail;
1610 }
1611 pr_debug("%s: Length = %zd\n", __func__, len);
1612 client->lsm_cal_phy_addr = (pad_zero +
1613 client->sound_model.phys +
1614 client->sound_model.size);
1615 client->lsm_cal_size = cal_block->cal_data.size;
1616 memcpy((client->sound_model.data + pad_zero +
1617 client->sound_model.size),
1618 (uint32_t *)cal_block->cal_data.kvaddr, client->lsm_cal_size);
1619 pr_debug("%s: Copy cal start virt_addr %pK phy_addr %pK\n"
1620 "Offset cal virtual Addr %pK\n", __func__,
1621 client->sound_model.data, &client->sound_model.phys,
1622 (pad_zero + client->sound_model.data +
1623 client->sound_model.size));
1624 } else {
1625 pr_err("%s: sound model busy\n", __func__);
1626 rc = -EBUSY;
1627 goto fail;
1628 }
1629 mutex_unlock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
1630 mutex_unlock(&client->cmd_lock);
1631
1632 rc = q6lsm_memory_map_regions(client, client->sound_model.phys,
1633 len,
1634 &client->sound_model.mem_map_handle);
1635 if (rc) {
1636 pr_err("%s: CMD Memory_map_regions failed %d\n", __func__, rc);
1637 goto exit;
1638 }
1639
1640 return 0;
1641fail:
1642 mutex_unlock(&lsm_common.cal_data[LSM_CAL_IDX]->lock);
1643 mutex_unlock(&client->cmd_lock);
1644exit:
1645 q6lsm_snd_model_buf_free(client);
1646 return rc;
1647}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301648EXPORT_SYMBOL(q6lsm_snd_model_buf_alloc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301649
1650static int q6lsm_cmd(struct lsm_client *client, int opcode, bool wait)
1651{
1652 struct apr_hdr hdr;
1653 int rc;
1654
1655 pr_debug("%s: enter opcode %x wait %d\n", __func__, opcode, wait);
1656 q6lsm_add_hdr(client, &hdr, sizeof(hdr), true);
1657 switch (opcode) {
1658 case LSM_SESSION_CMD_START:
1659 case LSM_SESSION_CMD_STOP:
1660 case LSM_SESSION_CMD_CLOSE_TX:
1661 case LSM_SESSION_CMD_EOB:
1662 hdr.opcode = opcode;
1663 break;
1664 default:
1665 pr_err("%s: Invalid opcode 0x%x\n", __func__, opcode);
1666 return -EINVAL;
1667 }
1668 rc = q6lsm_apr_send_pkt(client, client->apr, &hdr, wait, NULL);
1669 if (rc)
1670 pr_err("%s: Failed commmand 0x%x\n", __func__, hdr.opcode);
1671
1672 pr_debug("%s: leave %d\n", __func__, rc);
1673 return rc;
1674}
1675
1676static int q6lsm_send_param_epd_thres(
1677 struct lsm_client *client,
1678 void *data, struct lsm_module_param_ids *ids)
1679{
1680 struct snd_lsm_ep_det_thres *ep_det_data;
1681 struct lsm_cmd_set_epd_threshold epd_cmd;
1682 struct apr_hdr *msg_hdr = &epd_cmd.msg_hdr;
1683 struct lsm_set_params_hdr *param_hdr =
1684 &epd_cmd.param_hdr;
1685 struct lsm_param_epd_thres *epd_thres =
1686 &epd_cmd.epd_thres;
1687 int rc;
1688
1689 ep_det_data = (struct snd_lsm_ep_det_thres *) data;
1690 q6lsm_add_hdr(client, msg_hdr,
1691 sizeof(epd_cmd), true);
1692 msg_hdr->opcode = LSM_SESSION_CMD_SET_PARAMS_V2;
1693 q6lsm_set_param_hdr_info(param_hdr,
1694 sizeof(*epd_thres), 0, 0, 0);
1695 q6lsm_set_param_common(&epd_thres->common, ids,
1696 sizeof(*epd_thres) - sizeof(epd_thres->common),
1697 LSM_SESSION_CMD_SET_PARAMS_V2);
1698 epd_thres->minor_version = QLSM_PARAM_ID_MINOR_VERSION;
1699 epd_thres->epd_begin = ep_det_data->epd_begin;
1700 epd_thres->epd_end = ep_det_data->epd_end;
1701
1702 rc = q6lsm_apr_send_pkt(client, client->apr,
1703 &epd_cmd, true, NULL);
1704 if (unlikely(rc))
1705 pr_err("%s: EPD_THRESHOLD failed, rc %d\n",
1706 __func__, rc);
1707 return rc;
1708}
1709
1710static int q6lsm_send_param_gain(
1711 struct lsm_client *client,
1712 u16 gain, struct lsm_module_param_ids *ids)
1713{
1714 struct lsm_cmd_set_gain lsm_cmd_gain;
1715 struct apr_hdr *msg_hdr = &lsm_cmd_gain.msg_hdr;
1716 struct lsm_param_gain *lsm_gain = &lsm_cmd_gain.lsm_gain;
1717 int rc;
1718
1719 q6lsm_add_hdr(client, msg_hdr,
1720 sizeof(lsm_cmd_gain), true);
1721 msg_hdr->opcode = LSM_SESSION_CMD_SET_PARAMS_V2;
1722 q6lsm_set_param_hdr_info(&lsm_cmd_gain.param_hdr,
1723 sizeof(*lsm_gain), 0, 0, 0);
1724 q6lsm_set_param_common(&lsm_gain->common, ids,
1725 sizeof(*lsm_gain) - sizeof(lsm_gain->common),
1726 LSM_SESSION_CMD_SET_PARAMS_V2);
1727 lsm_gain->minor_version = QLSM_PARAM_ID_MINOR_VERSION;
1728 lsm_gain->gain = gain;
1729 lsm_gain->reserved = 0;
1730
1731 rc = q6lsm_apr_send_pkt(client, client->apr,
1732 &lsm_cmd_gain, true, NULL);
1733 if (unlikely(rc))
1734 pr_err("%s: LSM_GAIN CMD send failed, rc %d\n",
1735 __func__, rc);
1736 return rc;
1737}
1738
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301739/**
1740 * q6lsm_set_one_param -
1741 * command for LSM set params
1742 *
1743 * @client: LSM client handle
1744 * p_info: Params info
1745 * data: payload based on param type
1746 * param_type: LSM param type
1747 *
1748 * Returns 0 on success or error on failure
1749 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301750int q6lsm_set_one_param(struct lsm_client *client,
1751 struct lsm_params_info *p_info, void *data,
1752 uint32_t param_type)
1753{
1754 int rc = 0, pkt_sz;
1755 struct lsm_module_param_ids ids;
1756 u8 *packet;
1757
1758 memset(&ids, 0, sizeof(ids));
1759 switch (param_type) {
1760 case LSM_ENDPOINT_DETECT_THRESHOLD: {
1761 ids.module_id = p_info->module_id;
1762 ids.param_id = p_info->param_id;
1763 rc = q6lsm_send_param_epd_thres(client, data,
1764 &ids);
1765 break;
1766 }
1767
1768 case LSM_OPERATION_MODE: {
1769 struct snd_lsm_detect_mode *det_mode = data;
1770 struct lsm_module_param_ids opmode_ids;
1771
1772 if (det_mode->mode == LSM_MODE_KEYWORD_ONLY_DETECTION) {
1773 client->mode = 0x01;
1774 } else if (det_mode->mode == LSM_MODE_USER_KEYWORD_DETECTION) {
1775 client->mode = 0x03;
1776 } else {
1777 pr_err("%s: Incorrect detection mode %d\n",
1778 __func__, det_mode->mode);
1779 return -EINVAL;
1780 }
1781
1782 client->mode |= det_mode->detect_failure << 2;
1783
1784 opmode_ids.module_id = p_info->module_id;
1785 opmode_ids.param_id = p_info->param_id;
1786
1787 rc = q6lsm_send_param_opmode(client, &opmode_ids,
1788 LSM_SESSION_CMD_SET_PARAMS_V2);
1789 if (rc)
1790 pr_err("%s: OPERATION_MODE failed, rc %d\n",
1791 __func__, rc);
1792 break;
1793 }
1794
1795 case LSM_GAIN: {
1796 struct snd_lsm_gain *lsm_gain = (struct snd_lsm_gain *) data;
1797
1798 ids.module_id = p_info->module_id;
1799 ids.param_id = p_info->param_id;
1800 rc = q6lsm_send_param_gain(client, lsm_gain->gain, &ids);
1801 if (rc)
1802 pr_err("%s: LSM_GAIN command failed, rc %d\n",
1803 __func__, rc);
1804 break;
1805 }
1806
1807 case LSM_MIN_CONFIDENCE_LEVELS:
1808 ids.module_id = p_info->module_id;
1809 ids.param_id = p_info->param_id;
1810 rc = q6lsm_send_confidence_levels(client, &ids,
1811 LSM_SESSION_CMD_SET_PARAMS_V2);
1812 if (rc)
1813 pr_err("%s: CONFIDENCE_LEVELS cmd failed, rc %d\n",
1814 __func__, rc);
1815 break;
1816 case LSM_POLLING_ENABLE: {
1817 struct snd_lsm_poll_enable *lsm_poll_enable =
1818 (struct snd_lsm_poll_enable *) data;
1819 ids.module_id = p_info->module_id;
1820 ids.param_id = p_info->param_id;
1821 rc = q6lsm_send_param_polling_enable(client,
1822 lsm_poll_enable->poll_en, &ids,
1823 LSM_SESSION_CMD_SET_PARAMS_V2);
1824 if (rc)
1825 pr_err("%s: POLLING ENABLE cmd failed, rc %d\n",
1826 __func__, rc);
1827 break;
1828 }
1829
1830 case LSM_REG_SND_MODEL: {
1831 struct lsm_cmd_set_params model_param;
1832 u32 payload_size;
1833
1834 memset(&model_param, 0, sizeof(model_param));
1835 q6lsm_add_hdr(client, &model_param.msg_hdr,
1836 sizeof(model_param), true);
1837 model_param.msg_hdr.opcode = LSM_SESSION_CMD_SET_PARAMS_V2;
1838 payload_size = p_info->param_size +
1839 sizeof(struct lsm_param_payload_common);
1840 q6lsm_set_param_hdr_info(&model_param.param_hdr,
1841 payload_size,
1842 lower_32_bits(client->sound_model.phys),
1843 msm_audio_populate_upper_32_bits(
1844 client->sound_model.phys),
1845 client->sound_model.mem_map_handle);
1846
1847 rc = q6lsm_apr_send_pkt(client, client->apr,
1848 &model_param, true, NULL);
1849 if (rc) {
1850 pr_err("%s: REG_SND_MODEL failed, rc %d\n",
1851 __func__, rc);
1852 return rc;
1853 }
1854
1855 rc = q6lsm_send_cal(client, LSM_SESSION_CMD_SET_PARAMS);
1856 if (rc)
1857 pr_err("%s: Failed to send lsm cal, err = %d\n",
1858 __func__, rc);
1859 break;
1860 }
1861
1862 case LSM_DEREG_SND_MODEL: {
1863 struct lsm_param_payload_common *common;
1864 struct lsm_cmd_set_params *param;
1865
1866 pkt_sz = sizeof(*param) + sizeof(*common);
1867 packet = kzalloc(pkt_sz, GFP_KERNEL);
1868 if (!packet) {
1869 pr_err("%s: No memory for DEREG_SND_MODEL pkt, size = %d\n",
1870 __func__, pkt_sz);
1871 return -ENOMEM;
1872 }
1873
1874 param = (struct lsm_cmd_set_params *) packet;
1875 common = (struct lsm_param_payload_common *)
1876 (packet + sizeof(*param));
1877 q6lsm_add_hdr(client, &param->msg_hdr, pkt_sz, true);
1878 param->msg_hdr.opcode = LSM_SESSION_CMD_SET_PARAMS_V2;
1879 q6lsm_set_param_hdr_info(&param->param_hdr,
1880 sizeof(*common),
1881 0, 0, 0);
1882 ids.module_id = p_info->module_id;
1883 ids.param_id = p_info->param_id;
1884 q6lsm_set_param_common(common, &ids, 0,
1885 LSM_SESSION_CMD_SET_PARAMS_V2);
1886 rc = q6lsm_apr_send_pkt(client, client->apr,
1887 packet, true, NULL);
1888 if (rc)
1889 pr_err("%s: DEREG_SND_MODEL failed, rc %d\n",
1890 __func__, rc);
1891 kfree(packet);
1892 break;
1893 }
1894
1895 case LSM_CUSTOM_PARAMS: {
1896 struct apr_hdr *hdr;
1897 u8 *custom_data;
1898
1899 if (p_info->param_size <
1900 sizeof(struct lsm_param_payload_common)) {
1901 pr_err("%s: Invalid param_size %d\n",
1902 __func__, p_info->param_size);
1903 return -EINVAL;
1904 }
1905
1906 pkt_sz = p_info->param_size + sizeof(*hdr);
1907 packet = kzalloc(pkt_sz, GFP_KERNEL);
1908 if (!packet) {
1909 pr_err("%s: no memory for CUSTOM_PARAMS, size = %d\n",
1910 __func__, pkt_sz);
1911 return -ENOMEM;
1912 }
1913
1914 hdr = (struct apr_hdr *) packet;
1915 custom_data = (u8 *) (packet + sizeof(*hdr));
1916 q6lsm_add_hdr(client, hdr, pkt_sz, true);
1917 hdr->opcode = LSM_SESSION_CMD_SET_PARAMS_V2;
1918 memcpy(custom_data, data, p_info->param_size);
1919
1920 rc = q6lsm_apr_send_pkt(client, client->apr,
1921 packet, true, NULL);
1922 if (rc)
1923 pr_err("%s: CUSTOM_PARAMS failed, rc %d\n",
1924 __func__, rc);
1925 kfree(packet);
1926 break;
1927 }
1928 default:
1929 pr_err("%s: wrong param_type 0x%x\n",
1930 __func__, p_info->param_type);
1931 }
1932
1933 return rc;
1934}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301935EXPORT_SYMBOL(q6lsm_set_one_param);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301936
1937
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301938/**
1939 * q6lsm_start -
1940 * command for LSM start
1941 *
1942 * @client: LSM client handle
1943 *
1944 * Returns 0 on success or error on failure
1945 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301946int q6lsm_start(struct lsm_client *client, bool wait)
1947{
1948 return q6lsm_cmd(client, LSM_SESSION_CMD_START, wait);
1949}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301950EXPORT_SYMBOL(q6lsm_start);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301951
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301952/**
1953 * q6lsm_stop -
1954 * command for LSM stop
1955 *
1956 * @client: LSM client handle
1957 *
1958 * Returns 0 on success or error on failure
1959 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301960int q6lsm_stop(struct lsm_client *client, bool wait)
1961{
1962 return q6lsm_cmd(client, LSM_SESSION_CMD_STOP, wait);
1963}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301964EXPORT_SYMBOL(q6lsm_stop);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301965
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301966/**
1967 * q6lsm_close -
1968 * command for LSM close
1969 *
1970 * @client: LSM client handle
1971 *
1972 * Returns 0 on success or error on failure
1973 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301974int q6lsm_close(struct lsm_client *client)
1975{
1976 return q6lsm_cmd(client, LSM_SESSION_CMD_CLOSE_TX, true);
1977}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301978EXPORT_SYMBOL(q6lsm_close);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301979
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05301980/**
1981 * q6lsm_lab_control -
1982 * command to set LSM LAB control params
1983 *
1984 * @client: LSM client handle
1985 * @enable: bool flag to enable or disable LAB on DSP
1986 *
1987 * Returns 0 on success or error on failure
1988 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301989int q6lsm_lab_control(struct lsm_client *client, u32 enable)
1990{
1991 int rc = 0;
1992 struct lsm_params_lab_enable lab_enable;
1993 struct lsm_params_lab_config lab_config;
1994 struct lsm_module_param_ids lab_ids;
1995 u32 param_size;
1996
1997 if (!client) {
1998 pr_err("%s: invalid param client %pK\n", __func__, client);
1999 return -EINVAL;
2000 }
2001 /* enable/disable lab on dsp */
2002 q6lsm_add_hdr(client, &lab_enable.msg_hdr, sizeof(lab_enable), true);
2003 lab_enable.msg_hdr.opcode = LSM_SESSION_CMD_SET_PARAMS;
2004 q6lsm_set_param_hdr_info(&lab_enable.params_hdr,
2005 sizeof(struct lsm_lab_enable),
2006 0, 0, 0);
2007 param_size = (sizeof(struct lsm_lab_enable) -
2008 sizeof(struct lsm_param_payload_common));
2009 lab_ids.module_id = LSM_MODULE_ID_LAB;
2010 lab_ids.param_id = LSM_PARAM_ID_LAB_ENABLE;
2011 q6lsm_set_param_common(&lab_enable.lab_enable.common,
2012 &lab_ids, param_size,
2013 LSM_SESSION_CMD_SET_PARAMS);
2014 lab_enable.lab_enable.enable = (enable) ? 1 : 0;
2015 rc = q6lsm_apr_send_pkt(client, client->apr, &lab_enable, true, NULL);
2016 if (rc) {
2017 pr_err("%s: Lab enable failed rc %d\n", __func__, rc);
2018 return rc;
2019 }
2020 if (!enable)
2021 goto exit;
2022 /* lab session is being enabled set the config values */
2023 q6lsm_add_hdr(client, &lab_config.msg_hdr, sizeof(lab_config), true);
2024 lab_config.msg_hdr.opcode = LSM_SESSION_CMD_SET_PARAMS;
2025 q6lsm_set_param_hdr_info(&lab_config.params_hdr,
2026 sizeof(struct lsm_lab_config),
2027 0, 0, 0);
2028 lab_ids.module_id = LSM_MODULE_ID_LAB;
2029 lab_ids.param_id = LSM_PARAM_ID_LAB_CONFIG;
2030 param_size = (sizeof(struct lsm_lab_config) -
2031 sizeof(struct lsm_param_payload_common));
2032 q6lsm_set_param_common(&lab_config.lab_config.common,
2033 &lab_ids, param_size,
2034 LSM_SESSION_CMD_SET_PARAMS);
2035 lab_config.lab_config.minor_version = 1;
2036 lab_config.lab_config.wake_up_latency_ms = 250;
2037 rc = q6lsm_apr_send_pkt(client, client->apr, &lab_config, true, NULL);
2038 if (rc) {
2039 pr_err("%s: Lab config failed rc %d disable lab\n",
2040 __func__, rc);
2041 /* Lab config failed disable lab */
2042 lab_enable.lab_enable.enable = 0;
2043 if (q6lsm_apr_send_pkt(client, client->apr,
2044 &lab_enable, true, NULL))
2045 pr_err("%s: Lab disable failed\n", __func__);
2046 }
2047exit:
2048 return rc;
2049}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302050EXPORT_SYMBOL(q6lsm_lab_control);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302051
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302052/**
2053 * q6lsm_stop_lab -
2054 * command to stop LSM LAB
2055 *
2056 * @client: LSM client handle
2057 *
2058 * Returns 0 on success or error on failure
2059 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302060int q6lsm_stop_lab(struct lsm_client *client)
2061{
2062 int rc = 0;
2063
2064 if (!client) {
2065 pr_err("%s: invalid param client %pK\n", __func__, client);
2066 return -EINVAL;
2067 }
2068 rc = q6lsm_cmd(client, LSM_SESSION_CMD_EOB, true);
2069 if (rc)
2070 pr_err("%s: Lab stop failed %d\n", __func__, rc);
2071 return rc;
2072}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302073EXPORT_SYMBOL(q6lsm_stop_lab);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302074
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302075/**
2076 * q6lsm_read -
2077 * command for LSM read
2078 *
2079 * @client: LSM client handle
2080 * @lsm_cmd_read: LSM read command
2081 *
2082 * Returns 0 on success or error on failure
2083 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302084int q6lsm_read(struct lsm_client *client, struct lsm_cmd_read *read)
2085{
2086 int rc = 0;
2087
2088 if (!client || !read) {
2089 pr_err("%s: Invalid params client %pK read %pK\n", __func__,
2090 client, read);
2091 return -EINVAL;
2092 }
2093 pr_debug("%s: read call memmap handle %x address %x%x size %d\n",
2094 __func__, read->mem_map_handle, read->buf_addr_msw,
2095 read->buf_addr_lsw, read->buf_size);
2096 q6lsm_add_hdr(client, &read->hdr, sizeof(struct lsm_cmd_read), true);
2097 read->hdr.opcode = LSM_SESSION_CMD_READ;
2098 rc = q6lsm_apr_send_pkt(client, client->apr, read, false, NULL);
2099 if (rc)
2100 pr_err("%s: read buffer call failed rc %d\n", __func__, rc);
2101 return rc;
2102}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302103EXPORT_SYMBOL(q6lsm_read);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302104
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302105/**
2106 * q6lsm_lab_buffer_alloc -
2107 * Lab buffer allocation or de-alloc
2108 *
2109 * @client: LSM client handle
2110 * @alloc: Allocate or free ion memory
2111 *
2112 * Returns 0 on success or error on failure
2113 */
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302114int q6lsm_lab_buffer_alloc(struct lsm_client *client, bool alloc)
2115{
2116 int ret = 0, i = 0;
2117 size_t allocate_size = 0, len = 0;
2118
2119 if (!client) {
2120 pr_err("%s: invalid client\n", __func__);
2121 return -EINVAL;
2122 }
2123 if (alloc) {
2124 if (client->lab_buffer) {
2125 pr_err("%s: buffers are allocated period count %d period size %d\n",
2126 __func__,
2127 client->hw_params.period_count,
2128 client->hw_params.buf_sz);
2129 return -EINVAL;
2130 }
2131 allocate_size = client->hw_params.period_count *
2132 client->hw_params.buf_sz;
2133 allocate_size = PAGE_ALIGN(allocate_size);
2134 client->lab_buffer =
2135 kzalloc(sizeof(struct lsm_lab_buffer) *
2136 client->hw_params.period_count, GFP_KERNEL);
2137 if (!client->lab_buffer) {
2138 pr_err("%s: memory allocation for lab buffer failed count %d\n"
2139 , __func__,
2140 client->hw_params.period_count);
2141 return -ENOMEM;
2142 }
2143 ret = msm_audio_ion_alloc("lsm_lab",
2144 &client->lab_buffer[0].client,
2145 &client->lab_buffer[0].handle,
2146 allocate_size, &client->lab_buffer[0].phys,
2147 &len,
2148 &client->lab_buffer[0].data);
2149 if (ret)
2150 pr_err("%s: ion alloc failed ret %d size %zd\n",
2151 __func__, ret, allocate_size);
2152 else {
2153 ret = q6lsm_memory_map_regions(client,
2154 client->lab_buffer[0].phys, len,
2155 &client->lab_buffer[0].mem_map_handle);
2156 if (ret) {
2157 pr_err("%s: memory map filed ret %d size %zd\n",
2158 __func__, ret, len);
2159 msm_audio_ion_free(
2160 client->lab_buffer[0].client,
2161 client->lab_buffer[0].handle);
2162 }
2163 }
2164 if (ret) {
2165 pr_err("%s: alloc lab buffer failed ret %d\n",
2166 __func__, ret);
2167 kfree(client->lab_buffer);
2168 client->lab_buffer = NULL;
2169 } else {
2170 pr_debug("%s: Memory map handle %x phys %pK size %d\n",
2171 __func__,
2172 client->lab_buffer[0].mem_map_handle,
2173 &client->lab_buffer[0].phys,
2174 client->hw_params.buf_sz);
2175 for (i = 0; i < client->hw_params.period_count; i++) {
2176 client->lab_buffer[i].phys =
2177 client->lab_buffer[0].phys +
2178 (i * client->hw_params.buf_sz);
2179 client->lab_buffer[i].size =
2180 client->hw_params.buf_sz;
2181 client->lab_buffer[i].data =
2182 (u8 *)(client->lab_buffer[0].data) +
2183 (i * client->hw_params.buf_sz);
2184 client->lab_buffer[i].mem_map_handle =
2185 client->lab_buffer[0].mem_map_handle;
2186 }
2187 }
2188 } else {
2189 ret = q6lsm_memory_unmap_regions(client,
2190 client->lab_buffer[0].mem_map_handle);
2191 if (!ret)
2192 msm_audio_ion_free(
2193 client->lab_buffer[0].client,
2194 client->lab_buffer[0].handle);
2195 else
2196 pr_err("%s: unmap failed not freeing memory\n",
2197 __func__);
2198 kfree(client->lab_buffer);
2199 client->lab_buffer = NULL;
2200 }
2201 return ret;
2202}
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302203EXPORT_SYMBOL(q6lsm_lab_buffer_alloc);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302204
2205static int get_cal_type_index(int32_t cal_type)
2206{
2207 int ret = -EINVAL;
2208
2209 switch (cal_type) {
2210 case LSM_CUST_TOPOLOGY_CAL_TYPE:
2211 ret = LSM_CUSTOM_TOP_IDX;
2212 break;
2213 case LSM_TOPOLOGY_CAL_TYPE:
2214 ret = LSM_TOP_IDX;
2215 break;
2216 case LSM_CAL_TYPE:
2217 ret = LSM_CAL_IDX;
2218 break;
2219 default:
2220 pr_err("%s: invalid cal type %d!\n", __func__, cal_type);
2221 }
2222 return ret;
2223}
2224
2225static int q6lsm_alloc_cal(int32_t cal_type,
2226 size_t data_size, void *data)
2227{
2228 int ret = 0;
2229 int cal_index;
2230
2231 pr_debug("%s:\n", __func__);
2232
2233 cal_index = get_cal_type_index(cal_type);
2234 if (cal_index < 0) {
2235 pr_err("%s: could not get cal index %d!\n",
2236 __func__, cal_index);
2237 ret = -EINVAL;
2238 goto done;
2239 }
2240
2241 ret = cal_utils_alloc_cal(data_size, data,
2242 lsm_common.cal_data[cal_index], 0, NULL);
2243 if (ret < 0) {
2244 pr_err("%s: cal_utils_alloc_block failed, ret = %d, cal type = %d!\n",
2245 __func__, ret, cal_type);
2246 ret = -EINVAL;
2247 goto done;
2248 }
2249done:
2250 return ret;
2251}
2252
2253static int q6lsm_dealloc_cal(int32_t cal_type,
2254 size_t data_size, void *data)
2255{
2256 int ret = 0;
2257 int cal_index;
2258
2259 pr_debug("%s:\n", __func__);
2260
2261 cal_index = get_cal_type_index(cal_type);
2262 if (cal_index < 0) {
2263 pr_err("%s: could not get cal index %d!\n",
2264 __func__, cal_index);
2265 ret = -EINVAL;
2266 goto done;
2267 }
2268
2269 ret = cal_utils_dealloc_cal(data_size, data,
2270 lsm_common.cal_data[cal_index]);
2271 if (ret < 0) {
2272 pr_err("%s: cal_utils_dealloc_block failed, ret = %d, cal type = %d!\n",
2273 __func__, ret, cal_type);
2274 ret = -EINVAL;
2275 goto done;
2276 }
2277done:
2278 return ret;
2279}
2280
2281static int q6lsm_set_cal(int32_t cal_type,
2282 size_t data_size, void *data)
2283{
2284 int ret = 0;
2285 int cal_index;
2286
2287 pr_debug("%s:\n", __func__);
2288
2289 cal_index = get_cal_type_index(cal_type);
2290 if (cal_index < 0) {
2291 pr_err("%s: could not get cal index %d!\n",
2292 __func__, cal_index);
2293 ret = -EINVAL;
2294 goto done;
2295 }
2296
2297 ret = cal_utils_set_cal(data_size, data,
2298 lsm_common.cal_data[cal_index], 0, NULL);
2299 if (ret < 0) {
2300 pr_err("%s: cal_utils_set_cal failed, ret = %d, cal type = %d!\n",
2301 __func__, ret, cal_type);
2302 ret = -EINVAL;
2303 goto done;
2304 }
2305
2306 if (cal_index == LSM_CUSTOM_TOP_IDX) {
2307 mutex_lock(&lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]->lock);
2308 lsm_common.set_custom_topology = 1;
2309 mutex_unlock(&lsm_common.cal_data[LSM_CUSTOM_TOP_IDX]->lock);
2310 }
2311
2312done:
2313 return ret;
2314}
2315
2316static void lsm_delete_cal_data(void)
2317{
2318 pr_debug("%s:\n", __func__);
2319
2320 cal_utils_destroy_cal_types(LSM_MAX_CAL_IDX, lsm_common.cal_data);
2321}
2322
2323static int q6lsm_init_cal_data(void)
2324{
2325 int ret = 0;
2326 struct cal_type_info cal_type_info[] = {
2327 {{LSM_CUST_TOPOLOGY_CAL_TYPE,
2328 {q6lsm_alloc_cal, q6lsm_dealloc_cal, NULL,
2329 q6lsm_set_cal, NULL, NULL} },
2330 {NULL, NULL, cal_utils_match_buf_num} },
2331
2332 {{LSM_TOPOLOGY_CAL_TYPE,
2333 {NULL, NULL, NULL,
2334 q6lsm_set_cal, NULL, NULL} },
2335 {NULL, NULL, cal_utils_match_buf_num} },
2336
2337 {{LSM_CAL_TYPE,
2338 {q6lsm_alloc_cal, q6lsm_dealloc_cal, NULL,
2339 q6lsm_set_cal, NULL, NULL} },
2340 {NULL, NULL, cal_utils_match_buf_num} }
2341 };
2342 pr_debug("%s:\n", __func__);
2343
2344 ret = cal_utils_create_cal_types(LSM_MAX_CAL_IDX,
2345 lsm_common.cal_data, cal_type_info);
2346 if (ret < 0) {
2347 pr_err("%s: could not create cal type!\n",
2348 __func__);
2349 ret = -EINVAL;
2350 goto err;
2351 }
2352
2353 return ret;
2354err:
2355 lsm_delete_cal_data();
2356 return ret;
2357}
2358
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302359int __init q6lsm_init(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302360{
2361 int i = 0;
2362
2363 pr_debug("%s:\n", __func__);
2364 spin_lock_init(&lsm_session_lock);
2365 spin_lock_init(&mmap_lock);
2366 mutex_init(&lsm_common.apr_lock);
2367 for (; i <= LSM_MAX_SESSION_ID; i++) {
2368 lsm_common.common_client[i].session = LSM_CONTROL_SESSION;
2369 init_waitqueue_head(&lsm_common.common_client[i].cmd_wait);
2370 mutex_init(&lsm_common.common_client[i].cmd_lock);
2371 atomic_set(&lsm_common.common_client[i].cmd_state,
2372 CMD_STATE_CLEARED);
2373 }
2374
2375 if (q6lsm_init_cal_data())
2376 pr_err("%s: could not init cal data!\n", __func__);
2377
2378 return 0;
2379}
2380
Asish Bhattacharya5faacb32017-12-04 17:23:15 +05302381void q6lsm_exit(void)
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302382{
2383 lsm_delete_cal_data();
2384}