On Mon, Jul 29, 2013 at 10:46 PM, Takashi Iwai <tiwai@xxxxxxx> wrote: > At Mon, 29 Jul 2013 16:06:59 +1000, > Dave Airlie wrote: >> >> Add support for HDMI audio device on VGA cards that powerdown >> to D3cold using non-standard ACPI/PCI infrastructure (optimus). >> >> This does a couple of things to make it work: >> >> a) add a set of power ops for the hdmi domain, and enables them >> via vga_switcheroo when we are a switcheroo controlled card. This >> just replaces the runtime resume operation so that when the card >> is in D3cold the userspace pci config space access via sysfs, >> the vga switcheroon runtime resume gets called first and it calls >> the GPU resume callback before calling the sound card runtime >> resume. >> >> b) standard ACPI/PCI stacks won't put a device into D3cold without >> an ACPI handle, but since the hdmi audio devices on gpus don't have >> an ACPI handle, we need to manually force the device into D3cold >> after suspend from the switcheroo path only. >> >> c) don't try and do runtime s/r when the GPU is off. >> >> d) call runtime suspend/resume during switcheroo suspend/resume >> this is to make sure the runtime stack knows to try and resume >> the hdmi audio device for pci config space access. >> >> Signed-off-by: Dave Airlie <airlied@xxxxxxxxxx> >> --- >> sound/pci/hda/hda_intel.c | 40 +++++++++++++++++++++++++++++++++++++--- >> 1 file changed, 37 insertions(+), 3 deletions(-) >> >> diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c >> index 8860dd5..4b4d05b 100644 >> --- a/sound/pci/hda/hda_intel.c >> +++ b/sound/pci/hda/hda_intel.c >> @@ -555,6 +555,9 @@ struct azx { >> #ifdef CONFIG_SND_HDA_DSP_LOADER >> struct azx_dev saved_azx_dev; >> #endif >> + >> + /* secondary power domain for hdmi audio under vga device */ >> + struct dev_pm_domain hdmi_pm_domain; >> }; >> >> #define CREATE_TRACE_POINTS >> @@ -2898,7 +2901,7 @@ static int param_set_xint(const char *val, const struct kernel_param *kp) >> /* >> * power management >> */ >> -static int azx_suspend(struct device *dev) >> +static int azx_do_suspend(struct device *dev, pci_power_t state) >> { >> struct pci_dev *pci = to_pci_dev(dev); >> struct snd_card *card = dev_get_drvdata(dev); >> @@ -2920,16 +2923,30 @@ static int azx_suspend(struct device *dev) >> free_irq(chip->irq, chip); >> chip->irq = -1; >> } >> + >> + /* >> + * for vga switcheroo suspend we need to >> + * force runtime suspend so lspci works. >> + */ >> + if (state == PCI_D3cold) >> + pm_runtime_suspend(&pci->dev); >> + >> if (chip->msi) >> pci_disable_msi(chip->pci); >> pci_disable_device(pci); >> pci_save_state(pci); >> - pci_set_power_state(pci, PCI_D3hot); >> + >> + pci_set_power_state(pci, state); >> if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) >> hda_display_power(false); >> return 0; >> } >> >> +static int azx_suspend(struct device *dev) >> +{ >> + return azx_do_suspend(dev, PCI_D3hot); >> +} >> + >> static int azx_resume(struct device *dev) >> { >> struct pci_dev *pci = to_pci_dev(dev); >> @@ -2971,6 +2988,9 @@ static int azx_runtime_suspend(struct device *dev) >> struct snd_card *card = dev_get_drvdata(dev); >> struct azx *chip = card->private_data; >> >> + if (chip->disabled) >> + return 0; >> + >> azx_stop_chip(chip); >> azx_enter_link_reset(chip); >> azx_clear_irq_pending(chip); >> @@ -2984,6 +3004,9 @@ static int azx_runtime_resume(struct device *dev) >> struct snd_card *card = dev_get_drvdata(dev); >> struct azx *chip = card->private_data; >> >> + if (chip->disabled) >> + return 0; >> + >> if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL) >> hda_display_power(true); >> azx_init_pci(chip); >> @@ -2996,6 +3019,9 @@ static int azx_runtime_idle(struct device *dev) >> struct snd_card *card = dev_get_drvdata(dev); >> struct azx *chip = card->private_data; >> >> + if (chip->disabled) >> + return 0; >> + >> if (!power_save_controller || >> !(chip->driver_caps & AZX_DCAPS_PM_RUNTIME)) >> return -EBUSY; >> @@ -3078,7 +3104,11 @@ static void azx_vs_set_state(struct pci_dev *pci, >> "%s: %s via VGA-switcheroo\n", pci_name(chip->pci), >> disabled ? "Disabling" : "Enabling"); >> if (disabled) { >> - azx_suspend(&pci->dev); >> + azx_do_suspend(&pci->dev, PCI_D3cold); >> + /* when we get suspended by vga switcheroo we end up in D3cold, >> + * however we have no ACPI handle, so pci/acpi can't put us there, >> + * put ourselves there */ >> + pci->current_state = PCI_D3cold; >> chip->disabled = true; >> if (snd_hda_lock_devices(chip->bus)) >> snd_printk(KERN_WARNING SFX "%s: Cannot lock devices!\n", >> @@ -3087,6 +3117,7 @@ static void azx_vs_set_state(struct pci_dev *pci, >> snd_hda_unlock_devices(chip->bus); >> chip->disabled = false; >> azx_resume(&pci->dev); >> + pm_runtime_suspend(&pci->dev); > > Is this meant as pm_runtime_resume()? > Oh probably that seems likely alright! Dave. _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel