ASoC: implement ICN control in TAS2562

implement ICN control in TAS2562 kernel driver.
ICN enable = Receiver Configuration

Change-Id: I1ea32675096d6da77ea57bdb2c178872bf1b8947
Signed-off-by: zhouwl <zhouwl@lenovo.com>
Reviewed-on: https://gerrit.mot.com/1549428
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Hujun Liao <liaohj@motorola.com>
Submit-Approved: Jira Key
This commit is contained in:
zhouwl 2020-05-07 10:14:58 +08:00 • committed by Wanlong Zhou
commit bc6d75f62e
3 changed files with 79 additions and 0 deletions

View file

@ -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,

View file

@ -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,

View file

@ -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_ */