[PATCH] drm/i915: Add private api for power well usage

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Daniel/Paulo,

Any comments on this?
Add Jesse and Rafael in loop.

thanks
--xingchao


> -----Original Message-----
> From: Wang, Xingchao
> Sent: Wednesday, April 24, 2013 3:29 PM
> To: daniel.vetter at ffwll.ch; Zanoni, Paulo R; 'Takashi Iwai'
> Cc: ville.syrjala at linux.intel.com; Lin, Mengdong; Girdwood, Liam R; Li, Jocelyn;
> intel-gfx at lists.freedesktop.org; alsa-devel at alsa-project.org; 'Wang Xingchao'
> Subject: RE: [PATCH] drm/i915: Add private api for power well usage
> 
> Hi Guys,
> 
> Sorry I should Add Takashi and alsa maillist in loop.
> 
> I tested this patch against Daniel's "drm-intel-next-queued" Branch, on
> Haswell Mobile C3 stepping machines.
> 
> Test steps:
> 1. only connect one monitor through HDMI cable 2. echo 1 >
> /sys/module/i915/parameters/disable_power_well ==> I think this could be set
> as 1 by default if applied my patch.
> 3. plug out HDMI cable
> 4. cat /proc/asound/card0/codec#0
> 
> At step 3,  i915 will try to disable power well but rejected as display audio is
> using power well.
> Without the patch, display audio would crash at step 4.
> 
> I did not list suspend/resume test here, as during suspend sequence, i915 will
> _ENABLE_ power well, that's a BUG?
> 
> For me above test case is the only one to reproduce the issue, if you have more
> ideas and need more test, please let me know.
> 
> I'm afraid there's some risk because the dependency between alsa driver and
> drm driver. For example, if i915 module was not loaded, display audio Will call
> request_power_well() and meet symbol error. Even if i915 module loaded after
> snd-hda-intel module, there's such risk too. Any comment on this?
> 
> Another risk is the pointer "power_well_device", it should be set NULL when
> i915 module unloaded, I added the caller but have no idea where to call it, if
> anyone has suggestion, that would be fine.
> 
> thanks
> --xingchao
> 
> 
> > -----Original Message-----
> > From: Wang Xingchao [mailto:xingchao.wang at linux.intel.com]
> > Sent: Thursday, April 24, 2014 10:20 PM
> > To: daniel.vetter at ffwll.ch; Zanoni, Paulo R
> > Cc: ville.syrjala at linux.intel.com; Lin, Mengdong; Girdwood, Liam R;
> > Li, Jocelyn; intel-gfx at lists.freedesktop.org; Wang, Xingchao; Wang
> > Xingchao
> > Subject: [PATCH] drm/i915: Add private api for power well usage
> >
> > Display audio depends on power well in graphic side, it should request
> > power well before use it and release power well after use.
> > I915 will not shutdown power well if it detects audio is using.
> > This patch protects display audio crash for Intel Haswell mobile
> > C3 stepping board.
> >
> > Signed-off-by: Wang Xingchao <xingchao.wang at linux.intel.com>
> > ---
> >  drivers/gpu/drm/i915/intel_pm.c |   73
> > +++++++++++++++++++++++++++++++++++----
> >  include/drm/audio_drm.h         |   39 +++++++++++++++++++++
> >  sound/pci/hda/hda_intel.c       |    8 +++++
> >  3 files changed, 113 insertions(+), 7 deletions(-)  create mode
> > 100644 include/drm/audio_drm.h
> >
> > diff --git a/drivers/gpu/drm/i915/intel_pm.c
> > b/drivers/gpu/drm/i915/intel_pm.c index 2557926..9983f56 100644
> > --- a/drivers/gpu/drm/i915/intel_pm.c
> > +++ b/drivers/gpu/drm/i915/intel_pm.c
> > @@ -4298,18 +4298,12 @@ bool intel_using_power_well(struct drm_device
> > *dev)
> >  		return true;
> >  }
> >
> > -void intel_set_power_well(struct drm_device *dev, bool enable)
> > +void set_power_well(struct drm_device *dev, bool enable)
> >  {
> >  	struct drm_i915_private *dev_priv = dev->dev_private;
> >  	bool is_enabled, enable_requested;
> >  	uint32_t tmp;
> >
> > -	if (!HAS_POWER_WELL(dev))
> > -		return;
> > -
> > -	if (!i915_disable_power_well && !enable)
> > -		return;
> > -
> >  	tmp = I915_READ(HSW_PWR_WELL_DRIVER);
> >  	is_enabled = tmp & HSW_PWR_WELL_STATE;
> >  	enable_requested = tmp & HSW_PWR_WELL_ENABLE; @@ -4332,6
> > +4326,71 @@ void intel_set_power_well(struct drm_device *dev, bool
> > +enable)
> >  	}
> >  }
> >
> > +/* Global drm_device for display audio drvier usage */ static struct
> > +drm_device *power_well_device; static bool audio_power_well_using,
> > +i915_power_well_using;
> > +/* Lock protecting power well setting */
> > +DEFINE_SPINLOCK(powerwell_lock);
> > +
> > +void request_power_well(void)
> > +{
> > +	DRM_DEBUG_KMS("Display audio requesting power well\n");
> > +	spin_lock_irq(&powerwell_lock);
> > +	if (!power_well_device)
> > +		goto out;
> > +	if (i915_power_well_using == false)
> > +		set_power_well(power_well_device, true);
> > +	audio_power_well_using = true;
> > +out:
> > +	spin_unlock_irq(&powerwell_lock);
> > +	return;
> > +}
> > +EXPORT_SYMBOL_GPL(request_power_well);
> > +
> > +void release_power_well(void)
> > +{
> > +	DRM_DEBUG_KMS("Display audio releasing power well\n");
> > +	spin_lock_irq(&powerwell_lock);
> > +	if (!power_well_device)
> > +		goto out;
> > +	if (i915_power_well_using == false)
> > +		set_power_well(power_well_device, false);
> > +	audio_power_well_using = false;
> > +out:
> > +	spin_unlock_irq(&powerwell_lock);
> > +	return;
> > +}
> > +EXPORT_SYMBOL_GPL(release_power_well);
> > +
> > +/* TODO: Call this when i915 module unload */ void
> > +remove_power_well(void) {
> > +	spin_lock_irq(&powerwell_lock);
> > +	audio_power_well_using = false;
> > +	i915_power_well_using = false;
> > +	power_well_device = NULL;
> > +	spin_unlock_irq(&powerwell_lock);
> > +}
> > +
> > +void intel_set_power_well(struct drm_device *dev, bool enable) {
> > +	if (!HAS_POWER_WELL(dev))
> > +		return;
> > +
> > +	spin_lock_irq(&powerwell_lock);
> > +	power_well_device = dev;
> > +	i915_power_well_using = enable;
> > +	if (!enable && audio_power_well_using)
> > +		goto out;
> > +
> > +	if (!i915_disable_power_well && !enable)
> > +		goto out;
> > +	set_power_well(dev, enable);
> > +out:
> > +	spin_unlock_irq(&powerwell_lock);
> > +	return;
> > +}
> > +
> >  /*
> >   * Starting with Haswell, we have a "Power Down Well" that can be turned
> off
> >   * when not needed anymore. We have 4 registers that can request the
> > power well diff --git a/include/drm/audio_drm.h
> > b/include/drm/audio_drm.h new file mode 100644 index 0000000..4412b36
> > --- /dev/null
> > +++ b/include/drm/audio_drm.h
> > @@ -0,0 +1,39 @@
> >
> +/**************************************************************
> > ********
> > +****
> > + *
> > + * Copyright 2013 Intel Inc.
> > + * All Rights Reserved.
> > + *
> > + * Permission is hereby granted, free of charge, to any person
> > +obtaining a
> > + * copy of this software and associated documentation files (the
> > + * "Software"), to deal in the Software without restriction,
> > +including
> > + * without limitation the rights to use, copy, modify, merge,
> > +publish,
> > + * distribute, sub license, and/or sell copies of the Software, and
> > +to
> > + * permit persons to whom the Software is furnished to do so, subject
> > +to
> > + * the following conditions:
> > + *
> > + * The above copyright notice and this permission notice (including
> > +the
> > + * next paragraph) shall be included in all copies or substantial
> > +portions
> > + * of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
> KIND,
> > +EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> > +MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO
> > EVENT
> > +SHALL
> > + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE
> > FOR
> > +ANY CLAIM,
> > + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> > TORT
> > +OR
> > + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
> > SOFTWARE
> > +OR THE
> > + * USE OR OTHER DEALINGS IN THE SOFTWARE.
> > + *
> > + *
> > +
> >
> +***************************************************************
> > ********
> > +***/
> > +/*
> > + * Authors:
> > + * Wang Xingchao <xingchao.wang at intel.com>  */
> > +
> > +#ifndef _AUDIO_DRM_H_
> > +#define _AUDIO_DRM_H_
> > +
> > +extern void request_power_well(void); extern void
> > +release_power_well(void);
> > +
> > +#endif				/* _AUDIO_DRM_H_ */
> > diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
> > index 418bfc0..59a85de 100644
> > --- a/sound/pci/hda/hda_intel.c
> > +++ b/sound/pci/hda/hda_intel.c
> > @@ -50,6 +50,7 @@
> >  #include <linux/clocksource.h>
> >  #include <linux/time.h>
> >  #include <linux/completion.h>
> > +#include <drm/audio_drm.h>
> >
> >  #ifdef CONFIG_X86
> >  /* for snoop control */
> > @@ -2869,6 +2870,7 @@ static int azx_suspend(struct device *dev)
> >  	pci_disable_device(pci);
> >  	pci_save_state(pci);
> >  	pci_set_power_state(pci, PCI_D3hot);
> > +	release_power_well();
> >  	return 0;
> >  }
> >
> > @@ -2881,6 +2883,7 @@ static int azx_resume(struct device *dev)
> >  	if (chip->disabled)
> >  		return 0;
> >
> > +	request_power_well();
> >  	pci_set_power_state(pci, PCI_D0);
> >  	pci_restore_state(pci);
> >  	if (pci_enable_device(pci) < 0) {
> > @@ -2913,6 +2916,7 @@ static int azx_runtime_suspend(struct device
> > *dev)
> >
> >  	azx_stop_chip(chip);
> >  	azx_clear_irq_pending(chip);
> > +	release_power_well();
> >  	return 0;
> >  }
> >
> > @@ -2921,6 +2925,7 @@ static int azx_runtime_resume(struct device *dev)
> >  	struct snd_card *card = dev_get_drvdata(dev);
> >  	struct azx *chip = card->private_data;
> >
> > +	request_power_well();
> >  	azx_init_pci(chip);
> >  	azx_init_chip(chip, 1);
> >  	return 0;
> > @@ -3671,6 +3676,8 @@ static int azx_probe(struct pci_dev *pci,
> >  		return -ENOENT;
> >  	}
> >
> > +	request_power_well();
> > +
> >  	err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card);
> >  	if (err < 0) {
> >  		snd_printk(KERN_ERR "hda-intel: Error creating card!\n"); @@
> > -3806,6 +3813,7 @@ static void azx_remove(struct pci_dev *pci)
> >  	if (card)
> >  		snd_card_free(card);
> >  	pci_set_drvdata(pci, NULL);
> > +	release_power_well();
> >  }
> >
> >  /* PCI IDs */
> > --
> > 1.7.9.5



[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux