Message ID | 20200414024429.3979-2-hui.wang@canonical.com |
---|---|
State | Accepted |
Headers | show |
Series | alsa/sof: external mic can't be deteced on Lenovo and HP laptops | expand |
Acked-By: AceLan Kao <acelan.kao@canonical.com>
On 2020-04-14 10:44:28 , Hui Wang wrote: > BugLink: https://bugs.launchpad.net/bugs/1872569 > > On some Lenovo and HP laptops, if both codec driver and SOF driver > are in runtime suspend mode, we plug a headset to the audio jack, > the headphone could be detected but Mic couldn't. > > That is because when plugging, the headphone triggers a unsol event > first, and about 0.7s later (on the Lenovo X1 Carbon 7th), the Mic > triggers a unsol event. But if the codec driver enters runtime suspend > within 0.7s, the Mic can't trigger the unsol event. > > If we don't set autosuspend_delay to a non-zero value for the hda codec > driver, it will enter runtime suspend immediately after the headphone > triggers the unsol event. > > Follow the sequence of legacy hda driver and set a autosuspend delay > of 1sec after card registration (refer to pci/hda/hda_intel.c and > pci/hda/hda_codec.c). > > Signed-off-by: Hui Wang <hui.wang@canonical.com> > Co-developed-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> > Signed-off-by: Kai Vehmanen <kai.vehmanen@linux.intel.com> > Co-developed-by: Jaska Uimonen <jaska.uimonen@linux.intel.com> > Signed-off-by: Jaska Uimonen <jaska.uimonen@linux.intel.com> > (backported from commit 22d5e98fe5cf82e842fb025d59d6edcf9f03a528 > git://github.com/thesofproject/linux.git) > Signed-off-by: Hui Wang <hui.wang@canonical.com> > --- Applied to Eoan/master-next. Thank you! -Kelsey > sound/soc/intel/boards/skl_hda_dsp_generic.c | 29 +++++++++++++++++++- > 1 file changed, 28 insertions(+), 1 deletion(-) > > diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c > index 7378252a38cf..867f5fa25e0d 100644 > --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c > +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c > @@ -104,6 +104,8 @@ static struct snd_soc_card hda_soc_card = { > #define IDISP_ROUTE_COUNT (IDISP_DAI_COUNT * 2) > #define IDISP_CODEC_MASK 0x4 > > +#define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000 > + > static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) > { > struct snd_soc_card *card = &hda_soc_card; > @@ -147,6 +149,27 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) > return 0; > } > > +static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card) > +{ > + struct snd_soc_pcm_runtime *rtd = > + list_first_entry(&card->rtd_list, > + struct snd_soc_pcm_runtime, list); > + struct snd_soc_dai *codec_dai = rtd->codec_dai; > + struct hdac_hda_priv *hda_pvt; > + > + if (!codec_dai) > + return; > + > + /* > + * all codecs are on the same bus, so it's sufficient > + * to lookup the first runtime and its codec, and set > + * power save defaults for all codecs on the bus > + */ > + hda_pvt = snd_soc_component_get_drvdata(codec_dai->component); > + snd_hda_set_power_save(hda_pvt->codec.bus, > + HDA_CODEC_AUTOSUSPEND_DELAY_MS); > +} > + > static int skl_hda_audio_probe(struct platform_device *pdev) > { > struct snd_soc_acpi_mach *mach; > @@ -179,7 +202,11 @@ static int skl_hda_audio_probe(struct platform_device *pdev) > hda_soc_card.dev = &pdev->dev; > snd_soc_card_set_drvdata(&hda_soc_card, ctx); > > - return devm_snd_soc_register_card(&pdev->dev, &hda_soc_card); > + ret = devm_snd_soc_register_card(&pdev->dev, &hda_soc_card); > + if (!ret) > + skl_set_hda_codec_autosuspend_delay(&hda_soc_card); > + > + return ret; > } > > static struct platform_driver skl_hda_audio = { > -- > 2.17.1 > > > -- > kernel-team mailing list > kernel-team@lists.ubuntu.com > https://lists.ubuntu.com/mailman/listinfo/kernel-team
diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 7378252a38cf..867f5fa25e0d 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -104,6 +104,8 @@ static struct snd_soc_card hda_soc_card = { #define IDISP_ROUTE_COUNT (IDISP_DAI_COUNT * 2) #define IDISP_CODEC_MASK 0x4 +#define HDA_CODEC_AUTOSUSPEND_DELAY_MS 1000 + static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) { struct snd_soc_card *card = &hda_soc_card; @@ -147,6 +149,27 @@ static int skl_hda_fill_card_info(struct snd_soc_acpi_mach_params *mach_params) return 0; } +static void skl_set_hda_codec_autosuspend_delay(struct snd_soc_card *card) +{ + struct snd_soc_pcm_runtime *rtd = + list_first_entry(&card->rtd_list, + struct snd_soc_pcm_runtime, list); + struct snd_soc_dai *codec_dai = rtd->codec_dai; + struct hdac_hda_priv *hda_pvt; + + if (!codec_dai) + return; + + /* + * all codecs are on the same bus, so it's sufficient + * to lookup the first runtime and its codec, and set + * power save defaults for all codecs on the bus + */ + hda_pvt = snd_soc_component_get_drvdata(codec_dai->component); + snd_hda_set_power_save(hda_pvt->codec.bus, + HDA_CODEC_AUTOSUSPEND_DELAY_MS); +} + static int skl_hda_audio_probe(struct platform_device *pdev) { struct snd_soc_acpi_mach *mach; @@ -179,7 +202,11 @@ static int skl_hda_audio_probe(struct platform_device *pdev) hda_soc_card.dev = &pdev->dev; snd_soc_card_set_drvdata(&hda_soc_card, ctx); - return devm_snd_soc_register_card(&pdev->dev, &hda_soc_card); + ret = devm_snd_soc_register_card(&pdev->dev, &hda_soc_card); + if (!ret) + skl_set_hda_codec_autosuspend_delay(&hda_soc_card); + + return ret; } static struct platform_driver skl_hda_audio = {