From: Hui Wang Date: Thu, 9 Apr 2020 18:58:16 +0000 (-0500) Subject: ASoC: intel/skl/hda - set autosuspend timeout for hda codecs X-Git-Tag: microblaze-v5.10~23^2~75^2~183^2~11 X-Git-Url: http://git.monstr.eu/?a=commitdiff_plain;h=3a24f135e6cc58c2dc042dde44031ec31b706ce5;p=linux-2.6-microblaze.git ASoC: intel/skl/hda - set autosuspend timeout for hda codecs 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). Co-developed-by: Kai Vehmanen Co-developed-by: Jaska Uimonen Signed-off-by: Hui Wang Signed-off-by: Kai Vehmanen Signed-off-by: Jaska Uimonen Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Clarex Zhou Link: https://lore.kernel.org/r/20200409185827.16255-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c index 3be764299ab0..64197b010e7d 100644 --- a/sound/soc/intel/boards/skl_hda_dsp_generic.c +++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c @@ -113,6 +113,8 @@ static char hda_soc_components[30]; #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; @@ -168,6 +170,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; @@ -206,7 +229,11 @@ static int skl_hda_audio_probe(struct platform_device *pdev) hda_soc_card.components = hda_soc_components; } - 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 = {