ASoC: msm: qdsp6v2: Extend LSM support to 48khz, 24bit and 4 channel

Enhance LSM code to support maximum configuration of 48khz, 24bit
and 4 channel.

Change-Id: I03895c983527d87389ca69e85235b1def5b4a2fa
Signed-off-by: Chaithanya Krishna Bacharaju <chaithan@codeaurora.org>
Signed-off-by: Revathi Uddaraju <revathiu@codeaurora.org>
This commit is contained in:
Chaithanya Krishna Bacharaju 2016-07-21 11:08:56 +05:30 committed by Gerrit - the friendly Code Review server
parent 1f5681eec2
commit f7b4f38b89
5 changed files with 202 additions and 54 deletions

View file

@ -9063,6 +9063,7 @@ struct asm_aptx_dec_fmt_blk_v2 {
#define LSM_PARAM_ID_SWMAD_MODEL (0x00012C19)
#define LSM_PARAM_ID_SWMAD_ENABLE (0x00012C1A)
#define LSM_PARAM_ID_POLLING_ENABLE (0x00012C1B)
#define LSM_PARAM_ID_MEDIA_FMT (0x00012C1E)
#define LSM_PARAM_ID_FWK_MODE_CONFIG (0x00012C27)
/* HW MAD specific */

View file

@ -23,6 +23,8 @@
#define ADM_LSM_PORT_ID 0xADCB
#define LSM_MAX_NUM_CHANNELS 8
typedef void (*lsm_app_cb)(uint32_t opcode, uint32_t token,
uint32_t *payload, void *priv);
@ -51,11 +53,12 @@ struct lsm_lab_buffer {
uint32_t mem_map_handle;
};
struct lsm_lab_hw_params {
struct lsm_hw_params {
u16 sample_rate;
u16 sample_size;
u32 buf_sz;
u32 period_count;
u16 num_chs;
};
struct lsm_client {
@ -81,7 +84,7 @@ struct lsm_client {
bool lab_enable;
bool lab_started;
struct lsm_lab_buffer *lab_buffer;
struct lsm_lab_hw_params hw_params;
struct lsm_hw_params hw_params;
bool use_topology;
int session_state;
bool poll_enable;
@ -153,6 +156,15 @@ struct lsm_param_fwk_mode_cfg {
uint32_t mode;
} __packed;
struct lsm_param_media_fmt {
struct lsm_param_payload_common common;
uint32_t minor_version;
uint32_t sample_rate;
uint16_t num_channels;
uint16_t bit_width;
uint8_t channel_mapping[LSM_MAX_NUM_CHANNELS];
} __packed;
/*
* This param cannot be sent in this format.
* The actual number of confidence level values
@ -285,6 +297,13 @@ struct lsm_cmd_set_fwk_mode_cfg {
struct lsm_param_fwk_mode_cfg fwk_mode_cfg;
} __packed;
struct lsm_cmd_set_media_fmt {
struct apr_hdr msg_hdr;
struct lsm_set_params_hdr params_hdr;
struct lsm_param_media_fmt media_fmt;
} __packed;
struct lsm_client *q6lsm_client_alloc(lsm_app_cb cb, void *priv);
void q6lsm_client_free(struct lsm_client *client);
int q6lsm_open(struct lsm_client *client, uint16_t app_id);
@ -315,4 +334,5 @@ void q6lsm_sm_set_param_data(struct lsm_client *client,
size_t *offset);
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);
#endif /* __Q6LSM_H__ */

View file

@ -1,4 +1,4 @@
/* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@ -2203,12 +2203,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
.capture = {
.stream_name = "Listen 1 Audio Service Capture",
.aif_name = "LSM1_UL_HL",
.rates = SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_48000),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 1,
.channels_max = 4,
.rate_min = 16000,
.rate_max = 16000,
.rate_max = 48000,
},
.ops = &msm_fe_dai_ops,
.name = "LSM1",
@ -2218,12 +2220,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
.capture = {
.stream_name = "Listen 2 Audio Service Capture",
.aif_name = "LSM2_UL_HL",
.rates = SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_48000),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 1,
.channels_max = 4,
.rate_min = 16000,
.rate_max = 16000,
.rate_max = 48000,
},
.ops = &msm_fe_dai_ops,
.name = "LSM2",
@ -2233,12 +2237,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
.capture = {
.stream_name = "Listen 3 Audio Service Capture",
.aif_name = "LSM3_UL_HL",
.rates = SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_48000),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 1,
.channels_max = 4,
.rate_min = 16000,
.rate_max = 16000,
.rate_max = 48000,
},
.ops = &msm_fe_dai_ops,
.name = "LSM3",
@ -2248,12 +2254,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
.capture = {
.stream_name = "Listen 4 Audio Service Capture",
.aif_name = "LSM4_UL_HL",
.rates = SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_48000),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 1,
.channels_max = 4,
.rate_min = 16000,
.rate_max = 16000,
.rate_max = 48000,
},
.ops = &msm_fe_dai_ops,
.name = "LSM4",
@ -2263,12 +2271,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
.capture = {
.stream_name = "Listen 5 Audio Service Capture",
.aif_name = "LSM5_UL_HL",
.rates = SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_48000),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 1,
.channels_max = 4,
.rate_min = 16000,
.rate_max = 16000,
.rate_max = 48000,
},
.ops = &msm_fe_dai_ops,
.name = "LSM5",
@ -2278,12 +2288,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
.capture = {
.stream_name = "Listen 6 Audio Service Capture",
.aif_name = "LSM6_UL_HL",
.rates = SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_48000),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 1,
.channels_max = 4,
.rate_min = 16000,
.rate_max = 16000,
.rate_max = 48000,
},
.ops = &msm_fe_dai_ops,
.name = "LSM6",
@ -2293,12 +2305,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
.capture = {
.stream_name = "Listen 7 Audio Service Capture",
.aif_name = "LSM7_UL_HL",
.rates = SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_48000),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 1,
.channels_max = 4,
.rate_min = 16000,
.rate_max = 16000,
.rate_max = 48000,
},
.ops = &msm_fe_dai_ops,
.name = "LSM7",
@ -2308,12 +2322,14 @@ static struct snd_soc_dai_driver msm_fe_dais[] = {
.capture = {
.stream_name = "Listen 8 Audio Service Capture",
.aif_name = "LSM8_UL_HL",
.rates = SNDRV_PCM_RATE_16000,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_48000),
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.channels_min = 1,
.channels_max = 1,
.channels_max = 4,
.rate_min = 16000,
.rate_max = 16000,
.rate_max = 48000,
},
.ops = &msm_fe_dai_ops,
.name = "LSM8",

View file

@ -35,7 +35,7 @@
#define CAPTURE_MIN_NUM_PERIODS 2
#define CAPTURE_MAX_NUM_PERIODS 8
#define CAPTURE_MAX_PERIOD_SIZE 4096
#define CAPTURE_MAX_PERIOD_SIZE 61440
#define CAPTURE_MIN_PERIOD_SIZE 320
#define LISTEN_MAX_STATUS_PAYLOAD_SIZE 256
@ -47,12 +47,14 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = {
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_16000,
.formats = (SNDRV_PCM_FMTBIT_S16_LE |
SNDRV_PCM_FMTBIT_S24_LE),
.rates = (SNDRV_PCM_RATE_16000 |
SNDRV_PCM_RATE_48000),
.rate_min = 16000,
.rate_max = 16000,
.rate_max = 48000,
.channels_min = 1,
.channels_max = 1,
.channels_max = 4,
.buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS *
CAPTURE_MAX_PERIOD_SIZE,
.period_bytes_min = CAPTURE_MIN_PERIOD_SIZE,
@ -64,7 +66,7 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = {
/* Conventional and unconventional sample rate supported */
static unsigned int supported_sample_rates[] = {
16000,
16000, 48000,
};
static struct snd_pcm_hw_constraint_list constraints_sample_rates = {
@ -1962,6 +1964,10 @@ static int msm_lsm_prepare(struct snd_pcm_substream *substream)
return -EINVAL;
}
if (q6lsm_set_media_fmt_params(prtd->lsm_client))
dev_dbg(rtd->dev,
"%s: failed to set lsm media fmt params\n", __func__);
if (prtd->lsm_client->session_state == IDLE) {
ret = msm_pcm_routing_reg_phy_compr_stream(
rtd->dai_link->be_id,
@ -2053,7 +2059,7 @@ 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_lab_hw_params *hw_params = NULL;
struct lsm_hw_params *hw_params = NULL;
struct snd_soc_pcm_runtime *rtd;
if (!substream->private_data) {
@ -2069,25 +2075,36 @@ static int msm_lsm_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
hw_params = &prtd->lsm_client->hw_params;
hw_params->sample_rate = params_rate(params);
hw_params->sample_size =
(params_format(params) == SNDRV_PCM_FORMAT_S16_LE) ? 16 : 0;
hw_params->num_chs = params_channels(params);
hw_params->period_count = params_periods(params);
if (hw_params->sample_rate != 16000 || hw_params->sample_size != 16 ||
hw_params->period_count == 0) {
hw_params->sample_rate = params_rate(params);
if (((hw_params->sample_rate != 16000) &&
(hw_params->sample_rate != 48000)) ||
(hw_params->period_count == 0)) {
dev_err(rtd->dev,
"%s: Invalid params sample rate %d sample size %d period count %d",
"%s: Invalid Params sample rate %d period count %d\n",
__func__, hw_params->sample_rate,
hw_params->sample_size,
hw_params->period_count);
hw_params->period_count);
return -EINVAL;
}
if (params_format(params) == SNDRV_PCM_FORMAT_S16_LE) {
hw_params->sample_size = 16;
} else if (params_format(params) == SNDRV_PCM_FORMAT_S24_LE) {
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;
hw_params->period_count;
dev_dbg(rtd->dev,
"%s: sample rate %d sample size %d buffer size %d period count %d\n",
__func__, hw_params->sample_rate, hw_params->sample_size,
hw_params->buf_sz, hw_params->period_count);
"%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);
return 0;
}

View file

@ -38,6 +38,8 @@
#define LSM_ALIGN_BOUNDARY 512
#define LSM_SAMPLE_RATE 16000
#define QLSM_PARAM_ID_MINOR_VERSION 1
#define QLSM_PARAM_ID_MINOR_VERSION_2 2
static int lsm_afe_port;
enum {
@ -897,6 +899,98 @@ int q6lsm_set_fwk_mode_cfg(struct lsm_client *client,
return rc;
}
static int q6lsm_arrange_mch_map(struct lsm_param_media_fmt *media_fmt,
int channel_count)
{
int rc = 0;
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;
}
return rc;
}
int q6lsm_set_media_fmt_params(struct lsm_client *client)
{
int rc = 0;
struct lsm_cmd_set_media_fmt cmd;
struct lsm_module_param_ids media_fmt_ids;
struct apr_hdr *msg_hdr;
struct lsm_param_media_fmt *media_fmt;
u32 data_payload_size, param_size, set_param_opcode;
struct lsm_hw_params param = client->hw_params;
if (client->use_topology) {
set_param_opcode = LSM_SESSION_CMD_SET_PARAMS_V2;
media_fmt_ids.module_id = LSM_MODULE_ID_FRAMEWORK;
media_fmt_ids.param_id = LSM_PARAM_ID_MEDIA_FMT;
} else {
pr_debug("%s: Ignore sending media format\n", __func__);
goto err_ret;
}
msg_hdr = &cmd.msg_hdr;
q6lsm_add_hdr(client, msg_hdr,
sizeof(struct lsm_cmd_set_media_fmt), true);
msg_hdr->opcode = set_param_opcode;
data_payload_size = sizeof(struct lsm_cmd_set_media_fmt) -
sizeof(struct apr_hdr) -
sizeof(struct lsm_set_params_hdr);
q6lsm_set_param_hdr_info(&cmd.params_hdr,
data_payload_size, 0, 0, 0);
media_fmt = &cmd.media_fmt;
param_size = (sizeof(struct lsm_param_media_fmt) -
sizeof(media_fmt->common));
q6lsm_set_param_common(&media_fmt->common,
&media_fmt_ids, param_size,
set_param_opcode);
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);
if (rc)
goto err_ret;
pr_debug("%s: sample rate= %d, channels %d bit width %d\n",
__func__, media_fmt->sample_rate, media_fmt->num_channels,
media_fmt->bit_width);
rc = q6lsm_apr_send_pkt(client, client->apr,
&cmd, true, NULL);
if (rc)
pr_err("%s: Failed set_params opcode 0x%x, rc %d\n",
__func__, msg_hdr->opcode, rc);
err_ret:
return rc;
}
int q6lsm_set_data(struct lsm_client *client,
enum lsm_detection_mode mode,
bool detectfailure)