Message ID | 20211214133818.413207-2-chris.chiu@canonical.com |
---|---|
State | New |
Headers | show |
Series | New fix for jack detection after resume on CS8409 sound driver | expand |
On 14.12.21 14:38, Chris Chiu wrote: > From: Stefan Binding <sbinding@opensource.cirrus.com> > > BugLink: https://bugs.launchpad.net/bugs/1954773 > > For cs8409, it is required to run Jack Detect on resume. > Jack Detect on cs8409+cs42l42 requires an interrupt from > cs42l42 to be sent to cs8409 which is propogated to the driver > via an unsolicited event. > However, the hda_codec drops unsolicited events if the power_state > is not set to PMSG_ON. Which is set at the end of the resume call. > This means there is a race condition between setting power_state > to PMSG_ON and receiving the interrupt. > To solve this, we can add an API to set the power_state earlier > and call that before we start Jack Detect. > This does not cause issues, since we know inside our driver that > we are already initialized, and ready to handle the unsolicited > events. > > Signed-off-by: Stefan Binding <sbinding@opensource.cirrus.com> > Signed-off-by: Vitaly Rodionov <vitalyr@opensource.cirrus.com> > Cc: <stable@vger.kernel.org> # v5.15+ > Link: https://lore.kernel.org/r/20211128115558.71683-1-vitalyr@opensource.cirrus.com > Signed-off-by: Takashi Iwai <tiwai@suse.de> > (cherry picked from commit 65cc4ad62a9ed47c0b4fcd7af667d97d7c29f19d) > Signed-off-by: Chris Chiu <chris.chiu@canonical.com> Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> Thanks > --- > sound/pci/hda/hda_local.h | 9 +++++++++ > sound/pci/hda/patch_cs8409.c | 5 +++++ > 2 files changed, 14 insertions(+) > > diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h > index ea8ab8b43337..d22c96eb2f8f 100644 > --- a/sound/pci/hda/hda_local.h > +++ b/sound/pci/hda/hda_local.h > @@ -438,6 +438,15 @@ int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid, > #define for_each_hda_codec_node(nid, codec) \ > for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++) > > +/* Set the codec power_state flag to indicate to allow unsol event handling; > + * see hda_codec_unsol_event() in hda_bind.c. Calling this might confuse the > + * state tracking, so use with care. > + */ > +static inline void snd_hda_codec_allow_unsol_events(struct hda_codec *codec) > +{ > + codec->core.dev.power.power_state = PMSG_ON; > +} > + > /* > * get widget capabilities > */ > diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c > index 31ff11ab868e..039b9f2f8e94 100644 > --- a/sound/pci/hda/patch_cs8409.c > +++ b/sound/pci/hda/patch_cs8409.c > @@ -750,6 +750,11 @@ static void cs42l42_resume(struct sub_codec *cs42l42) > if (cs42l42->full_scale_vol) > cs8409_i2c_write(cs42l42, 0x2001, 0x01); > > + /* we have to explicitly allow unsol event handling even during the > + * resume phase so that the jack event is processed properly > + */ > + snd_hda_codec_allow_unsol_events(cs42l42->codec); > + > cs42l42_enable_jack_detect(cs42l42); > } >
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index ea8ab8b43337..d22c96eb2f8f 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h @@ -438,6 +438,15 @@ int snd_hda_codec_set_pin_target(struct hda_codec *codec, hda_nid_t nid, #define for_each_hda_codec_node(nid, codec) \ for ((nid) = (codec)->core.start_nid; (nid) < (codec)->core.end_nid; (nid)++) +/* Set the codec power_state flag to indicate to allow unsol event handling; + * see hda_codec_unsol_event() in hda_bind.c. Calling this might confuse the + * state tracking, so use with care. + */ +static inline void snd_hda_codec_allow_unsol_events(struct hda_codec *codec) +{ + codec->core.dev.power.power_state = PMSG_ON; +} + /* * get widget capabilities */ diff --git a/sound/pci/hda/patch_cs8409.c b/sound/pci/hda/patch_cs8409.c index 31ff11ab868e..039b9f2f8e94 100644 --- a/sound/pci/hda/patch_cs8409.c +++ b/sound/pci/hda/patch_cs8409.c @@ -750,6 +750,11 @@ static void cs42l42_resume(struct sub_codec *cs42l42) if (cs42l42->full_scale_vol) cs8409_i2c_write(cs42l42, 0x2001, 0x01); + /* we have to explicitly allow unsol event handling even during the + * resume phase so that the jack event is processed properly + */ + snd_hda_codec_allow_unsol_events(cs42l42->codec); + cs42l42_enable_jack_detect(cs42l42); }