@@ -536,6 +536,104 @@ static void avs_pci_remove(struct pci_dev *pci)
536536 pm_runtime_get_noresume (& pci -> dev );
537537}
538538
539+ static int __maybe_unused avs_suspend_common (struct avs_dev * adev )
540+ {
541+ struct hdac_bus * bus = & adev -> base .core ;
542+ int ret ;
543+
544+ flush_work (& adev -> probe_work );
545+
546+ snd_hdac_ext_bus_link_power_down_all (bus );
547+
548+ ret = avs_ipc_set_dx (adev , AVS_MAIN_CORE_MASK , false);
549+ /*
550+ * pm_runtime is blocked on DSP failure but system-wide suspend is not.
551+ * Do not block entire system from suspending if that's the case.
552+ */
553+ if (ret && ret != - EPERM ) {
554+ dev_err (adev -> dev , "set dx failed: %d\n" , ret );
555+ return AVS_IPC_RET (ret );
556+ }
557+
558+ avs_dsp_op (adev , int_control , false);
559+ snd_hdac_ext_bus_ppcap_int_enable (bus , false);
560+
561+ ret = avs_dsp_core_disable (adev , AVS_MAIN_CORE_MASK );
562+ if (ret < 0 ) {
563+ dev_err (adev -> dev , "core_mask %ld disable failed: %d\n" , AVS_MAIN_CORE_MASK , ret );
564+ return ret ;
565+ }
566+
567+ snd_hdac_ext_bus_ppcap_enable (bus , false);
568+ /* disable LP SRAM retention */
569+ avs_hda_power_gating_enable (adev , false);
570+ snd_hdac_bus_stop_chip (bus );
571+ /* disable CG when putting controller to reset */
572+ avs_hdac_clock_gating_enable (bus , false);
573+ snd_hdac_bus_enter_link_reset (bus );
574+ avs_hdac_clock_gating_enable (bus , true);
575+
576+ snd_hdac_display_power (bus , HDA_CODEC_IDX_CONTROLLER , false);
577+
578+ return 0 ;
579+ }
580+
581+ static int __maybe_unused avs_resume_common (struct avs_dev * adev , bool purge )
582+ {
583+ struct hdac_bus * bus = & adev -> base .core ;
584+ struct hdac_ext_link * hlink ;
585+ int ret ;
586+
587+ snd_hdac_display_power (bus , HDA_CODEC_IDX_CONTROLLER , true);
588+ avs_hdac_bus_init_chip (bus , true);
589+
590+ snd_hdac_ext_bus_ppcap_enable (bus , true);
591+ snd_hdac_ext_bus_ppcap_int_enable (bus , true);
592+
593+ ret = avs_dsp_boot_firmware (adev , purge );
594+ if (ret < 0 ) {
595+ dev_err (adev -> dev , "firmware boot failed: %d\n" , ret );
596+ return ret ;
597+ }
598+
599+ /* turn off the links that were off before suspend */
600+ list_for_each_entry (hlink , & bus -> hlink_list , list ) {
601+ if (!hlink -> ref_count )
602+ snd_hdac_ext_bus_link_power_down (hlink );
603+ }
604+
605+ /* check dma status and clean up CORB/RIRB buffers */
606+ if (!bus -> cmd_dma_state )
607+ snd_hdac_bus_stop_cmd_io (bus );
608+
609+ return 0 ;
610+ }
611+
612+ static int __maybe_unused avs_suspend (struct device * dev )
613+ {
614+ return avs_suspend_common (to_avs_dev (dev ));
615+ }
616+
617+ static int __maybe_unused avs_resume (struct device * dev )
618+ {
619+ return avs_resume_common (to_avs_dev (dev ), true);
620+ }
621+
622+ static int __maybe_unused avs_runtime_suspend (struct device * dev )
623+ {
624+ return avs_suspend_common (to_avs_dev (dev ));
625+ }
626+
627+ static int __maybe_unused avs_runtime_resume (struct device * dev )
628+ {
629+ return avs_resume_common (to_avs_dev (dev ), true);
630+ }
631+
632+ static const struct dev_pm_ops avs_dev_pm = {
633+ SET_SYSTEM_SLEEP_PM_OPS (avs_suspend , avs_resume )
634+ SET_RUNTIME_PM_OPS (avs_runtime_suspend , avs_runtime_resume , NULL )
635+ };
636+
539637static const struct pci_device_id avs_ids [] = {
540638 { 0 }
541639};
@@ -546,6 +644,9 @@ static struct pci_driver avs_pci_driver = {
546644 .id_table = avs_ids ,
547645 .probe = avs_pci_probe ,
548646 .remove = avs_pci_remove ,
647+ .driver = {
648+ .pm = & avs_dev_pm ,
649+ },
549650};
550651module_pci_driver (avs_pci_driver );
551652
0 commit comments