Merge "ASoC: Fix overflow error in routing driver" into audio-drivers.lnx.2.0.c7
diff --git a/asoc/msm-dai-q6-v2.c b/asoc/msm-dai-q6-v2.c
index 80f5e3d..3b7caff 100644
--- a/asoc/msm-dai-q6-v2.c
+++ b/asoc/msm-dai-q6-v2.c
@@ -33,6 +33,8 @@
#define MSM_DAI_QUAT_AUXPCM_DT_DEV_ID 4
#define MSM_DAI_QUIN_AUXPCM_DT_DEV_ID 5
+#define MSM_DAI_TWS_CHANNEL_MODE_ONE 1
+#define MSM_DAI_TWS_CHANNEL_MODE_TWO 2
#define spdif_clock_value(rate) (2*rate*32*2)
#define CHANNEL_STATUS_SIZE 24
@@ -2418,6 +2420,12 @@
SOC_ENUM_SINGLE_EXT(3, afe_input_bit_format_text),
};
+static const char *const tws_chs_mode_text[] = {"Zero", "One", "Two"};
+
+static const struct soc_enum tws_chs_mode_enum[] = {
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tws_chs_mode_text), tws_chs_mode_text),
+};
+
static int msm_dai_q6_afe_input_channel_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -2446,6 +2454,61 @@
return 0;
}
+static int msm_dai_q6_tws_channel_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *dai = kcontrol->private_data;
+ struct msm_dai_q6_dai_data *dai_data = NULL;
+
+ if (dai)
+ dai_data = dev_get_drvdata(dai->dev);
+
+ if (dai_data) {
+ ucontrol->value.integer.value[0] =
+ dai_data->enc_config.mono_mode;
+ pr_debug("%s:tws channel mode = %d\n",
+ __func__, dai_data->enc_config.mono_mode);
+ }
+
+ return 0;
+}
+
+static int msm_dai_q6_tws_channel_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_dai *dai = kcontrol->private_data;
+ struct msm_dai_q6_dai_data *dai_data = NULL;
+ int ret = 0;
+
+ if (dai)
+ dai_data = dev_get_drvdata(dai->dev);
+
+ if (dai_data && (dai_data->enc_config.format == ENC_FMT_APTX)) {
+ if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) {
+ ret = afe_set_tws_channel_mode(dai->id,
+ ucontrol->value.integer.value[0]);
+ if (ret < 0) {
+ pr_err("%s: channel mode setting failed for TWS\n",
+ __func__);
+ goto exit;
+ } else {
+ pr_debug("%s: updating tws channel mode : %d\n",
+ __func__, dai_data->enc_config.mono_mode);
+ }
+ }
+ if (ucontrol->value.integer.value[0] ==
+ MSM_DAI_TWS_CHANNEL_MODE_ONE ||
+ ucontrol->value.integer.value[0] ==
+ MSM_DAI_TWS_CHANNEL_MODE_TWO)
+ dai_data->enc_config.mono_mode =
+ ucontrol->value.integer.value[0];
+ else
+ return -EINVAL;
+ }
+exit:
+ return ret;
+}
+
static int msm_dai_q6_afe_input_bit_format_get(
struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -2554,6 +2617,9 @@
0, 0, 1, 0,
msm_dai_q6_afe_scrambler_mode_get,
msm_dai_q6_afe_scrambler_mode_put),
+ SOC_ENUM_EXT("TWS Channel Mode", tws_chs_mode_enum[0],
+ msm_dai_q6_tws_channel_mode_get,
+ msm_dai_q6_tws_channel_mode_put)
};
static int msm_dai_q6_afe_dec_cfg_info(struct snd_kcontrol *kcontrol,
@@ -2791,6 +2857,9 @@
snd_ctl_new1(&afe_enc_config_controls[3],
dai_data));
rc = snd_ctl_add(dai->component->card->snd_card,
+ snd_ctl_new1(&afe_enc_config_controls[4],
+ dai));
+ rc = snd_ctl_add(dai->component->card->snd_card,
snd_ctl_new1(&avd_drift_config_controls[2],
dai));
break;
diff --git a/dsp/q6afe.c b/dsp/q6afe.c
index 2243326..87b2c58 100644
--- a/dsp/q6afe.c
+++ b/dsp/q6afe.c
@@ -3132,7 +3132,7 @@
union afe_enc_config_data *cfg, u32 format,
union afe_port_config afe_config,
u16 afe_in_channels, u16 afe_in_bit_width,
- u32 scrambler_mode)
+ u32 scrambler_mode, u32 mono_mode)
{
struct afe_audioif_config_command config;
int index;
@@ -3253,6 +3253,21 @@
goto exit;
}
+ if (format == ASM_MEDIA_FMT_APTX) {
+ config.param.payload_size =
+ payload_size + sizeof(config.port.channel_mode_param);
+ pr_debug("%s:sending CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO mode= %d to DSP payload\n",
+ __func__, mono_mode);
+ config.pdata.param_id = CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO;
+ config.pdata.param_size = sizeof(config.port.channel_mode_param);
+ config.port.channel_mode_param.channel_mode = mono_mode;
+ ret = afe_apr_send_pkt(&config, &this_afe.wait[index]);
+ if (ret) {
+ pr_err("%s: CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+ }
+ }
+
if (format == ASM_MEDIA_FMT_LDAC) {
config.param.payload_size =
payload_size + sizeof(config.port.map_param);
@@ -3327,10 +3342,61 @@
return ret;
}
+int afe_set_tws_channel_mode(u16 port_id, u32 channel_mode)
+{
+ struct aptx_channel_mode_param_t channel_mode_param;
+ int ret = 0;
+ int index = 0;
+
+ pr_debug("%s: enter\n", __func__);
+ index = q6audio_get_port_index(port_id);
+ if (index < 0 || index >= AFE_MAX_PORTS) {
+ pr_err("%s: AFE port index[%d] invalid!\n",
+ __func__, index);
+ return -EINVAL;
+ }
+
+ ret = q6audio_validate_port(port_id);
+ if (ret < 0) {
+ pr_err("%s: port id: 0x%x ret %d\n", __func__, port_id, ret);
+ return -EINVAL;
+ }
+
+ channel_mode_param.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
+ APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER);
+ channel_mode_param.hdr.pkt_size = sizeof(channel_mode_param);
+ channel_mode_param.hdr.src_port = 0;
+ channel_mode_param.hdr.dest_port = 0;
+ channel_mode_param.hdr.token = index;
+
+ channel_mode_param.hdr.opcode = AFE_PORT_CMD_SET_PARAM_V2;
+ channel_mode_param.param.payload_size = sizeof(channel_mode_param) - sizeof(struct apr_hdr)
+ - sizeof(channel_mode_param.param);
+
+ channel_mode_param.param.payload_address_lsw = 0x00;
+ channel_mode_param.param.payload_address_msw = 0x00;
+ channel_mode_param.param.mem_map_handle = 0x00;
+ channel_mode_param.param.port_id = q6audio_get_port_id(port_id);
+ channel_mode_param.pdata.module_id = AFE_MODULE_ID_ENCODER;
+ channel_mode_param.pdata.param_id = CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO;
+ channel_mode_param.pdata.param_size = sizeof(channel_mode_param.channel_mode);
+
+ channel_mode_param.channel_mode = channel_mode;
+
+ ret = afe_apr_send_pkt(&channel_mode_param, &this_afe.wait[index]);
+
+ if (ret)
+ pr_err("%s: AFE set channel mode cfg for port 0x%x failed %d\n",
+ __func__, port_id, ret);
+
+ return ret;
+}
+EXPORT_SYMBOL(afe_set_tws_channel_mode);
+
static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
union afe_enc_config_data *enc_cfg,
- u32 codec_format, u32 scrambler_mode,
+ u32 codec_format, u32 scrambler_mode, u32 mono_mode,
struct afe_dec_config *dec_cfg)
{
struct afe_audioif_config_command config;
@@ -3598,7 +3664,7 @@
codec_format, *afe_config,
afe_in_channels,
afe_in_bit_width,
- scrambler_mode);
+ scrambler_mode, mono_mode);
if (ret) {
pr_err("%s: AFE encoder config for port 0x%x failed %d\n",
__func__, port_id, ret);
@@ -3663,7 +3729,7 @@
u32 rate)
{
return __afe_port_start(port_id, afe_config, rate,
- 0, 0, NULL, ASM_MEDIA_FMT_NONE, 0, NULL);
+ 0, 0, NULL, ASM_MEDIA_FMT_NONE, 0, 0, NULL);
}
EXPORT_SYMBOL(afe_port_start);
@@ -3692,11 +3758,12 @@
ret = __afe_port_start(port_id, afe_config, rate,
afe_in_channels, afe_in_bit_width,
&enc_cfg->data, enc_cfg->format,
- enc_cfg->scrambler_mode, NULL);
+ enc_cfg->scrambler_mode,
+ enc_cfg->mono_mode, NULL);
else if (dec_cfg != NULL)
ret = __afe_port_start(port_id, afe_config, rate,
afe_in_channels, afe_in_bit_width,
- NULL, dec_cfg->format, 0, dec_cfg);
+ NULL, dec_cfg->format, 0, 0, dec_cfg);
return ret;
}
diff --git a/include/dsp/apr_audio-v2.h b/include/dsp/apr_audio-v2.h
index dbeb6de..64380a5 100644
--- a/include/dsp/apr_audio-v2.h
+++ b/include/dsp/apr_audio-v2.h
@@ -3250,6 +3250,14 @@
*/
#define AFE_DECODER_PARAM_ID_DEPACKETIZER_ID 0x00013235
+#define CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO 0x0001332A
+
+struct aptx_channel_mode_param_t {
+ struct apr_hdr hdr;
+ struct afe_port_cmd_set_param_v2 param;
+ struct afe_port_param_data_v2 pdata;
+ u32 channel_mode;
+} __packed;
/*
* Data format to send compressed data
* is transmitted/received over Slimbus lines.
@@ -3630,6 +3638,7 @@
struct afe_enc_config {
u32 format;
u32 scrambler_mode;
+ u32 mono_mode;
union afe_enc_config_data data;
};
@@ -3671,6 +3680,18 @@
};
/*
+ * Payload of the CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO parameter.
+ */
+struct afe_enc_set_channel_mode_param_t {
+ /*
+ * Supported values:
+ * 1 : mono
+ * 2 : dual_mono
+ */
+ u32 channel_mode;
+};
+
+/*
* Payload of the AVS_ENCODER_PARAM_ID_BIT_RATE_LEVEL_MAP parameter.
*/
struct afe_enc_level_to_bitrate_map_param_t {
@@ -3725,6 +3746,7 @@
struct avs_dec_depacketizer_id_param_t dec_depkt_id_param;
struct afe_enc_level_to_bitrate_map_param_t map_param;
struct afe_enc_dec_imc_info_param_t imc_info_param;
+ struct afe_enc_set_channel_mode_param_t channel_mode_param;
} __packed;
struct afe_audioif_config_command_no_payload {
diff --git a/include/dsp/q6afe-v2.h b/include/dsp/q6afe-v2.h
index 7edbedd..45bcfd4 100644
--- a/include/dsp/q6afe-v2.h
+++ b/include/dsp/q6afe-v2.h
@@ -324,6 +324,7 @@
void afe_set_cal_mode(u16 port_id, enum afe_cal_mode afe_cal_mode);
int afe_port_start(u16 port_id, union afe_port_config *afe_config,
u32 rate);
+int afe_set_tws_channel_mode(u16 port_id, u32 channel_mode);
int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
u32 rate, u16 afe_in_channels, u16 afe_in_bit_width,
struct afe_enc_config *enc_config,