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