Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c9755e1c authored by Manisha Agarwal's avatar Manisha Agarwal Committed by Gerrit - the friendly Code Review server
Browse files

ASoC: Add TWS+ mono mode support



Add support to enable mono mode when one TWS+ earbud is
connected. Change the encoder config when device switches from two
earbuds to single earbud.

CRs-Fixed: 2341876
Change-Id: I880aa6a2767d88e99be2d80afff0e5fbec94b8a4
Signed-off-by: default avatarManisha Agarwal <maniagar@codeaurora.org>
parent 75fe2594
Loading
Loading
Loading
Loading
+69 −0
Original line number Diff line number Diff line
@@ -34,6 +34,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
@@ -2936,6 +2938,12 @@ static const struct soc_enum afe_bit_format_enum[] = {
	SOC_ENUM_SINGLE_EXT(3, afe_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)
{
@@ -2964,6 +2972,61 @@ static int msm_dai_q6_afe_input_channel_put(struct snd_kcontrol *kcontrol,
	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)
@@ -3157,6 +3220,9 @@ static const struct snd_kcontrol_new afe_enc_config_controls[] = {
		       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,
@@ -3439,6 +3505,9 @@ static int msm_dai_q6_dai_probe(struct snd_soc_dai *dai)
		rc = snd_ctl_add(dai->component->card->snd_card,
				 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));
+53 −6
Original line number Diff line number Diff line
@@ -3618,7 +3618,7 @@ static int q6afe_send_enc_config(u16 port_id,
				 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)
{
	u32 enc_fmt;
	struct afe_enc_cfg_blk_param_t enc_blk_param;
@@ -3629,6 +3629,7 @@ static int q6afe_send_enc_config(u16 port_id,
	struct afe_enc_level_to_bitrate_map_param_t map_param;
	struct afe_enc_dec_imc_info_param_t imc_info_param;
	struct afe_port_media_type_t media_type;
	struct aptx_channel_mode_param_t channel_mode_param;
	struct param_hdr_v3 param_hdr;
	int ret;

@@ -3763,6 +3764,23 @@ static int q6afe_send_enc_config(u16 port_id,
		goto exit;
	}

	if (format == ASM_MEDIA_FMT_APTX) {
		pr_debug("%s:sending CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO mode= %d to DSP payload\n",
			__func__, mono_mode);
		param_hdr.param_id = CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO;
		param_hdr.param_size = sizeof(channel_mode_param);
		channel_mode_param.channel_mode = mono_mode;
		ret = q6afe_pack_and_set_param_in_band(port_id,
				q6audio_get_port_index(port_id),
							param_hdr,
					(u8 *) &channel_mode_param);

		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 &&
	     cfg->ldac_config.abr_config.is_abr_enabled) ||
	     format == ASM_MEDIA_FMT_APTX_ADAPTIVE) {
@@ -3846,10 +3864,38 @@ static int q6afe_send_enc_config(u16 port_id,
	return ret;
}

int afe_set_tws_channel_mode(u16 port_id, u32 channel_mode)
{
	struct aptx_channel_mode_param_t channel_mode_param;
	struct param_hdr_v3 param_info;
	int ret = 0;

	memset(&param_info, 0, sizeof(param_info));
	memset(&channel_mode_param, 0, sizeof(channel_mode_param));

	param_info.module_id = AFE_MODULE_ID_ENCODER;
	param_info.instance_id = INSTANCE_ID_0;
	param_info.param_id = CAPI_V2_PARAM_ID_APTX_ENC_SWITCH_TO_MONO;
	param_info.param_size = sizeof(channel_mode_param);

	channel_mode_param.channel_mode = channel_mode;

	ret = q6afe_pack_and_set_param_in_band(port_id,
			q6audio_get_port_index(port_id),
						param_info,
				(u8 *) &channel_mode_param);
	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)
{
	union afe_port_config port_cfg;
@@ -4152,7 +4198,7 @@ static int __afe_port_start(u16 port_id, union afe_port_config *afe_config,
						    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);
@@ -4219,7 +4265,7 @@ int afe_port_start(u16 port_id, union afe_port_config *afe_config,
		   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);

@@ -4248,11 +4294,12 @@ int afe_port_start_v2(u16 port_id, union afe_port_config *afe_config,
		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, dec_cfg);
					enc_cfg->scrambler_mode,
					enc_cfg->mono_mode, dec_cfg);
	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;
}
+6 −0
Original line number Diff line number Diff line
@@ -3921,6 +3921,11 @@ struct afe_id_aptx_adaptive_enc_init
 */
#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 {
	u32 channel_mode;
} __packed;
/*
 * Decoder buffer ID parameter for the #AVS_MODULE_ID_DECODER module.
 * This parameter cannot be set runtime.
@@ -4411,6 +4416,7 @@ union afe_enc_config_data {
struct afe_enc_config {
	u32 format;
	u32 scrambler_mode;
	u32 mono_mode;
	union afe_enc_config_data data;
};

+1 −0
Original line number Diff line number Diff line
@@ -373,6 +373,7 @@ void afe_set_island_mode_cfg(u16 port_id, u32 enable_flag);
void afe_get_island_mode_cfg(u16 port_id, u32 *enable_flag);
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,