[PATCH 4/4] snd/hda: add runtime suspend/resume on optimus support
Dave Airlie
airlied at gmail.com
Mon Jul 29 23:46:07 PDT 2013
On Mon, Jul 29, 2013 at 10:46 PM, Takashi Iwai <tiwai at suse.de> 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 at redhat.com>
>> ---
>> 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.
More information about the dri-devel
mailing list