@@ -63,6 +63,7 @@ struct rtq9128_data {
int tdm_slots;
int tdm_slot_width;
bool tdm_input_data2_select;
+ bool tka470b_e1_ver;
};
struct rtq9128_init_reg {
@@ -171,7 +172,7 @@ static bool rtq9128_is_writeable_reg(struct device *dev, unsigned int reg)
case 0x80 ... 0x8B:
case 0xA0 ... 0xAD:
case 0xB0 ... 0xBA:
- case 0xC0:
+ case 0xC0 ... 0xC1:
case 0xD0 ... 0xDE:
case 0xE0 ... 0xE5:
case 0xF0 ... 0xF3:
@@ -283,6 +284,33 @@ static const struct snd_kcontrol_new rtq9128_snd_ctrls[] = {
SOC_ENUM("DVDD UV Threshold Select", rtq9128_dvdduv_select_enum),
};
+static int rtq9128_int_power_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *comp = snd_soc_dapm_to_component(w->dapm);
+ struct rtq9128_data *data = snd_soc_component_get_drvdata(comp);
+ int ret;
+
+ dev_dbg(comp->dev, "%s: event %d, ver %d\n", __func__, event, data->tka470b_e1_ver);
+
+ if (!data->tka470b_e1_ver)
+ return 0;
+
+ if (event == SND_SOC_DAPM_POST_PMU) {
+ ret = snd_soc_component_write(comp, 0xB9, 0x03);
+ if (ret)
+ return ret;
+
+ return snd_soc_component_write(comp, 0xC1, 0);
+ }
+
+ ret = snd_soc_component_write(comp, 0xA1, 0x02);
+ if (ret)
+ return ret;
+
+ return snd_soc_component_write(comp, 0xA8, 0x01);
+}
+
static int rtq9128_dac_power_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol,
int event)
{
@@ -320,6 +348,8 @@ static int rtq9128_dac_power_event(struct snd_soc_dapm_widget *w, struct snd_kco
}
static const struct snd_soc_dapm_widget rtq9128_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("PWR", SND_SOC_NOPM, 0, 0, rtq9128_int_power_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_DAC_E("DAC1", NULL, SND_SOC_NOPM, 0, 0, rtq9128_dac_power_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_DAC_E("DAC2", NULL, SND_SOC_NOPM, 0, 0, rtq9128_dac_power_event,
@@ -339,6 +369,10 @@ static const struct snd_soc_dapm_route rtq9128_dapm_routes[] = {
{ "DAC2", NULL, "Playback" },
{ "DAC3", NULL, "Playback" },
{ "DAC4", NULL, "Playback" },
+ { "DAC1", NULL, "PWR" },
+ { "DAC2", NULL, "PWR" },
+ { "DAC3", NULL, "PWR" },
+ { "DAC4", NULL, "PWR" },
{ "OUT1", NULL, "DAC1" },
{ "OUT2", NULL, "DAC2" },
{ "OUT3", NULL, "DAC3" },
@@ -358,9 +392,7 @@ static const struct rtq9128_init_reg rtq9128_tka470b_tables[] = {
{ 0x70, 0x11 },
{ 0x75, 0x1F },
{ 0xB6, 0x03 },
- { 0xB9, 0x03 },
{ 0xB8, 0x03 },
- { 0xC1, 0xFF },
{ 0xF8, 0x72 },
{ 0x30, 0x180 },
};
@@ -387,6 +419,7 @@ static const struct rtq9128_init_reg rtq9128_dl_tables[] = {
static int rtq9128_component_probe(struct snd_soc_component *comp)
{
+ struct rtq9128_data *data = snd_soc_component_get_drvdata(comp);
const struct rtq9128_init_reg *table, *curr;
size_t table_size;
unsigned int val;
@@ -402,6 +435,7 @@ static int rtq9128_component_probe(struct snd_soc_component *comp)
switch (FIELD_GET(RTQ9128_DIE_CHECK_MASK, val)) {
case RTQ9128_TKA470B_VAL:
+ data->tka470b_e1_ver = true;
table = rtq9128_tka470b_tables;
table_size = ARRAY_SIZE(rtq9128_tka470b_tables);
break;
@@ -630,12 +664,29 @@ static int rtq9128_dai_hw_params(struct snd_pcm_substream *stream, struct snd_pc
static int rtq9128_dai_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
{
+ struct rtq9128_data *data = snd_soc_dai_get_drvdata(dai);
struct snd_soc_component *comp = dai->component;
struct device *dev = dai->dev;
int ret;
dev_dbg(dev, "%s: mute (%d), stream (%d)\n", __func__, mute, stream);
+ if (data->tka470b_e1_ver && !mute) {
+ ret = snd_soc_component_write(comp, 0xB9, 0x02);
+ if (ret)
+ return ret;
+
+ usleep_range(10000, 11000);
+
+ ret = snd_soc_component_write(comp, 0xA1, 0xF2);
+ if (ret)
+ return ret;
+
+ ret = snd_soc_component_write(comp, 0xA8, 0x00);
+ if (ret)
+ return ret;
+ }
+
ret = snd_soc_component_write_field(comp, RTQ9128_REG_DSP_EN, RTQ9128_MSMUTE_MASK,
mute ? 1 : 0);
return ret < 0 ? ret : 0;