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