From: Viswanath L Date: Wed, 7 Jun 2017 12:41:04 +0000 (+0530) Subject: tegra-alt: mvc: Updated mixer controls X-Git-Url: https://rtime.felk.cvut.cz/gitweb/hercules2020/nv-tegra/linux-4.4.git/commitdiff_plain/618852884fc5481dd5028b9e16ab02f7231b8713 tegra-alt: mvc: Updated mixer controls Following updates: - "input bit format" ctl to set RX CIF bit-width - 100x scaling to "Vol" ctl for more granularity - Fixes in mixer ctl "get" functions so that current value is read - Fix in "Curve Type" ctl so that default volume gets set Bug 1936284 Change-Id: Ib54b17266c7c3a3e9e42cab13195389c5fa1fbe7 Signed-off-by: Viswanath L Reviewed-on: http://git-master/r/1505597 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Mohan Kumar D Reviewed-by: Ravindra Lokhande --- diff --git a/sound/soc/tegra-alt/tegra210_mvc_alt.c b/sound/soc/tegra-alt/tegra210_mvc_alt.c index a8865f66ef60..3e7dc2914b11 100644 --- a/sound/soc/tegra-alt/tegra210_mvc_alt.c +++ b/sound/soc/tegra-alt/tegra210_mvc_alt.c @@ -139,26 +139,25 @@ static int tegra210_mvc_get_vol(struct snd_kcontrol *kcontrol, struct tegra210_mvc *mvc = snd_soc_codec_get_drvdata(codec); unsigned int reg = mc->reg; - pm_runtime_get_sync(codec->dev); if (reg == TEGRA210_MVC_TARGET_VOL) { - s32 val; + s32 val = mvc->volume; - regmap_read(mvc->regmap, reg, &val); if (mvc->curve_type == CURVE_POLY) - val >>= 24; + val = ((val >> 16) * 100) >> 8; else { - val >>= 8; - val += 120; + val = (val * 100) >> 8; + val += 12000; } ucontrol->value.integer.value[0] = val; } else { u32 val; + pm_runtime_get_sync(codec->dev); regmap_read(mvc->regmap, reg, &val); + pm_runtime_put(codec->dev); ucontrol->value.integer.value[0] = ((val & TEGRA210_MVC_MUTE_MASK) != 0); } - pm_runtime_put(codec->dev); return 0; } @@ -187,15 +186,18 @@ static int tegra210_mvc_put_vol(struct snd_kcontrol *kcontrol, } while (value & TEGRA210_MVC_VOLUME_SWITCH_MASK); if (reg == TEGRA210_MVC_TARGET_VOL) { + /* Volume control read from mixer ctl is with */ + /* 100x scaling; for CURVE_POLY the reg range */ + /* is 0-100 (linear, Q24) and for CURVE_LINEAR */ + /* it is -120dB to +40dB (Q8) */ if (mvc->curve_type == CURVE_POLY) { val = ucontrol->value.integer.value[0]; - if (val > 100) - val = 100; - mvc->volume = val * (1<<24); + if (val > 10000) + val = 10000; + mvc->volume = ((val * (1<<8)) / 100) << 16; } else { - val = ucontrol->value.integer.value[0] - 120; - val <<= 8; - mvc->volume = val; + val = ucontrol->value.integer.value[0] - 12000; + mvc->volume = (val * (1<<8)) / 100; } ret = regmap_write(mvc->regmap, reg, mvc->volume); } else { @@ -219,15 +221,8 @@ static int tegra210_mvc_get_curve_type(struct snd_kcontrol *kcontrol, { struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tegra210_mvc *mvc = snd_soc_codec_get_drvdata(codec); - unsigned int reg = TEGRA210_MVC_CTRL; - u32 val; - pm_runtime_get_sync(codec->dev); - regmap_read(mvc->regmap, reg, &val); - ucontrol->value.integer.value[0] = - (val & TEGRA210_MVC_CURVE_TYPE_MASK) >> - TEGRA210_MVC_CURVE_TYPE_SHIFT; - pm_runtime_put(codec->dev); + ucontrol->value.integer.value[0] = mvc->curve_type; return 0; } @@ -274,6 +269,11 @@ static int tegra210_mvc_put_curve_type(struct snd_kcontrol *kcontrol, else mvc->volume = TEGRA210_MVC_INIT_VOL_DEFAULT_LINEAR; + regmap_write(mvc->regmap, TEGRA210_MVC_TARGET_VOL, mvc->volume); + ret |= regmap_update_bits(mvc->regmap, TEGRA210_MVC_SWITCH, + TEGRA210_MVC_VOLUME_SWITCH_MASK, + TEGRA210_MVC_VOLUME_SWITCH_TRIGGER); + end: pm_runtime_put(codec->dev); @@ -286,7 +286,10 @@ static int tegra210_mvc_get_audio_bits(struct snd_kcontrol *kcontrol, struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tegra210_mvc *mvc = snd_soc_codec_get_drvdata(codec); - ucontrol->value.integer.value[0] = (mvc->audio_bits + 1) * 4; + if (mvc->audio_bits > 0) + ucontrol->value.integer.value[0] = (mvc->audio_bits + 1) * 4; + else + ucontrol->value.integer.value[0] = 0; return 0; } @@ -306,34 +309,43 @@ static int tegra210_mvc_put_audio_bits(struct snd_kcontrol *kcontrol, return 0; } - -static int tegra210_mvc_get_channels(struct snd_kcontrol *kcontrol, +static int tegra210_mvc_get_format(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tegra210_mvc *mvc = snd_soc_codec_get_drvdata(codec); - ucontrol->value.integer.value[0] = mvc->cif_channels; + /* get the format control flag */ + if (strstr(kcontrol->id.name, "input bit format")) + ucontrol->value.integer.value[0] = mvc->format_in; + else if (strstr(kcontrol->id.name, "Channels")) + ucontrol->value.integer.value[0] = mvc->cif_channels; return 0; } -static int tegra210_mvc_put_channels(struct snd_kcontrol *kcontrol, +static int tegra210_mvc_put_format(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); struct tegra210_mvc *mvc = snd_soc_codec_get_drvdata(codec); - unsigned int val; + unsigned int value = ucontrol->value.integer.value[0]; - val = ucontrol->value.integer.value[0]; - if ((val > 0) && (val <= 8)) - mvc->cif_channels = val; - else - return -EINVAL; + /* set the format control flag */ + if (strstr(kcontrol->id.name, "input bit format")) + mvc->format_in = value; + else if (strstr(kcontrol->id.name, "Channels")) + mvc->cif_channels = value; return 0; } +static const int tegra210_mvc_fmt_values[] = { + 0, + TEGRA210_AUDIOCIF_BITS_16, + TEGRA210_AUDIOCIF_BITS_32, +}; + static int tegra210_mvc_set_audio_cif(struct tegra210_mvc *mvc, struct snd_pcm_hw_params *params, unsigned int reg) @@ -369,6 +381,10 @@ static int tegra210_mvc_set_audio_cif(struct tegra210_mvc *mvc, cif_conf.audio_bits = audio_bits; cif_conf.client_bits = audio_bits; + /* Override input format to MVC, if set */ + if (mvc->format_in && (reg == TEGRA210_MVC_AXBAR_RX_CIF_CTRL)) + cif_conf.audio_bits = tegra210_mvc_fmt_values[mvc->format_in]; + mvc->soc_data->set_audio_cif(mvc->regmap, reg, &cif_conf); return 0; @@ -456,8 +472,19 @@ static const char * const tegra210_mvc_curve_type_text[] = { static const struct soc_enum tegra210_mvc_curve_type_ctrl = SOC_ENUM_SINGLE_EXT(2, tegra210_mvc_curve_type_text); +static const char * const tegra210_mvc_format_text[] = { + "None", + "16", + "32", +}; + +static const struct soc_enum tegra210_mvc_format_enum = + SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, + ARRAY_SIZE(tegra210_mvc_format_text), + tegra210_mvc_format_text); + static const struct snd_kcontrol_new tegra210_mvc_vol_ctrl[] = { - SOC_SINGLE_EXT("Vol", TEGRA210_MVC_TARGET_VOL, 0, 160, 0, + SOC_SINGLE_EXT("Vol", TEGRA210_MVC_TARGET_VOL, 0, 16000, 0, tegra210_mvc_get_vol, tegra210_mvc_put_vol), SOC_SINGLE_EXT("Mute", TEGRA210_MVC_CTRL, 0, 1, 0, tegra210_mvc_get_vol, tegra210_mvc_put_vol), @@ -465,8 +492,10 @@ static const struct snd_kcontrol_new tegra210_mvc_vol_ctrl[] = { tegra210_mvc_get_curve_type, tegra210_mvc_put_curve_type), SOC_SINGLE_EXT("Bits", 0, 0, 32, 0, tegra210_mvc_get_audio_bits, tegra210_mvc_put_audio_bits), - SOC_SINGLE_EXT("Channels", 0, 0, 16, 0, - tegra210_mvc_get_channels, tegra210_mvc_put_channels), + SOC_SINGLE_EXT("Channels", 0, 0, 8, 0, + tegra210_mvc_get_format, tegra210_mvc_put_format), + SOC_ENUM_EXT("input bit format", tegra210_mvc_format_enum, + tegra210_mvc_get_format, tegra210_mvc_put_format), }; static struct snd_soc_dai_driver tegra210_mvc_dais[] = { @@ -656,7 +685,7 @@ static int tegra210_mvc_platform_probe(struct platform_device *pdev) mvc->poly_coeff[7] = 5527252; mvc->poly_coeff[8] = -785042; mvc->curve_type = CURVE_LINEAR; - mvc->volume = TEGRA210_MVC_INIT_VOL_DEFAULT_POLY; + mvc->volume = TEGRA210_MVC_INIT_VOL_DEFAULT_LINEAR; mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!mem) { diff --git a/sound/soc/tegra-alt/tegra210_mvc_alt.h b/sound/soc/tegra-alt/tegra210_mvc_alt.h index 1171c371947b..523ecd9fe497 100644 --- a/sound/soc/tegra-alt/tegra210_mvc_alt.h +++ b/sound/soc/tegra-alt/tegra210_mvc_alt.h @@ -144,6 +144,7 @@ struct tegra210_mvc { unsigned int curve_type; unsigned int cif_channels; unsigned int audio_bits; + unsigned int format_in; const struct tegra210_mvc_soc_data *soc_data; bool is_shutdown; };