clear-pkgs-linux-iot-lts2018/0158-ASoc-rt700-Fix-for-fir...

299 lines
10 KiB
Diff

From 2e4f033cf79f1b5e42a1d11278a35ea82d4cbc47 Mon Sep 17 00:00:00 2001
From: bardliao <bardliao@realtek.com>
Date: Tue, 10 Jan 2017 10:54:11 +0530
Subject: [PATCH 158/550] ASoc: rt700: Fix for first playback and capture no
audio issue
This patch fixes no audio issue observed with first playback and
capture after booting the platform with power disconnect/connect.
In case for playback the issue was randomly observed and in case of
capture, the issue was always reproducible.
Change-Id: I0d91afa26a83a25295ab0b8faa1221caa32c80dc
Signed-off-by: bardliao <bardliao@realtek.com>
Signed-off-by: Sanyog Kale <sanyog.r.kale@intel.com>
Reviewed-on:
Reviewed-by: Diwakar, Praveen <praveen.diwakar@intel.com>
Tested-by: Avati, Santosh Kumar <santosh.kumar.avati@intel.com>
---
sound/soc/codecs/rt700.c | 171 ++++++++++++++++++++++++---------------
1 file changed, 107 insertions(+), 64 deletions(-)
diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c
index 773e77bc7ed6..400f7bbc6245 100644
--- a/sound/soc/codecs/rt700.c
+++ b/sound/soc/codecs/rt700.c
@@ -623,16 +623,41 @@ int rt700_jack_detect(struct rt700_priv *rt700, bool *hp, bool *mic)
}
EXPORT_SYMBOL(rt700_jack_detect);
+static void rt700_get_gain(struct rt700_priv *rt700, unsigned int addr_h,
+ unsigned int addr_l, unsigned int val_h,
+ unsigned int *r_val, unsigned int *l_val)
+{
+ /* R Channel */
+ regmap_write(rt700->regmap, addr_h, val_h);
+ pr_debug("%s write %04x %02x\n", __func__, addr_h, val_h);
+ regmap_write(rt700->regmap, addr_l, 0);
+ pr_debug("%s write %04x %02x\n", __func__, addr_l, 0);
+ regmap_read(rt700->regmap, RT700_READ_HDA_0, r_val);
+ pr_debug("%s read %04x %02x\n", __func__, RT700_READ_HDA_0, *r_val);
+
+ /* L Channel */
+ val_h |= 0x20;
+ regmap_write(rt700->regmap, addr_h, val_h);
+ pr_debug("%s write %04x %02x\n", __func__, addr_h, val_h);
+ regmap_write(rt700->regmap, addr_l, 0);
+ pr_debug("%s write %04x %02x\n", __func__, addr_l, 0);
+ regmap_read(rt700->regmap, RT700_READ_HDA_0, l_val);
+ pr_debug("%s read %04x %02x\n", __func__, RT700_READ_HDA_0, *l_val);
+}
+
/* For Verb-Set Amplifier Gain (Verb ID = 3h) */
static int rt700_set_amp_gain_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_context *dapm =
+ snd_soc_component_get_dapm(component);
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
struct rt700_priv *rt700 = snd_soc_component_get_drvdata(component);
- unsigned int addr_h, addr_l, val_h, val_l;
+ unsigned int addr_h, addr_l, val_h, val_ll, val_lr;
unsigned int read_ll, read_rl;
+ int i;
/* Can't use update bit function, so read the original value first */
@@ -642,76 +667,107 @@ static int rt700_set_amp_gain_put(struct snd_kcontrol *kcontrol,
val_h = 0x80;
else /* input */
val_h = 0x0;
- /* R Channel */
- regmap_write(rt700->regmap, addr_h, val_h);
- pr_debug("%s write %04x %02x\n", __func__, addr_h, val_h);
- regmap_write(rt700->regmap, addr_l, 0);
- pr_debug("%s write %04x %02x\n", __func__, addr_l, 0);
- regmap_read(rt700->regmap, RT700_READ_HDA_0, &read_rl);
- pr_debug("%s read %04x %02x\n", __func__, RT700_READ_HDA_0, read_rl);
-
- /* L Channel */
- val_h |= 0x20;
- regmap_write(rt700->regmap, addr_h, val_h);
- pr_debug("%s write %04x %02x\n", __func__, addr_h, val_h);
- regmap_write(rt700->regmap, addr_l, 0);
- pr_debug("%s write %04x %02x\n", __func__, addr_l, 0);
- regmap_read(rt700->regmap, RT700_READ_HDA_0, &read_ll);
- pr_debug("%s read %04x %02x\n", __func__, RT700_READ_HDA_0, read_ll);
+ rt700_get_gain(rt700, addr_h, addr_l, val_h, &read_rl, &read_ll);
/* Now set value */
addr_h = mc->reg;
addr_l = mc->rreg;
- /*pr_debug("%s val = %d, %d\n", ucontrol->value.integer.value[0],
- ucontrol->value.integer.value[1]);*/
pr_debug("%s val = %d, %d\n", __func__, ucontrol->value.integer.value[0],
- ucontrol->value.integer.value[1]);
- /* L Channel */
- val_h = (1 << mc->shift) | (1 << 5);
+ ucontrol->value.integer.value[1]);
+ /* L Channel */
if (mc->invert) {
/* for mute */
- val_l = (mc->max - ucontrol->value.integer.value[0]) << 7;
+ val_ll = (mc->max - ucontrol->value.integer.value[0]) << 7;
/* keep gain */
read_ll = read_ll & 0x7f;
- val_l |= read_ll;
+ val_ll |= read_ll;
} else {
/* for gain */
- val_l = ((ucontrol->value.integer.value[0]) & mc->max);
+ val_ll = ((ucontrol->value.integer.value[0]) & 0x7f);
+ if (val_ll > mc->max)
+ val_ll = mc->max;
/* keep mute status */
read_ll = read_ll & 0x80;
- val_l |= read_ll;
+ val_ll |= read_ll;
}
- regmap_write(rt700->regmap, addr_h, val_h);
- pr_debug("%s write %04x %02x\n", __func__, addr_h, val_h);
- regmap_write(rt700->regmap, addr_l, val_l);
- pr_debug("%s write %04x %02x\n", __func__, addr_l, val_l);
-
/* R Channel */
- val_h = (1 << mc->shift) | (1 << 4);
-
if (mc->invert) {
+ regmap_write(rt700->regmap,
+ RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
/* for mute */
- val_l = (mc->max - ucontrol->value.integer.value[1]) << 7;
+ val_lr = (mc->max - ucontrol->value.integer.value[1]) << 7;
/* keep gain */
read_rl = read_rl & 0x7f;
- val_l |= read_rl;
+ val_lr |= read_rl;
} else {
/* for gain */
- val_l = ((ucontrol->value.integer.value[1]) & mc->max);
+ val_lr = ((ucontrol->value.integer.value[1]) & 0x7f);
+ if (val_lr > mc->max)
+ val_lr = mc->max;
/* keep mute status */
read_rl = read_rl & 0x80;
- val_l |= read_rl;
+ val_lr |= read_rl;
}
- val_h = (1 << mc->shift) | (1 << 4);
- regmap_write(rt700->regmap, addr_h, val_h);
- pr_debug("%s write %04x %02x\n", __func__, addr_h, val_h);
- regmap_write(rt700->regmap, addr_l, val_l);
- pr_debug("%s write %04x %02x\n", __func__, addr_l, val_l);
+ for (i = 0; i < 3; i++) { /* retry 3 times at most */
+ pr_debug("%s i=%d\n", __func__, i);
+ addr_h = mc->reg;
+ addr_l = mc->rreg;
+ if (val_ll == val_lr) {
+ /* Set both L/R channels at the same time */
+ val_h = (1 << mc->shift) | (3 << 4);
+ regmap_write(rt700->regmap, addr_h, val_h);
+ pr_debug("%s write %04x %02x\n",
+ __func__, addr_h, val_h);
+ regmap_write(rt700->regmap, addr_l, val_ll);
+ pr_debug("%s write %04x %02x\n",
+ __func__, addr_l, val_ll);
+
+ } else {
+ /* Lch*/
+ val_h = (1 << mc->shift) | (1 << 5);
+ regmap_write(rt700->regmap, addr_h, val_h);
+ pr_debug("%s write %04x %02x\n",
+ __func__, addr_h, val_h);
+ regmap_write(rt700->regmap, addr_l, val_ll);
+ pr_debug("%s write %04x %02x\n",
+ __func__, addr_l, val_ll);
+
+ /* Rch */
+ val_h = (1 << mc->shift) | (1 << 4);
+ regmap_write(rt700->regmap, addr_h, val_h);
+ pr_debug("%s write %04x %02x\n",
+ __func__, addr_h, val_h);
+ regmap_write(rt700->regmap, addr_l, val_lr);
+ pr_debug("%s write %04x %02x\n",
+ __func__, addr_l, val_lr);
+
+ }
+ /* check result */
+ addr_h = (mc->reg + 0x2000) | 0x800;
+ addr_l = (mc->rreg + 0x2000) | 0x800;
+ if (mc->shift == RT700_DIR_OUT_SFT) /* output */
+ val_h = 0x80;
+ else /* input */
+ val_h = 0x0;
+
+ rt700_get_gain(rt700, addr_h, addr_l, val_h,
+ &read_rl, &read_ll);
+ if (read_rl == val_lr && read_ll == val_ll) {
+ pr_debug("write command successful\n");
+ break;
+ }
+
+ pr_warn("write command unsuccessful, retry\n");
+ }
+
+ if (dapm->bias_level <= SND_SOC_BIAS_STANDBY)
+ regmap_write(rt700->regmap,
+ RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
return 0;
}
@@ -731,22 +787,8 @@ static int rt700_set_amp_gain_get(struct snd_kcontrol *kcontrol,
val_h = 0x80;
else /* input */
val_h = 0x0;
- /* R Channel */
- regmap_write(rt700->regmap, addr_h, val_h);
- pr_debug("%s write %04x %02x\n", __func__, addr_h, val_h);
- regmap_write(rt700->regmap, addr_l, 0);
- pr_debug("%s write %04x %02x\n", __func__, addr_l, 0);
- regmap_read(rt700->regmap, RT700_READ_HDA_0, &read_rl);
- pr_debug("%s read %04x %02x\n", __func__, RT700_READ_HDA_0, read_rl);
- /* L Channel */
- val_h |= 0x20;
- regmap_write(rt700->regmap, addr_h, val_h);
- pr_debug("%s write %04x %02x\n", __func__, addr_h, val_h);
- regmap_write(rt700->regmap, addr_l, 0);
- pr_debug("%s write %04x %02x\n", __func__, addr_l, 0);
- regmap_read(rt700->regmap, RT700_READ_HDA_0, &read_ll);
- pr_debug("%s read %04x %02x\n", __func__, RT700_READ_HDA_0, read_ll);
+ rt700_get_gain(rt700, addr_h, addr_l, val_h, &read_rl, &read_ll);
if (mc->invert) {
/* for mute status */
@@ -957,10 +999,14 @@ static int rt700_set_bias_level(struct snd_soc_component *component,
{
struct snd_soc_dapm_context *dapm =
snd_soc_component_get_dapm(component);
+ struct rt700_priv *rt700 = snd_soc_codec_get_drvdata(codec);
+ unsigned int sdw_data_0;
+ pr_debug("%s level=%d\n", __func__, level);
switch (level) {
case SND_SOC_BIAS_PREPARE:
if (SND_SOC_BIAS_STANDBY == dapm->bias_level) {
+ pm_runtime_get_sync(&rt700->sdw->mstr->dev);
snd_soc_component_write(component,
RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D0);
}
@@ -969,6 +1015,7 @@ static int rt700_set_bias_level(struct snd_soc_component *component,
case SND_SOC_BIAS_STANDBY:
snd_soc_component_write(component,
RT700_SET_AUDIO_POWER_STATE, AC_PWRST_D3);
+ pm_runtime_put_sync_autosuspend(&rt700->sdw->mstr->dev);
break;
default:
@@ -1379,12 +1426,6 @@ static ssize_t rt700_hda_cmd_store(struct device *dev,
sdw_data_3, sdw_data_2, sdw_data_1, sdw_data_0);
}
- /* Enable Jack Detection */
- regmap_write(rt700->regmap, RT700_SET_MIC2_UNSOLICITED_ENABLE, 0x82);
- regmap_write(rt700->regmap, RT700_SET_HP_UNSOLICITED_ENABLE, 0x81);
- rt700_index_write(rt700->regmap, 0x10, 0x2420);
- rt700_index_write(rt700->regmap, 0x19, 0x2e11);
-
return count;
}
@@ -1518,6 +1559,9 @@ int rt700_probe(struct device *dev, struct regmap *regmap,
&soc_component_dev_rt700, rt700_dai, ARRAY_SIZE(rt700_dai));
dev_info(&slave->dev, "%s\n", __func__);
+ /* Enable clock before setting */
+ pm_runtime_get_sync(&rt700->sdw->mstr->dev);
+
/* Set Tx route */
/* Filter 02: index 91[13:12] 07[3] */
/* Filter 03: index 5f[15:14] 07[4] */
@@ -1617,7 +1661,6 @@ int rt700_probe(struct device *dev, struct regmap *regmap,
if (ret < 0)
return ret;
- pm_runtime_get_sync(&rt700->sdw->mstr->dev);
pm_runtime_mark_last_busy(&rt700->sdw->mstr->dev);
pm_runtime_put_sync_autosuspend(&rt700->sdw->mstr->dev);
--
2.19.1