blob: ba8154a9319e232cefd5865699568ebba9bf47e5 [file] [log] [blame]
Quinn Male2e883752019-03-22 11:28:54 -07001/* st_hw_session_lsm.c
2 *
3 * This file implements the hw session functionality specific to LSM HW
4 *
Lakshman Chaluvaraju426ea362022-02-17 11:11:23 +05305 * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
sasevsb07d0c52022-06-01 13:03:40 +05306 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
Quinn Male2e883752019-03-22 11:28:54 -07007 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are
10 * met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of The Linux Foundation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
22 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
28 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
30 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
31 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34#define LOG_TAG "sound_trigger_hw"
35#define ATRACE_TAG (ATRACE_TAG_HAL)
36/* #define LOG_NDEBUG 0 */
37#define LOG_NDDEBUG 0
38
39#include <errno.h>
40#include <stdlib.h>
41#include <dlfcn.h>
42#include <fcntl.h>
43#include <sys/resource.h>
44#include <sys/prctl.h>
45#include <sys/ioctl.h>
46#include <cutils/log.h>
47#include <cutils/atomic.h>
48#include <cutils/trace.h>
49#include <system/thread_defs.h>
Meng Wang78b97242020-05-08 14:24:51 +080050#include <sound/asound.h>
Quinn Male2e883752019-03-22 11:28:54 -070051
52#include <stdarg.h>
53#include <unistd.h>
54
55#include "st_common_defs.h"
56#include "sound_trigger_platform.h"
57#include "st_hw_session_lsm.h"
58#include "sound_trigger_hw.h"
59#include "st_hw_common.h"
60
sasevsb07d0c52022-06-01 13:03:40 +053061#define LSM_LUT_CLEAR_INFO _IOW('U', 0xF0, int)
Quinn Male2e883752019-03-22 11:28:54 -070062#define XSTR(x) STR(x)
63#define STR(x) #x
64
65#define MAX_DOA_TRACKING_ANGLES 2
66#define DOA_POLAR_ACTIVITY_INDICATORS 360
67
68static int ape_reg_sm(st_hw_session_t* p_ses, void *sm_data,
Quinn Male58749452020-03-26 17:14:56 -070069 unsigned int sm_size, uint32_t model_id);
Quinn Male2e883752019-03-22 11:28:54 -070070static int ape_reg_sm_params(st_hw_session_t* p_ses, unsigned int recognition_mode,
Quinn Male58749452020-03-26 17:14:56 -070071 bool capture_requested, struct sound_trigger_recognition_config *rc_config);
Quinn Male2e883752019-03-22 11:28:54 -070072
Quinn Male58749452020-03-26 17:14:56 -070073static int ape_dereg_sm(st_hw_session_t* p_ses, uint32_t model_id);
Quinn Male2e883752019-03-22 11:28:54 -070074static int ape_dereg_sm_params(st_hw_session_t* p_ses);
75static int ape_start(st_hw_session_t* p_ses);
76static int ape_stop(st_hw_session_t* p_ses);
77static int ape_stop_buffering(st_hw_session_t* p_ses);
Harshal Ahire63dfba52020-07-13 02:38:14 +053078static int ape_open_session(st_hw_session_t* p_ses);
79static void ape_close_session(st_hw_session_t* p_ses);
80#ifdef SNDRV_LSM_GET_MODULE_PARAMS
81static int ape_get_module_version(st_hw_session_t *p_ses, void *param_info_payload,
82 size_t size);
83#endif
Quinn Male2e883752019-03-22 11:28:54 -070084
Quinn Male9a345522020-03-12 17:49:25 -070085/* Routing layer functions */
Quinn Male2e883752019-03-22 11:28:54 -070086static int route_reg_sm_ape(st_hw_session_t *p_ses,
Quinn Male58749452020-03-26 17:14:56 -070087 void *sm_data, unsigned int sm_size, uint32_t model_id);
Quinn Male2e883752019-03-22 11:28:54 -070088static int route_reg_sm_params_ape(st_hw_session_t* p_ses,
89 unsigned int recognition_mode, bool capture_requested,
Quinn Male58749452020-03-26 17:14:56 -070090 struct sound_trigger_recognition_config *rc_config);
91static int route_dereg_sm_ape(st_hw_session_t* p_ses, uint32_t model_id);
Quinn Male2e883752019-03-22 11:28:54 -070092static int route_dereg_sm_params_ape(st_hw_session_t* p_ses);
93static int route_restart_ape(st_hw_session_t* p_ses,
94 unsigned int recognition_mode,
Quinn Male58749452020-03-26 17:14:56 -070095 struct sound_trigger_recognition_config *rc_config);
Quinn Male2e883752019-03-22 11:28:54 -070096static int route_start_ape(st_hw_session_t* p_ses);
97static int route_stop_ape(st_hw_session_t* p_ses);
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -070098static int route_stop_buffering_ape(st_hw_session_t* p_ses);
Quinn Male2e883752019-03-22 11:28:54 -070099static int route_set_device_ape(st_hw_session_t* p_ses,
100 bool enable);
101static int route_read_pcm_ape(st_hw_session_t *p_ses,
102 unsigned char *buf,
103 unsigned int bytes);
104static void route_audio_capture_ape(st_hw_session_t* p_ses);
105static int route_send_custom_chmix_coeff_ape(st_hw_session_t *p_ses, char *str);
Quinn Male2e883752019-03-22 11:28:54 -0700106static int route_disable_device(st_hw_session_t *p_ses, bool setting_device);
107static int route_enable_device(st_hw_session_t *p_ses, bool setting_device);
108static void request_exit_callback_thread(st_hw_session_lsm_t *p_lsm_ses);
109static int get_param_data(st_hw_session_t* p_ses, const char *param,
110 void *payload, size_t payload_size, size_t *param_data_size);
111static int send_detection_request(st_hw_session_t *p_ses);
112
Quinn Male2e883752019-03-22 11:28:54 -0700113typedef struct {
114 int16_t target_angle_L16[MAX_DOA_TRACKING_ANGLES];
115 int16_t interf_angle_L16[MAX_DOA_TRACKING_ANGLES];
116 int8_t polarActivityGUI[DOA_POLAR_ACTIVITY_INDICATORS];
117} st_ffv_doa_tracking_monitor_t;
118
sasevsb07d0c52022-06-01 13:03:40 +0530119#ifdef ENABLE_SVA_MIXER_CTL
120struct st_lsm_cdev_info
121{
122 int fd;
123 int det_status;
124};
125#endif
126
Quinn Male2e883752019-03-22 11:28:54 -0700127static struct pcm_config stdev_ape_pcm_config = {
128 .channels = SOUND_TRIGGER_CHANNEL_MODE_MONO,
129 .rate = SOUND_TRIGGER_SAMPLING_RATE_16000,
130 .period_size = SOUND_TRIGGER_APE_PERIOD_SIZE,
131 .period_count = SOUND_TRIGGER_APE_PERIOD_COUNT,
132 .format = PCM_FORMAT_S16_LE,
133};
134
Quinn Male2e883752019-03-22 11:28:54 -0700135struct st_session_fptrs ape_fptrs = {
136
137 .reg_sm = route_reg_sm_ape ,
138 .reg_sm_params = route_reg_sm_params_ape,
139 .dereg_sm = route_dereg_sm_ape ,
140 .dereg_sm_params = route_dereg_sm_params_ape,
141 .start = route_start_ape,
142 .restart = route_restart_ape,
143 .stop = route_stop_ape,
144 .stop_buffering = route_stop_buffering_ape,
145 .set_device = route_set_device_ape,
146 .read_pcm = route_read_pcm_ape,
147 .process_lab_capture = route_audio_capture_ape,
148 .send_custom_chmix_coeff = route_send_custom_chmix_coeff_ape,
149 .disable_device = route_disable_device,
150 .enable_device = route_enable_device,
151 .get_param_data = get_param_data,
152 .send_detection_request = send_detection_request,
Harshal Ahire63dfba52020-07-13 02:38:14 +0530153 .open_session = ape_open_session,
154 .close_session = ape_close_session,
155#ifdef SNDRV_LSM_GET_MODULE_PARAMS
156 .get_module_version = ape_get_module_version,
157#endif
Quinn Male2e883752019-03-22 11:28:54 -0700158};
159
Quinn Male2e883752019-03-22 11:28:54 -0700160int pcm_ioctl(struct pcm *pcm, int request, ...)
161{
162 va_list ap;
163 void * arg;
164 int pcm_fd = *(int*)pcm;
165
166 va_start(ap, request);
167 arg = va_arg(ap, void *);
168 va_end(ap);
169
170 return ioctl(pcm_fd, request, arg);
171}
172
173#if (SNDRV_LSM_VERSION >= SNDRV_PROTOCOL_VERSION(0, 3, 1))
174typedef struct lsm_params_info_v2 lsm_param_info_t;
175typedef struct lsm_param_payload_v2 lsm_param_payload_t;
176
sasevsb07d0c52022-06-01 13:03:40 +0530177#ifdef ENABLE_SVA_MIXER_CTL
178int lsm_set_session_data(struct mixer * st_mixer, void *ses_data)
179{
180 struct mixer_ctl *ctl = NULL;
181 const char *mixer_ctl_name = "LSM SESSION_DATA SET";
182
183 ctl = mixer_get_ctl_by_name(st_mixer, mixer_ctl_name);
184 if (!ctl) {
185 ALOGE("%s: Could not get ctl for mixer cmd - %s",
186 __func__, mixer_ctl_name);
187 }
188
189 if (mixer_ctl_set_array(ctl, ses_data, sizeof(struct snd_lsm_session_data_v2)) < 0) {
190 ALOGE("%s: Could not set LSM load mixer control", __func__);
191 }
192
193 return 0;
194}
195#endif
196
Quinn Male2e883752019-03-22 11:28:54 -0700197static int lsm_set_session_data_v2(st_hw_session_t *p_ses)
198{
199 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t*)p_ses;
200 struct st_vendor_info *v_info = p_ses->vendor_uuid_info;
201 struct snd_lsm_session_data_v2 ses_data = {0};
202 uint16_t stage_idx = LSM_STAGE_INDEX_FIRST;
203 struct listnode *node;
204 st_lsm_ss_config_t *ss_cfg;
205 int status = 0;
206
207 ses_data.app_id = LSM_VOICE_WAKEUP_APP_ID_V2;
208 ses_data.num_stages = p_lsm_ses->num_stages;
209 ses_data.stage_info[stage_idx].app_type =
210 (v_info->app_type == 0) ?
Quinn Male8b2cb792020-07-13 14:41:32 -0700211 p_lsm_ses->lsm_usecase.app_type : v_info->app_type;
Quinn Male2e883752019-03-22 11:28:54 -0700212 ses_data.stage_info[stage_idx].lpi_enable = p_ses->lpi_enable;
Quinn Male24daf422019-05-29 16:12:55 -0700213 ALOGD("%s: Sending lpi_enable = %s to LSM", __func__,
214 p_ses->lpi_enable ? "true" : "false");
Quinn Male2e883752019-03-22 11:28:54 -0700215
216 list_for_each(node, &p_ses->lsm_ss_cfg_list) {
217 ss_cfg = node_to_item(node, st_lsm_ss_config_t, list_node);
218 stage_idx++;
219 ses_data.stage_info[stage_idx].app_type = ss_cfg->params->app_type;
220 ses_data.stage_info[stage_idx].lpi_enable = ss_cfg->params->lpi_enable;
Quinn Male24daf422019-05-29 16:12:55 -0700221 ALOGD("%s: Sending lpi_enable = %s to LSM for stage_idx %d", __func__,
222 ss_cfg->params->lpi_enable ? "true" : "false", stage_idx);
Quinn Male2e883752019-03-22 11:28:54 -0700223 }
224
225 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_lsm_set_session_data_v2");
sasevsb07d0c52022-06-01 13:03:40 +0530226#ifdef ENABLE_SVA_MIXER_CTL
227 status = lsm_set_session_data(p_ses->stdev->mixer, (void *)(&ses_data));
228#else
Quinn Male2e883752019-03-22 11:28:54 -0700229 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_SET_SESSION_DATA_V2, &ses_data);
sasevsb07d0c52022-06-01 13:03:40 +0530230#endif
Quinn Male2e883752019-03-22 11:28:54 -0700231 ATRACE_END();
232 if (status)
233 ALOGE("%s: ERROR. SNDRV_LSM_SET_SESSION_DATA_V2 failed status(%d)",
234 __func__, status);
235 return status;
236}
237
Harshal Ahire63dfba52020-07-13 02:38:14 +0530238#ifdef SNDRV_LSM_GET_MODULE_PARAMS
239static void lsm_fill_get_param_info
240(
241 uint32_t param_type,
242 struct lsm_params_get_info *p_info,
243 struct st_module_param_info *mparams,
244 uint16_t stage_idx
245)
246{
247 p_info->param_type = param_type;
248 p_info->module_id = mparams->module_id;
249 p_info->instance_id = mparams->instance_id;
250 p_info->param_id = mparams->param_id;
251 p_info->stage_idx = stage_idx;
252}
253
254static int lsm_get_module_params
255(
256 st_hw_session_lsm_t *p_lsm_ses,
257 struct lsm_params_get_info *lsm_params
258)
259{
260 int status = 0;
261
262 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_lsm_get_module_params");
263 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_GET_MODULE_PARAMS, lsm_params);
264 ATRACE_END();
265
266 if (status)
267 ALOGE("%s: ERROR. SNDRV_LSM_GET_MODULE_PARAMS status(%d)",
268 __func__, status);
269 return status;
270}
271#endif
272
Quinn Male2e883752019-03-22 11:28:54 -0700273static void lsm_fill_param_info
274(
275 uint32_t param_type,
276 lsm_param_info_t *p_info,
277 struct st_module_param_info *mparams,
278 uint16_t stage_idx
279)
280{
281 p_info->param_type = param_type;
282 p_info->module_id = mparams->module_id;
283 p_info->instance_id = mparams->instance_id;
284 p_info->param_id = mparams->param_id;
285 p_info->stage_idx = stage_idx;
286}
287
sasevsb07d0c52022-06-01 13:03:40 +0530288#ifdef ENABLE_SVA_MIXER_CTL
289static int lsm_mixer_set_module_params
290(
291 st_hw_session_lsm_t *p_lsm_ses,
292 struct snd_lsm_module_params *lsm_params
293)
294{
295 const char *mixer_ctl_name = "LSM MODULE_PARAMS SET";
296 struct mixer_ctl *ctl = NULL;
297 st_hw_session_t p_ses = p_lsm_ses->common;
298 int ret = 0;
299
300 ctl = mixer_get_ctl_by_name(p_ses.stdev->mixer, mixer_ctl_name);
301 if (!ctl) {
302 ALOGE("%s: Could not get ctl for mixer cmd - %s",
303 __func__, mixer_ctl_name);
304 }
305
306 ret = mixer_ctl_set_array(ctl, lsm_params, sizeof(struct snd_lsm_module_params));
307 if (ret < 0) {
308 ALOGE("%s: Could not set LSM set module params, ret = %d", __func__, ret);
309 }
310
311 return ret;
312}
313#endif
314
Quinn Male2e883752019-03-22 11:28:54 -0700315static int lsm_set_module_params
316(
317 st_hw_session_lsm_t *p_lsm_ses,
318 struct snd_lsm_module_params *lsm_params
319)
320{
321 int status = 0;
322
Harshal Ahire387953e2021-02-19 15:18:39 +0530323 if(!p_lsm_ses->pcm) {
324 ALOGE("%s: PCM is NULL", __func__);
325 return -EINVAL;
326 }
327
Quinn Male2e883752019-03-22 11:28:54 -0700328 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_lsm_set_module_params_v2");
sasevsb07d0c52022-06-01 13:03:40 +0530329#ifdef ENABLE_SVA_MIXER_CTL
330 status = lsm_mixer_set_module_params(p_lsm_ses, lsm_params);
331#else
Quinn Male2e883752019-03-22 11:28:54 -0700332 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_SET_MODULE_PARAMS_V2, lsm_params);
sasevsb07d0c52022-06-01 13:03:40 +0530333#endif
Quinn Male2e883752019-03-22 11:28:54 -0700334 ATRACE_END();
335
336 if (status)
337 ALOGE("%s: ERROR. SNDRV_LSM_SET_MODULE_PARAMS_V2 count(%d), status(%d)",
338 __func__, lsm_params->num_params, status);
339 return status;
340}
341
342bool st_hw_check_multi_stage_lsm_support()
343{
344 return true;
345}
346
347static void lsm_fill_param_header
348(
349 lsm_param_payload_t *custom_conf,
350 uint32_t payload_size,
351 struct st_module_param_info *mparams
352)
353{
354 custom_conf->module_id = mparams->module_id;
355 custom_conf->instance_id = mparams->instance_id;
356 custom_conf->reserved = 0;
357 custom_conf->param_id = mparams->param_id;
358 custom_conf->p_size = payload_size;
359}
360#else
361#define LSM_MAX_STAGES_PER_SESSION 1
362#define LSM_STAGE_INDEX_FIRST 0
363#define LSM_LAB_CONTROL -1
364typedef struct lsm_params_info lsm_param_info_t;
365typedef struct lsm_param_payload lsm_param_payload_t;
366
367static int lsm_set_session_data_v2(st_hw_session_t *p_ses __unused)
368{
369 ALOGE("%s: ERROR: unexpected call, check support from \"%s\" before using",
370 __func__, "st_hw_check_multi_stage_lsm_support");
371 return -ENOSYS;
372}
373
374static void lsm_fill_param_info
375(
376 uint32_t param_type,
377 lsm_param_info_t *p_info,
378 struct st_module_param_info *mparams,
379 uint16_t stage_idx __unused
380)
381{
382 p_info->param_type = param_type;
383 p_info->module_id = mparams->module_id;
384 p_info->param_id = mparams->param_id;
385}
386
387static int lsm_set_module_params
388(
389 st_hw_session_lsm_t *p_lsm_ses,
390 struct snd_lsm_module_params *lsm_params
391)
392{
393 int status = 0;
394
395 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_lsm_set_module_params");
396 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_SET_MODULE_PARAMS, lsm_params);
397 ATRACE_END();
398
399 if (status)
400 ALOGE("%s: ERROR. SNDRV_LSM_SET_MODULE_PARAMS count(%d), status(%d)",
401 __func__, lsm_params->num_params, status);
402 return status;
403}
404
405bool st_hw_check_multi_stage_lsm_support()
406{
407 return false;
408}
409
410static void lsm_fill_param_header
411(
412 lsm_param_payload_t *custom_conf,
413 uint32_t payload_size,
414 struct st_module_param_info *mparams
415)
416{
417 custom_conf->module_id = mparams->module_id;
418 custom_conf->param_id = mparams->param_id;
419 custom_conf->p_size = payload_size;
420}
421#endif
422
423#ifdef LSM_EVENT_TIMESTAMP_MODE_SUPPORT
sasevsb07d0c52022-06-01 13:03:40 +0530424
425#ifdef ENABLE_SVA_MIXER_CTL
426int lsm_set_fwk_mode_mixer_ctl(struct mixer * st_mixer, int buf_en)
427{
428 int ret = 0;
429 struct mixer_ctl *ctl = NULL;
430 const char *mixer_ctl_name = "LSM FWK_MODE SET";
431
432 ctl = mixer_get_ctl_by_name(st_mixer, mixer_ctl_name);
433 if (!ctl) {
434 ALOGE("%s: Could not get ctl for mixer cmd - %s",
435 __func__, mixer_ctl_name);
436 }
437
438 ret = mixer_ctl_set_value(ctl, 0, buf_en);
439 if (ret < 0) {
440 ALOGE("%s: Could not set LSM load mixer control", __func__);
441 }
442
443 return ret;
444}
445#endif
446
Quinn Male2e883752019-03-22 11:28:54 -0700447static int set_lsm_fwk_mode(st_hw_session_lsm_t *p_lsm_ses)
448{
449 int status;
450 struct st_vendor_info *v_info = p_lsm_ses->common.vendor_uuid_info;
451 unsigned int fwk_mode = LSM_EVENT_NON_TIME_STAMP_MODE;
sasevsb07d0c52022-06-01 13:03:40 +0530452 st_hw_session_t p_ses;
Quinn Male2e883752019-03-22 11:28:54 -0700453
Quinn Male2e883752019-03-22 11:28:54 -0700454 if (v_info && (v_info->fwk_mode == SOUND_TRIGGER_EVENT_TIME_STAMP_MODE))
455 fwk_mode = LSM_EVENT_TIME_STAMP_MODE;
456
sasevsb07d0c52022-06-01 13:03:40 +0530457 p_ses = p_lsm_ses->common;
458#ifdef ENABLE_SVA_MIXER_CTL
459 status = lsm_set_fwk_mode_mixer_ctl(p_ses.stdev->mixer, fwk_mode);
460#else
Quinn Male2e883752019-03-22 11:28:54 -0700461 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_SET_FWK_MODE_CONFIG,
462 &fwk_mode);
sasevsb07d0c52022-06-01 13:03:40 +0530463#endif
Quinn Male2e883752019-03-22 11:28:54 -0700464 if (status)
465 ALOGE("%s: SNDRV_LSM_SET_FWK_MODE_CONFIG status=%d", __func__, status);
466
467 return status;
468}
469
470static void update_lsm_event_status_info(st_hw_session_lsm_t *p_lsm_ses,
471 int *request,
472 char **st_lsm_event_cmd)
473{
474#ifdef LSM_DET_EVENT_TYPE_GENERIC
475 if (p_lsm_ses->common.is_generic_event) {
476 *request = SNDRV_LSM_GENERIC_DET_EVENT;
477 *st_lsm_event_cmd = strdup("SNDRV_LSM_GENERIC_DET_EVENT");
478 }
479 else
480#endif
481 if (!p_lsm_ses->common.is_generic_event) {
482 *request = SNDRV_LSM_EVENT_STATUS_V3;
483 *st_lsm_event_cmd = strdup("SNDRV_LSM_EVENT_STATUS_V3");
484 }
485}
486
487static uint64_t get_event_timestamp(st_lsm_event_status_t *params)
488{
489 uint64_t timestamp;
490
491 timestamp = ((uint64_t)params->timestamp_msw << 32) |
492 params->timestamp_lsw;
493 return timestamp;
494}
495#else
496static int set_lsm_fwk_mode(st_hw_session_lsm_t *p_lsm_ses __unused)
497{
498 /* set fwk mode not supported */
499 return 0;
500}
501
502static void update_lsm_event_status_info(st_hw_session_lsm_t *p_lsm_ses,
503 int *request,
504 char **st_lsm_event_cmd)
505{
506#ifdef LSM_DET_EVENT_TYPE_GENERIC
507 if (p_lsm_ses->common.is_generic_event) {
508 *request = SNDRV_LSM_GENERIC_DET_EVENT;
509 *st_lsm_event_cmd = strdup("SNDRV_LSM_GENERIC_DET_EVENT");
510 }
511 else
512#endif
513 if (!p_lsm_ses->common.is_generic_event) {
514 *request = SNDRV_LSM_EVENT_STATUS;
515 *st_lsm_event_cmd = strdup("SNDRV_LSM_EVENT_STATUS");
516 }
517}
518
519static uint64_t get_event_timestamp(st_lsm_event_status_t *params __unused)
520{
521 /* timestamp mode not supported */
522 return 0;
523}
524#endif
525
526#ifdef LSM_POLLING_ENABLE_SUPPORT
sasevsb07d0c52022-06-01 13:03:40 +0530527
528#ifdef ENABLE_SVA_MIXER_CTL
529int lsm_set_port_mixer_ctl(struct mixer * st_mixer)
530{
531 int ret = 0;
532 struct mixer_ctl *ctl = NULL;
533 const char *mixer_ctl_name = "LSM PORT SET";
534
535 ctl = mixer_get_ctl_by_name(st_mixer, mixer_ctl_name);
536 if (!ctl) {
537 ALOGE("%s: Could not get ctl for mixer cmd - %s",
538 __func__, mixer_ctl_name);
539 }
540 ret = mixer_ctl_set_value(ctl, 0, 0);
541 if (ret < 0) {
542 ALOGE("%s: Could not set LSM load mixer control", __func__);
543 }
544 return ret;
545}
546#endif
547
Quinn Male2e883752019-03-22 11:28:54 -0700548static int lsm_set_port(st_hw_session_lsm_t *p_lsm_ses)
549{
Quinn Male3d7d9d42019-05-20 13:35:01 -0700550 int status = 0;
sasevsb07d0c52022-06-01 13:03:40 +0530551 st_hw_session_t p_ses;
Quinn Male3d7d9d42019-05-20 13:35:01 -0700552
553 if (p_lsm_ses->common.stdev->lpi_enable &&
554 p_lsm_ses->common.vendor_uuid_info->lab_dam_cfg_payload.token_id) {
555 status = platform_stdev_set_shared_buf_fmt(
556 p_lsm_ses->common.stdev->platform, p_lsm_ses->pcm_id,
557 p_lsm_ses->common.vendor_uuid_info->shared_buf_fmt);
558 if (status)
559 return status;
560 }
sasevsb07d0c52022-06-01 13:03:40 +0530561 p_ses = p_lsm_ses->common;
562#ifdef ENABLE_SVA_MIXER_CTL
563 status = lsm_set_port_mixer_ctl(p_ses.stdev->mixer);
564#else
Quinn Male2e883752019-03-22 11:28:54 -0700565 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_SET_PORT);
sasevsb07d0c52022-06-01 13:03:40 +0530566#endif
Quinn Male2e883752019-03-22 11:28:54 -0700567 if (status)
568 ALOGE("%s: ERROR. SNDRV_LSM_SET_PORT, status=%d", __func__, status);
569 return status;
570}
571
572static bool fill_lsm_poll_enable_params
573(
574 struct st_vendor_info *v_info,
575 st_lsm_poll_enable_t *poll_enable,
576 lsm_param_info_t *poll_en_params,
577 struct st_module_param_info *mparams,
578 uint16_t stage_idx
579)
580{
581 poll_enable->poll_en = v_info->profile_type == ST_PROFILE_TYPE_NONE;
582
583 poll_en_params->param_size = sizeof(*poll_enable);
584 poll_en_params->param_data = (unsigned char *)poll_enable;
585 lsm_fill_param_info(LSM_POLLING_ENABLE, poll_en_params,
586 &mparams[POLLING_ENABLE], stage_idx);
587 return true;
588}
589#else
590static int lsm_set_port(st_hw_session_lsm_t *p_lsm_ses __unused)
591{
592 return 0;
593}
594
595static bool fill_lsm_poll_enable_params
596(
597 struct st_vendor_info *v_info __unused,
598 st_lsm_poll_enable_t *poll_enable __unused,
599 lsm_param_info_t *poll_en_params __unused,
600 struct st_module_param_info *mparams __unused,
601 uint16_t stage_idx __unused
602)
603{
604 return false;
605}
606#endif
607
608#if (SNDRV_LSM_VERSION >= SNDRV_PROTOCOL_VERSION(0, 3, 0))
sasevsb07d0c52022-06-01 13:03:40 +0530609
610#ifdef ENABLE_SVA_MIXER_CTL
611int lsm_set_input_hw_params_mixer_ctl(struct mixer * st_mixer, struct snd_lsm_input_hw_params *params)
612{
613 int ret = 0;
614 struct mixer_ctl *ctl = NULL;
615 const char *mixer_ctl_name = "LSM INPUT_HW_PARAMS SET";
616
617 ctl = mixer_get_ctl_by_name(st_mixer, mixer_ctl_name);
618 if (!ctl) {
619 ALOGE("%s: Could not get ctl for mixer cmd - %s",
620 __func__, mixer_ctl_name);
621 }
622 ret = mixer_ctl_set_array(ctl, params, sizeof(struct snd_lsm_input_hw_params));
623 if (ret < 0) {
624 ALOGE("%s: Could not set input hw params control", __func__);
625 }
626 return ret;
627}
628#endif
629
Quinn Male2e883752019-03-22 11:28:54 -0700630static int send_lsm_input_hw_params(st_hw_session_t *p_ses)
631{
632 struct st_vendor_info *v_info = p_ses->vendor_uuid_info;
633 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t*)p_ses;
634 struct snd_lsm_input_hw_params params;
635 int status = 0;
636
637 params.sample_rate = v_info->sample_rate;
638 params.bit_width = pcm_format_to_bits(v_info->format);
Quinn Male3d7d9d42019-05-20 13:35:01 -0700639 if (platform_get_lpi_mode(p_ses->stdev->platform))
Quinn Male8b2cb792020-07-13 14:41:32 -0700640 params.num_channels = p_lsm_ses->lsm_usecase.in_channels_lpi;
Quinn Male3d7d9d42019-05-20 13:35:01 -0700641 else
Quinn Male8b2cb792020-07-13 14:41:32 -0700642 params.num_channels = p_lsm_ses->lsm_usecase.in_channels;
Quinn Male2e883752019-03-22 11:28:54 -0700643
644 ALOGV("%s: set SNDRV_LSM_SET_INPUT_HW_PARAMS sr=%d bw=%d ch=%d ", __func__,
645 params.sample_rate, params.bit_width, params.num_channels);
646
sasevsb07d0c52022-06-01 13:03:40 +0530647#ifdef ENABLE_SVA_MIXER_CTL
648 status = lsm_set_input_hw_params_mixer_ctl(p_ses->stdev->mixer, &params);
649#else
Quinn Male2e883752019-03-22 11:28:54 -0700650 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_SET_INPUT_HW_PARAMS,
651 &params);
sasevsb07d0c52022-06-01 13:03:40 +0530652#endif
Quinn Male2e883752019-03-22 11:28:54 -0700653 if (status) {
654 ALOGE("%s: SNDRV_LSM_SET_INPUT_HW_PARAMS failed, status [%d] - %s",
655 __func__, status, strerror(errno));
656 }
657 return status;
658}
659#else
660#define send_lsm_input_hw_params(a) (0)
661#endif
662
663static void fill_set_params_payload(struct lsm_setparam_payload *custom_conf_setparam,
664 uint32_t data_payload_size, uint32_t data_payload_addr_lsw,
665 uint32_t data_payload_addr_msw, uint32_t mem_map_handle)
666{
667 custom_conf_setparam->data_payload_size = data_payload_size;
668 custom_conf_setparam->data_payload_addr_lsw = data_payload_addr_lsw;
669 custom_conf_setparam->data_payload_addr_msw = data_payload_addr_msw;
670 custom_conf_setparam->mem_map_handle = mem_map_handle;
671}
672
673#ifdef LSM_DET_EVENT_TYPE_GENERIC
674static bool fill_lsm_det_event_type_params
675(
676 st_lsm_det_event_type_t *det_event_type,
677 lsm_param_info_t *det_event_type_params,
678 struct st_module_param_info *mparams,
Quinn Male58749452020-03-26 17:14:56 -0700679 uint16_t stage_idx,
Tahir Dawson016b9f92021-05-28 13:49:09 -0400680 st_module_type_t version,
681 st_hw_session_lsm_t *p_lsm_ses
Quinn Male2e883752019-03-22 11:28:54 -0700682)
683{
684 /* fill event type params */
685 det_event_type->event_type = LSM_DET_EVENT_TYPE_GENERIC;
686 /* request for confidence level and timestamp */
Quinn Male58749452020-03-26 17:14:56 -0700687 if (version == ST_MODULE_TYPE_PDK5)
688 det_event_type->mode = DET_EVENT_MULTI_MODEL_RESULT_INFO_BIT;
689 else
690 det_event_type->mode =
691 DET_EVENT_CONFIDENCE_LEVELS_BIT | DET_EVENT_KEYWORD_INDEX_BIT |
692 DET_EVENT_TIMESTAMP_INFO_BIT;
Quinn Male2e883752019-03-22 11:28:54 -0700693
Tahir Dawson016b9f92021-05-28 13:49:09 -0400694 if ((version != ST_MODULE_TYPE_PDK5) &&
695 (platform_is_best_channel_index_supported(p_lsm_ses->common.stdev->platform)))
696 det_event_type->mode |= DET_EVENT_CHANNEL_INDEX_INFO_BIT;
697
Quinn Male2e883752019-03-22 11:28:54 -0700698 det_event_type_params->param_size = sizeof(*det_event_type);
699 det_event_type_params->param_data = (unsigned char *)det_event_type;
700 lsm_fill_param_info(LSM_DET_EVENT_TYPE, det_event_type_params,
701 &mparams[DET_EVENT_TYPE], stage_idx);
702 return true;
703}
704#else
705static bool fill_lsm_det_event_type_params
706(
707 st_lsm_det_event_type_t *det_event_type __unused,
708 lsm_param_info_t *det_event_type_params __unused,
709 struct st_module_param_info *mparams __unused,
Quinn Male58749452020-03-26 17:14:56 -0700710 uint16_t stage_idx __unused,
711 st_module_type_t version __unused
Quinn Male2e883752019-03-22 11:28:54 -0700712)
713{
714 return false;
715}
716#endif
717
718static st_profile_type_t get_profile_type(st_hw_session_t *p_ses)
719{
720 st_profile_type_t profile_type;
721
Zhou Songa2828582019-11-29 18:26:10 +0800722 profile_type = (p_ses->vendor_uuid_info && !p_ses->lpi_enable) ?
Quinn Male2e883752019-03-22 11:28:54 -0700723 p_ses->vendor_uuid_info->profile_type : ST_PROFILE_TYPE_NONE;
724 return profile_type;
725}
726
Quinn Male2e883752019-03-22 11:28:54 -0700727static void ape_enable_use_case(bool enable, st_hw_session_t *p_ses)
728{
729 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
730 st_profile_type_t profile_type = get_profile_type(p_ses);
731 char use_case[USECASE_STRING_SIZE];
Zhou Song859c81e2021-03-04 00:30:00 +0800732 audio_devices_t capture_device = 0;
733 st_device_t st_device = 0;
Quinn Male2e883752019-03-22 11:28:54 -0700734
735 if (enable) {
736 strlcpy(use_case,
737 p_ses->stdev->ape_pcm_use_cases[p_ses->use_case_idx].use_case,
738 USECASE_STRING_SIZE);
739 platform_stdev_check_and_append_usecase(p_ses->stdev->platform,
Quinn Male1c764fd2019-10-18 13:29:40 -0700740 use_case);
Quinn Male2e883752019-03-22 11:28:54 -0700741 ALOGD("%s: enable use case = %s", __func__, use_case);
Zhou Song859c81e2021-03-04 00:30:00 +0800742 capture_device = platform_stdev_get_capture_device(p_ses->stdev->platform);
743 st_device = platform_stdev_get_device_for_cal(p_ses->stdev->platform,
744 p_ses->vendor_uuid_info, capture_device, p_ses->exec_mode);
Quinn Male2e883752019-03-22 11:28:54 -0700745 platform_stdev_send_stream_app_type_cfg(p_ses->stdev->platform,
Zhou Song859c81e2021-03-04 00:30:00 +0800746 p_lsm_ses->pcm_id, st_device,
Quinn Male2e883752019-03-22 11:28:54 -0700747 p_ses->exec_mode, profile_type);
748
749 platform_stdev_send_ec_ref_cfg(p_ses->stdev->platform, profile_type, true);
750
751
752 ATRACE_BEGIN("sthal:lsm: audio_route_apply_and_update_path");
753 audio_route_apply_and_update_path(p_ses->stdev->audio_route, use_case);
754 ATRACE_END();
755 if (p_lsm_ses->use_case)
756 free(p_lsm_ses->use_case);
757
758 p_lsm_ses->use_case = strdup(use_case);
759 } else {
760 if (!p_lsm_ses->use_case) {
761 ALOGE("%s: Invalid sound trigger usecase control", __func__);
762 return;
763 }
764
765 ALOGD("%s: disable use case = %s", __func__, p_lsm_ses->use_case);
766 ATRACE_BEGIN("sthal:lsm: audio_route_reset_and_update_path");
767 audio_route_reset_and_update_path(p_ses->stdev->audio_route, p_lsm_ses->use_case);
768 ATRACE_END();
769
770 platform_stdev_send_ec_ref_cfg(p_ses->stdev->platform, profile_type, false);
771 free(p_lsm_ses->use_case);
772 p_lsm_ses->use_case = NULL;
773 }
774}
775
776static int ape_enable_port_control(bool enable, st_hw_session_t *p_ses)
777{
778 int ret = 0;
779 char port_ctrl[USECASE_STRING_SIZE] = {0};
Quinn Male2e883752019-03-22 11:28:54 -0700780 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
781
782 if (enable) {
783 strlcpy(port_ctrl,
784 p_ses->stdev->ape_pcm_use_cases[p_ses->use_case_idx].use_case,
785 USECASE_STRING_SIZE);
786 platform_stdev_check_and_append_usecase(p_ses->stdev->platform,
Quinn Male1c764fd2019-10-18 13:29:40 -0700787 port_ctrl);
Quinn Male2e883752019-03-22 11:28:54 -0700788 strlcat(port_ctrl, " port", USECASE_STRING_SIZE);
789
790 ALOGV("%s: enable = %s", __func__, port_ctrl);
791 ret = audio_route_apply_and_update_path(p_ses->stdev->audio_route, port_ctrl);
792 if (!ret) {
793 if (p_lsm_ses->port_ctrl)
794 free(p_lsm_ses->port_ctrl);
795 p_lsm_ses->port_ctrl = strdup(port_ctrl);
796 }
797 } else {
798 if (!p_lsm_ses->port_ctrl) {
799 ALOGW("%s: Invalid sound trigger port control", __func__);
800 ret = -EINVAL;
801 } else {
802 ALOGV("%s: disable = %s", __func__, p_lsm_ses->port_ctrl);
803 /*
804 * Do not send reset controls as driver is not maintaining
805 * state per session since current implementation limits port
806 * settings to be shared globaly and cannot vary per session.
807 * After first session resets port value as part of its disable
808 * sequence, driver is missing info if the next session to be
809 * disabled was using adm/non-adm path.
810 * Port update if applicable would be done as part of enable
811 * sequence of any one of the sessions.
812 */
813 free(p_lsm_ses->port_ctrl);
814 p_lsm_ses->port_ctrl = NULL;
815 }
816 }
817
818 return ret;
819}
820
821static int read_pcm_data(st_hw_session_lsm_t *p_ses,
822 unsigned char *buf,
823 unsigned int bytes)
824{
825 unsigned int read_bytes = 0, move_bytes = 0, delay_bytes = 0;
826 unsigned int requested_bytes = 0;
827 struct timespec tspec;
828 int ret = 0;
829
830 pthread_mutex_lock(&p_ses->lock);
831 ALOGVV("%s: bytes=%d, unread_bytes=%d", __func__, bytes,
832 p_ses->unread_bytes);
833
834 if (p_ses->move_client_ptr) {
835 /*
836 * This logic is needed if LAB was enabled due to second stage being enabled,
837 * but the client did not request LAB. The client read pointer will be shifted
838 * to the keyword end index in this usecase.
839 */
Quinn Male58749452020-03-26 17:14:56 -0700840
841 if (p_ses->common.enable_second_stage &&
842 !p_ses->common.max_hist_buf)
843 delay_bytes = p_ses->common.kw_end_idx;
844 else
845 delay_bytes = convert_ms_to_bytes(
846 (p_ses->common.max_preroll - p_ses->common.detected_preroll),
847 &p_ses->common.config);
848
Quinn Male2e883752019-03-22 11:28:54 -0700849 move_bytes = MIN(delay_bytes, p_ses->unread_bytes);
850 ALOGD("%s: Moving client ptr by %d bytes", __func__, move_bytes);
851 st_buffer_flush(p_ses->common.buffer, move_bytes);
852 p_ses->unread_bytes -= move_bytes;
853 p_ses->move_client_ptr = false;
854 }
855
856 requested_bytes = bytes;
857 while (!p_ses->exit_lab_processing && (bytes > 0)) {
858 if (!p_ses->unread_bytes) {
859 ALOGVV("%s: waiting on cond, bytes=%d", __func__, bytes);
860 /* Time out to unblock read thread in case if write thread is
861 stuck filling the buffers */
Quinn Malee90f4722019-06-14 15:01:15 -0700862 GET_WAIT_TIMESPEC(tspec, convert_bytes_to_ms(
863 (p_ses->lab_drv_buf_size * 4), &p_ses->common.config) *
864 NSECS_PER_MSEC);
Quinn Male2e883752019-03-22 11:28:54 -0700865 ret = pthread_cond_timedwait(&p_ses->cond, &p_ses->lock, &tspec);
866 ALOGVV("%s: done waiting on cond", __func__);
867 if (ret) {
868 ALOGE("%s: ERROR. read wait timed out, ret %d", __func__, ret);
869 p_ses->exit_lab_processing = true;
870 ret = -EIO;
871 goto exit;
872 }
873 if (p_ses->exit_lab_processing) {
874 ALOGVV("%s: buffering stopped while waiting on cond, exiting",
875 __func__);
876 ret = -EIO;
877 goto exit;
878 }
879 }
880 read_bytes = MIN(bytes, p_ses->unread_bytes);
881
882 ret = st_buffer_read(p_ses->common.buffer, buf, read_bytes,
883 NULL, true);
884 if (ret) {
885 ALOGE("%s: st_buffer_read failed, status %d", __func__, ret);
886 goto exit;
887 }
888
889 pthread_cond_signal(&p_ses->cond);
890 p_ses->unread_bytes -= read_bytes;
891 bytes -= read_bytes;
892 buf += read_bytes;
893 }
894
895exit:
896 pthread_mutex_unlock(&p_ses->lock);
897 return 0;
898}
899
Quinn Male2e883752019-03-22 11:28:54 -0700900static int write_pcm_data_ape(st_hw_session_lsm_t *p_lsm_ses,
901 unsigned char *buf,
902 unsigned int bytes)
903{
904 int status = 0;
905 struct listnode *node = NULL, *tmp_node = NULL;
906 st_arm_second_stage_t *st_sec_stage = NULL;
907
908 status = st_buffer_write(p_lsm_ses->common.buffer, buf, bytes);
909 if (status) {
910 p_lsm_ses->exit_lab_processing = true;
911 if (p_lsm_ses->common.enable_second_stage) {
912 list_for_each_safe(node, tmp_node, p_lsm_ses->common.second_stage_list) {
913 st_sec_stage = node_to_item(node, st_arm_second_stage_t, list_node);
914 pthread_mutex_lock(&st_sec_stage->ss_session->lock);
915 ALOGW("%s: Exit 2nd stage processing due to buf overflow",
916 __func__);
917 st_sec_stage->ss_session->exit_buffering = true;
918 pthread_cond_signal(&st_sec_stage->ss_session->cond);
919 pthread_mutex_unlock(&st_sec_stage->ss_session->lock);
920 }
921 }
922 goto exit;
923 }
924 p_lsm_ses->unread_bytes += bytes;
925 p_lsm_ses->bytes_written += bytes;
926
927 if (p_lsm_ses->common.enable_second_stage) {
928 list_for_each_safe(node, tmp_node, p_lsm_ses->common.second_stage_list) {
929 st_sec_stage = node_to_item(node, st_arm_second_stage_t, list_node);
930
931 /*
932 * When the current written frame passes the number of bytes indicated
933 * in buf_start, give the second stage session its read pointer.
934 */
935 pthread_mutex_lock(&st_sec_stage->ss_session->lock);
936 if ((p_lsm_ses->bytes_written >= st_sec_stage->ss_session->buf_start) &&
937 !st_sec_stage->ss_session->start_processing) {
938 st_sec_stage->ss_session->hw_rd_ptr =
939 st_buffer_get_wr_ptr(p_lsm_ses->common.buffer);
940 st_sec_stage->ss_session->hw_rd_ptr -= bytes;
941 st_sec_stage->ss_session->start_processing = true;
942 }
943
944 if (st_sec_stage->ss_session->start_processing) {
945 st_sec_stage->ss_session->unread_bytes += bytes;
946 pthread_cond_signal(&st_sec_stage->ss_session->cond);
947 }
948 pthread_mutex_unlock(&st_sec_stage->ss_session->lock);
949 }
950 }
951
952exit:
953 ALOGVV("%s: about to signal condition", __func__);
954 pthread_cond_signal(&p_lsm_ses->cond);
955 return status;
956}
957
Quinn Male2e883752019-03-22 11:28:54 -0700958static void adjust_ss_buff_end(st_hw_session_t *p_ses,
959 uint32_t cnn_append_bytes, uint32_t vop_append_bytes)
960{
961 st_hw_session_lsm_t *p_hw_ses = (st_hw_session_lsm_t *)p_ses;
962 struct listnode *node = NULL, *tmp_node = NULL;
963 st_arm_second_stage_t *st_sec_stage = NULL;
964
965 list_for_each_safe(node, tmp_node, p_ses->second_stage_list) {
966 st_sec_stage = node_to_item(node, st_arm_second_stage_t, list_node);
967
968 pthread_mutex_lock(&st_sec_stage->ss_session->lock);
969 if ((st_sec_stage->ss_info->sm_detection_type ==
970 ST_SM_TYPE_KEYWORD_DETECTION) &&
971 ((p_hw_ses->bytes_written + cnn_append_bytes) <
972 st_sec_stage->ss_session->buf_end)) {
973 ALOGV("%s: Adjusting CNN buf_end from %d to %d bytes", __func__,
974 st_sec_stage->ss_session->buf_end,
975 p_hw_ses->bytes_written + cnn_append_bytes);
976 st_sec_stage->ss_session->buf_end = p_hw_ses->bytes_written +
977 cnn_append_bytes;
978 } else if ((st_sec_stage->ss_info->sm_detection_type ==
979 ST_SM_TYPE_USER_VERIFICATION) &&
980 ((p_hw_ses->bytes_written + vop_append_bytes) <
981 st_sec_stage->ss_session->buff_sz)) {
982 ALOGV("%s: Adjusting VOP buff_sz from %d to %d bytes", __func__,
983 st_sec_stage->ss_session->buff_sz,
984 (p_hw_ses->bytes_written + vop_append_bytes));
985 st_sec_stage->ss_session->buff_sz =
986 (p_hw_ses->bytes_written + vop_append_bytes);
987 }
988 pthread_mutex_unlock(&st_sec_stage->ss_session->lock);
989 }
990}
991
Quinn Male48490df2020-03-25 10:25:42 -0700992static void *buffer_thread_loop(void *context)
Quinn Male2e883752019-03-22 11:28:54 -0700993{
Quinn Male48490df2020-03-25 10:25:42 -0700994 st_hw_session_lsm_t *p_lsm_ses =
995 (st_hw_session_lsm_t *)context;
Quinn Male2e883752019-03-22 11:28:54 -0700996 int status = 0;
997 struct listnode *node = NULL, *tmp_node = NULL;
998 st_arm_second_stage_t *st_sec_stage = NULL;
Zhou Songebe8a932020-02-10 12:18:31 +0800999 unsigned int cnn_prepend_bytes = 0, vop_prepend_bytes = 0;
1000 unsigned int cnn_append_bytes = 0, vop_append_bytes = 0;
Quinn Male2e883752019-03-22 11:28:54 -07001001 unsigned int kw_duration_bytes = 0;
Quinn Maled0814de2019-05-29 17:33:22 -07001002 bool real_time_check = true;
Quinn Male2e883752019-03-22 11:28:54 -07001003 uint64_t frame_receive_time = 0, frame_send_time = 0;
Quinn Maled0814de2019-05-29 17:33:22 -07001004 uint64_t frame_read_time = 0, buffering_start_time = 0;
Harshal Ahire081894b2020-05-22 03:57:39 +05301005 uint64_t ss_buf_time = 0;
Quinn Male48490df2020-03-25 10:25:42 -07001006 st_hw_sess_event_t hw_sess_event = {0};
Quinn Male2e883752019-03-22 11:28:54 -07001007
Quinn Male48490df2020-03-25 10:25:42 -07001008 if (p_lsm_ses == NULL) {
1009 ALOGE("%s: input is NULL, exiting", __func__);
1010 return NULL;
Quinn Maleaba13db2019-07-11 15:52:14 -07001011 }
Quinn Male2e883752019-03-22 11:28:54 -07001012
1013 pthread_mutex_lock(&p_lsm_ses->lock);
Quinn Male48490df2020-03-25 10:25:42 -07001014 while (!p_lsm_ses->exit_buffer_thread) {
1015 ALOGV("%s: waiting to start buffering", __func__);
1016 pthread_cond_wait(&p_lsm_ses->cond, &p_lsm_ses->lock);
1017 ALOGV("%s: done waiting to start buffering, exit = %d", __func__,
1018 p_lsm_ses->exit_buffer_thread);
1019 if (p_lsm_ses->exit_buffer_thread) {
1020 pthread_mutex_unlock(&p_lsm_ses->lock);
1021 return NULL;
Quinn Male2e883752019-03-22 11:28:54 -07001022 }
1023
Quinn Male48490df2020-03-25 10:25:42 -07001024 ST_DBG_DECLARE(FILE *fptr_drv = NULL; static int file_cnt = 0);
Quinn Maleaba13db2019-07-11 15:52:14 -07001025 if (p_lsm_ses->common.stdev->enable_debug_dumps) {
Quinn Male48490df2020-03-25 10:25:42 -07001026 ST_DBG_FILE_OPEN_WR(fptr_drv, ST_DEBUG_DUMP_LOCATION,
Quinn Male201b59d2020-08-27 16:53:51 -07001027 "st_lab_drv_data_ape", "pcm", file_cnt);
1028 ALOGD("%s: Buffer data from DSP stored in: st_lab_drv_data_ape_%d.bin",
1029 __func__, file_cnt);
1030 file_cnt++;
Quinn Maleaba13db2019-07-11 15:52:14 -07001031 }
Quinn Male2e883752019-03-22 11:28:54 -07001032
Quinn Male48490df2020-03-25 10:25:42 -07001033 ATRACE_BEGIN("sthal:lsm: buffer_thread_loop");
1034
1035 status = 0;
1036 real_time_check = true;
1037 p_lsm_ses->unread_bytes = 0;
1038 p_lsm_ses->bytes_written = 0;
1039
1040 st_buffer_reset(p_lsm_ses->common.buffer);
1041
1042 if (p_lsm_ses->common.enable_second_stage) {
Quinn Male58749452020-03-26 17:14:56 -07001043 if (p_lsm_ses->common.max_hist_buf) {
Quinn Male48490df2020-03-25 10:25:42 -07001044 kw_duration_bytes =
1045 convert_ms_to_bytes(
Quinn Male58749452020-03-26 17:14:56 -07001046 p_lsm_ses->common.max_hist_buf,
Quinn Male48490df2020-03-25 10:25:42 -07001047 &p_lsm_ses->common.config);
1048 } else {
1049 kw_duration_bytes =
1050 convert_ms_to_bytes(
1051 p_lsm_ses->common.vendor_uuid_info->kw_duration,
1052 &p_lsm_ses->common.config);
1053 }
1054
1055 list_for_each_safe(node, tmp_node,
1056 p_lsm_ses->common.second_stage_list) {
1057 st_sec_stage = node_to_item(node, st_arm_second_stage_t,
1058 list_node);
1059 /*
1060 * At the start of buffering, initialize the variables needed
1061 * by the second stage sessions.
1062 */
1063 pthread_mutex_lock(&st_sec_stage->ss_session->lock);
1064 /*
1065 * In the generic detection event usecase, the start of the
1066 * buffer sent to 2nd stage is determined by the 1st stage
1067 * keyword start index. This index can have some error, so the
1068 * start of the buffer is moved forward to ensure there are no
1069 * resulting missed detections. Similarly, error tolerance is
1070 * added to the end of the buffer for generic and non generic
1071 * detection event usecases.
1072 */
1073 if (st_sec_stage->ss_info->sm_detection_type ==
1074 ST_SM_TYPE_KEYWORD_DETECTION) {
1075 cnn_prepend_bytes =
1076 convert_ms_to_bytes(
1077 p_lsm_ses->common.vendor_uuid_info->kw_start_tolerance,
1078 &p_lsm_ses->common.config);
1079
1080 if (p_lsm_ses->common.kw_start_idx > cnn_prepend_bytes) {
1081 st_sec_stage->ss_session->buf_start =
1082 p_lsm_ses->common.kw_start_idx - cnn_prepend_bytes;
1083 } else {
1084 st_sec_stage->ss_session->buf_start = 0;
1085 }
1086
1087 cnn_append_bytes =
1088 convert_ms_to_bytes(
1089 (p_lsm_ses->common.vendor_uuid_info->kw_end_tolerance +
1090 st_sec_stage->ss_info->data_after_kw_end),
1091 &p_lsm_ses->common.config);
1092
1093 if (p_lsm_ses->common.kw_end_idx < kw_duration_bytes) {
1094 st_sec_stage->ss_session->buf_end =
1095 p_lsm_ses->common.kw_end_idx + cnn_append_bytes;
1096 } else {
1097 st_sec_stage->ss_session->buf_end = kw_duration_bytes +
1098 cnn_append_bytes;
1099 }
1100 /*
1101 * The first second-stage keyword buffer frame needs to
1102 * contain ((kwd_start_idx - kwd_start_tolerance) -
1103 * kwd_end_idx) from the first stage keyword.
1104 */
1105 st_sec_stage->ss_session->buff_sz =
1106 (p_lsm_ses->common.kw_end_idx -
1107 st_sec_stage->ss_session->buf_start);
Harshal Ahire081894b2020-05-22 03:57:39 +05301108
1109 /*
1110 * As per requirement in PDK, input buffer size for
1111 * second stage should be in multiple of 10 ms.
1112 */
1113 ss_buf_time = convert_bytes_to_ms(st_sec_stage->ss_session->buff_sz,
1114 &p_lsm_ses->common.config);
1115
1116 if (ss_buf_time % 10) {
1117 ss_buf_time -= (ss_buf_time % 10);
1118 st_sec_stage->ss_session->buff_sz = convert_ms_to_bytes(ss_buf_time,
1119 &p_lsm_ses->common.config);
1120 }
1121
Quinn Male48490df2020-03-25 10:25:42 -07001122 st_sec_stage->ss_session->lab_buf_sz =
1123 p_lsm_ses->lab_drv_buf_size;
1124 st_sec_stage->ss_session->det_status =
1125 KEYWORD_DETECTION_PENDING;
1126 } else if (st_sec_stage->ss_info->sm_detection_type ==
1127 ST_SM_TYPE_USER_VERIFICATION) {
1128 vop_prepend_bytes =
1129 convert_ms_to_bytes(
1130 st_sec_stage->ss_info->data_before_kw_start,
1131 &p_lsm_ses->common.config);
1132
1133 if (p_lsm_ses->common.kw_start_idx > vop_prepend_bytes) {
1134 st_sec_stage->ss_session->buf_start =
1135 p_lsm_ses->common.kw_start_idx - vop_prepend_bytes;
1136 } else {
1137 st_sec_stage->ss_session->buf_start = 0;
1138 }
1139
1140 vop_append_bytes =
1141 convert_ms_to_bytes(
1142 p_lsm_ses->common.vendor_uuid_info->kw_end_tolerance,
1143 &p_lsm_ses->common.config);
1144
1145 if ((p_lsm_ses->common.kw_end_idx + vop_append_bytes) <
1146 kw_duration_bytes) {
1147 st_sec_stage->ss_session->buf_end =
1148 p_lsm_ses->common.kw_end_idx + vop_append_bytes;
1149 } else {
1150 st_sec_stage->ss_session->buf_end = kw_duration_bytes;
1151 }
1152
1153 st_sec_stage->ss_session->buff_sz =
1154 (st_sec_stage->ss_session->buf_end -
1155 st_sec_stage->ss_session->buf_start);
1156 st_sec_stage->ss_session->det_status =
1157 USER_VERIFICATION_PENDING;
1158 }
1159 st_sec_stage->ss_session->unread_bytes = 0;
1160 st_sec_stage->ss_session->exit_buffering = false;
1161 st_sec_stage->ss_session->bytes_processed = 0;
1162 st_sec_stage->ss_session->start_processing = false;
1163 st_sec_stage->ss_session->confidence_score = 0;
1164 pthread_mutex_unlock(&st_sec_stage->ss_session->lock);
1165 }
1166
Quinn Male58749452020-03-26 17:14:56 -07001167 if ((p_lsm_ses->common.enable_second_stage &&
1168 !p_lsm_ses->common.max_hist_buf) ||
1169 (p_lsm_ses->common.detected_preroll <
1170 p_lsm_ses->common.max_preroll))
Quinn Male48490df2020-03-25 10:25:42 -07001171 p_lsm_ses->move_client_ptr = true;
1172 else
1173 p_lsm_ses->move_client_ptr = false;
1174 }
1175
1176 buffering_start_time = get_current_time_ns();
1177
1178 while (!p_lsm_ses->exit_lab_processing) {
1179 ALOGVV("%s: pcm_read reading bytes=%d", __func__,
1180 p_lsm_ses->lab_drv_buf_size);
1181 pthread_mutex_unlock(&p_lsm_ses->lock);
1182 frame_send_time = get_current_time_ns();
1183 ATRACE_ASYNC_BEGIN("sthal:lsm:ape: pcm_read",
1184 p_lsm_ses->common.sm_handle);
1185 status = pcm_read(p_lsm_ses->pcm, p_lsm_ses->lab_drv_buf,
1186 p_lsm_ses->lab_drv_buf_size);
1187 ATRACE_ASYNC_END("sthal:lsm:ape: pcm_read",
1188 p_lsm_ses->common.sm_handle);
1189 pthread_mutex_lock(&p_lsm_ses->lock);
1190 frame_receive_time = get_current_time_ns();
1191
1192 ALOGVV("%s: pcm_read done", __func__);
1193 if (p_lsm_ses->common.stdev->enable_debug_dumps) {
1194 ST_DBG_FILE_WRITE(fptr_drv, p_lsm_ses->lab_drv_buf,
1195 p_lsm_ses->lab_drv_buf_size);
1196 }
1197
1198 if (status) {
1199 ALOGE("%s: pcm read failed status %d - %s", __func__, status,
1200 pcm_get_error(p_lsm_ses->pcm));
1201 pcm_stop(p_lsm_ses->pcm);
1202 pcm_start(p_lsm_ses->pcm);
1203 break;
1204 }
1205
1206 status = write_pcm_data_ape(p_lsm_ses, p_lsm_ses->lab_drv_buf,
1207 p_lsm_ses->lab_drv_buf_size);
1208 if (status) {
1209 ALOGE("%s: Failed to write to circ buff, status %d", __func__,
1210 status);
1211 break;
1212 }
1213 frame_read_time = frame_receive_time - frame_send_time;
1214 if (real_time_check &&
1215 (frame_read_time > APE_MAX_LAB_FTRT_FRAME_RD_TIME_NS)) {
1216 uint32_t ftrt_bytes_written_ms =
1217 convert_bytes_to_ms(p_lsm_ses->bytes_written -
1218 p_lsm_ses->lab_drv_buf_size, &p_lsm_ses->common.config);
1219
1220 ALOGD("%s: FTRT data transfer: %dms of data received in %llums",
1221 __func__, ftrt_bytes_written_ms, ((frame_send_time -
1222 buffering_start_time) / NSECS_PER_MSEC));
1223
1224 if (p_lsm_ses->common.enable_second_stage &&
1225 !p_lsm_ses->common.is_generic_event) {
1226 ALOGD("%s: First real time frame took %llums", __func__,
1227 (frame_read_time / NSECS_PER_MSEC));
1228 adjust_ss_buff_end(&p_lsm_ses->common, cnn_append_bytes,
1229 vop_append_bytes);
1230 }
1231 real_time_check = false;
1232 }
1233 }
1234 ALOGV("%s: Exited buffering, status=%d", __func__, status);
1235 ape_stop_buffering(&p_lsm_ses->common);
1236 p_lsm_ses->lab_on_detection = false;
1237 p_lsm_ses->lab_processing_active = false;
1238 pthread_cond_broadcast(&p_lsm_ses->cond);
1239 if (p_lsm_ses->common.stdev->enable_debug_dumps)
1240 ST_DBG_FILE_CLOSE(fptr_drv);
1241 ATRACE_END();
1242
Quinn Male2e883752019-03-22 11:28:54 -07001243 if (status) {
Quinn Male48490df2020-03-25 10:25:42 -07001244 hw_sess_event.event_id = ST_HW_SESS_EVENT_BUFFERING_STOPPED;
1245 pthread_mutex_unlock(&p_lsm_ses->lock);
1246 p_lsm_ses->common.callback_to_st_session(&hw_sess_event,
1247 p_lsm_ses->common.cookie);
1248 pthread_mutex_lock(&p_lsm_ses->lock);
Quinn Male2e883752019-03-22 11:28:54 -07001249 }
1250 }
Quinn Male2e883752019-03-22 11:28:54 -07001251 pthread_mutex_unlock(&p_lsm_ses->lock);
Quinn Male48490df2020-03-25 10:25:42 -07001252 return NULL;
Quinn Male2e883752019-03-22 11:28:54 -07001253}
1254
sasevsb07d0c52022-06-01 13:03:40 +05301255#ifdef ENABLE_SVA_MIXER_CTL
1256int lsm_get_det_event_info_control(struct mixer * st_mixer, void *arg)
1257{
1258 struct mixer_ctl *ctl = NULL;
1259 const char *mixer_ctl_name = "LSM DET_EVENT_INFO GET";
1260
1261 struct snd_lsm_event_status *params = (struct snd_lsm_event_status *)arg;
1262
1263 ctl = mixer_get_ctl_by_name(st_mixer, mixer_ctl_name);
1264 if (!ctl) {
1265 ALOGE("%s: Could not get ctl for mixer cmd - %s",
1266 __func__, mixer_ctl_name);
1267 }
1268
1269 if (mixer_ctl_get_array(ctl, params, params->payload_size + sizeof(*params)) < 0) {
1270 ALOGE("%s: Could not get det event info", __func__);
1271 return -EFAULT;
1272 }
1273
1274 return 0;
1275}
1276#endif
Quinn Male48490df2020-03-25 10:25:42 -07001277
Quinn Male2e883752019-03-22 11:28:54 -07001278static void *callback_thread_loop(void *context)
1279{
1280 st_hw_session_lsm_t *p_lsm_ses =
1281 (st_hw_session_lsm_t *)context;
1282 st_lsm_event_status_t *params;
1283 char *st_lsm_event_cmd = NULL;
1284 unsigned int payload_alloc_size = SOUND_TRIGGER_MAX_EVNT_PAYLOAD_SIZE;
1285 int status = 0;
sasevsb07d0c52022-06-01 13:03:40 +05301286 void *params_status = NULL;
Quinn Male2e883752019-03-22 11:28:54 -07001287 int event_status, request;
1288 st_hw_sess_event_t hw_sess_event; /* used to report event to st_session */
1289
sasevsb07d0c52022-06-01 13:03:40 +05301290#ifdef ENABLE_SVA_MIXER_CTL
1291 struct mixer * st_mixer = NULL;
1292 st_mixer = p_lsm_ses->common.stdev->mixer;
1293 int lsm_cdev = 0;
1294 struct st_lsm_cdev_info *cdev_query = NULL;
1295
1296 lsm_cdev = open("/dev/msm_lsm_cdev", O_RDONLY|O_WRONLY);
1297 if (lsm_cdev < 0)
1298 ALOGE("LSM CDEV open failed");
1299
1300 cdev_query = calloc(1, sizeof(*cdev_query));
1301 if (cdev_query == NULL) {
1302 ALOGE("%s: ERROR. insufficient memory for cdev query", __func__);
1303 goto exit;
1304 }
1305#endif
1306
Quinn Male2e883752019-03-22 11:28:54 -07001307 if (p_lsm_ses == NULL) {
1308 ALOGE("%s: ERROR. null context.. exiting", __func__);
1309 return NULL;
1310 }
1311 ALOGD("%s:[%d] Enter", __func__, p_lsm_ses->common.sm_handle);
1312
1313 setpriority(PRIO_PROCESS, 0, ANDROID_PRIORITY_DEFAULT);
1314 prctl(PR_SET_NAME, (unsigned long)"sound trigger callback", 0, 0, 0);
1315
1316 pthread_mutex_lock(&p_lsm_ses->callback_thread_lock);
1317 params = calloc(1, sizeof(*params) + payload_alloc_size);
1318 if (params == NULL) {
1319 ALOGE("%s: ERROR. insufficient memory for payload", __func__);
1320 goto exit;
1321 }
1322
1323 set_lsm_fwk_mode(p_lsm_ses);
1324 update_lsm_event_status_info(p_lsm_ses, &request, &st_lsm_event_cmd);
sasevsb07d0c52022-06-01 13:03:40 +05301325 params_status = (void *)(&(params->status));
Quinn Male2e883752019-03-22 11:28:54 -07001326
1327 while (!p_lsm_ses->exit_callback_thread) {
1328 params->payload_size = payload_alloc_size;
1329 ALOGI("%s:[%d] Waiting for %s",
1330 __func__, p_lsm_ses->common.sm_handle, st_lsm_event_cmd);
1331 pthread_mutex_unlock(&p_lsm_ses->callback_thread_lock);
sasevsb07d0c52022-06-01 13:03:40 +05301332#ifdef ENABLE_SVA_MIXER_CTL
1333 cdev_query->fd = p_lsm_ses->pcm_id;
1334 status = ioctl(lsm_cdev, SNDRV_LSM_GENERIC_DET_EVENT, cdev_query);
1335
1336 if (cdev_query->det_status == LSM_VOICE_WAKEUP_STATUS_DETECTED)
1337 status = lsm_get_det_event_info_control(st_mixer, params_status);
1338#else
Quinn Male2e883752019-03-22 11:28:54 -07001339 if (p_lsm_ses->common.is_generic_event)
1340 status = pcm_ioctl(p_lsm_ses->pcm, request, &params->status);
1341 else
1342 status = pcm_ioctl(p_lsm_ses->pcm, request, params);
sasevsb07d0c52022-06-01 13:03:40 +05301343#endif
Quinn Male2e883752019-03-22 11:28:54 -07001344 pthread_mutex_lock(&p_lsm_ses->callback_thread_lock);
1345
1346 ALOGI("%s:[%d] Received %s status=%d",
1347 __func__, p_lsm_ses->common.sm_handle, st_lsm_event_cmd, status);
Quinn Male58749452020-03-26 17:14:56 -07001348
1349 /*
1350 * For Multi SM usecases, other keywords can get detected while
1351 * LAB buffering is active for another keyword. This dual buffering
1352 * is not supported, so the event will be ignored.
1353 */
1354 if (p_lsm_ses->lab_processing_active) {
1355 ALOGI("%s: LAB buffering is active, ignore detection event",
1356 __func__);
1357 continue;
1358 }
1359
Quinn Male2e883752019-03-22 11:28:54 -07001360 if (status < 0) {
1361 if (errno == ENOMEM) {
1362 payload_alloc_size = payload_alloc_size << 1;
1363 params = realloc(params, sizeof(*params) + payload_alloc_size);
1364
1365 if (params == NULL) {
1366 ALOGE("%s: ERROR. Not enough memory for payload",
1367 __func__);
1368 p_lsm_ses->exit_callback_thread = true;
1369 break;
1370 }
1371 continue;
1372 } else {
1373 ALOGE("%s: ERROR. %s failed status %d",
1374 __func__, st_lsm_event_cmd, status);
1375 p_lsm_ses->exit_callback_thread = true;
1376 break;
1377 }
1378 }
1379 if (p_lsm_ses->exit_callback_thread)
1380 break;
1381
1382 ALOGD("%s: params status %d", __func__, params->status);
1383 switch (params->status) {
1384 case LSM_VOICE_WAKEUP_STATUS_RUNNING:
1385 continue;
1386 case LSM_VOICE_WAKEUP_STATUS_DETECTED:
1387 /*
1388 * Currently, DSP does not support the inclusion of detection
1389 * timestamp within the payload. So the timestamp is filled here
1390 * instead.
1391 */
1392 p_lsm_ses->common.first_stage_det_event_time = get_current_time_ns();
1393 /* The duration of this trace log indicates the detection latency. */
1394 ATRACE_ASYNC_BEGIN("sthal: detection success",
1395 p_lsm_ses->common.sm_handle);
1396 ATRACE_ASYNC_BEGIN("sthal: detection reject",
1397 p_lsm_ses->common.sm_handle);
1398 event_status = RECOGNITION_STATUS_SUCCESS;
1399 /*
1400 * note: since now we are dispatching the detected event to the
1401 * state machine there is no need to check if buffering enabled or
1402 * concurrency is active here, it will now be handled by the st_session
1403 * state machine
1404 */
1405 break;
1406
1407 case LSM_VOICE_WAKEUP_STATUS_END_SPEECH:
1408 case LSM_VOICE_WAKEUP_STATUS_REJECTED:
1409 event_status = RECOGNITION_STATUS_FAILURE;
1410 break;
1411 default:
1412 ALOGW("%s: Unknown status %d", __func__, params->status);
1413 continue;
1414 }
1415
1416 /* inform st_sessoin of the event */
1417 hw_sess_event.event_id = ST_HW_SESS_EVENT_DETECTED;
1418 hw_sess_event.payload.detected.timestamp = get_event_timestamp(params);
1419 hw_sess_event.payload.detected.detect_status = event_status;
1420 if (p_lsm_ses->common.is_generic_event &&
1421 p_lsm_ses->common.vendor_uuid_info->is_qcmd_uuid) {
1422 unsigned int payload_offset = sizeof(struct st_param_header) +
1423 GENERIC_DET_EVENT_HEADER_SIZE;
1424 hw_sess_event.payload.detected.detect_payload =
1425 (void*)((unsigned char *)params->payload + payload_offset);
1426 hw_sess_event.payload.detected.payload_size =
1427 params->payload_size - payload_offset;
1428 } else {
1429 hw_sess_event.payload.detected.detect_payload =
1430 (void*)params->payload;
1431 hw_sess_event.payload.detected.payload_size = params->payload_size;
1432 }
1433
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07001434 if (p_lsm_ses->common.lab_enabled)
1435 p_lsm_ses->lab_on_detection = true;
1436
Quinn Maleaba13db2019-07-11 15:52:14 -07001437 if (p_lsm_ses->common.stdev->enable_debug_dumps) {
1438 ST_DBG_DECLARE(FILE *detect_fd = NULL;
1439 static int detect_fd_cnt = 0);
1440 ST_DBG_FILE_OPEN_WR(detect_fd, ST_DEBUG_DUMP_LOCATION,
Quinn Male201b59d2020-08-27 16:53:51 -07001441 "lsm_detection_event", "bin", detect_fd_cnt);
Quinn Maleaba13db2019-07-11 15:52:14 -07001442 ST_DBG_FILE_WRITE(detect_fd,
1443 hw_sess_event.payload.detected.detect_payload,
1444 hw_sess_event.payload.detected.payload_size);
1445 ST_DBG_FILE_CLOSE(detect_fd);
Quinn Male201b59d2020-08-27 16:53:51 -07001446 ALOGD("%s: Detection payload from DSP stored in: lsm_detection_event_%d.bin",
1447 __func__, detect_fd_cnt);
1448 detect_fd_cnt++;
Quinn Maleaba13db2019-07-11 15:52:14 -07001449 }
Quinn Male2e883752019-03-22 11:28:54 -07001450
1451 pthread_mutex_unlock(&p_lsm_ses->callback_thread_lock);
1452 p_lsm_ses->common.callback_to_st_session(&hw_sess_event,
1453 p_lsm_ses->common.cookie);
1454 pthread_mutex_lock(&p_lsm_ses->callback_thread_lock);
1455 }
1456
sasevsb07d0c52022-06-01 13:03:40 +05301457#ifdef ENABLE_SVA_MIXER_CTL
1458 //Before exiting the thread, intimate lut to clear the info.
1459 status = ioctl(lsm_cdev, LSM_LUT_CLEAR_INFO, p_lsm_ses->pcm_id);
1460 free(cdev_query);
1461 close(lsm_cdev);
1462#endif
Quinn Male2e883752019-03-22 11:28:54 -07001463 if (st_lsm_event_cmd)
1464 free(st_lsm_event_cmd);
1465
1466 if (params)
1467 free(params);
1468
1469exit:
1470 pthread_cond_signal(&p_lsm_ses->callback_thread_cond);
1471 pthread_mutex_unlock(&p_lsm_ses->callback_thread_lock);
1472 ALOGD("%s:[%d] Exit", __func__, p_lsm_ses->common.sm_handle);
1473 return NULL;
1474}
1475
1476static int deallocate_lab_buffers_ape(st_hw_session_lsm_t* p_ses)
1477{
1478 ALOGVV("%s:[%d] Enter", __func__, p_ses->common.sm_handle);
1479 st_buffer_deinit(p_ses->common.buffer);
Quinn Male24daf422019-05-29 16:12:55 -07001480 p_ses->common.buffer = NULL;
Quinn Male2e883752019-03-22 11:28:54 -07001481 if (p_ses->lab_drv_buf) {
1482 free(p_ses->lab_drv_buf);
1483 p_ses->lab_drv_buf = NULL;
1484 }
1485 p_ses->lab_buffers_allocated = false;
1486
Quinn Male48490df2020-03-25 10:25:42 -07001487 p_ses->exit_buffer_thread = true;
1488 pthread_mutex_lock(&p_ses->lock);
1489 pthread_cond_signal(&p_ses->cond);
1490 pthread_mutex_unlock(&p_ses->lock);
1491 pthread_join(p_ses->buffer_thread, NULL);
1492
Quinn Male2e883752019-03-22 11:28:54 -07001493 return 0;
1494}
1495
Quinn Male2e883752019-03-22 11:28:54 -07001496static int allocate_lab_buffers_ape(st_hw_session_lsm_t* p_lsm_ses)
1497{
1498 int status = 0, circ_buff_sz = 0;
1499 struct st_vendor_info *v_info = p_lsm_ses->common.vendor_uuid_info;
1500 unsigned int rt_bytes_one_sec;
Quinn Male48490df2020-03-25 10:25:42 -07001501 pthread_attr_t attr;
Quinn Male2e883752019-03-22 11:28:54 -07001502
1503 p_lsm_ses->lab_drv_buf_size = pcm_frames_to_bytes(p_lsm_ses->pcm,
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07001504 p_lsm_ses->common.config.period_size);
1505 p_lsm_ses->lab_drv_buf = (unsigned char *)calloc(1,
1506 p_lsm_ses->lab_drv_buf_size);
Quinn Male2e883752019-03-22 11:28:54 -07001507 if (!p_lsm_ses->lab_drv_buf) {
1508 ALOGE("%s: ERROR. Can not allocate lab buffer size %d", __func__,
1509 p_lsm_ses->lab_drv_buf_size);
1510 status = -ENOMEM;
1511 goto error_exit;
1512 }
1513 ALOGV("%s: Allocated lab buffer period size bytes =%d",
1514 __func__, p_lsm_ses->lab_drv_buf_size);
1515
1516 rt_bytes_one_sec = (p_lsm_ses->common.config.rate *
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07001517 p_lsm_ses->common.config.channels *
1518 (pcm_format_to_bits(p_lsm_ses->common.config.format) >> 3));
Quinn Male2e883752019-03-22 11:28:54 -07001519
Quinn Male58749452020-03-26 17:14:56 -07001520 if ((p_lsm_ses->common.max_hist_buf +
1521 p_lsm_ses->common.max_preroll) > v_info->kw_duration) {
1522 circ_buff_sz = ((p_lsm_ses->common.max_hist_buf +
1523 p_lsm_ses->common.max_preroll +
Quinn Male24daf422019-05-29 16:12:55 -07001524 v_info->client_capture_read_delay) * rt_bytes_one_sec) / 1000;
1525 } else {
1526 circ_buff_sz = ((v_info->kw_duration +
1527 v_info->client_capture_read_delay) * rt_bytes_one_sec) / 1000;
1528 }
Quinn Male2e883752019-03-22 11:28:54 -07001529 p_lsm_ses->common.buffer = st_buffer_init(circ_buff_sz);
1530 if (!p_lsm_ses->common.buffer) {
1531 ALOGE("%s: failed to allocate circ buffer", __func__);
1532 status = -ENOMEM;
1533 goto error_exit;
1534 }
1535
1536 ALOGV("%s: Allocated out buffer size=%d", __func__, circ_buff_sz);
1537 p_lsm_ses->lab_buffers_allocated = true;
1538
Quinn Male48490df2020-03-25 10:25:42 -07001539 p_lsm_ses->exit_buffer_thread = false;
1540 pthread_attr_init(&attr);
1541 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1542 pthread_create(&p_lsm_ses->buffer_thread, &attr,
1543 buffer_thread_loop, p_lsm_ses);
1544
Karan Naidufaf0bff2022-05-18 23:05:15 +05301545 pthread_attr_destroy(&attr);
Quinn Male2e883752019-03-22 11:28:54 -07001546 return status;
1547
1548error_exit:
1549 deallocate_lab_buffers_ape(p_lsm_ses);
1550 return status;
1551}
1552
1553static int sound_trigger_set_device
1554(
1555 st_hw_session_t* p_ses,
1556 bool enable
1557)
1558{
1559 char st_device_name[DEVICE_NAME_MAX_SIZE] = { 0 };
Quinn Maledd105082019-11-07 18:36:02 -08001560 int ref_cnt_idx = 0, ref_cnt = 0, ref_enable_idx = 0;
Quinn Male2e883752019-03-22 11:28:54 -07001561 int status = 0;
1562 st_device_t st_device = 0;
1563 audio_devices_t capture_device = 0;
1564 int app_type = 0;
1565 st_profile_type_t profile_type = 0;
1566 bool is_hwmad_device = false;
1567 struct st_vendor_info *v_info = p_ses->vendor_uuid_info;
1568 bool backend_cfg_change = true;
1569
1570 is_hwmad_device = platform_stdev_is_hwmad_backend(p_ses->stdev->platform,
1571 p_ses->st_device, p_ses->exec_mode);
1572
1573 profile_type = get_profile_type(p_ses);
1574 if (enable) {
1575 status = platform_stdev_check_and_set_codec_backend_cfg(
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07001576 p_ses->stdev->platform, v_info, &backend_cfg_change,
1577 p_ses->stdev->lpi_enable, p_ses->stdev->vad_enable,
Quinn Male58749452020-03-26 17:14:56 -07001578 p_ses->max_preroll);
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07001579
Quinn Male2e883752019-03-22 11:28:54 -07001580 if (status) {
1581 ALOGE("%s: ERROR. codec backend config update failed, status=%d",
1582 __func__, status);
1583 return status;
1584 }
1585
1586 capture_device = platform_stdev_get_capture_device(p_ses->stdev->platform);
1587 st_device = platform_stdev_get_device(p_ses->stdev->platform,
1588 p_ses->vendor_uuid_info, capture_device, p_ses->exec_mode);
1589
1590 if (platform_stdev_get_device_name(p_ses->stdev->platform, p_ses->exec_mode,
1591 st_device, st_device_name) < 0) {
1592 ALOGE("%s: Invalid sound trigger device name returned", __func__);
1593 return -EINVAL;
1594 }
1595
1596 /*
1597 * Send device cal irrespective of ref cnt as driver expects
1598 * this to be sent per instance.
1599 */
1600
1601 pthread_mutex_lock(&p_ses->stdev->ref_cnt_lock);
1602 ref_cnt_idx = (p_ses->exec_mode * ST_DEVICE_MAX) + st_device;
Quinn Maledd105082019-11-07 18:36:02 -08001603 ref_enable_idx = (p_ses->exec_mode * ST_DEVICE_MAX) +
1604 platform_get_lpi_st_device(st_device);
Quinn Male2e883752019-03-22 11:28:54 -07001605 ref_cnt = ++(p_ses->stdev->dev_ref_cnt[ref_cnt_idx]);
1606 app_type = platform_stdev_get_device_app_type(p_ses->stdev->platform,
1607 profile_type);
1608
1609 status = platform_stdev_send_calibration(p_ses->stdev->platform,
1610 capture_device,
1611 p_ses->exec_mode,
1612 p_ses->vendor_uuid_info,
1613 app_type,
1614 false, ST_DEVICE_CAL);
1615
1616 if (!status) {
1617 if (1 == ref_cnt) {
1618 /*
1619 * If no dedicated path, make sure to disable device first and then
1620 * enable with conc enabled to handle below scenario:
1621 * 1. STHAL and AHAL runs concurrently with conc capture enabled
1622 * 2. STHAL session closed then it will not disable device as AHAL
1623 * usecase is going on. Then AHAL disables device when it closes session
1624 * 3. If STHAL is started again then device will not be enabled as stdev
1625 * mixer value in audio route is not reset, so detections won't work
1626 * 4. To fix this call audio reset then enable device
1627 */
Zhou Songd18c6712019-06-10 11:20:10 +08001628 if (!platform_stdev_is_dedicated_sva_path(p_ses->stdev->platform) &&
Quinn Male2e883752019-03-22 11:28:54 -07001629 p_ses->stdev->conc_capture_supported &&
1630 p_ses->stdev->reset_backend &&
1631 !is_hwmad_device) {
1632 ALOGV("%s: conc capture supported, reset device controls (%x) = %s",
Zhou Song826ca042021-02-03 14:33:43 +08001633 __func__, p_ses->st_device, st_device_name);
Quinn Male2e883752019-03-22 11:28:54 -07001634 audio_route_reset_and_update_path(p_ses->stdev->audio_route,
1635 st_device_name);
Quinn Maledd105082019-11-07 18:36:02 -08001636 if (0 < p_ses->stdev->dev_enable_cnt[ref_enable_idx])
1637 --(p_ses->stdev->dev_enable_cnt[ref_enable_idx]);
Quinn Male2e883752019-03-22 11:28:54 -07001638 }
1639
Quinn Maledd105082019-11-07 18:36:02 -08001640 if (0 == p_ses->stdev->dev_enable_cnt[ref_enable_idx]) {
1641 ALOGD("%s: enable device (%x) = %s", __func__, st_device,
1642 st_device_name);
1643 ATRACE_BEGIN("sthal:lsm: audio_route_apply_and_update_path");
1644 audio_route_apply_and_update_path(p_ses->stdev->audio_route,
1645 st_device_name);
1646 ATRACE_END();
1647 update_hw_mad_exec_mode(p_ses->exec_mode, profile_type);
1648 ++(p_ses->stdev->dev_enable_cnt[ref_enable_idx]);
1649 } else {
Quinn Male58749452020-03-26 17:14:56 -07001650 ALOGD("%s: Device already enabled, do not re-enable",
Quinn Maledd105082019-11-07 18:36:02 -08001651 __func__);
1652 }
Quinn Male2e883752019-03-22 11:28:54 -07001653 }
1654 } else {
1655 --(p_ses->stdev->dev_ref_cnt[ref_cnt_idx]);
1656 ALOGE("%s: failed to send calibration %d", __func__, status);
1657 }
1658 pthread_mutex_unlock(&p_ses->stdev->ref_cnt_lock);
1659 p_ses->st_device = st_device;
1660 p_ses->st_device_name = strdup(st_device_name);
1661 } else {
1662 if (!p_ses->st_device_name) {
1663 ALOGE("%s: Invalid sound trigger device name", __func__);
1664 return -EINVAL;
1665 }
1666
1667 ref_cnt_idx = (p_ses->exec_mode * ST_DEVICE_MAX) + p_ses->st_device;
Quinn Maledd105082019-11-07 18:36:02 -08001668 ref_enable_idx = (p_ses->exec_mode * ST_DEVICE_MAX) +
1669 platform_get_lpi_st_device(p_ses->st_device);
Quinn Male2e883752019-03-22 11:28:54 -07001670 pthread_mutex_lock(&p_ses->stdev->ref_cnt_lock);
1671 ref_cnt = p_ses->stdev->dev_ref_cnt[ref_cnt_idx];
1672 if (0 < ref_cnt) {
1673 ref_cnt = --(p_ses->stdev->dev_ref_cnt[ref_cnt_idx]);
1674 } else {
1675 ALOGV("%s: ref_cnt = %d", __func__, ref_cnt);
1676 pthread_mutex_unlock(&p_ses->stdev->ref_cnt_lock);
1677 return status;
1678 }
1679
1680 if (0 == ref_cnt) {
1681 if (p_ses->stdev->reset_backend || is_hwmad_device) {
1682 ALOGD("%s: disable device (%x) = %s", __func__, p_ses->st_device,
1683 p_ses->st_device_name);
1684 ATRACE_BEGIN("sthal:lsm: audio_route_reset_and_update_path");
1685 audio_route_reset_and_update_path(p_ses->stdev->audio_route,
1686 p_ses->st_device_name);
1687 ATRACE_END();
1688 update_hw_mad_exec_mode(ST_EXEC_MODE_NONE, profile_type);
Quinn Maledd105082019-11-07 18:36:02 -08001689 if (0 < p_ses->stdev->dev_enable_cnt[ref_enable_idx])
1690 --(p_ses->stdev->dev_enable_cnt[ref_enable_idx]);
Quinn Male2e883752019-03-22 11:28:54 -07001691 } else {
1692 ALOGD("%s: Non-hwmad device, concurrent capture on, do not disable", __func__);
1693 }
1694 }
1695 pthread_mutex_unlock(&p_ses->stdev->ref_cnt_lock);
1696 free(p_ses->st_device_name);
1697 }
1698 return status;
1699}
1700
Quinn Male58749452020-03-26 17:14:56 -07001701static int set_param_reg_multi_sm(st_hw_session_lsm_t *p_ses, void *sm_data,
1702 unsigned int sm_size, uint32_t model_id)
1703{
1704 st_lsm_reg_sm_header_t sm_header = {0};
1705 unsigned int sm_payload_size =
1706 sizeof(st_lsm_reg_sm_header_t) + sm_size;
1707 uint8_t *sm_payload = NULL;
1708 int status = 0;
1709 lsm_param_info_t param_info = {0};
1710 struct snd_lsm_module_params lsm_params = {0};
1711 struct st_module_param_info *mparams = NULL;
1712
Quinn Male201b59d2020-08-27 16:53:51 -07001713 ALOGD("%s: Reg PDK5 sound model", __func__);
1714
Quinn Male8b2cb792020-07-13 14:41:32 -07001715 mparams = p_ses->lsm_usecase.params;
Quinn Male58749452020-03-26 17:14:56 -07001716 sm_header.model_id = model_id;
1717 sm_header.model_size = sm_size;
1718 sm_payload = calloc(1, sm_payload_size);
1719 if (!sm_payload) {
1720 ALOGE("%s: ERROR. Cannot allocate memory for sm_payload", __func__);
1721 return -ENOMEM;
1722 }
1723 memcpy(sm_payload, (uint8_t *)&sm_header, sizeof(sm_header));
1724 memcpy(sm_payload + sizeof(sm_header), (uint8_t *)sm_data, sm_size);
1725 param_info.param_data = sm_payload;
1726 param_info.param_size = sm_payload_size;
1727#if (SNDRV_LSM_VERSION >= SNDRV_PROTOCOL_VERSION(0, 3, 2))
1728 param_info.model_id = model_id;
1729 lsm_fill_param_info(LSM_REG_MULTI_SND_MODEL, &param_info,
1730 &mparams[LOAD_SOUND_MODEL],
1731 LSM_STAGE_INDEX_FIRST);
1732#endif
1733 lsm_params.params = (unsigned char*)&param_info;
1734 lsm_params.num_params = 1;
1735 lsm_params.data_size = sizeof(lsm_param_info_t);
1736 status = lsm_set_module_params(p_ses, &lsm_params);
1737 if (status) {
1738 ALOGE("%s: ERROR. registering sound model. status %d",
1739 __func__, status);
1740 }
1741
1742 free(sm_payload);
1743 sm_payload = NULL;
1744
1745 return status;
1746}
1747
Quinn Male2e883752019-03-22 11:28:54 -07001748static int ape_reg_sm(st_hw_session_t *p_ses, void *sm_data,
Quinn Male58749452020-03-26 17:14:56 -07001749 unsigned int sm_size, uint32_t model_id)
Quinn Male2e883752019-03-22 11:28:54 -07001750{
1751 int status = 0, param_count = 0, stage_idx = 0;
1752 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t*)p_ses;
1753 struct st_vendor_info *v_info = p_ses->vendor_uuid_info;
Quinn Male2e883752019-03-22 11:28:54 -07001754 struct snd_lsm_session_data ses_data;
1755 struct snd_lsm_module_params lsm_params;
1756 lsm_param_info_t param_info[LSM_MAX_STAGES_PER_SESSION];
Quinn Male58749452020-03-26 17:14:56 -07001757 st_lsm_det_event_type_t det_event_type = {0};
Quinn Male2e883752019-03-22 11:28:54 -07001758 pthread_attr_t attr;
1759 struct listnode *node = NULL;
1760 st_lsm_ss_config_t *ss_cfg = NULL;
1761 struct st_module_param_info *mparams = NULL;
1762 audio_devices_t capture_device = 0;
1763
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07001764 ALOGD("%s:[%d] Enter", __func__, p_ses->sm_handle);
Quinn Male2e883752019-03-22 11:28:54 -07001765
Quinn Male58749452020-03-26 17:14:56 -07001766 memset((uint8_t *)param_info, 0, sizeof(lsm_param_info_t) *
1767 LSM_MAX_STAGES_PER_SESSION);
Quinn Male2e883752019-03-22 11:28:54 -07001768
Quinn Male8b2cb792020-07-13 14:41:32 -07001769 status = platform_get_lsm_usecase(p_ses->stdev->platform, v_info,
Quinn Male58749452020-03-26 17:14:56 -07001770 &p_lsm_ses->lsm_usecase, p_ses->exec_mode, p_ses->lpi_enable,
1771 p_ses->f_stage_version);
Quinn Male8b2cb792020-07-13 14:41:32 -07001772 if (status) {
Quinn Male2e883752019-03-22 11:28:54 -07001773 ALOGE("%s: couldn't get lsm usecase", __func__);
Quinn Male58749452020-03-26 17:14:56 -07001774 status = -EINVAL;
Quinn Male2e883752019-03-22 11:28:54 -07001775 goto sm_error;
1776 }
1777
Quinn Male58749452020-03-26 17:14:56 -07001778 if (p_ses->f_stage_version == ST_MODULE_TYPE_PDK5 &&
1779 p_ses->num_reg_sm > 0) {
1780
1781 status = set_param_reg_multi_sm(p_lsm_ses, sm_data, sm_size, model_id);
1782 if (status) {
1783 ALOGE("%s: ERROR. registering multi sound model. status %d",
1784 __func__, status);
1785 return status;
1786 }
1787 p_ses->num_reg_sm++;
1788
1789 return 0;
1790 } else {
1791 p_lsm_ses->pcm_id = platform_ape_get_pcm_device_id(
1792 p_ses->stdev->platform, &p_ses->use_case_idx);
1793 if (p_lsm_ses->pcm_id < 0)
1794 return -ENODEV;
1795 }
1796
Quinn Male2e883752019-03-22 11:28:54 -07001797 p_lsm_ses->num_stages = 1;
1798 list_for_each(node, &p_ses->lsm_ss_cfg_list) {
1799 p_lsm_ses->num_stages++;
1800 }
1801 if ((p_lsm_ses->num_stages > 1) &&
1802 !st_hw_check_multi_stage_lsm_support()) {
1803 ALOGE("%s: lsm driver/dsp support for mult-stage(%d) session is missing",
1804 __func__, p_lsm_ses->num_stages);
Quinn Male58749452020-03-26 17:14:56 -07001805 status = -EINVAL;
Quinn Male2e883752019-03-22 11:28:54 -07001806 goto sm_error;
1807 }
1808
1809 /* Backward compatibility with previous XML version <= 0x0102 */
1810 int app_type = (v_info->app_type == 0) ?
Quinn Male8b2cb792020-07-13 14:41:32 -07001811 p_lsm_ses->lsm_usecase.app_type : v_info->app_type;
Quinn Male2e883752019-03-22 11:28:54 -07001812
1813 capture_device = platform_stdev_get_capture_device(p_ses->stdev->platform);
1814 status = platform_stdev_send_calibration(p_ses->stdev->platform,
1815 capture_device,
1816 p_ses->exec_mode,
1817 p_ses->vendor_uuid_info,
1818 app_type, true,
1819 ST_SESSION_CAL);
1820
1821 if (status) {
1822 ALOGE("%s: ERROR. sending calibration failed status %d, idx 0",
1823 __func__, status);
1824 goto sm_error;
1825 }
1826
1827 if (p_lsm_ses->num_stages > 1) {
1828 /*
1829 * Send cal for additional stages, if any,
1830 * Start cal index from One as first index is already taken care.
1831 */
1832 int index = ST_CAL_INDEX_0;
1833 list_for_each(node, &p_ses->lsm_ss_cfg_list) {
1834 index++;
1835 ss_cfg = node_to_item(node, st_lsm_ss_config_t, list_node);
1836 status = platform_stdev_send_calibration_v2(p_ses->stdev->platform,
1837 capture_device, p_ses->exec_mode,
1838 p_ses->vendor_uuid_info, ss_cfg->params->app_type,
1839 true, ST_SESSION_CAL, index);
1840 if (status) {
1841 ALOGE("%s: ERROR. sending calibration failed status %d idx %d",
1842 __func__, status, index);
1843 goto sm_error;
1844 }
1845 ALOGV("%s: sent lsm cal for app_type=%d idx %d cal status=%d",
1846 __func__, ss_cfg->params->app_type, index, status);
1847 }
1848 }
1849
1850 p_lsm_ses->common.config = stdev_ape_pcm_config;
1851
Quinn Male9a345522020-03-12 17:49:25 -07001852 platform_stdev_check_and_update_pcm_config(&p_lsm_ses->common.config,
1853 v_info);
Quinn Male2e883752019-03-22 11:28:54 -07001854
1855 ALOGD("%s: opening pcm device=%d", __func__, p_lsm_ses->pcm_id);
1856 ALOGV("%s: config: channels=%d rate=%d, period_size=%d, period_cnt=%d, format=%d",
1857 __func__, p_lsm_ses->common.config.channels, p_lsm_ses->common.config.rate,
1858 p_lsm_ses->common.config.period_size, p_lsm_ses->common.config.period_count,
1859 p_lsm_ses->common.config.format);
1860 ATRACE_BEGIN("sthal:lsm: pcm_open");
1861 p_lsm_ses->pcm = pcm_open(p_ses->stdev->snd_card, p_lsm_ses->pcm_id,
1862 PCM_IN, &p_lsm_ses->common.config);
1863 ATRACE_END();
1864 if (!p_lsm_ses->pcm) {
1865 ALOGE("%s: ERROR. pcm_open failed", __func__);
1866 status = -ENODEV;
1867 goto sm_error;
1868 }
1869 if (!pcm_is_ready(p_lsm_ses->pcm)) {
1870 ALOGE("%s: ERROR. pcm_is_ready failed err=%s", __func__,
1871 pcm_get_error(p_lsm_ses->pcm));
1872 status = -ENODEV;
1873 goto sm_error;
1874 }
1875
1876 /*
1877 * Using V2 APIs when multi-stage support is available in driver,
1878 * this would avoid confusion on code flow,
1879 * as only either legacy or V2 APIs would be used for a particular platform.
1880 */
1881 if (st_hw_check_multi_stage_lsm_support()) {
1882 status = lsm_set_session_data_v2(p_ses);
1883 if (status)
1884 goto sm_error;
1885 } else {
1886 /* Although app_id is valid only for non-topology solution. The driver
1887 opens DSP LSM session with this ioctl cmd */
1888 ses_data.app_id = LSM_VOICE_WAKEUP_APP_ID_V2;
1889 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_lsm_set_session_data");
sasevsb07d0c52022-06-01 13:03:40 +05301890#ifdef ENABLE_SVA_MIXER_CTL
1891 status = lsm_set_session_data(p_ses->stdev->mixer, (void *)(&ses_data));
1892#else
Quinn Male2e883752019-03-22 11:28:54 -07001893 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_SET_SESSION_DATA, &ses_data);
sasevsb07d0c52022-06-01 13:03:40 +05301894#endif
Quinn Male2e883752019-03-22 11:28:54 -07001895 ATRACE_END();
1896 if (status) {
1897 ALOGE("%s: ERROR. SNDRV_LSM_SET_SESSION_DATA failed status %d",
1898 __func__, status);
1899 goto sm_error;
1900 }
1901 }
1902
Quinn Male58749452020-03-26 17:14:56 -07001903 if (p_ses->f_stage_version == ST_MODULE_TYPE_PDK5) {
1904 if (!LSM_MULTI_SM_SUPPORT) {
1905 ALOGE("%s: Multi SM not supported in LSM, exiting",
1906 __func__);
1907 status = -EINVAL;
1908 goto sm_error;
1909 }
1910 status = set_param_reg_multi_sm(p_lsm_ses, sm_data, sm_size, model_id);
1911 if (status) {
1912 ALOGE("%s: ERROR. registering multi sound model. status %d",
1913 __func__, status);
1914 goto sm_error;
1915 }
1916 p_ses->num_reg_sm++;
1917 } else {
1918 /* Send Reg SM param for each stages */
1919 param_count = 0;
1920 stage_idx = LSM_STAGE_INDEX_FIRST;
1921 lsm_params.params = (unsigned char*)&param_info[0];
Quinn Male8b2cb792020-07-13 14:41:32 -07001922 mparams = p_lsm_ses->lsm_usecase.params;
Quinn Male58749452020-03-26 17:14:56 -07001923 param_info[param_count].param_data = sm_data;
1924 param_info[param_count].param_size = sm_size;
Quinn Male2e883752019-03-22 11:28:54 -07001925 lsm_fill_param_info(LSM_REG_SND_MODEL, &param_info[param_count++],
1926 &mparams[LOAD_SOUND_MODEL], stage_idx);
Quinn Male2e883752019-03-22 11:28:54 -07001927
Quinn Male58749452020-03-26 17:14:56 -07001928 list_for_each(node, &p_ses->lsm_ss_cfg_list) {
1929 ss_cfg = node_to_item(node, st_lsm_ss_config_t, list_node);
1930 mparams = ss_cfg->params->params;
1931 stage_idx++;
1932
1933 param_info[param_count].param_size = ss_cfg->sm_size;
1934 param_info[param_count].param_data = ss_cfg->sm_data;
1935 lsm_fill_param_info(LSM_REG_SND_MODEL, &param_info[param_count++],
1936 &mparams[LOAD_SOUND_MODEL], stage_idx);
1937 }
1938
1939 lsm_params.num_params = param_count;
1940 lsm_params.data_size =
1941 lsm_params.num_params * sizeof(lsm_param_info_t);
1942 status = lsm_set_module_params(p_lsm_ses, &lsm_params);
1943 if (status) {
1944 ALOGE("%s: ERROR. registering sound models. status %d",
1945 __func__, status);
1946 goto sm_error;
1947 }
Quinn Male2e883752019-03-22 11:28:54 -07001948 }
1949
Quinn Male2e883752019-03-22 11:28:54 -07001950 /* Send detection event type for last stage only, if params set in config */
1951 mparams = NULL;
1952 if ((p_lsm_ses->num_stages == 1) &&
Quinn Male8b2cb792020-07-13 14:41:32 -07001953 (p_lsm_ses->lsm_usecase.param_tag_tracker & PARAM_DET_EVENT_TYPE_BIT)) {
1954 mparams = p_lsm_ses->lsm_usecase.params;
Quinn Male2e883752019-03-22 11:28:54 -07001955 } else if (p_lsm_ses->num_stages > 1) {
1956 node = list_tail(&p_ses->lsm_ss_cfg_list);
1957 ss_cfg = node_to_item(node, st_lsm_ss_config_t, list_node);
1958 if (ss_cfg->params->param_tag_tracker & PARAM_DET_EVENT_TYPE_BIT)
1959 mparams = ss_cfg->params->params;
1960 }
1961 if (mparams) {
1962 stage_idx = LSM_STAGE_INDEX_FIRST + p_lsm_ses->num_stages - 1;
1963 if (fill_lsm_det_event_type_params(&det_event_type,
Quinn Male58749452020-03-26 17:14:56 -07001964 &param_info[0], mparams, stage_idx,
Tahir Dawson016b9f92021-05-28 13:49:09 -04001965 p_ses->f_stage_version, p_lsm_ses)) {
Quinn Male2e883752019-03-22 11:28:54 -07001966 p_ses->is_generic_event = true;
1967
1968 lsm_params.num_params = 1;
1969 lsm_params.params = (unsigned char*)&param_info[0];
1970 lsm_params.data_size = sizeof(lsm_param_info_t);
1971 status = lsm_set_module_params(p_lsm_ses, &lsm_params);
1972 if (status) {
1973 ALOGE("%s: ERROR. setting detection event type. status %d",
1974 __func__, status);
Harshal Ahire387953e2021-02-19 15:18:39 +05301975 goto det_event_err;
Quinn Male2e883752019-03-22 11:28:54 -07001976 }
1977 }
1978 }
1979
1980 /* Callback thread to wait on event detection */
1981 p_lsm_ses->exit_callback_thread = false;
1982 pthread_attr_init(&attr);
1983 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1984 pthread_create(&p_lsm_ses->callback_thread, &attr,
1985 callback_thread_loop, p_lsm_ses);
1986
1987 ALOGD("%s:[%d] Exit, status=%d", __func__, p_lsm_ses->common.sm_handle,
1988 status);
1989 return 0;
1990
Harshal Ahire387953e2021-02-19 15:18:39 +05301991det_event_err:
1992 if (p_ses->f_stage_version == ST_MODULE_TYPE_PDK5)
1993 p_ses->num_reg_sm--;
Quinn Male2e883752019-03-22 11:28:54 -07001994sm_error:
1995 platform_ape_free_pcm_device_id(p_ses->stdev->platform, p_lsm_ses->pcm_id);
1996 if (p_lsm_ses->pcm) {
1997 pcm_close(p_lsm_ses->pcm);
1998 p_lsm_ses->pcm = NULL;
1999 }
2000
2001 ALOGD("%s:[%d] Exit, status=%d", __func__,
2002 p_lsm_ses->common.sm_handle, status);
2003 return status;
2004}
2005
Quinn Male58749452020-03-26 17:14:56 -07002006static int set_param_dereg_multi_sm(st_hw_session_lsm_t *p_ses,
2007 uint32_t model_id)
2008{
2009 int status = 0;
2010 lsm_param_info_t param_info = {0};
2011 struct snd_lsm_module_params lsm_params = {0};
2012 struct st_module_param_info *mparams = NULL;
2013
Quinn Male8b2cb792020-07-13 14:41:32 -07002014 mparams = p_ses->lsm_usecase.params;
Quinn Male58749452020-03-26 17:14:56 -07002015 param_info.param_size = sizeof(model_id);
2016 param_info.param_data = (uint8_t *)&model_id;
2017#if (SNDRV_LSM_VERSION >= SNDRV_PROTOCOL_VERSION(0, 3, 2))
2018 param_info.model_id = model_id;
2019 lsm_fill_param_info(LSM_DEREG_MULTI_SND_MODEL, &param_info,
2020 &mparams[UNLOAD_SOUND_MODEL],
2021 LSM_STAGE_INDEX_FIRST);
2022#endif
2023 lsm_params.params = (uint8_t *)&param_info;
2024 lsm_params.num_params = 1;
2025 lsm_params.data_size = sizeof(lsm_param_info_t);
2026 status = lsm_set_module_params(p_ses, &lsm_params);
2027 if (status)
2028 ALOGE("%s: ERROR. dereg multi sound model, status %d",
2029 __func__, status);
2030
2031 return status;
2032}
2033
sasevsb07d0c52022-06-01 13:03:40 +05302034#ifdef ENABLE_SVA_MIXER_CTL
2035int lsm_send_lab_control_mixer_ctl(struct mixer * st_mixer, int buf_en)
2036{
2037 const char *mixer_ctl_name = "LSM LAB_CONTROL SET";
2038 struct mixer_ctl *ctl = NULL;
2039 ctl = mixer_get_ctl_by_name(st_mixer, mixer_ctl_name);
2040 if (!ctl) {
2041 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2042 __func__, mixer_ctl_name);
2043 }
2044 if (mixer_ctl_set_value(ctl, 0, buf_en) < 0) {
2045 ALOGE("%s: Could not set LSM load mixer control", __func__);
2046 return -EFAULT;
2047 }
2048 return 0;
2049}
2050#endif
2051
Quinn Male58749452020-03-26 17:14:56 -07002052static int ape_dereg_sm(st_hw_session_t *p_ses, uint32_t model_id)
Quinn Male2e883752019-03-22 11:28:54 -07002053{
2054 int status = 0, buf_en = 0;
2055 struct snd_lsm_module_params lsm_params;
2056 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
2057 struct st_module_param_info *mparams = NULL;
2058 lsm_param_info_t param_info[LSM_MAX_STAGES_PER_SESSION];
2059 struct listnode *node = NULL;
2060 st_lsm_ss_config_t *ss_cfg = NULL;
2061 int stage_idx, param_count;
2062
2063 ALOGD("%s:[%d] Enter", __func__, p_lsm_ses->common.sm_handle);
2064
Quinn Male58749452020-03-26 17:14:56 -07002065 memset((uint8_t *)param_info, 0, sizeof(lsm_param_info_t) *
2066 LSM_MAX_STAGES_PER_SESSION);
2067
Quinn Male2e883752019-03-22 11:28:54 -07002068 if (!p_lsm_ses->pcm) {
2069 ALOGV("%s: pcm NULL", __func__);
2070 return status;
2071 }
2072
Quinn Male58749452020-03-26 17:14:56 -07002073 if (p_ses->f_stage_version == ST_MODULE_TYPE_PDK5 &&
2074 p_ses->num_reg_sm > 1) {
2075
2076 status = set_param_dereg_multi_sm(p_lsm_ses, model_id);
2077 if (status) {
2078 ALOGE("%s: ERROR. deregistering multi sound model. status %d",
2079 __func__, status);
2080 }
2081 p_ses->num_reg_sm--;
2082 return status;
2083 }
2084
Quinn Male2e883752019-03-22 11:28:54 -07002085 /* Exit the callback thread waiting on event detection */
2086 request_exit_callback_thread(p_lsm_ses);
2087
2088 pthread_join(p_lsm_ses->callback_thread, (void **) NULL);
2089
2090 /*
2091 * Disable lab capture requests.
2092 * Note: lab for internal stages gets enabled even when lab capture is not required.
2093 */
2094 stage_idx = LSM_STAGE_INDEX_FIRST;
2095 param_count = 0;
2096 lsm_params.params = (unsigned char*)&param_info[0];
Quinn Male8b2cb792020-07-13 14:41:32 -07002097 mparams = p_lsm_ses->lsm_usecase.params;
Quinn Male2e883752019-03-22 11:28:54 -07002098
2099 /* reset last stage only if lab capture was set */
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002100 if ((stage_idx == p_lsm_ses->num_stages - 1) && p_ses->lab_enabled &&
Quinn Male8b2cb792020-07-13 14:41:32 -07002101 (p_lsm_ses->lsm_usecase.param_tag_tracker & PARAM_LAB_CONTROL_BIT)) {
Quinn Male2e883752019-03-22 11:28:54 -07002102 param_info[param_count].param_size = sizeof(buf_en);
2103 param_info[param_count].param_data = (unsigned char *)&buf_en;
2104 lsm_fill_param_info(LSM_LAB_CONTROL, &param_info[param_count++],
2105 &mparams[LAB_CONTROL], stage_idx);
2106 }
2107
2108 list_for_each(node, &p_ses->lsm_ss_cfg_list) {
2109 stage_idx++;
2110 ss_cfg = node_to_item(node, st_lsm_ss_config_t, list_node);
2111 mparams = ss_cfg->params->params;
2112 /* reset last stage only if lab capture was set */
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002113 if ((stage_idx == p_lsm_ses->num_stages) && (!p_ses->lab_enabled))
Quinn Male2e883752019-03-22 11:28:54 -07002114 break;
2115
2116 param_info[param_count].param_size = sizeof(buf_en);
2117 param_info[param_count].param_data = (unsigned char *)&buf_en;
2118 lsm_fill_param_info(LSM_LAB_CONTROL, &param_info[param_count++],
2119 &mparams[LAB_CONTROL], stage_idx);
2120 }
2121
2122 lsm_params.num_params = param_count;
2123 if (lsm_params.num_params) {
2124 lsm_params.data_size =
2125 lsm_params.num_params * sizeof(lsm_param_info_t);
2126 status = lsm_set_module_params(p_lsm_ses, &lsm_params);
2127 if (status)
2128 ALOGE("%s: ERROR. Sending LAB_CONTROL module params, status=%d",
2129 __func__, status);
2130 }
2131
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002132 if (p_ses->lab_enabled) {
Quinn Male2e883752019-03-22 11:28:54 -07002133 /*
2134 * Check and reset lab if ses was non-multi-stage,
2135 * and lab control param bit was not set.
2136 * LAB_CONTROL params is optional only for single stage session.
2137 */
Harshal Ahire387953e2021-02-19 15:18:39 +05302138 if(p_lsm_ses->pcm) {
2139 if ((p_lsm_ses->num_stages == 1) &&
2140 !(p_lsm_ses->lsm_usecase.param_tag_tracker & PARAM_LAB_CONTROL_BIT)) {
2141 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_lsm_lab_control");
sasevsb07d0c52022-06-01 13:03:40 +05302142#ifdef ENABLE_SVA_MIXER_CTL
2143 status = lsm_send_lab_control_mixer_ctl(p_ses->stdev->mixer, buf_en);
2144#else
Harshal Ahire387953e2021-02-19 15:18:39 +05302145 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_LAB_CONTROL, &buf_en);
sasevsb07d0c52022-06-01 13:03:40 +05302146#endif
Harshal Ahire387953e2021-02-19 15:18:39 +05302147 ATRACE_END();
2148 if (status)
2149 ALOGE("%s: ERROR. SNDRV_LSM_LAB_CONTROL failed, status=%d",
2150 __func__, status);
2151 }
2152 }
2153 else {
2154 ALOGE("%s: PCM is NULL", __func__);
Quinn Male2e883752019-03-22 11:28:54 -07002155 }
2156
2157 /* Deallocate lab buffes if allocated during start_recognition */
2158 if (p_lsm_ses->lab_buffers_allocated)
2159 deallocate_lab_buffers_ape(p_lsm_ses);
2160 }
2161
2162 /* Dereg Sound Models */
Quinn Male58749452020-03-26 17:14:56 -07002163 if (p_ses->f_stage_version == ST_MODULE_TYPE_PDK5) {
Quinn Male2e883752019-03-22 11:28:54 -07002164
Quinn Male58749452020-03-26 17:14:56 -07002165 status = set_param_dereg_multi_sm(p_lsm_ses, model_id);
2166 if (status) {
2167 ALOGE("%s: ERROR. deregistering multi sound model. status %d",
2168 __func__, status);
2169 }
2170 p_ses->num_reg_sm--;
2171 } else {
2172 stage_idx = LSM_STAGE_INDEX_FIRST;
2173 param_count = 0;
2174 lsm_params.params = (unsigned char*)&param_info[0];
Quinn Male8b2cb792020-07-13 14:41:32 -07002175 mparams = p_lsm_ses->lsm_usecase.params;
Quinn Male2e883752019-03-22 11:28:54 -07002176 param_info[param_count].param_size = 0;
Quinn Male58749452020-03-26 17:14:56 -07002177
Quinn Male2e883752019-03-22 11:28:54 -07002178 lsm_fill_param_info(LSM_DEREG_SND_MODEL, &param_info[param_count++],
2179 &mparams[UNLOAD_SOUND_MODEL], stage_idx);
Quinn Male2e883752019-03-22 11:28:54 -07002180
Quinn Male58749452020-03-26 17:14:56 -07002181 list_for_each(node, &p_ses->lsm_ss_cfg_list) {
2182 stage_idx++;
2183 ss_cfg = node_to_item(node, st_lsm_ss_config_t, list_node);
2184 mparams = ss_cfg->params->params;
2185 param_info[param_count].param_size = 0;
2186 lsm_fill_param_info(LSM_DEREG_SND_MODEL, &param_info[param_count++],
2187 &mparams[UNLOAD_SOUND_MODEL], stage_idx);
2188 }
2189
2190 lsm_params.num_params = param_count;
2191 lsm_params.data_size =
2192 lsm_params.num_params * sizeof(lsm_param_info_t);
2193 status = lsm_set_module_params(p_lsm_ses, &lsm_params);
2194 if (status)
2195 ALOGE("%s: ERROR. dereg sound model module params, status %d",
2196 __func__, status);
2197 }
Quinn Male2e883752019-03-22 11:28:54 -07002198
2199 ATRACE_BEGIN("sthal:lsm: pcm_close");
2200 pcm_close(p_lsm_ses->pcm);
2201 ATRACE_END();
2202 p_lsm_ses->pcm = NULL;
2203
2204 platform_ape_free_pcm_device_id(p_ses->stdev->platform, p_lsm_ses->pcm_id);
2205
2206 ALOGD("%s:[%d] Exit, status=%d", __func__, p_lsm_ses->common.sm_handle,
2207 status);
2208 return status;
2209}
2210
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002211static int ape_reg_sm_params(st_hw_session_t* p_ses,
2212 unsigned int recognition_mode, bool capture_requested,
Quinn Male58749452020-03-26 17:14:56 -07002213 struct sound_trigger_recognition_config *rc_config __unused)
Quinn Male2e883752019-03-22 11:28:54 -07002214{
2215 int status = 0, buf_en = 1, retry_num = 0, offset = 0;
2216 int param_tag_tracker;
2217 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t*)p_ses;
2218 uint32_t custom_payload_size, smm_th_conf_param_size;
2219 uint32_t data_payload_size, lsm_param_payload_size;
2220 uint32_t data_payload_addr_lsw = 0, data_payload_addr_msw = 0, mem_map_handle = 0;
Quinn Male3d7d9d42019-05-20 13:35:01 -07002221 uint32_t lab_dam_payload_size = 0;
Quinn Male2e883752019-03-22 11:28:54 -07002222 unsigned char *custom_payload = NULL, *smm_th_conf_param = NULL;
Quinn Male3d7d9d42019-05-20 13:35:01 -07002223 unsigned char *lab_dam_payload = NULL;
Quinn Male2e883752019-03-22 11:28:54 -07002224 struct st_vendor_info *v_info = p_lsm_ses->common.vendor_uuid_info;
2225 struct snd_lsm_module_params lsm_params;
Quinn Maleaba13db2019-07-11 15:52:14 -07002226 lsm_param_info_t param_info[LSM_SM_PARAMS_INFO_MAX];
Quinn Male58749452020-03-26 17:14:56 -07002227 lsm_param_info_t *cfl_params = NULL;
2228 lsm_param_info_t *op_params = NULL;
2229 lsm_param_info_t *cus_params = NULL;
2230 lsm_param_info_t *poll_en_params = NULL;
2231 lsm_param_info_t *lab_params = NULL;
2232 lsm_param_info_t *lab_dam_cfg_params = NULL;
Quinn Male2e883752019-03-22 11:28:54 -07002233 struct snd_lsm_detect_mode det_mode;
Quinn Male58749452020-03-26 17:14:56 -07002234 st_lsm_conf_levels_t conf_levels_payload[MAX_MULTI_SOUND_MODELS] = {0};
Quinn Male2e883752019-03-22 11:28:54 -07002235 st_lsm_poll_enable_t poll_enable;
2236 bool disable_custom_config = false;
2237 struct listnode *node = NULL;
2238 struct st_module_param_info *mparams = NULL;
2239 st_lsm_ss_config_t *ss_cfg = NULL;
Quinn Male58749452020-03-26 17:14:56 -07002240 int param_count = 0, stage_idx = 0, sm_count = 0;
Quinn Male2e883752019-03-22 11:28:54 -07002241 struct lsm_param_custom_config custom_conf_params;
2242 lsm_param_payload_t custom_conf_params_v2 = {0};
Quinn Male3d7d9d42019-05-20 13:35:01 -07002243 lsm_param_payload_t cus_dam_cfg_params = {0};
Quinn Male58749452020-03-26 17:14:56 -07002244 struct st_hw_ses_config *sthw_cfg = NULL;
Quinn Male2e883752019-03-22 11:28:54 -07002245
2246 ALOGD("%s:[%d] Enter", __func__, p_lsm_ses->common.sm_handle);
2247 if (!p_lsm_ses->pcm) {
2248 ALOGW("%s: pcm NULL", __func__);
2249 return status;
2250 }
2251
Quinn Male58749452020-03-26 17:14:56 -07002252 memset((uint8_t *)param_info, 0, sizeof(lsm_param_info_t) *
2253 LSM_SM_PARAMS_INFO_MAX);
2254
Quinn Male2e883752019-03-22 11:28:54 -07002255 /*
2256 * While dynamically switching ports,
2257 * port info needs to be sent to driver before enabling usecase.
2258 * If port controls are available seprately,
2259 * set port control and ioctl before enabling usecase.
2260 * Note: error from enable port control,
2261 * implies no support for separate port controls.
2262 */
2263 if (ape_enable_port_control(true, p_ses) == 0) {
2264 status = lsm_set_port(p_lsm_ses);
2265 if (!status)
2266 ape_enable_use_case(true, p_ses);
2267 } else {
2268 ape_enable_use_case(true, p_ses);
2269 status = lsm_set_port(p_lsm_ses);
2270 }
2271 if (status) {
2272 ALOGE("%s: ERROR. set port failed, returned status %d",
2273 __func__, status);
2274 goto error_exit;
2275 }
2276
Quinn Male3d7d9d42019-05-20 13:35:01 -07002277 status = send_lsm_input_hw_params(p_ses);
2278 if (status)
2279 goto error_exit;
2280
Quinn Male58749452020-03-26 17:14:56 -07002281 if ((p_ses->custom_data_size > CUSTOM_CONFIG_OPAQUE_DATA_SIZE) &&
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002282 v_info->is_qcva_uuid && !capture_requested)
Quinn Male2e883752019-03-22 11:28:54 -07002283 disable_custom_config = true;
2284
2285 ATRACE_BEGIN("sthal:lsm: pcm_start");
2286 status = pcm_start(p_lsm_ses->pcm);
2287 while (status && (retry_num < SOUND_TRIGGER_PCM_MAX_RETRY)) {
2288 usleep(SOUND_TRIGGER_PCM_SLEEP_WAIT);
2289 retry_num++;
Lakshman Chaluvaraju61036ac2022-01-18 17:27:22 +05302290 pcm_stop(p_lsm_ses->pcm);
Quinn Male2e883752019-03-22 11:28:54 -07002291 ALOGI("%s: pcm_start retrying..status %d errno %d, retry cnt %d",
2292 __func__, status, errno, retry_num);
2293 status = pcm_start(p_lsm_ses->pcm);
2294 }
2295 ATRACE_END();
2296 if (status) {
2297 ALOGE("%s: ERROR. pcm_start failed, returned status %d",
2298 __func__, status);
2299 goto error_exit;
2300 }
2301
Zhou Song68bfc6e2020-03-03 14:32:39 +08002302 if (!p_ses->stdev->lpi_enable && !p_ses->stdev->barge_in_mode &&
2303 p_ses->stdev->support_barge_in_mode) {
Quinn Malecc1affd2019-07-18 16:13:31 -07002304 status = platform_stdev_update_ec_effect(p_ses->stdev->platform,
2305 false);
2306 if (status) {
2307 ALOGE("%s: ERROR. Failed to update EC ref, returned status %d",
2308 __func__, status);
2309 goto error_exit_1;
2310 }
2311 }
2312
Quinn Male2e883752019-03-22 11:28:54 -07002313 /* SVA doesn't support per keyword recogntion mode.
2314 Use the per soundmodel recognition mode */
2315 if (recognition_mode & RECOGNITION_MODE_VOICE_TRIGGER){
2316 det_mode.mode= LSM_MODE_KEYWORD_ONLY_DETECTION;
2317 if (recognition_mode & RECOGNITION_MODE_USER_IDENTIFICATION)
2318 det_mode.mode = LSM_MODE_USER_KEYWORD_DETECTION;
2319 } else {
2320 ALOGE("%s: Unknown recognition mode %d", __func__, recognition_mode);
Quinn Male58749452020-03-26 17:14:56 -07002321 status = -EINVAL;
Quinn Male3d7d9d42019-05-20 13:35:01 -07002322 goto error_exit_1;
Quinn Male2e883752019-03-22 11:28:54 -07002323 }
Venkatesh Mangalappalia934ec92019-10-01 13:46:25 -07002324 ALOGD("%s: st_recogntion_mode %d, det_mode %d, lab %d", __func__,
2325 recognition_mode, det_mode.mode, capture_requested);
Quinn Male2e883752019-03-22 11:28:54 -07002326
2327 stage_idx = LSM_STAGE_INDEX_FIRST;
2328 param_count = 0;
2329 lsm_params.params = (unsigned char*)&param_info[0];
Quinn Male8b2cb792020-07-13 14:41:32 -07002330 param_tag_tracker = p_lsm_ses->lsm_usecase.param_tag_tracker;
2331 mparams = p_lsm_ses->lsm_usecase.params;
Quinn Male2e883752019-03-22 11:28:54 -07002332
2333 /*
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002334 * For other than QTI VA, pass only the opaque data as custom params and
Quinn Male2e883752019-03-22 11:28:54 -07002335 * ignore sending all other params
2336 */
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002337 if (v_info->is_qcva_uuid || v_info->is_qcmd_uuid) {
Quinn Male2e883752019-03-22 11:28:54 -07002338 det_mode.detect_failure = p_ses->stdev->detect_failure;
2339 ALOGV("%s: dm %d df %d lab %d", __func__,
2340 det_mode.mode, det_mode.detect_failure, capture_requested);
2341 if (param_tag_tracker & PARAM_CONFIDENCE_LEVELS_BIT) {
2342 /* fill confidence level params */
Quinn Male58749452020-03-26 17:14:56 -07002343 if (p_ses->f_stage_version == ST_MODULE_TYPE_PDK5) {
2344 list_for_each(node, &p_ses->sthw_cfg_list) {
2345 sthw_cfg = node_to_item(node, struct st_hw_ses_config,
2346 sthw_cfg_list_node);
2347
2348 conf_levels_payload[sm_count].model_id =
2349 sthw_cfg->model_id;
2350 conf_levels_payload[sm_count].num_conf_levels =
2351 sthw_cfg->num_conf_levels;
2352 /*
2353 * If a sound model is in loaded state while another
2354 * is active, its num_conf_levels will be 0 and the
2355 * conf levels array will have the max value. Set the
2356 * num to 1 so that it can get sent properly to DSP.
2357 */
2358 if (!conf_levels_payload[sm_count].num_conf_levels)
2359 conf_levels_payload[sm_count].num_conf_levels = 1;
2360 ALOGV("%s: ncl %d", __func__,
2361 conf_levels_payload[sm_count].num_conf_levels);
2362 for (int i = 0;
2363 i < conf_levels_payload[sm_count].num_conf_levels;
2364 i++) {
2365 conf_levels_payload[sm_count].conf_levels[i] =
2366 *(sthw_cfg->conf_levels + i);
2367 ALOGD("%s: 1st stage cl for m_id[%d], kw_id[%d] = %d",
2368 __func__, sthw_cfg->model_id, i,
2369 conf_levels_payload[sm_count].conf_levels[i]);
2370 }
2371 cfl_params = &param_info[param_count++];
2372 cfl_params->param_size =
2373 conf_levels_payload[sm_count].num_conf_levels;
2374 cfl_params->param_data =
2375 (uint8_t *)&conf_levels_payload[sm_count].conf_levels;
2376#if (SNDRV_LSM_VERSION >= SNDRV_PROTOCOL_VERSION(0, 3, 2))
2377 cfl_params->model_id = sthw_cfg->model_id;
2378 lsm_fill_param_info(LSM_MULTI_SND_MODEL_CONFIDENCE_LEVELS,
2379 cfl_params, &mparams[CONFIDENCE_LEVELS], stage_idx);
2380#endif
2381 sm_count++;
2382 }
2383 } else {
2384 if (!list_empty(&p_ses->sthw_cfg_list)) {
2385 node = list_head(&p_ses->sthw_cfg_list);
2386 sthw_cfg = node_to_item(node, struct st_hw_ses_config,
2387 sthw_cfg_list_node);
2388 } else {
2389 ALOGE("%s: Unexpected, sthw_cfg list is empty", __func__);
2390 status = -EINVAL;
2391 goto error_exit_1;
2392 }
2393 cfl_params = &param_info[param_count++];
2394 cfl_params->param_size = sthw_cfg->num_conf_levels;
2395 cfl_params->param_data = sthw_cfg->conf_levels;
2396 lsm_fill_param_info(LSM_MIN_CONFIDENCE_LEVELS, cfl_params,
2397 &mparams[CONFIDENCE_LEVELS], stage_idx);
2398 {
2399 unsigned int i;
2400 ALOGV("%s: ncl %d", __func__, cfl_params->param_size);
2401 for (i = 0; i < cfl_params->param_size; i++) {
2402 ALOGD("%s: First stage conf_levels[%d] = %d",
2403 __func__, i, cfl_params->param_data[i]);
2404 }
Quinn Male2e883752019-03-22 11:28:54 -07002405 }
2406 }
2407 }
2408 if (param_tag_tracker & PARAM_OPERATION_MODE_BIT) {
2409 /* fill operation mode params */
2410 op_params = &param_info[param_count++];
2411 op_params->param_size = sizeof(det_mode);
2412 op_params->param_data = (unsigned char *)&det_mode;
2413 lsm_fill_param_info(LSM_OPERATION_MODE, op_params,
2414 &mparams[OPERATION_MODE], stage_idx);
2415 }
2416 if (param_tag_tracker & PARAM_POLLING_ENABLE_BIT) {
2417 poll_en_params = &param_info[param_count];
2418 if (fill_lsm_poll_enable_params(v_info,
2419 &poll_enable, poll_en_params, mparams, stage_idx)) {
2420 param_count++;
2421 }
2422 }
2423 }
2424 /*
2425 * Custom config is mandatory for adsp multi-stage session,
2426 * Default config would be sent if not explicitly set from client applicaiton.
2427 */
Shalini Manjunathaf3029142021-05-10 16:46:43 +05302428 ALOGD("%s: second state detection %s",__func__,
2429 p_ses->vendor_uuid_info->second_stage_supported ? "supported" : "not supported");
2430 if (((p_ses->custom_data_size && !disable_custom_config) ||
2431 !list_empty(&p_ses->lsm_ss_cfg_list)) && p_ses->vendor_uuid_info->second_stage_supported) {
Quinn Male2e883752019-03-22 11:28:54 -07002432 /* fill opaque data as custom params */
2433 cus_params = &param_info[param_count++];
2434 if (param_tag_tracker & PARAM_CUSTOM_CONFIG_BIT) {
2435 /*
2436 * For both cases below, fill module_id and param_id obtained from platform info
2437 * xml. Also fill custom_config set_param. Package this with recognition config
2438 * opaque data in the required format and send it.
2439 */
2440 if (platform_stdev_get_xml_version(p_ses->stdev->platform) >
2441 PLATFORM_XML_VERSION_0x0102) {
2442 int lsm_param_payload_size;
2443 /*
2444 * lsm_param_payload_size = size of opaque data.
2445 * custom_payload_size = size of param data + size of opaque data.
2446 */
2447 lsm_param_payload_size = sizeof(struct st_hist_buffer_info);
2448 lsm_fill_param_header(&custom_conf_params_v2,
2449 lsm_param_payload_size, &mparams[CUSTOM_CONFIG]);
2450
2451 custom_payload_size = sizeof(custom_conf_params_v2) + lsm_param_payload_size;
2452 custom_payload = (unsigned char *)calloc(1, custom_payload_size);
2453 if (!custom_payload) {
2454 ALOGE("%s: ERROR. Cannot allocate memory for custom_payload", __func__);
Quinn Male3d7d9d42019-05-20 13:35:01 -07002455 goto error_exit_1;
Quinn Male2e883752019-03-22 11:28:54 -07002456 }
2457 /* copy custom config params to payload */
2458 memcpy(custom_payload, &custom_conf_params_v2, sizeof(custom_conf_params_v2));
2459 offset = sizeof(custom_conf_params_v2);
2460
2461 } else {
2462 cus_params->param_type = LSM_CUSTOM_PARAMS;
2463 /*
2464 * p_size = size of opaque data.
2465 * data_payload_size = size of payload data + size of opaque data.
2466 */
2467 lsm_param_payload_size = sizeof(custom_conf_params) -
2468 sizeof(custom_conf_params.set_param);
2469 data_payload_size = lsm_param_payload_size + sizeof(struct st_hist_buffer_info);
2470 fill_set_params_payload(&custom_conf_params.set_param, data_payload_size,
2471 data_payload_addr_lsw, data_payload_addr_msw, mem_map_handle);
2472
2473 lsm_fill_param_header((lsm_param_payload_t *)&custom_conf_params.common,
2474 lsm_param_payload_size, &mparams[CUSTOM_CONFIG]);
2475
2476 custom_payload_size = sizeof(struct lsm_param_custom_config) +
2477 sizeof(struct st_hist_buffer_info);
2478 custom_payload = (unsigned char *)calloc(1, custom_payload_size);
2479 if (!custom_payload) {
2480 ALOGE("%s: ERROR. Cannot allcoate memory for custom_payload", __func__);
Quinn Male3d7d9d42019-05-20 13:35:01 -07002481 goto error_exit_1;
Quinn Male2e883752019-03-22 11:28:54 -07002482 }
2483 /* copy custom config params to payload */
2484 memcpy(custom_payload, &custom_conf_params, sizeof(struct lsm_param_custom_config));
2485 offset += sizeof(struct lsm_param_custom_config);
2486 }
2487
2488 /* copy opaque data from recognition config to payload */
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002489 if (v_info->is_qcva_uuid &&
Quinn Male58749452020-03-26 17:14:56 -07002490 ((p_ses->custom_data_size == 0) ||
2491 (p_ses->custom_data_size >
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002492 CUSTOM_CONFIG_OPAQUE_DATA_SIZE))) {
2493 st_hw_ses_get_hist_buff_payload(p_ses,
2494 (uint8_t *)custom_payload + offset,
2495 custom_payload_size - offset);
Quinn Male2e883752019-03-22 11:28:54 -07002496 } else {
2497 /* copy opaque data from recognition config to payload */
2498 memcpy((char *)custom_payload + offset,
Quinn Male58749452020-03-26 17:14:56 -07002499 p_ses->custom_data,
2500 p_ses->custom_data_size);
Quinn Male2e883752019-03-22 11:28:54 -07002501 }
2502 } else {
2503 /*
2504 * Send opaque data as it is,
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002505 * Using legacy custom param where app needs to form appropriate
2506 * payload.
Quinn Male2e883752019-03-22 11:28:54 -07002507 */
Quinn Male58749452020-03-26 17:14:56 -07002508 custom_payload_size = p_ses->custom_data_size;
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002509 custom_payload = calloc(1, custom_payload_size);
Quinn Male2e883752019-03-22 11:28:54 -07002510 if (!custom_payload) {
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002511 ALOGE("%s: ERROR. Cannot allocate memory for custom_payload",
2512 __func__);
Quinn Male3d7d9d42019-05-20 13:35:01 -07002513 goto error_exit_1;
Quinn Male2e883752019-03-22 11:28:54 -07002514 }
Quinn Male58749452020-03-26 17:14:56 -07002515 memcpy(custom_payload, p_ses->custom_data,
2516 p_ses->custom_data_size);
Quinn Male2e883752019-03-22 11:28:54 -07002517 }
2518 cus_params->param_size = custom_payload_size;
2519 cus_params->param_data = (unsigned char *)custom_payload;
2520 lsm_fill_param_info(LSM_CUSTOM_PARAMS, cus_params,
2521 &mparams[CUSTOM_CONFIG], stage_idx);
2522 }
2523
2524 /* set lab for last stage, only when capturing lab */
2525 if ((param_tag_tracker & PARAM_LAB_CONTROL_BIT) &&
2526 ((stage_idx != p_lsm_ses->num_stages - 1) || capture_requested)) {
2527 lab_params = &param_info[param_count++];
2528
2529 lab_params->param_size = sizeof(buf_en);
2530 lab_params->param_data = (unsigned char *)&buf_en;
2531 lsm_fill_param_info(LSM_LAB_CONTROL, lab_params,
2532 &mparams[LAB_CONTROL], stage_idx);
2533 }
2534
Quinn Male3d7d9d42019-05-20 13:35:01 -07002535 /*
2536 * If shared buffering is supported and LPI mode is enabled, send the DAM
2537 * driver param to DSP to set the shared buffer token for this session.
2538 */
2539 if (capture_requested && p_ses->stdev->lpi_enable &&
2540 p_ses->vendor_uuid_info->lab_dam_cfg_payload.token_id &&
Quinn Male8b2cb792020-07-13 14:41:32 -07002541 (p_lsm_ses->lsm_usecase.param_tag_tracker &
Quinn Male3d7d9d42019-05-20 13:35:01 -07002542 PARAM_LAB_DAM_CFG_BIT)) {
2543
2544 lab_dam_cfg_params = &param_info[param_count++];
2545 p_ses->vendor_uuid_info->lab_dam_cfg_payload.minor_version = 0x1;
2546
2547 lsm_param_payload_size = sizeof(struct lab_dam_cfg_payload);
2548
2549 lsm_fill_param_header(&cus_dam_cfg_params,
2550 lsm_param_payload_size, &mparams[LAB_DAM_CFG]);
2551
2552 lab_dam_payload_size = sizeof(cus_dam_cfg_params) +
2553 lsm_param_payload_size;
2554 lab_dam_payload = (unsigned char *)calloc(1, lab_dam_payload_size);
2555 if (!lab_dam_payload) {
2556 ALOGE("%s: ERROR. Cannot allocate memory for lab_dam_payload",
2557 __func__);
2558 goto error_exit_1;
2559 }
2560 /* copy custom config params to payload */
2561 memcpy(lab_dam_payload, &cus_dam_cfg_params,
2562 sizeof(cus_dam_cfg_params));
2563 memcpy(lab_dam_payload + sizeof(cus_dam_cfg_params),
2564 &p_ses->vendor_uuid_info->lab_dam_cfg_payload,
2565 lsm_param_payload_size);
2566
2567 lab_dam_cfg_params->param_size = lab_dam_payload_size;
2568 lab_dam_cfg_params->param_data = (unsigned char *)lab_dam_payload;
2569 lsm_fill_param_info(LSM_CUSTOM_PARAMS, lab_dam_cfg_params,
2570 &mparams[LAB_DAM_CFG], stage_idx);
2571 }
2572
Quinn Male2e883752019-03-22 11:28:54 -07002573 /* Send all applicable module params for this(first) stage */
2574 lsm_params.num_params = param_count;
2575 if (lsm_params.num_params) {
2576 lsm_params.data_size =
2577 lsm_params.num_params * sizeof(lsm_param_info_t);
2578
Quinn Maleaba13db2019-07-11 15:52:14 -07002579 if (p_lsm_ses->common.stdev->enable_debug_dumps) {
2580 ST_DBG_DECLARE(FILE *lsm_params_fd = NULL;
2581 static int lsm_params_cnt = 0);
2582 ST_DBG_FILE_OPEN_WR(lsm_params_fd, ST_DEBUG_DUMP_LOCATION,
Quinn Male201b59d2020-08-27 16:53:51 -07002583 "lsm_params_data", "bin", lsm_params_cnt);
Quinn Maleaba13db2019-07-11 15:52:14 -07002584 ST_DBG_FILE_WRITE(lsm_params_fd, lsm_params.params,
2585 lsm_params.data_size);
2586 ST_DBG_FILE_CLOSE(lsm_params_fd);
Quinn Male201b59d2020-08-27 16:53:51 -07002587 ALOGD("%s: LSM module params stored in: lsm_params_data_%d.bin",
2588 __func__, lsm_params_cnt);
2589 lsm_params_cnt++;
Quinn Maleaba13db2019-07-11 15:52:14 -07002590 }
Quinn Male2e883752019-03-22 11:28:54 -07002591
2592 status = lsm_set_module_params(p_lsm_ses, &lsm_params);
2593 if (status) {
2594 ALOGE("%s: ERROR. sending sm_params, status %d, stage 0",
2595 __func__, status);
Quinn Male3d7d9d42019-05-20 13:35:01 -07002596 goto error_exit_1;
Quinn Male2e883752019-03-22 11:28:54 -07002597 }
2598 }
2599
2600 /* Send sm params for additional stages if available */
2601 list_for_each(node, &p_ses->lsm_ss_cfg_list) {
2602 /* reset param_count for each stage, but not stage_idx */
2603 stage_idx++;
2604 param_count = 0;
2605 lsm_params.params = (unsigned char*)&param_info[0];
2606 ss_cfg = node_to_item(node, st_lsm_ss_config_t, list_node);
2607 mparams = ss_cfg->params->params;
2608 param_tag_tracker = ss_cfg->params->param_tag_tracker;
2609
2610 /*
2611 * Multi stage usecase must have PARAM_LAB_CONTROL_BIT set,
2612 * As legacy ioctl do not support multi-stage.
2613 */
2614 if (!(param_tag_tracker & PARAM_LAB_CONTROL_BIT)) {
2615 ALOGE("%s: ERROR: lab control param not set for multi-stage ses %p, stage %d",
2616 __func__, p_ses, stage_idx);
Quinn Male3d7d9d42019-05-20 13:35:01 -07002617 goto error_exit_1;
Quinn Male2e883752019-03-22 11:28:54 -07002618 }
2619
2620 if (param_tag_tracker & PARAM_CONFIDENCE_LEVELS_BIT) {
2621 struct lsm_param_smm_th_config *smm_th_conf = NULL;
2622 smm_th_conf_param_size =
2623 sizeof(lsm_param_payload_t) + sizeof(*smm_th_conf);
2624
2625 smm_th_conf_param = (unsigned char *)calloc(1, smm_th_conf_param_size);
2626 if (!smm_th_conf_param) {
2627 ALOGE("%s: ERROR. Cannot allocate memory for smm_th_config", __func__);
Quinn Male3d7d9d42019-05-20 13:35:01 -07002628 goto error_exit_1;
Quinn Male2e883752019-03-22 11:28:54 -07002629 }
2630
2631 lsm_fill_param_header((lsm_param_payload_t *)smm_th_conf_param,
2632 sizeof(*smm_th_conf), &mparams[CONFIDENCE_LEVELS]);
2633
2634 ALOGV("%s: confidence threshold %d", __func__, ss_cfg->confidence_threshold);
2635 smm_th_conf = (struct lsm_param_smm_th_config *)
2636 (smm_th_conf_param + sizeof(lsm_param_payload_t));
2637 smm_th_conf->minor_version = 1;
2638 smm_th_conf->smm_threshold = ss_cfg->confidence_threshold;
2639
2640 cfl_params = &param_info[param_count++];
2641 cfl_params->param_size = smm_th_conf_param_size;
2642 cfl_params->param_data = smm_th_conf_param;
2643 /*
2644 * Cannot use LSM_MIN_CONFIDENCE_LEVELS type to send confidence levels
2645 * for non-GMM sound models, as this param type have special handling
2646 * in driver to form payload having multiple keyword and user conf levels
2647 * which is not applicable for GMM sound models.
2648 * Params can be sent using custom param type without extending driver,
2649 * as custom param can take any param payload.
2650 */
2651 lsm_fill_param_info(LSM_CUSTOM_PARAMS, cfl_params,
2652 &mparams[CONFIDENCE_LEVELS], stage_idx);
2653 }
2654
2655 if (param_tag_tracker & PARAM_OPERATION_MODE_BIT) {
2656 op_params = &param_info[param_count++];
2657
Dallas Delaneyf5132c72019-07-01 15:09:06 -07002658 /* CNN and RNN only support keyword detection */
2659 if (ss_cfg->params->common_params.sm_id & ST_SM_ID_SVA_KWD)
Quinn Male2e883752019-03-22 11:28:54 -07002660 det_mode.mode = LSM_MODE_KEYWORD_ONLY_DETECTION;
2661
2662 op_params->param_size = sizeof(det_mode);
2663 op_params->param_data = (unsigned char *)&det_mode;
2664
2665 lsm_fill_param_info(LSM_OPERATION_MODE, op_params,
2666 &mparams[OPERATION_MODE], stage_idx);
2667 }
2668
2669 /*
2670 * Reusing custom config payload from first stage if available,
2671 * MultiStage SM is expected to use same custom config,
2672 * Since same keyword/history buffering is applicable to all stages.
2673 */
2674 if ((param_tag_tracker & PARAM_CUSTOM_CONFIG_BIT) && custom_payload) {
2675 cus_params = &param_info[param_count++];
2676
2677 /* keep the payload as is but need to update param info */
2678 lsm_fill_param_header((lsm_param_payload_t *)custom_payload,
2679 (custom_payload_size - sizeof(lsm_param_payload_t)),
2680 &mparams[CUSTOM_CONFIG]);
2681
2682 cus_params->param_size = custom_payload_size;
2683 cus_params->param_data = (unsigned char *)custom_payload;
2684
2685 lsm_fill_param_info(LSM_CUSTOM_PARAMS, cus_params,
2686 &mparams[CUSTOM_CONFIG], stage_idx);
2687 }
2688
2689 /* set lab for last stage, only when capturing lab */
2690 if ((stage_idx != p_lsm_ses->num_stages - 1) || capture_requested) {
2691 lab_params = &param_info[param_count++];
2692
2693 lab_params->param_size = sizeof(buf_en);
2694 lab_params->param_data = (unsigned char *)&buf_en;
2695
2696 lsm_fill_param_info(LSM_LAB_CONTROL, lab_params,
2697 &mparams[LAB_CONTROL], stage_idx);
2698 }
2699
2700 /* Send all applicable module params for this stage */
2701 lsm_params.num_params = param_count;
2702 if (lsm_params.num_params) {
2703 lsm_params.data_size =
2704 lsm_params.num_params * sizeof(lsm_param_info_t);
2705
Quinn Maleaba13db2019-07-11 15:52:14 -07002706 if (p_lsm_ses->common.stdev->enable_debug_dumps) {
2707 ST_DBG_DECLARE(FILE *lsm_params_fd = NULL;
2708 static int lsm_params_cnt = 0);
2709 ST_DBG_FILE_OPEN_WR(lsm_params_fd, ST_DEBUG_DUMP_LOCATION,
Quinn Male201b59d2020-08-27 16:53:51 -07002710 "lsm_params_data", "bin", lsm_params_cnt);
Quinn Maleaba13db2019-07-11 15:52:14 -07002711 ST_DBG_FILE_WRITE(lsm_params_fd, lsm_params.params,
2712 lsm_params.data_size);
2713 ST_DBG_FILE_CLOSE(lsm_params_fd);
Quinn Male201b59d2020-08-27 16:53:51 -07002714 ALOGD("%s: Multi Stage LSM module params stored in: lsm_params_data_%d.bin",
2715 __func__, lsm_params_cnt);
2716 lsm_params_cnt++;
Quinn Maleaba13db2019-07-11 15:52:14 -07002717 }
Quinn Male2e883752019-03-22 11:28:54 -07002718
2719 status = lsm_set_module_params(p_lsm_ses, &lsm_params);
2720 if (status) {
2721 ALOGE("%s: ERROR. sending reg_sm_params, status %d stage %d",
2722 __func__, status, stage_idx);
Quinn Male3d7d9d42019-05-20 13:35:01 -07002723 goto error_exit_1;
Quinn Male2e883752019-03-22 11:28:54 -07002724 }
2725 }
2726 }
2727
2728 if (capture_requested) {
2729 /*
2730 * Check and set lab if ses was non-multi-stage,
2731 * and lab control param bit was not set.
2732 * LAB_CONTROL params is optional only for single stage session.
2733 */
2734 if (p_lsm_ses->num_stages == 1 &&
Quinn Male8b2cb792020-07-13 14:41:32 -07002735 !(p_lsm_ses->lsm_usecase.param_tag_tracker & PARAM_LAB_CONTROL_BIT)) {
Quinn Male2e883752019-03-22 11:28:54 -07002736 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_lsm_lab_control");
sasevsb07d0c52022-06-01 13:03:40 +05302737#ifdef ENABLE_SVA_MIXER_CTL
2738 status = lsm_send_lab_control_mixer_ctl(p_ses->stdev->mixer, buf_en);
2739#else
Quinn Male2e883752019-03-22 11:28:54 -07002740 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_LAB_CONTROL, &buf_en);
sasevsb07d0c52022-06-01 13:03:40 +05302741#endif
2742
Quinn Male2e883752019-03-22 11:28:54 -07002743 ATRACE_END();
2744 if (status) {
2745 ALOGE("%s: ERROR. SNDRV_LSM_LAB_CONTROL failed, status=%d",
2746 __func__, status);
Quinn Male3d7d9d42019-05-20 13:35:01 -07002747 goto error_exit_1;
Quinn Male2e883752019-03-22 11:28:54 -07002748 }
2749 }
2750
2751 if (!p_lsm_ses->lab_buffers_allocated) {
2752 status = allocate_lab_buffers_ape(p_lsm_ses);
2753 if (status)
Quinn Male3d7d9d42019-05-20 13:35:01 -07002754 goto error_exit_1;
Quinn Male2e883752019-03-22 11:28:54 -07002755 }
2756 }
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07002757 p_ses->lab_enabled = capture_requested;
Quinn Male2e883752019-03-22 11:28:54 -07002758 return status;
2759
Quinn Male3d7d9d42019-05-20 13:35:01 -07002760error_exit_1:
Quinn Male2e883752019-03-22 11:28:54 -07002761
2762 if (p_lsm_ses->lab_buffers_allocated)
2763 deallocate_lab_buffers_ape(p_lsm_ses);
2764
Quinn Male3d7d9d42019-05-20 13:35:01 -07002765 if (smm_th_conf_param)
2766 free(smm_th_conf_param);
2767
2768 if (lab_dam_payload)
2769 free(lab_dam_payload);
Quinn Male2e883752019-03-22 11:28:54 -07002770
2771 if (custom_payload)
2772 free(custom_payload);
2773
Quinn Male3d7d9d42019-05-20 13:35:01 -07002774 pcm_stop(p_lsm_ses->pcm);
2775
2776error_exit:
2777
2778 ape_enable_use_case(false, p_ses);
2779 ape_enable_port_control(false, p_ses);
Quinn Male2e883752019-03-22 11:28:54 -07002780
2781 ALOGD("%s:[%d] Exit, status=%d", __func__,
2782 p_lsm_ses->common.sm_handle, status);
2783
2784 return status;
2785}
2786
2787static int ape_dereg_sm_params(st_hw_session_t* p_ses)
2788{
2789 st_hw_session_lsm_t *p_lsm_ses =
2790 (st_hw_session_lsm_t *)p_ses;
2791
2792 ALOGD("%s:[%d] Enter", __func__, p_lsm_ses->common.sm_handle);
2793 if (p_lsm_ses->pcm){
2794 ATRACE_BEGIN("sthal:lsm: pcm_stop");
2795 pcm_stop(p_lsm_ses->pcm);
2796 ATRACE_END();
2797 }
2798 ape_enable_use_case(false, p_ses);
2799 ape_enable_port_control(false, p_ses);
2800
2801 return 0;
2802}
2803
sasevsb07d0c52022-06-01 13:03:40 +05302804#ifdef ENABLE_SVA_MIXER_CTL
2805int lsm_set_ape_control_mixer_ctl(struct mixer * st_mixer, int operation)
2806{
2807 struct mixer_ctl *ctl = NULL;
2808 const char *mixer_ctl_name = "LSM APE_CONTROL CMD";
2809
2810 ctl = mixer_get_ctl_by_name(st_mixer, mixer_ctl_name);
2811 if (!ctl) {
2812 ALOGE("%s: Could not get ctl for mixer cmd - %s",
2813 __func__, mixer_ctl_name);
2814 }
2815 if (mixer_ctl_set_value(ctl, 0, operation) < 0) {
2816 ALOGE("%s: Could not set LSM load mixer control", __func__);
2817 return -EFAULT;
2818 }
2819 return 0;
2820}
2821#endif
2822
Quinn Male2e883752019-03-22 11:28:54 -07002823static int ape_start(st_hw_session_t* p_ses)
2824{
2825 int status = 0;
2826 st_hw_session_lsm_t *p_lsm_ses =
2827 (st_hw_session_lsm_t *)p_ses;
2828
2829 ALOGD("%s:[%d] Enter", __func__, p_lsm_ses->common.sm_handle);
2830 if (!p_lsm_ses->pcm) {
2831 ALOGW("%s: pcm NULL", __func__);
2832 return status;
2833 }
2834
2835 p_lsm_ses->exit_lab_processing = false;
2836
2837 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_lsm_start");
sasevsb07d0c52022-06-01 13:03:40 +05302838#ifdef ENABLE_SVA_MIXER_CTL
2839 status = lsm_set_ape_control_mixer_ctl(p_ses->stdev->mixer, ST_LSM_START);
2840#else
Quinn Male2e883752019-03-22 11:28:54 -07002841 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_START);
sasevsb07d0c52022-06-01 13:03:40 +05302842#endif
Quinn Male2e883752019-03-22 11:28:54 -07002843 ATRACE_END();
2844 if (status) {
2845 ALOGE("%s: ERROR. SNDRV_LSM_START failed, status=%d", __func__, status);
2846 }
2847
2848 ALOGD("%s:[%d] Exit, status=%d", __func__, p_lsm_ses->common.sm_handle,
2849 status);
2850 return status;
2851}
2852
2853static int ape_stop(st_hw_session_t* p_ses)
2854{
2855 int status = 0;
2856 st_hw_session_lsm_t *p_lsm_ses =
2857 (st_hw_session_lsm_t *)p_ses;
2858
2859 ALOGD("%s:[%d] Enter", __func__, p_lsm_ses->common.sm_handle);
2860 if (!p_lsm_ses->pcm) {
2861 ALOGW("%s: pcm NULL", __func__);
2862 return status;
2863 }
2864
2865 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_lsm_stop");
sasevsb07d0c52022-06-01 13:03:40 +05302866#ifdef ENABLE_SVA_MIXER_CTL
2867 status = lsm_set_ape_control_mixer_ctl(p_ses->stdev->mixer, ST_LSM_STOP);
2868#else
Quinn Male2e883752019-03-22 11:28:54 -07002869 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_STOP);
sasevsb07d0c52022-06-01 13:03:40 +05302870#endif
Quinn Male2e883752019-03-22 11:28:54 -07002871 ATRACE_END();
2872 if (status)
2873 ALOGE("%s: ERROR. SNDDRV_LSM_STOP failed, status=%d", __func__, status);
2874
2875 ALOGD("%s:[%d] Exit, status=%d", __func__, p_lsm_ses->common.sm_handle,
2876 status);
2877 return status;
2878}
2879
2880static int ape_stop_buffering(st_hw_session_t* p_ses)
2881{
2882 int status = 0;
2883 st_hw_session_lsm_t *p_lsm_ses =
2884 (st_hw_session_lsm_t *)p_ses;
2885
2886 ALOGD("%s:[%d] Enter pcm %p", __func__, p_lsm_ses->common.sm_handle,
2887 p_lsm_ses->pcm);
2888 if (!p_lsm_ses->pcm) {
2889 ALOGW("%s: pcm NULL", __func__);
2890 return status;
2891 }
2892
2893 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_lsm_stop_lab");
sasevsb07d0c52022-06-01 13:03:40 +05302894#ifdef ENABLE_SVA_MIXER_CTL
2895 status = lsm_set_ape_control_mixer_ctl(p_ses->stdev->mixer, ST_LSM_STOP_LAB);
2896#else
Quinn Male2e883752019-03-22 11:28:54 -07002897 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_STOP_LAB);
sasevsb07d0c52022-06-01 13:03:40 +05302898#endif
Quinn Male2e883752019-03-22 11:28:54 -07002899 ATRACE_END();
2900 if (status) {
2901 ALOGE("%s: ERROR. SNDRV_LSM_STOP_BUFFERING failed status %d", __func__,
2902 status);
sasevsb07d0c52022-06-01 13:03:40 +05302903 }
2904#ifndef ENABLE_SVA_MIXER_CTL
2905 else {
Quinn Male2e883752019-03-22 11:28:54 -07002906 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_pcm_ioctl_reset");
2907 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_PCM_IOCTL_RESET);
2908 ATRACE_END();
2909 if (status) ALOGE("%s: ERROR. SNDRV_PCM_IOCTL_RESET failed status %d", __func__,
2910 status);
2911 }
sasevsb07d0c52022-06-01 13:03:40 +05302912#endif
Quinn Male2e883752019-03-22 11:28:54 -07002913
2914 ALOGD("%s:[%d] Exit, status=%d", __func__, p_ses->sm_handle, status);
2915 return status;
2916}
2917
Harshal Ahire63dfba52020-07-13 02:38:14 +05302918#ifdef SNDRV_LSM_GET_MODULE_PARAMS
2919static int ape_open_session(st_hw_session_t *p_ses)
2920{
2921 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t*)p_ses;
2922 struct st_vendor_info *v_info = p_ses->vendor_uuid_info;
2923 int status = 0;
2924 audio_devices_t capture_device = 0;
2925
2926 status = platform_get_lsm_usecase(p_ses->stdev->platform, v_info,
2927 &p_lsm_ses->lsm_usecase, p_ses->exec_mode, p_ses->lpi_enable,
2928 p_ses->f_stage_version);
2929
2930 if (status) {
2931 ALOGE("%s: couldn't get lsm usecase", __func__);
2932 return -EINVAL;
2933 }
2934
2935 p_lsm_ses->pcm_id = platform_ape_get_pcm_device_id(
2936 p_ses->stdev->platform, &p_ses->use_case_idx);
2937 if (p_lsm_ses->pcm_id < 0) {
2938 ALOGE("%s: get pcm id failed %d\n",__func__, p_lsm_ses->pcm_id);
2939 return -ENODEV;
2940 }
2941
2942 int app_type = (v_info->app_type == 0) ?
2943 p_lsm_ses->lsm_usecase.app_type : v_info->app_type;
2944
2945 capture_device = platform_stdev_get_capture_device(p_ses->stdev->platform);
2946 status = platform_stdev_send_calibration(p_ses->stdev->platform,
2947 capture_device,
2948 p_ses->exec_mode,
2949 p_ses->vendor_uuid_info,
2950 app_type, true,
2951 ST_SESSION_CAL);
2952
2953 if (status) {
2954 ALOGE("%s: ERROR. sending calibration failed status %d, idx 0",
2955 __func__, status);
2956 goto error;
2957 }
2958 p_lsm_ses->num_stages = 1;
2959 p_lsm_ses->common.config = stdev_ape_pcm_config;
2960 platform_stdev_check_and_update_pcm_config(&p_lsm_ses->common.config,
2961 v_info);
2962
2963 ALOGD("%s: opening pcm device=%d", __func__, p_lsm_ses->pcm_id);
2964 ALOGV("%s: config: channels=%d rate=%d, period_size=%d, period_cnt=%d, format=%d",
2965 __func__, p_lsm_ses->common.config.channels, p_lsm_ses->common.config.rate,
2966 p_lsm_ses->common.config.period_size, p_lsm_ses->common.config.period_count,
2967 p_lsm_ses->common.config.format);
2968
2969 ATRACE_BEGIN("sthal:lsm: pcm_open");
2970 p_lsm_ses->pcm = pcm_open(p_ses->stdev->snd_card, p_lsm_ses->pcm_id,
2971 PCM_IN, &p_lsm_ses->common.config);
2972 ATRACE_END();
2973
2974 if (!p_lsm_ses->pcm) {
2975 ALOGE("%s: ERROR. pcm_open failed", __func__);
2976 status = -ENODEV;
2977 goto error;
2978 }
2979 if (!pcm_is_ready(p_lsm_ses->pcm)) {
2980 ALOGE("%s: ERROR. pcm_is_ready failed err=%s", __func__,
2981 pcm_get_error(p_lsm_ses->pcm));
2982 status = -ENODEV;
2983 goto error;
2984 }
2985
2986 if (st_hw_check_multi_stage_lsm_support()) {
2987 status = lsm_set_session_data_v2(p_ses);
2988 if (status)
2989 goto error;
2990 }
2991 return 0;
2992
2993error:
2994 platform_ape_free_pcm_device_id(p_ses->stdev->platform, p_lsm_ses->pcm_id);
2995 if (p_lsm_ses->pcm) {
2996 pcm_close(p_lsm_ses->pcm);
2997 p_lsm_ses->pcm = NULL;
2998 }
2999 return status;
3000}
3001
3002void ape_close_session(st_hw_session_t *p_ses)
3003{
3004 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t*)p_ses;
3005
3006 ATRACE_BEGIN("sthal:lsm: pcm_close");
3007 pcm_close(p_lsm_ses->pcm);
3008 ATRACE_END();
3009 p_lsm_ses->pcm = NULL;
3010}
3011
3012int ape_get_module_version(st_hw_session_t *p_ses, void *param_info_payload,
3013 size_t param_size)
3014{
3015 struct st_module_param_info *mparams = NULL;
3016 struct lsm_params_get_info *get_params;
3017 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t*)p_ses;
3018 int status = 0;
3019 size_t size = 0;
3020
3021 mparams = p_lsm_ses->lsm_usecase.params;
3022 size = sizeof(struct lsm_params_get_info) + param_size;
3023 get_params = calloc(1, size);
3024 if (!get_params) {
3025 ALOGE("%s: ERROR. Can not allocate memory for get params", __func__);
3026 return -ENOMEM;
3027 }
3028
3029 get_params->param_size = param_size;
3030 lsm_fill_get_param_info(LSM_GET_CUSTOM_PARAMS, get_params,
3031 &mparams[VERSION_ID],
3032 LSM_STAGE_INDEX_FIRST);
3033 status = lsm_get_module_params(p_lsm_ses, get_params);
3034 if (status) {
3035 ALOGE("%s: ERROR. getting module version. status %d",
3036 __func__, status);
3037 goto done;
3038 }
3039 memcpy(param_info_payload, get_params->payload, param_size);
3040done:
3041 free(get_params);
3042 return status;
3043}
3044#else
3045static int ape_open_session(st_hw_session_t* p_ses __unused)
3046{
3047 return -ENOSYS;
3048}
3049
3050static void ape_close_session(st_hw_session_t* p_ses __unused)
3051{
3052 return;
3053}
3054#endif
3055
Quinn Male2e883752019-03-22 11:28:54 -07003056static int route_reg_sm_ape(st_hw_session_t *p_ses,void *sm_data,
Quinn Male58749452020-03-26 17:14:56 -07003057 unsigned int sm_size, uint32_t model_id)
Quinn Male2e883752019-03-22 11:28:54 -07003058{
Quinn Male58749452020-03-26 17:14:56 -07003059 return ape_reg_sm(p_ses, sm_data, sm_size, model_id);
Quinn Male2e883752019-03-22 11:28:54 -07003060}
3061
3062static int route_reg_sm_params_ape(st_hw_session_t* p_ses,
3063 unsigned int recognition_mode, bool capture_requested,
Quinn Male58749452020-03-26 17:14:56 -07003064 struct sound_trigger_recognition_config *rc_config)
Quinn Male2e883752019-03-22 11:28:54 -07003065{
3066 return ape_reg_sm_params(p_ses, recognition_mode, capture_requested,
Quinn Male58749452020-03-26 17:14:56 -07003067 rc_config);
Quinn Male2e883752019-03-22 11:28:54 -07003068}
3069
3070static int route_dereg_sm_params_ape(st_hw_session_t* p_ses)
3071{
3072 return ape_dereg_sm_params(p_ses);
3073}
3074
Quinn Male58749452020-03-26 17:14:56 -07003075static int route_dereg_sm_ape(st_hw_session_t* p_ses, uint32_t model_id)
Quinn Male2e883752019-03-22 11:28:54 -07003076{
3077 int status = 0;
3078
Quinn Male58749452020-03-26 17:14:56 -07003079 status = ape_dereg_sm(p_ses, model_id);
Quinn Male2e883752019-03-22 11:28:54 -07003080
3081 return status;
3082}
3083
3084static int route_start_ape(st_hw_session_t* p_ses)
3085{
3086
3087 return ape_start(p_ses);
3088}
3089
3090static int route_restart_ape(st_hw_session_t* p_ses,
3091 unsigned int recognition_mode __unused,
Quinn Male58749452020-03-26 17:14:56 -07003092 struct sound_trigger_recognition_config *rc_config __unused)
Quinn Male2e883752019-03-22 11:28:54 -07003093{
3094 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
3095
3096 ALOGD("%s:[%d] Enter", __func__, p_lsm_ses->common.sm_handle);
3097 p_lsm_ses->exit_lab_processing = false;
3098 return 0;
3099}
3100
3101static int route_stop_ape(st_hw_session_t* p_ses)
3102{
3103
3104 return ape_stop(p_ses);
3105}
3106
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07003107static int route_stop_buffering_ape(st_hw_session_t* p_ses)
Quinn Male2e883752019-03-22 11:28:54 -07003108{
3109 int status = 0;
3110 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
3111 struct timespec tspec;
3112 st_arm_second_stage_t *st_sec_stage;
3113 struct listnode *node = NULL, *tmp_node = NULL;
3114 bool restart_pcm_on_timeout = true;
3115
3116 if (p_ses->enable_second_stage) {
3117 list_for_each_safe(node, tmp_node, p_lsm_ses->common.second_stage_list) {
3118 st_sec_stage = node_to_item(node, st_arm_second_stage_t, list_node);
3119 pthread_mutex_lock(&st_sec_stage->ss_session->lock);
3120 st_sec_stage->ss_session->exit_buffering = true;
3121 pthread_cond_signal(&st_sec_stage->ss_session->cond);
3122 pthread_mutex_unlock(&st_sec_stage->ss_session->lock);
3123 }
3124 }
3125
3126 p_lsm_ses->exit_lab_processing = true;
3127 pthread_mutex_lock(&p_lsm_ses->lock);
3128
3129 /* wait for buffering thread to exit */
3130 while (p_lsm_ses->lab_processing_active) {
3131 GET_WAIT_TIMESPEC(tspec,
3132 convert_bytes_to_ms((p_lsm_ses->lab_drv_buf_size * 2),
3133 &p_ses->config) * NSECS_PER_MSEC);
3134 ALOGV("%s: waiting on exit cond", __func__);
3135 status = pthread_cond_timedwait(&p_lsm_ses->cond, &p_lsm_ses->lock,
3136 &tspec);
3137 ALOGV("%s: done waiting on exit cond", __func__);
3138 if (status) {
3139 ALOGE("%s: ERROR. wait timed out, ret %d, retry = %d",
3140 __func__, status, restart_pcm_on_timeout);
3141 /*
3142 * retry once more after aborting ongoing read with
3143 * pcm_stop/start
3144 */
3145 if (restart_pcm_on_timeout && p_lsm_ses->pcm) {
3146 pcm_stop(p_lsm_ses->pcm);
3147 pcm_start(p_lsm_ses->pcm);
3148 restart_pcm_on_timeout = false;
3149 continue;
3150 }
3151 status = -status;
3152 break;
3153 }
3154 }
Venkatesh Mangalappalie4f17532019-06-04 16:30:28 -07003155 if (p_lsm_ses->lab_on_detection) {
3156 ape_stop_buffering(&p_lsm_ses->common);
3157 p_lsm_ses->lab_on_detection = false;
3158 }
3159
Quinn Male2e883752019-03-22 11:28:54 -07003160 pthread_mutex_unlock(&p_lsm_ses->lock);
3161
3162 return status;
3163}
3164
3165static int route_set_device_ape(st_hw_session_t *p_ses,
3166 bool enable)
3167{
3168 return sound_trigger_set_device(p_ses, enable);
3169}
3170
3171static int route_read_pcm_ape(st_hw_session_t *p_ses,
3172 unsigned char *buf,
3173 unsigned int bytes)
3174{
3175 int status = 0;
3176 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
3177
Quinn Maled0814de2019-05-29 17:33:22 -07003178 ATRACE_BEGIN("sthal:lsm:client: read_pcm_data");
Quinn Male2e883752019-03-22 11:28:54 -07003179 status = read_pcm_data(p_lsm_ses, buf, bytes);
3180 ATRACE_END();
3181
3182 return status;
3183}
3184
3185static void route_audio_capture_ape(st_hw_session_t *p_ses)
3186{
3187 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
3188
Quinn Male48490df2020-03-25 10:25:42 -07003189 pthread_mutex_lock(&p_lsm_ses->lock);
3190 p_lsm_ses->lab_processing_active = true;
3191 pthread_cond_signal(&p_lsm_ses->cond);
3192 pthread_mutex_unlock(&p_lsm_ses->lock);
Quinn Male2e883752019-03-22 11:28:54 -07003193}
3194
3195int route_send_custom_chmix_coeff_ape(st_hw_session_t *p_ses, char *str)
3196{
3197 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
3198
3199 return platform_stdev_send_custom_channel_mixing_coefficients(p_ses->stdev->platform,
3200 p_ses->vendor_uuid_info,
3201 p_lsm_ses->pcm_id,
3202 str);
3203}
3204
Quinn Male2e883752019-03-22 11:28:54 -07003205static int route_disable_device(st_hw_session_t *p_ses, bool setting_device)
3206{
3207 int status = 0;
3208 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t*)p_ses;
3209
Quinn Male9a345522020-03-12 17:49:25 -07003210 if (!setting_device)
Quinn Male2e883752019-03-22 11:28:54 -07003211 return status;
3212
3213 ALOGD("%s: Enter", __func__);
3214
3215 status = ape_stop(p_ses);
3216 if (status)
3217 return status;
3218
3219 if (p_lsm_ses->pcm)
3220 pcm_stop(p_lsm_ses->pcm);
3221
3222 ape_enable_use_case(false, p_ses);
3223 ape_enable_port_control(false, p_ses);
3224
3225 status = sound_trigger_set_device(p_ses, false);
3226 if (status)
3227 return status;
3228
3229 ALOGD("%s: Exit", __func__);
3230 return status;
3231}
3232
3233static int route_enable_device(st_hw_session_t *p_ses, bool setting_device)
3234{
3235 int status = 0;
3236 int retry_num = 0;
3237 struct st_vendor_info *v_info = p_ses->vendor_uuid_info;
3238 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t*)p_ses;
3239 audio_devices_t capture_device = 0;
3240
Quinn Male2e883752019-03-22 11:28:54 -07003241 ALOGD("%s: Enter", __func__);
3242
Quinn Male26359bb2019-08-09 14:17:59 -07003243 if (!p_lsm_ses->pcm) {
3244 ALOGE("%s: pcm NULL", __func__);
3245 return -ENODEV;
3246 }
3247
Quinn Male2e883752019-03-22 11:28:54 -07003248 capture_device = platform_stdev_get_capture_device(p_ses->stdev->platform);
3249
Quinn Male8b2cb792020-07-13 14:41:32 -07003250 status = platform_get_lsm_usecase(p_ses->stdev->platform, v_info,
Quinn Male58749452020-03-26 17:14:56 -07003251 &p_lsm_ses->lsm_usecase, p_ses->exec_mode, p_ses->lpi_enable,
3252 p_ses->f_stage_version);
Quinn Male8b2cb792020-07-13 14:41:32 -07003253 if (status) {
3254 ALOGE("%s: failed to get the lsm usecase for the session", __func__);
Quinn Male2e883752019-03-22 11:28:54 -07003255 return -ENODEV;
3256 }
3257
3258 status = platform_stdev_send_calibration(p_ses->stdev->platform,
3259 capture_device,
3260 p_ses->exec_mode,
3261 p_ses->vendor_uuid_info,
3262 v_info->app_type, true,
3263 ST_SESSION_CAL);
3264
3265 status = send_lsm_input_hw_params(p_ses);
3266 if (status)
3267 return status;
3268
3269 /*
3270 * If the setting_device flag is true, the session is in the active state.
3271 * Otherwise, session is in the loaded state and bringup will happen
3272 * when the session is started/resumed.
3273 */
3274 if (!setting_device)
3275 return status;
3276
3277 status = sound_trigger_set_device(p_ses, true);
3278 if (status)
3279 return status;
3280
3281 if (ape_enable_port_control(true, p_ses) == 0) {
3282 status = lsm_set_port(p_lsm_ses);
3283 if (!status)
3284 ape_enable_use_case(true, p_ses);
3285 } else {
3286 ape_enable_use_case(true, p_ses);
3287 status = lsm_set_port(p_lsm_ses);
3288 }
3289 if (status) {
3290 ALOGE("%s: ERROR. set port failed, returned status %d",
3291 __func__, status);
3292 goto exit_1;
3293 }
3294
3295 status = pcm_start(p_lsm_ses->pcm);
3296 while (status && (retry_num < SOUND_TRIGGER_PCM_MAX_RETRY)) {
3297 usleep(SOUND_TRIGGER_PCM_SLEEP_WAIT);
3298 retry_num++;
3299 ALOGE("%s: pcm_start retrying..status %d: %s, retry cnt %d",
3300 __func__, status, strerror(errno), retry_num);
3301 status = pcm_start(p_lsm_ses->pcm);
3302 }
3303 if (status) {
3304 ALOGE("%s: ERROR. pcm_start failed, %s",
3305 __func__, strerror(errno));
3306 goto exit_1;
3307 }
3308
Zhou Song68bfc6e2020-03-03 14:32:39 +08003309 if (!p_ses->stdev->lpi_enable && !p_ses->stdev->barge_in_mode &&
3310 p_ses->stdev->support_barge_in_mode) {
Quinn Malecc1affd2019-07-18 16:13:31 -07003311 status = platform_stdev_update_ec_effect(p_ses->stdev->platform,
3312 false);
3313 if (status) {
3314 ALOGE("%s: ERROR. Failed to update EC ref, %d",
3315 __func__, status);
3316 goto exit_2;
3317 }
3318 }
3319
Quinn Male2e883752019-03-22 11:28:54 -07003320 status = ape_start(p_ses);
3321 if (status)
3322 goto exit_2;
3323
3324 ALOGD("%s: Exit", __func__);
3325 return status;
3326
3327exit_2:
3328 pcm_stop(p_lsm_ses->pcm);
3329
3330exit_1:
3331 ape_enable_use_case(false, p_ses);
3332 ape_enable_port_control(false, p_ses);
3333 sound_trigger_set_device(p_ses, false);
3334 return status;
3335}
3336
3337static void request_exit_callback_thread(st_hw_session_lsm_t *p_lsm_ses)
3338{
3339 int status;
3340 int wait_result;
3341 struct timespec timeout;
sasevsb07d0c52022-06-01 13:03:40 +05303342 st_hw_session_t p_ses;
Quinn Male2e883752019-03-22 11:28:54 -07003343
sasevsb07d0c52022-06-01 13:03:40 +05303344 p_ses = p_lsm_ses->common;
Quinn Male2e883752019-03-22 11:28:54 -07003345 pthread_mutex_lock(&p_lsm_ses->callback_thread_lock);
3346 p_lsm_ses->exit_callback_thread = true;
3347 for (int i = 0; i < LSM_ABORT_RETRY_COUNT; i++) {
3348 ATRACE_BEGIN("sthal:lsm: pcm_ioctl sndrv_lsm_abort_event");
Harshal Ahire387953e2021-02-19 15:18:39 +05303349 if(!p_lsm_ses->pcm) {
3350 ALOGE("%s: PCM is NULL",__func__);
3351 pthread_mutex_unlock(&p_lsm_ses->callback_thread_lock);
3352 return;
3353 }
sasevsb07d0c52022-06-01 13:03:40 +05303354#ifdef ENABLE_SVA_MIXER_CTL
3355 status = lsm_set_ape_control_mixer_ctl(p_ses.stdev->mixer, ST_LSM_ABORT_EVENT);
3356#else
Quinn Male2e883752019-03-22 11:28:54 -07003357 status = pcm_ioctl(p_lsm_ses->pcm, SNDRV_LSM_ABORT_EVENT);
sasevsb07d0c52022-06-01 13:03:40 +05303358#endif
Quinn Male2e883752019-03-22 11:28:54 -07003359 ATRACE_END();
3360 GET_WAIT_TIMESPEC(timeout, LSM_ABORT_WAIT_TIMEOUT_NS);
3361 wait_result = pthread_cond_timedwait(&p_lsm_ses->callback_thread_cond,
3362 &p_lsm_ses->callback_thread_lock, &timeout);
3363 if (wait_result == ETIMEDOUT) {
3364 ALOGW("%s: wait for callback thread exit timeout, retry...", __func__);
3365 continue;
3366 } else {
3367 break;
3368 }
3369 }
3370 pthread_mutex_unlock(&p_lsm_ses->callback_thread_lock);
3371
3372 if (status)
3373 ALOGE("%s: ERROR. SNDRV_LSM_ABORT_EVENT failed, status=%d", __func__,
3374 status);
3375}
3376
3377static int get_param_data(st_hw_session_t *p_ses, const char *param,
3378 void *payload, size_t payload_size,
3379 size_t *param_data_size)
3380{
3381 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
3382 int ret = -EINVAL, i = 0;
3383 unsigned int count = 0;
3384 size_t param_size = 0;
3385 char doa_mixer_ctl_name[MIXER_PATH_MAX_LENGTH] = "Doa Tracking Monitor Listen";
3386 struct mixer_ctl *ctl = NULL;
3387 st_ffv_doa_tracking_monitor_t doa_data = {{0}, {0}, {0}};
3388 struct qsthw_source_tracking_param st_params = {{0}, {0}, {0}};
3389
3390 if (!param || !payload || !param_data_size) {
3391 ALOGE("%s: ERROR. Invalid params", __func__);
3392 goto exit;
3393 }
3394
Quinn Male2e883752019-03-22 11:28:54 -07003395 ALOGD("%s:[%d] Enter param %s", __func__, p_lsm_ses->common.sm_handle, param);
3396 if (!strncmp(param, QSTHW_PARAMETER_DIRECTION_OF_ARRIVAL,
3397 sizeof(QSTHW_PARAMETER_DIRECTION_OF_ARRIVAL))) {
3398 param_size = sizeof(struct qsthw_source_tracking_param);
3399 if (payload_size < param_size) {
3400 ALOGE("%s: ERROR. Invalid payload size %zu", __func__, payload_size);
3401 goto exit;
3402 }
3403
3404 ret = platform_stdev_derive_mixer_ctl_from_backend(p_ses->stdev->platform,
3405 doa_mixer_ctl_name);
3406 if (ret) {
3407 ALOGE("%s: ERROR. Could not derive mixer ctl from backend", __func__);
3408 goto exit;
3409 }
3410
3411 ctl = mixer_get_ctl_by_name(p_ses->stdev->mixer, doa_mixer_ctl_name);
3412 if (!ctl) {
3413 ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
3414 __func__, doa_mixer_ctl_name);
3415 goto exit;
3416 }
3417
3418 mixer_ctl_update(ctl);
3419 count = mixer_ctl_get_num_values(ctl);
3420 if (count != sizeof(st_ffv_doa_tracking_monitor_t)) {
3421 ALOGE("%s: ERROR. Invalid doa data size %d", __func__, count);
3422 goto exit;
3423 }
3424
3425 ret = mixer_ctl_get_array(ctl, (void *)&doa_data, count);
3426 if (!ret) {
3427 /* copy adsp doa payload to client requested format */
3428 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
3429 st_params.target_angle_L16[i] = doa_data.target_angle_L16[i];
3430 ALOGV("%s: target angle[%d] = %d", __func__, i,
3431 st_params.target_angle_L16[i]);
3432 }
3433
3434 for (i = 0; i < MAX_DOA_TRACKING_ANGLES; i++) {
3435 st_params.interf_angle_L16[i] = doa_data.interf_angle_L16[i];
3436 ALOGV("%s: interference angle[%d] = %d", __func__, i,
3437 st_params.interf_angle_L16[i]);
3438 }
3439
3440 memcpy(&st_params.polarActivityGUI, &doa_data.polarActivityGUI,
3441 DOA_POLAR_ACTIVITY_INDICATORS);
3442
3443 memcpy(payload, &st_params, param_size);
3444 *param_data_size = param_size;
3445 } else {
3446 ALOGE("%s: ERROR. Invalid doa data returned", __func__);
3447 }
3448 } else {
3449 ALOGE("%s: ERROR. Unsupported param %s", __func__, param);
3450 goto exit;
3451 }
3452
3453exit:
3454 return ret;
3455}
3456
3457static int send_detection_request(st_hw_session_t *p_ses)
3458{
3459 int status = 0, stage_idx = 0;
3460 st_hw_session_lsm_t *p_lsm_ses =
3461 (st_hw_session_lsm_t *)p_ses;
3462 struct lsm_param_custom_config custom_conf_params = {{0}, {0}};
3463 struct snd_lsm_module_params lsm_params = {0};
3464 struct st_module_param_info *mparams = NULL;
3465 lsm_param_info_t param_info = {0};
3466 lsm_param_payload_t lsm_param_payload = {0};
3467 unsigned char *custom_payload = NULL;
3468 uint32_t data_payload_size = 0, lsm_param_payload_size = 0;
3469 uint32_t data_payload_addr_lsw = 0, data_payload_addr_msw = 0;
3470 uint32_t custom_payload_size = 0, mem_map_handle = 0;
3471
Quinn Male8b2cb792020-07-13 14:41:32 -07003472 if (!(p_lsm_ses->lsm_usecase.param_tag_tracker &
Quinn Male2e883752019-03-22 11:28:54 -07003473 PARAM_REQUEST_DETECTION_BIT)) {
3474 ALOGE("%s: No request detection IDs set, exiting", __func__);
3475 return -EINVAL;
3476 }
3477
Quinn Male8b2cb792020-07-13 14:41:32 -07003478 mparams = p_lsm_ses->lsm_usecase.params;
Quinn Male2e883752019-03-22 11:28:54 -07003479 stage_idx = LSM_STAGE_INDEX_FIRST;
3480 if (platform_stdev_get_xml_version(p_ses->stdev->platform) >
3481 PLATFORM_XML_VERSION_0x0102) {
3482 lsm_fill_param_header(&lsm_param_payload,
3483 lsm_param_payload_size, &mparams[REQUEST_DETECTION]);
3484
3485 custom_payload_size = sizeof(lsm_param_payload);
3486 custom_payload = (unsigned char *)calloc(1, custom_payload_size);
3487 if (!custom_payload) {
3488 ALOGE("%s: ERROR. Cannot allocate memory for custom_payload",
3489 __func__);
3490 status = -ENOMEM;
3491 goto error_exit;
3492 }
3493
3494 memcpy(custom_payload, &lsm_param_payload,
3495 sizeof(lsm_param_payload));
3496 } else {
3497 param_info.param_type = LSM_CUSTOM_PARAMS;
3498 lsm_param_payload_size = sizeof(custom_conf_params) -
3499 sizeof(custom_conf_params.set_param);
3500 data_payload_size = lsm_param_payload_size;
3501 fill_set_params_payload(&custom_conf_params.set_param,
3502 data_payload_size, data_payload_addr_lsw, data_payload_addr_msw,
3503 mem_map_handle);
3504
3505 lsm_fill_param_header((lsm_param_payload_t *)&custom_conf_params.common,
3506 lsm_param_payload_size, &mparams[REQUEST_DETECTION]);
3507
3508 custom_payload_size = sizeof(struct lsm_param_custom_config);
3509 custom_payload = (unsigned char *)calloc(1, custom_payload_size);
3510 if (!custom_payload) {
3511 ALOGE("%s: ERROR. Cannot allcoate memory for custom_payload",
3512 __func__);
3513 status = -ENOMEM;
3514 goto error_exit;
3515 }
3516
3517 memcpy(custom_payload, &custom_conf_params,
3518 sizeof(struct lsm_param_custom_config));
3519 }
3520
3521 param_info.param_size = custom_payload_size;
3522 param_info.param_data = (unsigned char *)custom_payload;
3523 lsm_fill_param_info(LSM_CUSTOM_PARAMS, &param_info,
3524 &mparams[REQUEST_DETECTION], stage_idx);
3525
3526 lsm_params.params = (unsigned char*)&param_info;
3527 lsm_params.num_params = 1;
3528 lsm_params.data_size = sizeof(lsm_param_info_t);
3529
Quinn Maleaba13db2019-07-11 15:52:14 -07003530 if (p_ses->stdev->enable_debug_dumps) {
3531 ST_DBG_DECLARE(FILE *req_event_fd = NULL;
3532 static int req_event_cnt = 0);
3533 ST_DBG_FILE_OPEN_WR(req_event_fd, ST_DEBUG_DUMP_LOCATION,
Quinn Male201b59d2020-08-27 16:53:51 -07003534 "requested_event_lsm", "bin", req_event_cnt);
Quinn Maleaba13db2019-07-11 15:52:14 -07003535 ST_DBG_FILE_WRITE(req_event_fd, param_info.param_data,
3536 param_info.param_size);
3537 ST_DBG_FILE_CLOSE(req_event_fd);
Quinn Male201b59d2020-08-27 16:53:51 -07003538 ALOGD("%s: Requested detection event dump stored in: lsm_params_data_%d.bin",
3539 __func__, req_event_cnt);
3540 req_event_cnt++;
Quinn Maleaba13db2019-07-11 15:52:14 -07003541 }
Quinn Male2e883752019-03-22 11:28:54 -07003542
3543 status = lsm_set_module_params(p_lsm_ses, &lsm_params);
3544 if (status)
3545 ALOGE("%s: ERROR. setting module params. status %d",
3546 __func__, status);
3547
3548error_exit:
3549 if (custom_payload)
3550 free(custom_payload);
3551
3552 return status;
3553}
3554
3555int st_hw_sess_lsm_init(st_hw_session_t *const p_ses,
3556 hw_ses_event_callback_t cb, void* cookie, st_exec_mode_t exec_mode,
3557 struct st_vendor_info* v_info, sound_model_handle_t sm_handle,
3558 sound_trigger_device_t *stdev)
3559{
3560 int status = 0;
3561 pthread_condattr_t c_attr;
3562 pthread_condattr_t c_attr_buf;
3563 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
3564
3565 p_ses->exec_mode = exec_mode;
Quinn Male9a345522020-03-12 17:49:25 -07003566 p_ses->fptrs = &ape_fptrs;
Quinn Male2e883752019-03-22 11:28:54 -07003567
3568 p_ses->callback_to_st_session = cb;
3569 p_ses->cookie = cookie;
3570 p_ses->vendor_uuid_info = v_info;
3571 p_ses->sm_handle = sm_handle;
3572 p_ses->stdev = stdev;
3573 p_ses->is_generic_event = false;
Quinn Male2e883752019-03-22 11:28:54 -07003574
3575 p_lsm_ses->exit_lab_processing = false;
3576 p_lsm_ses->lab_processing_active = false;
3577 list_init(&p_ses->lsm_ss_cfg_list);
Quinn Male58749452020-03-26 17:14:56 -07003578 list_init(&p_ses->sthw_cfg_list);
Quinn Male2e883752019-03-22 11:28:54 -07003579
3580 pthread_condattr_init(&c_attr);
3581 pthread_condattr_setclock(&c_attr, CLOCK_MONOTONIC);
3582 pthread_cond_init(&p_lsm_ses->callback_thread_cond, &c_attr);
3583 pthread_mutex_init(&p_lsm_ses->callback_thread_lock, NULL);
3584
3585 pthread_mutex_init(&p_lsm_ses->lock,
3586 (const pthread_mutexattr_t *) NULL);
3587 pthread_condattr_init(&c_attr_buf);
3588 pthread_condattr_setclock(&c_attr_buf, CLOCK_MONOTONIC);
3589 pthread_cond_init(&p_lsm_ses->cond, &c_attr_buf);
3590
3591 return status;
3592}
3593
3594void st_hw_sess_lsm_deinit(st_hw_session_t *const p_ses)
3595{
3596 st_hw_session_lsm_t *p_lsm_ses = (st_hw_session_lsm_t *)p_ses;
3597
3598 pthread_cond_destroy(&p_lsm_ses->callback_thread_cond);
3599 pthread_mutex_destroy(&p_lsm_ses->callback_thread_lock);
3600 pthread_cond_destroy(&p_lsm_ses->cond);
3601 pthread_mutex_destroy(&p_lsm_ses->lock);
3602}