OSDN Git Service

ALSA: hda/cs8409: Support multiple sub_codecs for Suspend/Resume/Unsol events
authorStefan Binding <sbinding@opensource.cirrus.com>
Wed, 11 Aug 2021 18:56:46 +0000 (19:56 +0100)
committerTakashi Iwai <tiwai@suse.de>
Thu, 12 Aug 2021 11:41:54 +0000 (13:41 +0200)
Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com>
Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com>
Link: https://lore.kernel.org/r/20210811185654.6837-20-vitalyr@opensource.cirrus.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/patch_cs8409.c

index 9d1a457..5b3221d 100644 (file)
@@ -388,16 +388,21 @@ static int cs8409_build_controls(struct hda_codec *codec)
        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)
 {
-       /* 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,
-                           flag ? CS8409_CS42L42_INT : 0);
+                           flag ? ur_gpios : 0);
 
        snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_UNSOLICITED_ENABLE,
                            flag ? AC_UNSOL_ENABLED : 0);
-
 }
 
 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)
 
 static void cs42l42_resume(struct sub_codec *cs42l42)
 {
+       struct hda_codec *codec = cs42l42->codec;
+       unsigned int gpio_data;
        struct cs8409_i2c_param irq_regs[] = {
                { 0x1308, 0x00 },
                { 0x1309, 0x00 },
@@ -636,6 +643,12 @@ static void cs42l42_resume(struct sub_codec *cs42l42)
                { 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;
 
        /* Initialize CS42L42 companion codec */
@@ -661,10 +674,18 @@ static void cs42l42_resume(struct sub_codec *cs42l42)
 #ifdef CONFIG_PM
 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 */
        cs8409_i2c_write(cs42l42, 0x1101, 0xfe);
        cs42l42->suspended = 1;
        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
 
@@ -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)
 {
        struct cs8409_spec *spec = codec->spec;
+       int i;
 
        cs8409_enable_ur(codec, 0);
 
-       cs42l42_suspend(spec->scodecs[CS8409_CODEC0]);
-
-       /* Assert CS42L42 RTS# line */
-       snd_hda_codec_write(codec, CS8409_PIN_AFG, 0, AC_VERB_SET_GPIO_DATA, 0);
+       for (i = 0; i < spec->num_scodecs; i++)
+               cs42l42_suspend(spec->scodecs[i]);
 
        /* Cancel i2c clock disable timer, and disable clock if left enabled */
        cancel_delayed_work_sync(&spec->i2c_clk_work);
@@ -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)
                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);
 
        /* Enable Unsolicited Response */