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

Commit 97ddf9fd authored by Phani Kumar Uppalapati's avatar Phani Kumar Uppalapati
Browse files

ASoC: wcd934x: Create mixer control to select asrc output mode



Create mixer control to select asrc (asynchronous sample rate
converter) output mode to integer or fractional rate based on
the playback sample rate of the main path or DSD path.

CRs-Fixed: 1078253
Change-Id: I941a357d63f1024c5f7648de10af10df0148c6a7
Signed-off-by: default avatarPhani Kumar Uppalapati <phaniu@codeaurora.org>
parent 52912bb7
Loading
Loading
Loading
Loading
+101 −13
Original line number Diff line number Diff line
@@ -358,6 +358,15 @@ enum {
	ASRC_MAX,
};

enum {
	CONV_88P2K_TO_384K,
	CONV_96K_TO_352P8K,
	CONV_352P8K_TO_384K,
	CONV_384K_TO_352P8K,
	CONV_384K_TO_384K,
	CONV_96K_TO_384K,
};

static struct afe_param_slimbus_slave_port_cfg tavil_slimbus_slave_port_cfg = {
	.minor_version = 1,
	.slimbus_dev_id = AFE_SLIMBUS_DEVICE_1,
@@ -616,6 +625,7 @@ struct tavil_priv {
	int native_clk_users;
	/* ASRC users count */
	int asrc_users[ASRC_MAX];
	int asrc_output_mode[ASRC_MAX];
	/* Main path clock users count */
	int main_clk_users[WCD934X_NUM_INTERPOLATORS];
	struct tavil_dsd_config *dsd_config;
@@ -2581,6 +2591,45 @@ done:
	return rc;
}

static int tavil_get_asrc_mode(struct tavil_priv *tavil, int asrc,
			       u8 main_sr, u8 mix_sr)
{
	u8 asrc_output_mode;
	int asrc_mode = CONV_88P2K_TO_384K;

	if ((asrc < 0) || (asrc >= ASRC_MAX))
		return 0;

	asrc_output_mode = tavil->asrc_output_mode[asrc];

	if (asrc_output_mode) {
		/*
		 * If Mix sample rate is < 96KHz, use 96K to 352.8K
		 * conversion, or else use 384K to 352.8K conversion
		 */
		if (mix_sr < 5)
			asrc_mode = CONV_96K_TO_352P8K;
		else
			asrc_mode = CONV_384K_TO_352P8K;
	} else {
		/* Integer main and Fractional mix path */
		if (main_sr < 8 && mix_sr > 9) {
			asrc_mode = CONV_352P8K_TO_384K;
		} else if (main_sr > 8 && mix_sr < 8) {
			/* Fractional main and Integer mix path */
			if (mix_sr < 5)
				asrc_mode = CONV_96K_TO_352P8K;
			else
				asrc_mode = CONV_384K_TO_352P8K;
		} else if (main_sr < 8 && mix_sr < 8) {
			/* Integer main and Integer mix path */
			asrc_mode = CONV_96K_TO_384K;
		}
	}

	return asrc_mode;
}

static int tavil_codec_enable_asrc(struct snd_soc_codec *codec,
				   int asrc_in, int event)
{
@@ -2647,19 +2696,8 @@ static int tavil_codec_enable_asrc(struct snd_soc_codec *codec,
			main_sr = snd_soc_read(codec, ctl_reg) & 0x0F;
			mix_ctl_reg = ctl_reg + 5;
			mix_sr = snd_soc_read(codec, mix_ctl_reg) & 0x0F;
			/* Integer main and Fractional mix path */
			if (main_sr < 8 && mix_sr > 9) {
				asrc_mode = 2;
			} else if (main_sr > 8 && mix_sr < 8) {
				/* Fractional main and Integer mix path */
				if (mix_sr < 5)
					asrc_mode = 1;
				else
					asrc_mode = 3;
			} else if (main_sr < 8 && mix_sr < 8) {
				/* Integer main and Integer mix path */
				asrc_mode = 5;
			}
			asrc_mode = tavil_get_asrc_mode(tavil, asrc,
							main_sr, mix_sr);
			dev_dbg(codec->dev, "%s: main_sr:%d mix_sr:%d asrc_mode %d\n",
				__func__, main_sr, mix_sr, asrc_mode);
			snd_soc_update_bits(codec, asrc_ctl, 0x07, asrc_mode);
@@ -4737,6 +4775,46 @@ static int tavil_compander_put(struct snd_kcontrol *kcontrol,
	return 0;
}

static int tavil_hph_asrc_mode_put(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
	struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
	int index = -EINVAL;

	if (!strcmp(kcontrol->id.name, "ASRC0 Output Mode"))
		index = ASRC0;
	if (!strcmp(kcontrol->id.name, "ASRC1 Output Mode"))
		index = ASRC1;

	if (tavil && (index >= 0) && (index < ASRC_MAX))
		tavil->asrc_output_mode[index] =
			ucontrol->value.integer.value[0];

	return 0;
}

static int tavil_hph_asrc_mode_get(struct snd_kcontrol *kcontrol,
				   struct snd_ctl_elem_value *ucontrol)
{
	struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
	struct tavil_priv *tavil = snd_soc_codec_get_drvdata(codec);
	int val = 0;
	int index = -EINVAL;

	if (!strcmp(kcontrol->id.name, "ASRC0 Output Mode"))
		index = ASRC0;
	if (!strcmp(kcontrol->id.name, "ASRC1 Output Mode"))
		index = ASRC1;

	if (tavil && (index >= 0) && (index < ASRC_MAX))
		val = tavil->asrc_output_mode[index];

	ucontrol->value.integer.value[0] = val;

	return 0;
}

static int tavil_hph_idle_detect_get(struct snd_kcontrol *kcontrol,
				     struct snd_ctl_elem_value *ucontrol)
{
@@ -5131,6 +5209,10 @@ static const char * const hph_idle_detect_text[] = {
	"OFF", "ON"
};

static const char * const asrc_mode_text[] = {
	"INT", "FRAC"
};

static const char * const tavil_ear_pa_gain_text[] = {
	"G_6_DB", "G_4P5_DB", "G_3_DB", "G_1P5_DB",
	"G_0_DB", "G_M2P5_DB", "UNDEFINED", "G_M12_DB"
@@ -5146,6 +5228,7 @@ static SOC_ENUM_SINGLE_EXT_DECL(tavil_ear_spkr_pa_gain_enum,
				tavil_ear_spkr_pa_gain_text);
static SOC_ENUM_SINGLE_EXT_DECL(amic_pwr_lvl_enum, amic_pwr_lvl_text);
static SOC_ENUM_SINGLE_EXT_DECL(hph_idle_detect_enum, hph_idle_detect_text);
static SOC_ENUM_SINGLE_EXT_DECL(asrc_mode_enum, asrc_mode_text);
static SOC_ENUM_SINGLE_DECL(cf_dec0_enum, WCD934X_CDC_TX0_TX_PATH_CFG0, 5,
							cf_text);
static SOC_ENUM_SINGLE_DECL(cf_dec1_enum, WCD934X_CDC_TX1_TX_PATH_CFG0, 5,
@@ -5380,6 +5463,11 @@ static const struct snd_kcontrol_new tavil_snd_controls[] = {
	SOC_SINGLE_EXT("COMP8 Switch", SND_SOC_NOPM, COMPANDER_8, 1, 0,
		tavil_compander_get, tavil_compander_put),

	SOC_ENUM_EXT("ASRC0 Output Mode", asrc_mode_enum,
		tavil_hph_asrc_mode_get, tavil_hph_asrc_mode_put),
	SOC_ENUM_EXT("ASRC1 Output Mode", asrc_mode_enum,
		tavil_hph_asrc_mode_get, tavil_hph_asrc_mode_put),

	SOC_ENUM_EXT("HPH Idle Detect", hph_idle_detect_enum,
		tavil_hph_idle_detect_get, tavil_hph_idle_detect_put),