From bc6d75f62e54b722b612ff898947e4d348df8585 Mon Sep 17 00:00:00 2001 From: zhouwl Date: Thu, 7 May 2020 10:14:58 +0800 Subject: [PATCH] ASoC: implement ICN control in TAS2562 implement ICN control in TAS2562 kernel driver. ICN enable = Receiver Configuration Change-Id: I1ea32675096d6da77ea57bdb2c178872bf1b8947 Signed-off-by: zhouwl Reviewed-on: https://gerrit.mot.com/1549428 SME-Granted: SME Approvals Granted SLTApproved: Slta Waiver Tested-by: Jira Key Reviewed-by: Hujun Liao Submit-Approved: Jira Key --- sound/soc/codecs/tas2562-codec.c | 64 +++++++++++++++++++++++++++++++ sound/soc/codecs/tas2562-regmap.c | 13 +++++++ sound/soc/codecs/tas2562.h | 2 + 3 files changed, 79 insertions(+) diff --git a/sound/soc/codecs/tas2562-codec.c b/sound/soc/codecs/tas2562-codec.c index c56c4bc2c764..e68924ec2035 100644 --- a/sound/soc/codecs/tas2562-codec.c +++ b/sound/soc/codecs/tas2562-codec.c @@ -53,6 +53,7 @@ #define TAS2562_MSLEEP 0xFFFFFFFD #define TAS2562_IVSENSER_ENABLE 1 #define TAS2562_IVSENSER_DISABLE 0 +#define MAX_STRING 200 /* #define TAS2558_CODEC */ static char const *iv_enable_text[] = {"Off", "On"}; @@ -390,11 +391,71 @@ static int tas2562_brownout_get(struct snd_kcontrol *kcontrol, return 0; } +static int tas2562_icn_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas2562_priv *p_tas2562 = NULL; + + if (codec == NULL) { + pr_err("%s:codec is NULL\n", __func__); + return 0; + } + + p_tas2562 = snd_soc_codec_get_drvdata(codec); + if (p_tas2562 == NULL) { + pr_err("%s:p_tas2562 is NULL\n", __func__); + return 0; + } + + if (strnstr(ucontrol->id.name, "RIGHT", MAX_STRING)) { + ucontrol->value.integer.value[0] = p_tas2562->icn_enable_right; + } else { /*Assumed Left*/ + ucontrol->value.integer.value[0] = p_tas2562->icn_enable_left; + } + + dev_err(p_tas2562->dev, "icn enable %d\n", (int)ucontrol->value.integer.value[0]); + + return 0; +} + +static int tas2562_icn_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas2562_priv *p_tas2562 = NULL; + + if (codec == NULL) { + pr_err("%s:codec is NULL\n", __func__); + return 0; + } + + p_tas2562 = snd_soc_codec_get_drvdata(codec); + if (p_tas2562 == NULL) { + pr_err("%s:p_tas2562 is NULL\n", __func__); + return 0; + } + + if (strnstr(ucontrol->id.name, "RIGHT", MAX_STRING)) { + p_tas2562->icn_enable_right = ucontrol->value.integer.value[0]; + } else { /*Assumed Left*/ + p_tas2562->icn_enable_left = ucontrol->value.integer.value[0]; + } + + pr_debug("%s: icn_enable = %d\n", __func__, (int)ucontrol->value.integer.value[0]); + + return 0; +} + static const struct snd_kcontrol_new tas2562_controls[] = { SOC_ENUM_EXT("TAS2562 IVSENSE ENABLE", tas2562_enum[0], tas2562iv_get, tas2562iv_put), SOC_ENUM_EXT("TAS2562 BROWNOUT PROTECT ENABLE", tas2562_enum[1], tas2562_brownout_get, tas2562_brownout_put), +SOC_ENUM_EXT("TAS2562 ICN ENABLE LEFT", tas2562_enum[1], + tas2562_icn_get, tas2562_icn_put), +SOC_ENUM_EXT("TAS2562 ICN ENABLE RIGHT", tas2562_enum[1], + tas2562_icn_get, tas2562_icn_put), }; static int tas2562_codec_write(struct snd_soc_codec *codec, unsigned int reg, @@ -554,6 +615,9 @@ static int tas2562_set_power_state(struct tas2562_priv *p_tas2562, break; case TAS2562_POWER_SHUTDOWN: + // Disable Comparator Hystersis befor Power Down. + n_result = p_tas2562->write(p_tas2562, chn, + TAS2562_REG(0x0, 0x01, 0x21), 0x0); n_result = p_tas2562->update_bits(p_tas2562, chn, TAS2562_POWERCONTROL, diff --git a/sound/soc/codecs/tas2562-regmap.c b/sound/soc/codecs/tas2562-regmap.c index f1ad3429dbb6..fac5a2a32061 100644 --- a/sound/soc/codecs/tas2562-regmap.c +++ b/sound/soc/codecs/tas2562-regmap.c @@ -708,6 +708,19 @@ static void irq_work_routine(struct work_struct *work) TAS2562_POWERCONTROL_OPERATIONALMODE10_ACTIVE); if (n_result < 0) goto reload; + // Let the Power Up complete + msleep(2); + // Enable Comparator Hystersis + if (p_tas2562->icn_enable_left) { + n_result = p_tas2562->write(p_tas2562, channel_left, + TAS2562_REG(0x0, 0x01, 0x21), 0x08); + dev_info(p_tas2562->dev, "ICN enabled for Left\n"); + } + if (p_tas2562->icn_enable_right) { + n_result = p_tas2562->write(p_tas2562, channel_right, + TAS2562_REG(0x0, 0x01, 0x21), 0x08); + dev_info(p_tas2562->dev, "ICN enabled for Right\n"); + } dev_info(p_tas2562->dev, "set ICN to -80dB\n"); n_result = p_tas2562->bulk_write(p_tas2562, chn, diff --git a/sound/soc/codecs/tas2562.h b/sound/soc/codecs/tas2562.h index 01be02df5fa5..78ba6de0c6f2 100644 --- a/sound/soc/codecs/tas2562.h +++ b/sound/soc/codecs/tas2562.h @@ -699,6 +699,8 @@ int max_ant; int lim_th_max; int lim_th_min; bool tas2562brownout_enable; +bool icn_enable_left; +bool icn_enable_right; }; #endif /* __TAS2562_ */