mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-12 15:49:17 -04:00
msm-lsm-client: decouple input and output hardware parameters
With multichannel voice activation support in LSM, it could be possible that the input media format/hw_params to LSM would be different than the output media format/hw_params. This change decouples the input and output hw_params for LSM. The output hw_params are obtained through ALSA pcm_hw_params operation, whereas the input hw_params are obtained though the LSM_SET_INPUT_HW_PARAMS ioctl to LSM. At the same time, the below parameter IDs are added to send the channel information to LSM service: - LSM_PARAM_ID_MEDIA_FMT_V2 - LSM_PARAM_ID_LAB_OUTPUT_CHANNEL_CONFIG Change-Id: Ie53a087b0ec54e83c4eba93a0828f9bdd6cc147d Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
This commit is contained in:
parent
1f6b04af93
commit
6ee5b50fd4
4 changed files with 293 additions and 105 deletions
|
|
@ -53,8 +53,8 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = {
|
|||
SNDRV_PCM_RATE_48000),
|
||||
.rate_min = 16000,
|
||||
.rate_max = 48000,
|
||||
.channels_min = 1,
|
||||
.channels_max = 4,
|
||||
.channels_min = LSM_INPUT_NUM_CHANNELS_MIN,
|
||||
.channels_max = LSM_INPUT_NUM_CHANNELS_MAX,
|
||||
.buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS *
|
||||
CAPTURE_MAX_PERIOD_SIZE,
|
||||
.period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
|
||||
|
|
@ -116,11 +116,11 @@ static int msm_lsm_queue_lab_buffer(struct lsm_priv *prtd, int i)
|
|||
rtd = prtd->substream->private_data;
|
||||
|
||||
if (!prtd->lsm_client->lab_buffer ||
|
||||
i >= prtd->lsm_client->hw_params.period_count) {
|
||||
i >= prtd->lsm_client->out_hw_params.period_count) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: Lab buffer not setup %pK incorrect index %d period count %d\n",
|
||||
__func__, prtd->lsm_client->lab_buffer, i,
|
||||
prtd->lsm_client->hw_params.period_count);
|
||||
prtd->lsm_client->out_hw_params.period_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
cmd_read.buf_addr_lsw =
|
||||
|
|
@ -165,7 +165,7 @@ static int lsm_lab_buffer_sanity(struct lsm_priv *prtd,
|
|||
prtd->lsm_client->lab_buffer);
|
||||
return -EINVAL;
|
||||
}
|
||||
for (i = 0; i < prtd->lsm_client->hw_params.period_count; i++) {
|
||||
for (i = 0; i < prtd->lsm_client->out_hw_params.period_count; i++) {
|
||||
if ((lower_32_bits(prtd->lsm_client->lab_buffer[i].phys) ==
|
||||
read_done->buf_addr_lsw) &&
|
||||
(msm_audio_populate_upper_32_bits
|
||||
|
|
@ -240,11 +240,11 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
|
|||
"%s: process read done index %d\n",
|
||||
__func__, buf_index);
|
||||
if (buf_index >=
|
||||
prtd->lsm_client->hw_params.period_count) {
|
||||
prtd->lsm_client->out_hw_params.period_count) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: Invalid index %d buf_index max cnt %d\n",
|
||||
__func__, buf_index,
|
||||
prtd->lsm_client->hw_params.period_count);
|
||||
prtd->lsm_client->out_hw_params.period_count);
|
||||
return;
|
||||
}
|
||||
prtd->dma_write += read_done->total_size;
|
||||
|
|
@ -253,7 +253,7 @@ static void lsm_event_handler(uint32_t opcode, uint32_t token,
|
|||
wake_up(&prtd->period_wait);
|
||||
/* queue the next period buffer */
|
||||
buf_index = (buf_index + 1) %
|
||||
prtd->lsm_client->hw_params.period_count;
|
||||
prtd->lsm_client->out_hw_params.period_count;
|
||||
rc = msm_lsm_queue_lab_buffer(prtd, buf_index);
|
||||
if (rc)
|
||||
dev_err(rtd->dev,
|
||||
|
|
@ -405,8 +405,8 @@ static int msm_lsm_lab_buffer_alloc(struct lsm_priv *lsm, int alloc)
|
|||
dma_buf->private_data = NULL;
|
||||
dma_buf->area = lsm->lsm_client->lab_buffer[0].data;
|
||||
dma_buf->addr = lsm->lsm_client->lab_buffer[0].phys;
|
||||
dma_buf->bytes = lsm->lsm_client->hw_params.buf_sz *
|
||||
lsm->lsm_client->hw_params.period_count;
|
||||
dma_buf->bytes = lsm->lsm_client->out_hw_params.buf_sz *
|
||||
lsm->lsm_client->out_hw_params.period_count;
|
||||
snd_pcm_set_runtime_buffer(lsm->substream, dma_buf);
|
||||
} else {
|
||||
ret = q6lsm_lab_buffer_alloc(lsm->lsm_client, alloc);
|
||||
|
|
@ -1260,7 +1260,10 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
|||
break;
|
||||
}
|
||||
case SNDRV_LSM_LAB_CONTROL: {
|
||||
u32 enable;
|
||||
struct lsm_hw_params *out_hw_params =
|
||||
&prtd->lsm_client->out_hw_params;
|
||||
u8 chmap[out_hw_params->num_chs];
|
||||
u32 enable, ch_idx;
|
||||
|
||||
if (copy_from_user(&enable, arg, sizeof(enable))) {
|
||||
dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n",
|
||||
|
|
@ -1270,39 +1273,61 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
|||
|
||||
dev_dbg(rtd->dev, "%s: ioctl %s, enable = %d\n",
|
||||
__func__, "SNDRV_LSM_LAB_CONTROL", enable);
|
||||
if (!prtd->lsm_client->started) {
|
||||
if (prtd->lsm_client->lab_enable == enable) {
|
||||
dev_dbg(rtd->dev,
|
||||
"%s: Lab for session %d already %s\n",
|
||||
__func__, prtd->lsm_client->session,
|
||||
enable ? "enabled" : "disabled");
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
rc = q6lsm_lab_control(prtd->lsm_client, enable);
|
||||
if (rc) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: ioctl %s failed rc %d to %s lab for session %d\n",
|
||||
__func__, "SNDRV_LAB_CONTROL", rc,
|
||||
enable ? "enable" : "disable",
|
||||
prtd->lsm_client->session);
|
||||
} else {
|
||||
rc = msm_lsm_lab_buffer_alloc(prtd,
|
||||
enable ? LAB_BUFFER_ALLOC
|
||||
: LAB_BUFFER_DEALLOC);
|
||||
if (rc)
|
||||
dev_err(rtd->dev,
|
||||
"%s: msm_lsm_lab_buffer_alloc failed rc %d for %s",
|
||||
__func__, rc,
|
||||
enable ? "ALLOC" : "DEALLOC");
|
||||
if (!rc)
|
||||
prtd->lsm_client->lab_enable = enable;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (prtd->lsm_client->started) {
|
||||
dev_err(rtd->dev, "%s: ioctl %s issued after start",
|
||||
__func__, "SNDRV_LSM_LAB_CONTROL");
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (prtd->lsm_client->lab_enable == enable) {
|
||||
dev_dbg(rtd->dev,
|
||||
"%s: Lab for session %d already %s\n",
|
||||
__func__, prtd->lsm_client->session,
|
||||
enable ? "enabled" : "disabled");
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
rc = q6lsm_lab_control(prtd->lsm_client, enable);
|
||||
if (rc) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: ioctl %s failed rc %d to %s lab for session %d\n",
|
||||
__func__, "SNDRV_LAB_CONTROL", rc,
|
||||
enable ? "enable" : "disable",
|
||||
prtd->lsm_client->session);
|
||||
break;
|
||||
}
|
||||
|
||||
rc = msm_lsm_lab_buffer_alloc(prtd,
|
||||
enable ? LAB_BUFFER_ALLOC
|
||||
: LAB_BUFFER_DEALLOC);
|
||||
if (rc) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: msm_lsm_lab_buffer_alloc failed rc %d for %s",
|
||||
__func__, rc,
|
||||
enable ? "ALLOC" : "DEALLOC");
|
||||
break;
|
||||
}
|
||||
|
||||
prtd->lsm_client->lab_enable = enable;
|
||||
memset(chmap, 0, out_hw_params->num_chs);
|
||||
/*
|
||||
* First channel to be read from lab is always the
|
||||
* best channel (0xff). For second channel onwards,
|
||||
* the channel indices are 0, 1, .. etc
|
||||
*/
|
||||
chmap[0] = 0xFF;
|
||||
for (ch_idx = 1; ch_idx < out_hw_params->num_chs; ch_idx++)
|
||||
chmap[ch_idx] = ch_idx - 1;
|
||||
|
||||
rc = q6lsm_lab_out_ch_cfg(prtd->lsm_client, chmap);
|
||||
if (rc)
|
||||
dev_err(rtd->dev,
|
||||
"%s: Failed to set lab out ch cfg %d\n",
|
||||
__func__, rc);
|
||||
|
||||
break;
|
||||
}
|
||||
case SNDRV_LSM_STOP_LAB:
|
||||
|
|
@ -1354,6 +1379,23 @@ static int msm_lsm_ioctl_shared(struct snd_pcm_substream *substream,
|
|||
}
|
||||
break;
|
||||
}
|
||||
case SNDRV_LSM_SET_INPUT_HW_PARAMS: {
|
||||
struct lsm_hw_params *in_params;
|
||||
struct snd_lsm_input_hw_params params;
|
||||
|
||||
if (copy_from_user(¶ms, arg, sizeof(params))) {
|
||||
dev_err(rtd->dev, "%s: %s: copy_from_user failed\n",
|
||||
__func__, "LSM_SET_INPUT_HW_PARAMS");
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
in_params = &prtd->lsm_client->in_hw_params;
|
||||
in_params->sample_rate = params.sample_rate;
|
||||
in_params->sample_size = params.bit_width;
|
||||
in_params->num_chs = params.num_channels;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
dev_dbg(rtd->dev,
|
||||
|
|
@ -2241,7 +2283,7 @@ static int msm_lsm_prepare(struct snd_pcm_substream *substream)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (q6lsm_set_media_fmt_params(prtd->lsm_client))
|
||||
if (q6lsm_set_media_fmt_v2_params(prtd->lsm_client))
|
||||
dev_dbg(rtd->dev,
|
||||
"%s: failed to set lsm media fmt params\n", __func__);
|
||||
|
||||
|
|
@ -2339,7 +2381,8 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream,
|
|||
{
|
||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||
struct lsm_priv *prtd = runtime->private_data;
|
||||
struct lsm_hw_params *hw_params = NULL;
|
||||
struct lsm_hw_params *out_hw_params = NULL;
|
||||
struct lsm_hw_params *in_hw_params = NULL;
|
||||
struct snd_soc_pcm_runtime *rtd;
|
||||
|
||||
if (!substream->private_data) {
|
||||
|
|
@ -2354,37 +2397,48 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream,
|
|||
__func__, prtd, params);
|
||||
return -EINVAL;
|
||||
}
|
||||
hw_params = &prtd->lsm_client->hw_params;
|
||||
hw_params->num_chs = params_channels(params);
|
||||
hw_params->period_count = params_periods(params);
|
||||
hw_params->sample_rate = params_rate(params);
|
||||
if (((hw_params->sample_rate != 16000) &&
|
||||
(hw_params->sample_rate != 48000)) ||
|
||||
(hw_params->period_count == 0)) {
|
||||
in_hw_params = &prtd->lsm_client->in_hw_params;
|
||||
out_hw_params = &prtd->lsm_client->out_hw_params;
|
||||
out_hw_params->num_chs = params_channels(params);
|
||||
out_hw_params->period_count = params_periods(params);
|
||||
out_hw_params->sample_rate = params_rate(params);
|
||||
if (((out_hw_params->sample_rate != 16000) &&
|
||||
(out_hw_params->sample_rate != 48000)) ||
|
||||
(out_hw_params->period_count == 0)) {
|
||||
dev_err(rtd->dev,
|
||||
"%s: Invalid Params sample rate %d period count %d\n",
|
||||
__func__, hw_params->sample_rate,
|
||||
hw_params->period_count);
|
||||
__func__, out_hw_params->sample_rate,
|
||||
out_hw_params->period_count);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE) {
|
||||
hw_params->sample_size = 16;
|
||||
out_hw_params->sample_size = 16;
|
||||
} else if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE) {
|
||||
hw_params->sample_size = 24;
|
||||
out_hw_params->sample_size = 24;
|
||||
} else {
|
||||
dev_err(rtd->dev, "%s: Invalid Format 0x%x\n",
|
||||
__func__, params_format(params));
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hw_params->buf_sz = params_buffer_bytes(params) /
|
||||
hw_params->period_count;
|
||||
out_hw_params->buf_sz = params_buffer_bytes(params) /
|
||||
out_hw_params->period_count;
|
||||
dev_dbg(rtd->dev,
|
||||
"%s: channels %d sample rate %d sample size %d buffer size %d period count %d\n",
|
||||
__func__, hw_params->num_chs, hw_params->sample_rate,
|
||||
hw_params->sample_size, hw_params->buf_sz,
|
||||
hw_params->period_count);
|
||||
__func__, out_hw_params->num_chs, out_hw_params->sample_rate,
|
||||
out_hw_params->sample_size, out_hw_params->buf_sz,
|
||||
out_hw_params->period_count);
|
||||
|
||||
/*
|
||||
* copy the out_hw_params to in_hw_params. in_hw_params will be
|
||||
* over-written with LSM_SET_INPUT_HW_PARAMS ioctl from userspace.
|
||||
* If this ioctl is not set, then it is assumed that input and
|
||||
* output hw params for LSM are the same.
|
||||
* Currently the period_count and buf_sz are unused for input params.
|
||||
*/
|
||||
memcpy(in_hw_params, out_hw_params,
|
||||
sizeof(struct lsm_hw_params));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2456,7 +2510,7 @@ static int msm_lsm_pcm_copy(struct snd_pcm_substream *substream, int ch,
|
|||
return -EIO;
|
||||
}
|
||||
prtd->appl_cnt = prtd->appl_cnt %
|
||||
prtd->lsm_client->hw_params.period_count;
|
||||
prtd->lsm_client->out_hw_params.period_count;
|
||||
pcm_buf = prtd->lsm_client->lab_buffer[prtd->appl_cnt].data;
|
||||
dev_dbg(rtd->dev,
|
||||
"%s: copy the pcm data size %lu\n",
|
||||
|
|
@ -2474,7 +2528,7 @@ static int msm_lsm_pcm_copy(struct snd_pcm_substream *substream, int ch,
|
|||
return -EINVAL;
|
||||
}
|
||||
prtd->appl_cnt = (prtd->appl_cnt + 1) %
|
||||
prtd->lsm_client->hw_params.period_count;
|
||||
prtd->lsm_client->out_hw_params.period_count;
|
||||
atomic_dec(&prtd->buf_count);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
201
dsp/q6lsm.c
201
dsp/q6lsm.c
|
|
@ -1028,38 +1028,33 @@ int q6lsm_set_fwk_mode_cfg(struct lsm_client *client,
|
|||
}
|
||||
EXPORT_SYMBOL(q6lsm_set_fwk_mode_cfg);
|
||||
|
||||
static int q6lsm_arrange_mch_map(struct lsm_param_media_fmt *media_fmt,
|
||||
int channel_count)
|
||||
static int q6lsm_arrange_mch_map(uint8_t *ch_map, int ch_cnt)
|
||||
{
|
||||
int rc = 0;
|
||||
int ch_idx;
|
||||
u8 mch_map[LSM_V3P0_MAX_NUM_CHANNELS] = {
|
||||
PCM_CHANNEL_FL, PCM_CHANNEL_FR, PCM_CHANNEL_FC,
|
||||
PCM_CHANNEL_LS, PCM_CHANNEL_RS, PCM_CHANNEL_LFE,
|
||||
PCM_CHANNEL_LB, PCM_CHANNEL_RB, PCM_CHANNEL_CS};
|
||||
|
||||
memset(media_fmt->channel_mapping, 0, LSM_MAX_NUM_CHANNELS);
|
||||
|
||||
switch (channel_count) {
|
||||
case 1:
|
||||
media_fmt->channel_mapping[0] = PCM_CHANNEL_FC;
|
||||
break;
|
||||
case 2:
|
||||
media_fmt->channel_mapping[0] = PCM_CHANNEL_FL;
|
||||
media_fmt->channel_mapping[1] = PCM_CHANNEL_FR;
|
||||
break;
|
||||
case 3:
|
||||
media_fmt->channel_mapping[0] = PCM_CHANNEL_FL;
|
||||
media_fmt->channel_mapping[1] = PCM_CHANNEL_FR;
|
||||
media_fmt->channel_mapping[2] = PCM_CHANNEL_FC;
|
||||
break;
|
||||
case 4:
|
||||
media_fmt->channel_mapping[0] = PCM_CHANNEL_FL;
|
||||
media_fmt->channel_mapping[1] = PCM_CHANNEL_FR;
|
||||
media_fmt->channel_mapping[2] = PCM_CHANNEL_LS;
|
||||
media_fmt->channel_mapping[3] = PCM_CHANNEL_RS;
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: invalid num_chan %d\n", __func__, channel_count);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
if (ch_cnt > LSM_V3P0_MAX_NUM_CHANNELS) {
|
||||
pr_err("%s: invalid num_chan %d\n", __func__, ch_cnt);
|
||||
return -EINVAL;
|
||||
}
|
||||
return rc;
|
||||
|
||||
if (ch_cnt == 1) {
|
||||
ch_map[0] = PCM_CHANNEL_FC;
|
||||
} else if (ch_cnt == 4) {
|
||||
ch_map[0] = PCM_CHANNEL_FL;
|
||||
ch_map[1] = PCM_CHANNEL_FR;
|
||||
ch_map[2] = PCM_CHANNEL_LS;
|
||||
ch_map[3] = PCM_CHANNEL_RS;
|
||||
} else {
|
||||
for (ch_idx = 0; ch_idx < ch_cnt; ch_idx++)
|
||||
ch_map[ch_idx] = mch_map[ch_idx];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1073,7 +1068,7 @@ static int q6lsm_arrange_mch_map(struct lsm_param_media_fmt *media_fmt,
|
|||
int q6lsm_set_media_fmt_params(struct lsm_client *client)
|
||||
{
|
||||
struct lsm_param_media_fmt media_fmt;
|
||||
struct lsm_hw_params param = client->hw_params;
|
||||
struct lsm_hw_params in_param = client->in_hw_params;
|
||||
struct param_hdr_v3 media_fmt_hdr;
|
||||
int rc = 0;
|
||||
|
||||
|
|
@ -1091,10 +1086,11 @@ int q6lsm_set_media_fmt_params(struct lsm_client *client)
|
|||
media_fmt_hdr.param_size = sizeof(media_fmt);
|
||||
|
||||
media_fmt.minor_version = QLSM_PARAM_ID_MINOR_VERSION_2;
|
||||
media_fmt.sample_rate = param.sample_rate;
|
||||
media_fmt.num_channels = param.num_chs;
|
||||
media_fmt.bit_width = param.sample_size;
|
||||
rc = q6lsm_arrange_mch_map(&media_fmt, media_fmt.num_channels);
|
||||
media_fmt.sample_rate = in_param.sample_rate;
|
||||
media_fmt.num_channels = in_param.num_chs;
|
||||
media_fmt.bit_width = in_param.sample_size;
|
||||
rc = q6lsm_arrange_mch_map(media_fmt.channel_mapping,
|
||||
media_fmt.num_channels);
|
||||
if (rc)
|
||||
goto err_ret;
|
||||
|
||||
|
|
@ -1112,6 +1108,65 @@ err_ret:
|
|||
}
|
||||
EXPORT_SYMBOL(q6lsm_set_media_fmt_params);
|
||||
|
||||
/*
|
||||
* q6lsm_set_media_fmt_v2_params -
|
||||
* command to set LSM media fmt (version2) params
|
||||
*
|
||||
* @client: LSM client handle
|
||||
*
|
||||
* Returns 0 on success or error on failure
|
||||
*/
|
||||
int q6lsm_set_media_fmt_v2_params(struct lsm_client *client)
|
||||
{
|
||||
u8 *param_buf;
|
||||
struct lsm_param_media_fmt_v2 *media_fmt_v2;
|
||||
struct lsm_hw_params *in_param = &client->in_hw_params;
|
||||
struct param_hdr_v3 media_fmt_v2_hdr;
|
||||
int param_len = 0, rc = 0;
|
||||
|
||||
memset(&media_fmt_v2_hdr, 0, sizeof(media_fmt_v2_hdr));
|
||||
|
||||
param_len = sizeof(*media_fmt_v2) +
|
||||
(sizeof(uint8_t) * in_param->num_chs);
|
||||
|
||||
/* Add padding to make sure total length is 4-byte aligned */
|
||||
if (param_len % 4)
|
||||
param_len += (4 - (param_len % 4));
|
||||
|
||||
param_buf = kzalloc(param_len, GFP_KERNEL);
|
||||
if (!param_buf)
|
||||
return -ENOMEM;
|
||||
media_fmt_v2 = (struct lsm_param_media_fmt_v2 *) param_buf;
|
||||
media_fmt_v2->minor_version = QLSM_PARAM_ID_MINOR_VERSION;
|
||||
media_fmt_v2->sample_rate = in_param->sample_rate;
|
||||
media_fmt_v2->num_channels = in_param->num_chs;
|
||||
media_fmt_v2->bit_width = in_param->sample_size;
|
||||
rc = q6lsm_arrange_mch_map(media_fmt_v2->channel_mapping,
|
||||
in_param->num_chs);
|
||||
if (rc)
|
||||
goto err_mch_map;
|
||||
|
||||
media_fmt_v2_hdr.module_id = LSM_MODULE_ID_FRAMEWORK;
|
||||
media_fmt_v2_hdr.instance_id = INSTANCE_ID_0;
|
||||
media_fmt_v2_hdr.param_id = LSM_PARAM_ID_MEDIA_FMT_V2;
|
||||
media_fmt_v2_hdr.param_size = param_len;
|
||||
|
||||
pr_debug("%s: sample rate= %d, channels %d bit width %d\n", __func__,
|
||||
media_fmt_v2->sample_rate, media_fmt_v2->num_channels,
|
||||
media_fmt_v2->bit_width);
|
||||
|
||||
rc = q6lsm_pack_and_set_params(client, &media_fmt_v2_hdr,
|
||||
param_buf,
|
||||
LSM_SESSION_CMD_SET_PARAMS_V2);
|
||||
if (rc)
|
||||
pr_err("%s: Failed set_params, rc %d\n", __func__, rc);
|
||||
|
||||
err_mch_map:
|
||||
kfree(param_buf);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(q6lsm_set_media_fmt_v2_params);
|
||||
|
||||
/**
|
||||
* q6lsm_set_data -
|
||||
* Command to set LSM data
|
||||
|
|
@ -2051,6 +2106,62 @@ exit:
|
|||
}
|
||||
EXPORT_SYMBOL(q6lsm_lab_control);
|
||||
|
||||
/*
|
||||
* q6lsm_lab_out_ch_cfg -
|
||||
* Command to set the channel configuration
|
||||
* for look-ahead buffer.
|
||||
*
|
||||
* @client: LSM client handle
|
||||
* @ch_map: Channel map indicating the order
|
||||
* of channels to be configured.
|
||||
*
|
||||
* Returns 0 on success or error on failure
|
||||
*/
|
||||
int q6lsm_lab_out_ch_cfg(struct lsm_client *client,
|
||||
u8 *ch_map)
|
||||
{
|
||||
u8 *param_buf;
|
||||
struct lsm_param_lab_out_ch_cfg *lab_out_cfg;
|
||||
struct param_hdr_v3 lab_out_cfg_hdr;
|
||||
struct lsm_hw_params *out_params = &client->out_hw_params;
|
||||
int i, rc = 0, param_len = 0;
|
||||
|
||||
param_len = sizeof(*lab_out_cfg) +
|
||||
sizeof(u8) * out_params->num_chs;
|
||||
|
||||
if (param_len % 4)
|
||||
param_len += (4 - (param_len % 4));
|
||||
|
||||
param_buf = kzalloc(param_len, GFP_KERNEL);
|
||||
if (!param_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
lab_out_cfg = (struct lsm_param_lab_out_ch_cfg *) param_buf;
|
||||
lab_out_cfg->minor_version = QLSM_PARAM_ID_MINOR_VERSION;
|
||||
lab_out_cfg->num_channels = out_params->num_chs;
|
||||
|
||||
for (i = 0; i < out_params->num_chs; i++)
|
||||
lab_out_cfg->channel_indices[i] = ch_map[i];
|
||||
|
||||
memset(&lab_out_cfg_hdr, 0, sizeof(lab_out_cfg_hdr));
|
||||
lab_out_cfg_hdr.module_id = LSM_MODULE_ID_LAB;
|
||||
lab_out_cfg_hdr.instance_id = INSTANCE_ID_0;
|
||||
lab_out_cfg_hdr.param_id = LSM_PARAM_ID_LAB_OUTPUT_CHANNEL_CONFIG;
|
||||
lab_out_cfg_hdr.param_size = param_len;
|
||||
|
||||
rc = q6lsm_pack_and_set_params(client, &lab_out_cfg_hdr,
|
||||
param_buf,
|
||||
LSM_SESSION_CMD_SET_PARAMS_V2);
|
||||
if (rc)
|
||||
pr_err("%s: Lab out channel config failed %d\n",
|
||||
__func__, rc);
|
||||
|
||||
kfree(param_buf);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(q6lsm_lab_out_ch_cfg);
|
||||
|
||||
/**
|
||||
* q6lsm_stop_lab -
|
||||
* command to stop LSM LAB
|
||||
|
|
@ -2117,6 +2228,7 @@ int q6lsm_lab_buffer_alloc(struct lsm_client *client, bool alloc)
|
|||
{
|
||||
int ret = 0, i = 0;
|
||||
size_t allocate_size = 0, len = 0;
|
||||
struct lsm_hw_params *out_params = &client->out_hw_params;
|
||||
|
||||
if (!client) {
|
||||
pr_err("%s: invalid client\n", __func__);
|
||||
|
|
@ -2126,20 +2238,20 @@ int q6lsm_lab_buffer_alloc(struct lsm_client *client, bool alloc)
|
|||
if (client->lab_buffer) {
|
||||
pr_err("%s: buffers are allocated period count %d period size %d\n",
|
||||
__func__,
|
||||
client->hw_params.period_count,
|
||||
client->hw_params.buf_sz);
|
||||
out_params->period_count,
|
||||
out_params->buf_sz);
|
||||
return -EINVAL;
|
||||
}
|
||||
allocate_size = client->hw_params.period_count *
|
||||
client->hw_params.buf_sz;
|
||||
allocate_size = out_params->period_count *
|
||||
out_params->buf_sz;
|
||||
allocate_size = PAGE_ALIGN(allocate_size);
|
||||
client->lab_buffer =
|
||||
kzalloc(sizeof(struct lsm_lab_buffer) *
|
||||
client->hw_params.period_count, GFP_KERNEL);
|
||||
out_params->period_count, GFP_KERNEL);
|
||||
if (!client->lab_buffer) {
|
||||
pr_err("%s: memory allocation for lab buffer failed count %d\n"
|
||||
, __func__,
|
||||
client->hw_params.period_count);
|
||||
out_params->period_count);
|
||||
return -ENOMEM;
|
||||
}
|
||||
ret = msm_audio_ion_alloc(&client->lab_buffer[0].dma_buf,
|
||||
|
|
@ -2170,16 +2282,17 @@ int q6lsm_lab_buffer_alloc(struct lsm_client *client, bool alloc)
|
|||
__func__,
|
||||
client->lab_buffer[0].mem_map_handle,
|
||||
&client->lab_buffer[0].phys,
|
||||
client->hw_params.buf_sz);
|
||||
for (i = 0; i < client->hw_params.period_count; i++) {
|
||||
out_params->buf_sz);
|
||||
|
||||
for (i = 0; i < out_params->period_count; i++) {
|
||||
client->lab_buffer[i].phys =
|
||||
client->lab_buffer[0].phys +
|
||||
(i * client->hw_params.buf_sz);
|
||||
(i * out_params->buf_sz);
|
||||
client->lab_buffer[i].size =
|
||||
client->hw_params.buf_sz;
|
||||
out_params->buf_sz;
|
||||
client->lab_buffer[i].data =
|
||||
(u8 *)(client->lab_buffer[0].data) +
|
||||
(i * client->hw_params.buf_sz);
|
||||
(i * out_params->buf_sz);
|
||||
client->lab_buffer[i].mem_map_handle =
|
||||
client->lab_buffer[0].mem_map_handle;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9951,6 +9951,8 @@ struct avcs_fwk_ver_info {
|
|||
#define LSM_PARAM_ID_POLLING_ENABLE (0x00012C1B)
|
||||
#define LSM_PARAM_ID_MEDIA_FMT (0x00012C1E)
|
||||
#define LSM_PARAM_ID_FWK_MODE_CONFIG (0x00012C27)
|
||||
#define LSM_PARAM_ID_MEDIA_FMT_V2 (0x00012C32)
|
||||
#define LSM_PARAM_ID_LAB_OUTPUT_CHANNEL_CONFIG (0x00012C2D)
|
||||
|
||||
/* HW MAD specific */
|
||||
#define AFE_MODULE_HW_MAD (0x00010230)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#define ADM_LSM_PORT_ID 0xADCB
|
||||
|
||||
#define LSM_MAX_NUM_CHANNELS 8
|
||||
#define LSM_V3P0_MAX_NUM_CHANNELS 9
|
||||
|
||||
typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token,
|
||||
uint32_t *payload, void *priv);
|
||||
|
|
@ -82,7 +83,8 @@ struct lsm_client {
|
|||
bool lab_enable;
|
||||
bool lab_started;
|
||||
struct lsm_lab_buffer *lab_buffer;
|
||||
struct lsm_hw_params hw_params;
|
||||
struct lsm_hw_params out_hw_params;
|
||||
struct lsm_hw_params in_hw_params;
|
||||
bool use_topology;
|
||||
int session_state;
|
||||
bool poll_enable;
|
||||
|
|
@ -157,6 +159,15 @@ struct lsm_param_media_fmt {
|
|||
uint8_t channel_mapping[LSM_MAX_NUM_CHANNELS];
|
||||
} __packed;
|
||||
|
||||
struct lsm_param_media_fmt_v2 {
|
||||
uint32_t minor_version;
|
||||
uint32_t sample_rate;
|
||||
uint16_t bit_width;
|
||||
uint16_t num_channels;
|
||||
uint8_t channel_mapping[0];
|
||||
} __packed;
|
||||
|
||||
|
||||
struct lsm_param_confidence_levels {
|
||||
uint8_t num_confidence_levels;
|
||||
uint8_t confidence_levels[0];
|
||||
|
|
@ -192,6 +203,12 @@ struct lsm_param_lab_config {
|
|||
uint32_t wake_up_latency_ms;
|
||||
} __packed;
|
||||
|
||||
struct lsm_param_lab_out_ch_cfg {
|
||||
uint32_t minor_version;
|
||||
uint32_t num_channels;
|
||||
uint8_t channel_indices[0];
|
||||
} __packed;
|
||||
|
||||
struct lsm_cmd_read {
|
||||
struct apr_hdr hdr;
|
||||
uint32_t buf_addr_lsw;
|
||||
|
|
@ -250,4 +267,6 @@ void q6lsm_sm_set_param_data(struct lsm_client *client,
|
|||
int q6lsm_set_port_connected(struct lsm_client *client);
|
||||
int q6lsm_set_fwk_mode_cfg(struct lsm_client *client, uint32_t event_mode);
|
||||
int q6lsm_set_media_fmt_params(struct lsm_client *client);
|
||||
int q6lsm_set_media_fmt_v2_params(struct lsm_client *client);
|
||||
int q6lsm_lab_out_ch_cfg(struct lsm_client *client, u8 *ch_map);
|
||||
#endif /* __Q6LSM_H__ */
|
||||
|
|
|
|||
Loading…
Reference in a new issue