Commit c076e201 authored by Stefan Binding's avatar Stefan Binding Committed by Takashi Iwai

ALSA: hda/cs8409: Support multiple sub_codecs for Suspend/Resume/Unsol events

Signed-off-by: default avatarStefan Binding <sbinding@opensource.cirrus.com>
Signed-off-by: default avatarVitaly Rodionov <vitalyr@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20210811185654.6837-20-vitalyr@opensource.cirrus.comSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 24f7ac3d
...@@ -388,16 +388,21 @@ static int cs8409_build_controls(struct hda_codec *codec) ...@@ -388,16 +388,21 @@ static int cs8409_build_controls(struct hda_codec *codec)
return 0; return 0;
} }
/* Enable/Disable Unsolicited Response for gpio(s) 3,4 */ /* Enable/Disable Unsolicited Response */
static void cs8409_enable_ur(struct hda_codec *codec, int flag) static void cs8409_enable_ur(struct hda_codec *codec, int flag)
{ {
/* GPIO4 INT# and GPIO3 WAKE# */ struct cs8409_spec *spec = codec->spec;
unsigned int ur_gpios = 0;
int i;
for (i = 0; i < spec->num_scodecs; i++)
ur_gpios |= spec->scodecs[i]->irq_mask;
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK,
flag ? CS8409_CS42L42_INT : 0); flag ? ur_gpios : 0);
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_UNSOLICITED_ENABLE, snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_UNSOLICITED_ENABLE,
flag ? AC_UNSOL_ENABLED : 0); flag ? AC_UNSOL_ENABLED : 0);
} }
static void cs8409_fix_caps(struct hda_codec *codec, unsigned int nid) static void cs8409_fix_caps(struct hda_codec *codec, unsigned int nid)
...@@ -629,6 +634,8 @@ static int cs42l42_jack_unsol_event(struct sub_codec *cs42l42) ...@@ -629,6 +634,8 @@ static int cs42l42_jack_unsol_event(struct sub_codec *cs42l42)
static void cs42l42_resume(struct sub_codec *cs42l42) static void cs42l42_resume(struct sub_codec *cs42l42)
{ {
struct hda_codec *codec = cs42l42->codec;
unsigned int gpio_data;
struct cs8409_i2c_param irq_regs[] = { struct cs8409_i2c_param irq_regs[] = {
{ 0x1308, 0x00 }, { 0x1308, 0x00 },
{ 0x1309, 0x00 }, { 0x1309, 0x00 },
...@@ -636,6 +643,12 @@ static void cs42l42_resume(struct sub_codec *cs42l42) ...@@ -636,6 +643,12 @@ static void cs42l42_resume(struct sub_codec *cs42l42)
{ 0x130F, 0x00 }, { 0x130F, 0x00 },
}; };
/* Bring CS42L42 out of Reset */
gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
gpio_data |= cs42l42->reset_gpio;
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
usleep_range(10000, 15000);
cs42l42->suspended = 0; cs42l42->suspended = 0;
/* Initialize CS42L42 companion codec */ /* Initialize CS42L42 companion codec */
...@@ -661,10 +674,18 @@ static void cs42l42_resume(struct sub_codec *cs42l42) ...@@ -661,10 +674,18 @@ static void cs42l42_resume(struct sub_codec *cs42l42)
#ifdef CONFIG_PM #ifdef CONFIG_PM
static void cs42l42_suspend(struct sub_codec *cs42l42) static void cs42l42_suspend(struct sub_codec *cs42l42)
{ {
struct hda_codec *codec = cs42l42->codec;
unsigned int gpio_data;
/* Power down CS42L42 ASP/EQ/MIX/HP */ /* Power down CS42L42 ASP/EQ/MIX/HP */
cs8409_i2c_write(cs42l42, 0x1101, 0xfe); cs8409_i2c_write(cs42l42, 0x1101, 0xfe);
cs42l42->suspended = 1; cs42l42->suspended = 1;
cs42l42->last_page = 0; cs42l42->last_page = 0;
/* Put CS42L42 into Reset */
gpio_data = snd_hda_codec_read(codec, CS8409_PIN_AFG, 0, AC_VERB_GET_GPIO_DATA, 0);
gpio_data &= ~cs42l42->reset_gpio;
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
} }
#endif #endif
...@@ -726,13 +747,12 @@ static void cs8409_cs42l42_jack_unsol_event(struct hda_codec *codec, unsigned in ...@@ -726,13 +747,12 @@ static void cs8409_cs42l42_jack_unsol_event(struct hda_codec *codec, unsigned in
static int cs8409_cs42l42_suspend(struct hda_codec *codec) static int cs8409_cs42l42_suspend(struct hda_codec *codec)
{ {
struct cs8409_spec *spec = codec->spec; struct cs8409_spec *spec = codec->spec;
int i;
cs8409_enable_ur(codec, 0); cs8409_enable_ur(codec, 0);
cs42l42_suspend(spec->scodecs[CS8409_CODEC0]); for (i = 0; i < spec->num_scodecs; i++)
cs42l42_suspend(spec->scodecs[i]);
/* Assert CS42L42 RTS# line */
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, 0);
/* Cancel i2c clock disable timer, and disable clock if left enabled */ /* Cancel i2c clock disable timer, and disable clock if left enabled */
cancel_delayed_work_sync(&spec->i2c_clk_work); cancel_delayed_work_sync(&spec->i2c_clk_work);
...@@ -775,11 +795,6 @@ static void cs8409_cs42l42_hw_init(struct hda_codec *codec) ...@@ -775,11 +795,6 @@ static void cs8409_cs42l42_hw_init(struct hda_codec *codec)
if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_CYBORG) if (codec->fixup_id == CS8409_WARLOCK || codec->fixup_id == CS8409_CYBORG)
cs8409_vendor_coef_set(codec, 0x09, 0x0003); cs8409_vendor_coef_set(codec, 0x09, 0x0003);
/* Release RTS# line */
snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, CS8409_CS42L42_RESET);
/* wait ~10ms */
usleep_range(10000, 15000);
cs42l42_resume(cs42l42); cs42l42_resume(cs42l42);
/* Enable Unsolicited Response */ /* Enable Unsolicited Response */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment