diff mbox series

drm/i915: Stop calling intel_opregion unregister/register in suspend/resume

Message ID 20181005180026.414-1-chris@chris-wilson.co.uk (mailing list archive)
State New, archived
Headers show
Series drm/i915: Stop calling intel_opregion unregister/register in suspend/resume | expand

Commit Message

Chris Wilson Oct. 5, 2018, 6 p.m. UTC
If we reduce the suspend function for intel_opregion to do the minimum
required, the resume function can also do the simple task of notifier
the ACPI bios that we are back. This avoid some nasty restrictions on
the likes of register_acpi_notifier() that are not allowed during the
early phase of resume.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Imre Deak <imre.deak@intel.com>
Cc: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.c       |   9 +-
 drivers/gpu/drm/i915/intel_opregion.c | 155 +++++++++++++++-----------
 drivers/gpu/drm/i915/intel_opregion.h |  15 +++
 3 files changed, 108 insertions(+), 71 deletions(-)

Comments

Jani Nikula Oct. 8, 2018, 6:44 a.m. UTC | #1
On Fri, 05 Oct 2018, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> If we reduce the suspend function for intel_opregion to do the minimum
> required, the resume function can also do the simple task of notifier
> the ACPI bios that we are back. This avoid some nasty restrictions on
> the likes of register_acpi_notifier() that are not allowed during the
> early phase of resume.

Something like this has been on the back of my mind for a long time, but
never got around to it. Couple of nitpicks/observations inline.

>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Imre Deak <imre.deak@intel.com>
> Cc: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.c       |   9 +-
>  drivers/gpu/drm/i915/intel_opregion.c | 155 +++++++++++++++-----------
>  drivers/gpu/drm/i915/intel_opregion.h |  15 +++
>  3 files changed, 108 insertions(+), 71 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 193023427b40..9b0887746bac 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -1919,9 +1919,7 @@ static int i915_drm_suspend(struct drm_device *dev)
>  	i915_save_state(dev_priv);
>  
>  	opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
> -	intel_opregion_notify_adapter(dev_priv, opregion_target_state);
> -
> -	intel_opregion_unregister(dev_priv);
> +	intel_opregion_suspend(dev_priv, opregion_target_state);
>  
>  	intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
>  
> @@ -2040,7 +2038,6 @@ static int i915_drm_resume(struct drm_device *dev)
>  
>  	i915_restore_state(dev_priv);
>  	intel_pps_unlock_regs_wa(dev_priv);
> -	intel_opregion_setup(dev_priv);
>  
>  	intel_init_pch_refclk(dev_priv);
>  
> @@ -2082,12 +2079,10 @@ static int i915_drm_resume(struct drm_device *dev)
>  	 * */
>  	intel_hpd_init(dev_priv);
>  
> -	intel_opregion_register(dev_priv);
> +	intel_opregion_resume(dev_priv);
>  
>  	intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
>  
> -	intel_opregion_notify_adapter(dev_priv, PCI_D0);
> -
>  	intel_power_domains_enable(dev_priv);
>  
>  	enable_rpm_wakeref_asserts(dev_priv);
> diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
> index e034b4166d32..379e8c64a248 100644
> --- a/drivers/gpu/drm/i915/intel_opregion.c
> +++ b/drivers/gpu/drm/i915/intel_opregion.c
> @@ -773,70 +773,6 @@ static void intel_setup_cadls(struct drm_i915_private *dev_priv)
>  		opregion->acpi->cadl[i] = 0;
>  }
>  
> -void intel_opregion_register(struct drm_i915_private *dev_priv)
> -{
> -	struct intel_opregion *opregion = &dev_priv->opregion;
> -
> -	if (!opregion->header)
> -		return;
> -
> -	if (opregion->acpi) {
> -		intel_didl_outputs(dev_priv);
> -		intel_setup_cadls(dev_priv);
> -
> -		/* Notify BIOS we are ready to handle ACPI video ext notifs.
> -		 * Right now, all the events are handled by the ACPI video module.
> -		 * We don't actually need to do anything with them. */
> -		opregion->acpi->csts = 0;
> -		opregion->acpi->drdy = 1;
> -
> -		opregion->acpi_notifier.notifier_call = intel_opregion_video_event;
> -		register_acpi_notifier(&opregion->acpi_notifier);
> -	}
> -
> -	if (opregion->asle) {
> -		opregion->asle->tche = ASLE_TCHE_BLC_EN;
> -		opregion->asle->ardy = ASLE_ARDY_READY;
> -	}
> -}
> -
> -void intel_opregion_unregister(struct drm_i915_private *dev_priv)
> -{
> -	struct intel_opregion *opregion = &dev_priv->opregion;
> -
> -	if (!opregion->header)
> -		return;
> -
> -	if (opregion->asle)
> -		opregion->asle->ardy = ASLE_ARDY_NOT_READY;
> -
> -	cancel_work_sync(&dev_priv->opregion.asle_work);
> -
> -	if (opregion->acpi) {
> -		opregion->acpi->drdy = 0;
> -
> -		unregister_acpi_notifier(&opregion->acpi_notifier);
> -		opregion->acpi_notifier.notifier_call = NULL;
> -	}
> -
> -	/* just clear all opregion memory pointers now */
> -	memunmap(opregion->header);
> -	if (opregion->rvda) {
> -		memunmap(opregion->rvda);
> -		opregion->rvda = NULL;
> -	}
> -	if (opregion->vbt_firmware) {
> -		kfree(opregion->vbt_firmware);
> -		opregion->vbt_firmware = NULL;
> -	}
> -	opregion->header = NULL;
> -	opregion->acpi = NULL;
> -	opregion->swsci = NULL;
> -	opregion->asle = NULL;
> -	opregion->vbt = NULL;
> -	opregion->lid_state = NULL;
> -}
> -
>  static void swsci_setup(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_opregion *opregion = &dev_priv->opregion;
> @@ -1115,3 +1051,94 @@ intel_opregion_get_panel_type(struct drm_i915_private *dev_priv)
>  
>  	return ret - 1;
>  }
> +
> +void intel_opregion_register(struct drm_i915_private *i915)
> +{
> +	struct intel_opregion *opregion = &i915->opregion;
> +
> +	if (!opregion->header)
> +		return;
> +
> +	if (opregion->acpi) {
> +		opregion->acpi_notifier.notifier_call = intel_opregion_video_event;
> +		register_acpi_notifier(&opregion->acpi_notifier);
> +	}
> +
> +	intel_opregion_resume(i915);
> +}
> +
> +void intel_opregion_resume(struct drm_i915_private *i915)
> +{
> +	struct intel_opregion *opregion = &i915->opregion;
> +
> +	if (!opregion->header)
> +		return;
> +
> +	if (opregion->acpi) {
> +		intel_didl_outputs(i915);
> +		intel_setup_cadls(i915);
> +
> +		/* Notify BIOS we are ready to handle ACPI video ext notifs.
> +		 * Right now, all the events are handled by the ACPI video module.
> +		 * We don't actually need to do anything with them. */
> +		opregion->acpi->csts = 0;
> +		opregion->acpi->drdy = 1;
> +	}
> +
> +	if (opregion->asle) {
> +		opregion->asle->tche = ASLE_TCHE_BLC_EN;
> +		opregion->asle->ardy = ASLE_ARDY_READY;
> +	}
> +
> +	intel_opregion_notify_adapter(i915, PCI_D0);
> +}
> +
> +void intel_opregion_suspend(struct drm_i915_private *i915, pci_power_t state)
> +{
> +	struct intel_opregion *opregion = &i915->opregion;
> +
> +	if (!opregion->header)
> +		return;
> +
> +	if (opregion->asle)
> +		opregion->asle->ardy = ASLE_ARDY_NOT_READY;
> +
> +	cancel_work_sync(&i915->opregion.asle_work);
> +
> +	if (opregion->acpi)
> +		opregion->acpi->drdy = 0;
> +
> +	intel_opregion_notify_adapter(i915, state);

The order between drdy clear and notify changes. Depends on the BIOS
whether that has any significance, i.e. I have no clue. If you think the
reordering is justified, please split it out to a separate patch. Or
just drop the order change completely. With that,

Reviewed-by: Jani Nikula <jani.nikula@intel.com>

Side note, it would seem like drdy clear should happen before canceling
the work. In theory that should block new asle interrupts. But that's
another change anyway, and perhaps not worth the risk.

> +}
> +
> +void intel_opregion_unregister(struct drm_i915_private *i915)
> +{
> +	struct intel_opregion *opregion = &i915->opregion;
> +
> +	intel_opregion_suspend(i915, PCI_D1);
> +
> +	if (!opregion->header)
> +		return;
> +
> +	if (opregion->acpi_notifier.notifier_call) {
> +		unregister_acpi_notifier(&opregion->acpi_notifier);
> +		opregion->acpi_notifier.notifier_call = NULL;
> +	}
> +
> +	/* just clear all opregion memory pointers now */
> +	memunmap(opregion->header);
> +	if (opregion->rvda) {
> +		memunmap(opregion->rvda);
> +		opregion->rvda = NULL;
> +	}
> +	if (opregion->vbt_firmware) {
> +		kfree(opregion->vbt_firmware);
> +		opregion->vbt_firmware = NULL;
> +	}
> +	opregion->header = NULL;
> +	opregion->acpi = NULL;
> +	opregion->swsci = NULL;
> +	opregion->asle = NULL;
> +	opregion->vbt = NULL;
> +	opregion->lid_state = NULL;

Side note #2, this patch highlights (but does not change) how we have
two init functions setup and register undone by a single unregister
function. The asymmetry has always bugged me, but it's no fault of this
patch.

> +}
> diff --git a/drivers/gpu/drm/i915/intel_opregion.h b/drivers/gpu/drm/i915/intel_opregion.h
> index e8498a8cda3d..d84b6d2d2fae 100644
> --- a/drivers/gpu/drm/i915/intel_opregion.h
> +++ b/drivers/gpu/drm/i915/intel_opregion.h
> @@ -57,8 +57,14 @@ struct intel_opregion {
>  #ifdef CONFIG_ACPI
>  
>  int intel_opregion_setup(struct drm_i915_private *dev_priv);
> +
>  void intel_opregion_register(struct drm_i915_private *dev_priv);
>  void intel_opregion_unregister(struct drm_i915_private *dev_priv);
> +
> +void intel_opregion_resume(struct drm_i915_private *dev_priv);
> +void intel_opregion_suspend(struct drm_i915_private *dev_priv,
> +			    pci_power_t state);
> +
>  void intel_opregion_asle_intr(struct drm_i915_private *dev_priv);
>  int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
>  				  bool enable);
> @@ -81,6 +87,15 @@ static inline void intel_opregion_unregister(struct drm_i915_private *dev_priv)
>  {
>  }
>  
> +void intel_opregion_resume(struct drm_i915_private *dev_priv)
> +{
> +}
> +
> +void intel_opregion_suspend(struct drm_i915_private *dev_priv,
> +			    pci_power_t state)
> +{
> +}
> +
>  static inline void intel_opregion_asle_intr(struct drm_i915_private *dev_priv)
>  {
>  }
Imre Deak Oct. 8, 2018, 2:04 p.m. UTC | #2
On Mon, Oct 08, 2018 at 09:44:08AM +0300, Jani Nikula wrote:
> On Fri, 05 Oct 2018, Chris Wilson <chris@chris-wilson.co.uk> wrote:
> > If we reduce the suspend function for intel_opregion to do the minimum
> > required, the resume function can also do the simple task of notifier
> > the ACPI bios that we are back. This avoid some nasty restrictions on
> > the likes of register_acpi_notifier() that are not allowed during the
> > early phase of resume.
> 
> Something like this has been on the back of my mind for a long time, but
> never got around to it. Couple of nitpicks/observations inline.
> 
> >
> > Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> > Cc: Imre Deak <imre.deak@intel.com>
> > Cc: Jani Nikula <jani.nikula@intel.com>

Simplifies the task of moving some steps from the suspend/resume hooks
to the suspend_late/resume_early hooks, which is needed by the audio/
CDCLK workaround we are working towards, so:

Acked-by: Imre Deak <imre.deak@intel.com>

> > ---
> >  drivers/gpu/drm/i915/i915_drv.c       |   9 +-
> >  drivers/gpu/drm/i915/intel_opregion.c | 155 +++++++++++++++-----------
> >  drivers/gpu/drm/i915/intel_opregion.h |  15 +++
> >  3 files changed, 108 insertions(+), 71 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> > index 193023427b40..9b0887746bac 100644
> > --- a/drivers/gpu/drm/i915/i915_drv.c
> > +++ b/drivers/gpu/drm/i915/i915_drv.c
> > @@ -1919,9 +1919,7 @@ static int i915_drm_suspend(struct drm_device *dev)
> >  	i915_save_state(dev_priv);
> >  
> >  	opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
> > -	intel_opregion_notify_adapter(dev_priv, opregion_target_state);
> > -
> > -	intel_opregion_unregister(dev_priv);
> > +	intel_opregion_suspend(dev_priv, opregion_target_state);
> >  
> >  	intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
> >  
> > @@ -2040,7 +2038,6 @@ static int i915_drm_resume(struct drm_device *dev)
> >  
> >  	i915_restore_state(dev_priv);
> >  	intel_pps_unlock_regs_wa(dev_priv);
> > -	intel_opregion_setup(dev_priv);
> >  
> >  	intel_init_pch_refclk(dev_priv);
> >  
> > @@ -2082,12 +2079,10 @@ static int i915_drm_resume(struct drm_device *dev)
> >  	 * */
> >  	intel_hpd_init(dev_priv);
> >  
> > -	intel_opregion_register(dev_priv);
> > +	intel_opregion_resume(dev_priv);
> >  
> >  	intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
> >  
> > -	intel_opregion_notify_adapter(dev_priv, PCI_D0);
> > -
> >  	intel_power_domains_enable(dev_priv);
> >  
> >  	enable_rpm_wakeref_asserts(dev_priv);
> > diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
> > index e034b4166d32..379e8c64a248 100644
> > --- a/drivers/gpu/drm/i915/intel_opregion.c
> > +++ b/drivers/gpu/drm/i915/intel_opregion.c
> > @@ -773,70 +773,6 @@ static void intel_setup_cadls(struct drm_i915_private *dev_priv)
> >  		opregion->acpi->cadl[i] = 0;
> >  }
> >  
> > -void intel_opregion_register(struct drm_i915_private *dev_priv)
> > -{
> > -	struct intel_opregion *opregion = &dev_priv->opregion;
> > -
> > -	if (!opregion->header)
> > -		return;
> > -
> > -	if (opregion->acpi) {
> > -		intel_didl_outputs(dev_priv);
> > -		intel_setup_cadls(dev_priv);
> > -
> > -		/* Notify BIOS we are ready to handle ACPI video ext notifs.
> > -		 * Right now, all the events are handled by the ACPI video module.
> > -		 * We don't actually need to do anything with them. */
> > -		opregion->acpi->csts = 0;
> > -		opregion->acpi->drdy = 1;
> > -
> > -		opregion->acpi_notifier.notifier_call = intel_opregion_video_event;
> > -		register_acpi_notifier(&opregion->acpi_notifier);
> > -	}
> > -
> > -	if (opregion->asle) {
> > -		opregion->asle->tche = ASLE_TCHE_BLC_EN;
> > -		opregion->asle->ardy = ASLE_ARDY_READY;
> > -	}
> > -}
> > -
> > -void intel_opregion_unregister(struct drm_i915_private *dev_priv)
> > -{
> > -	struct intel_opregion *opregion = &dev_priv->opregion;
> > -
> > -	if (!opregion->header)
> > -		return;
> > -
> > -	if (opregion->asle)
> > -		opregion->asle->ardy = ASLE_ARDY_NOT_READY;
> > -
> > -	cancel_work_sync(&dev_priv->opregion.asle_work);
> > -
> > -	if (opregion->acpi) {
> > -		opregion->acpi->drdy = 0;
> > -
> > -		unregister_acpi_notifier(&opregion->acpi_notifier);
> > -		opregion->acpi_notifier.notifier_call = NULL;
> > -	}
> > -
> > -	/* just clear all opregion memory pointers now */
> > -	memunmap(opregion->header);
> > -	if (opregion->rvda) {
> > -		memunmap(opregion->rvda);
> > -		opregion->rvda = NULL;
> > -	}
> > -	if (opregion->vbt_firmware) {
> > -		kfree(opregion->vbt_firmware);
> > -		opregion->vbt_firmware = NULL;
> > -	}
> > -	opregion->header = NULL;
> > -	opregion->acpi = NULL;
> > -	opregion->swsci = NULL;
> > -	opregion->asle = NULL;
> > -	opregion->vbt = NULL;
> > -	opregion->lid_state = NULL;
> > -}
> > -
> >  static void swsci_setup(struct drm_i915_private *dev_priv)
> >  {
> >  	struct intel_opregion *opregion = &dev_priv->opregion;
> > @@ -1115,3 +1051,94 @@ intel_opregion_get_panel_type(struct drm_i915_private *dev_priv)
> >  
> >  	return ret - 1;
> >  }
> > +
> > +void intel_opregion_register(struct drm_i915_private *i915)
> > +{
> > +	struct intel_opregion *opregion = &i915->opregion;
> > +
> > +	if (!opregion->header)
> > +		return;
> > +
> > +	if (opregion->acpi) {
> > +		opregion->acpi_notifier.notifier_call = intel_opregion_video_event;
> > +		register_acpi_notifier(&opregion->acpi_notifier);
> > +	}
> > +
> > +	intel_opregion_resume(i915);
> > +}
> > +
> > +void intel_opregion_resume(struct drm_i915_private *i915)
> > +{
> > +	struct intel_opregion *opregion = &i915->opregion;
> > +
> > +	if (!opregion->header)
> > +		return;
> > +
> > +	if (opregion->acpi) {
> > +		intel_didl_outputs(i915);
> > +		intel_setup_cadls(i915);
> > +
> > +		/* Notify BIOS we are ready to handle ACPI video ext notifs.
> > +		 * Right now, all the events are handled by the ACPI video module.
> > +		 * We don't actually need to do anything with them. */
> > +		opregion->acpi->csts = 0;
> > +		opregion->acpi->drdy = 1;
> > +	}
> > +
> > +	if (opregion->asle) {
> > +		opregion->asle->tche = ASLE_TCHE_BLC_EN;
> > +		opregion->asle->ardy = ASLE_ARDY_READY;
> > +	}
> > +
> > +	intel_opregion_notify_adapter(i915, PCI_D0);
> > +}
> > +
> > +void intel_opregion_suspend(struct drm_i915_private *i915, pci_power_t state)
> > +{
> > +	struct intel_opregion *opregion = &i915->opregion;
> > +
> > +	if (!opregion->header)
> > +		return;
> > +
> > +	if (opregion->asle)
> > +		opregion->asle->ardy = ASLE_ARDY_NOT_READY;
> > +
> > +	cancel_work_sync(&i915->opregion.asle_work);
> > +
> > +	if (opregion->acpi)
> > +		opregion->acpi->drdy = 0;
> > +
> > +	intel_opregion_notify_adapter(i915, state);
> 
> The order between drdy clear and notify changes. Depends on the BIOS
> whether that has any significance, i.e. I have no clue. If you think the
> reordering is justified, please split it out to a separate patch. Or
> just drop the order change completely. With that,
> 
> Reviewed-by: Jani Nikula <jani.nikula@intel.com>
> 
> Side note, it would seem like drdy clear should happen before canceling
> the work. In theory that should block new asle interrupts. But that's
> another change anyway, and perhaps not worth the risk.
> 
> > +}
> > +
> > +void intel_opregion_unregister(struct drm_i915_private *i915)
> > +{
> > +	struct intel_opregion *opregion = &i915->opregion;
> > +
> > +	intel_opregion_suspend(i915, PCI_D1);
> > +
> > +	if (!opregion->header)
> > +		return;
> > +
> > +	if (opregion->acpi_notifier.notifier_call) {
> > +		unregister_acpi_notifier(&opregion->acpi_notifier);
> > +		opregion->acpi_notifier.notifier_call = NULL;
> > +	}
> > +
> > +	/* just clear all opregion memory pointers now */
> > +	memunmap(opregion->header);
> > +	if (opregion->rvda) {
> > +		memunmap(opregion->rvda);
> > +		opregion->rvda = NULL;
> > +	}
> > +	if (opregion->vbt_firmware) {
> > +		kfree(opregion->vbt_firmware);
> > +		opregion->vbt_firmware = NULL;
> > +	}
> > +	opregion->header = NULL;
> > +	opregion->acpi = NULL;
> > +	opregion->swsci = NULL;
> > +	opregion->asle = NULL;
> > +	opregion->vbt = NULL;
> > +	opregion->lid_state = NULL;
> 
> Side note #2, this patch highlights (but does not change) how we have
> two init functions setup and register undone by a single unregister
> function. The asymmetry has always bugged me, but it's no fault of this
> patch.
> 
> > +}
> > diff --git a/drivers/gpu/drm/i915/intel_opregion.h b/drivers/gpu/drm/i915/intel_opregion.h
> > index e8498a8cda3d..d84b6d2d2fae 100644
> > --- a/drivers/gpu/drm/i915/intel_opregion.h
> > +++ b/drivers/gpu/drm/i915/intel_opregion.h
> > @@ -57,8 +57,14 @@ struct intel_opregion {
> >  #ifdef CONFIG_ACPI
> >  
> >  int intel_opregion_setup(struct drm_i915_private *dev_priv);
> > +
> >  void intel_opregion_register(struct drm_i915_private *dev_priv);
> >  void intel_opregion_unregister(struct drm_i915_private *dev_priv);
> > +
> > +void intel_opregion_resume(struct drm_i915_private *dev_priv);
> > +void intel_opregion_suspend(struct drm_i915_private *dev_priv,
> > +			    pci_power_t state);
> > +
> >  void intel_opregion_asle_intr(struct drm_i915_private *dev_priv);
> >  int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
> >  				  bool enable);
> > @@ -81,6 +87,15 @@ static inline void intel_opregion_unregister(struct drm_i915_private *dev_priv)
> >  {
> >  }
> >  
> > +void intel_opregion_resume(struct drm_i915_private *dev_priv)
> > +{
> > +}
> > +
> > +void intel_opregion_suspend(struct drm_i915_private *dev_priv,
> > +			    pci_power_t state)
> > +{
> > +}
> > +
> >  static inline void intel_opregion_asle_intr(struct drm_i915_private *dev_priv)
> >  {
> >  }
> 
> -- 
> Jani Nikula, Intel Open Source Graphics Center
diff mbox series

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 193023427b40..9b0887746bac 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1919,9 +1919,7 @@  static int i915_drm_suspend(struct drm_device *dev)
 	i915_save_state(dev_priv);
 
 	opregion_target_state = suspend_to_idle(dev_priv) ? PCI_D1 : PCI_D3cold;
-	intel_opregion_notify_adapter(dev_priv, opregion_target_state);
-
-	intel_opregion_unregister(dev_priv);
+	intel_opregion_suspend(dev_priv, opregion_target_state);
 
 	intel_fbdev_set_suspend(dev, FBINFO_STATE_SUSPENDED, true);
 
@@ -2040,7 +2038,6 @@  static int i915_drm_resume(struct drm_device *dev)
 
 	i915_restore_state(dev_priv);
 	intel_pps_unlock_regs_wa(dev_priv);
-	intel_opregion_setup(dev_priv);
 
 	intel_init_pch_refclk(dev_priv);
 
@@ -2082,12 +2079,10 @@  static int i915_drm_resume(struct drm_device *dev)
 	 * */
 	intel_hpd_init(dev_priv);
 
-	intel_opregion_register(dev_priv);
+	intel_opregion_resume(dev_priv);
 
 	intel_fbdev_set_suspend(dev, FBINFO_STATE_RUNNING, false);
 
-	intel_opregion_notify_adapter(dev_priv, PCI_D0);
-
 	intel_power_domains_enable(dev_priv);
 
 	enable_rpm_wakeref_asserts(dev_priv);
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index e034b4166d32..379e8c64a248 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -773,70 +773,6 @@  static void intel_setup_cadls(struct drm_i915_private *dev_priv)
 		opregion->acpi->cadl[i] = 0;
 }
 
-void intel_opregion_register(struct drm_i915_private *dev_priv)
-{
-	struct intel_opregion *opregion = &dev_priv->opregion;
-
-	if (!opregion->header)
-		return;
-
-	if (opregion->acpi) {
-		intel_didl_outputs(dev_priv);
-		intel_setup_cadls(dev_priv);
-
-		/* Notify BIOS we are ready to handle ACPI video ext notifs.
-		 * Right now, all the events are handled by the ACPI video module.
-		 * We don't actually need to do anything with them. */
-		opregion->acpi->csts = 0;
-		opregion->acpi->drdy = 1;
-
-		opregion->acpi_notifier.notifier_call = intel_opregion_video_event;
-		register_acpi_notifier(&opregion->acpi_notifier);
-	}
-
-	if (opregion->asle) {
-		opregion->asle->tche = ASLE_TCHE_BLC_EN;
-		opregion->asle->ardy = ASLE_ARDY_READY;
-	}
-}
-
-void intel_opregion_unregister(struct drm_i915_private *dev_priv)
-{
-	struct intel_opregion *opregion = &dev_priv->opregion;
-
-	if (!opregion->header)
-		return;
-
-	if (opregion->asle)
-		opregion->asle->ardy = ASLE_ARDY_NOT_READY;
-
-	cancel_work_sync(&dev_priv->opregion.asle_work);
-
-	if (opregion->acpi) {
-		opregion->acpi->drdy = 0;
-
-		unregister_acpi_notifier(&opregion->acpi_notifier);
-		opregion->acpi_notifier.notifier_call = NULL;
-	}
-
-	/* just clear all opregion memory pointers now */
-	memunmap(opregion->header);
-	if (opregion->rvda) {
-		memunmap(opregion->rvda);
-		opregion->rvda = NULL;
-	}
-	if (opregion->vbt_firmware) {
-		kfree(opregion->vbt_firmware);
-		opregion->vbt_firmware = NULL;
-	}
-	opregion->header = NULL;
-	opregion->acpi = NULL;
-	opregion->swsci = NULL;
-	opregion->asle = NULL;
-	opregion->vbt = NULL;
-	opregion->lid_state = NULL;
-}
-
 static void swsci_setup(struct drm_i915_private *dev_priv)
 {
 	struct intel_opregion *opregion = &dev_priv->opregion;
@@ -1115,3 +1051,94 @@  intel_opregion_get_panel_type(struct drm_i915_private *dev_priv)
 
 	return ret - 1;
 }
+
+void intel_opregion_register(struct drm_i915_private *i915)
+{
+	struct intel_opregion *opregion = &i915->opregion;
+
+	if (!opregion->header)
+		return;
+
+	if (opregion->acpi) {
+		opregion->acpi_notifier.notifier_call = intel_opregion_video_event;
+		register_acpi_notifier(&opregion->acpi_notifier);
+	}
+
+	intel_opregion_resume(i915);
+}
+
+void intel_opregion_resume(struct drm_i915_private *i915)
+{
+	struct intel_opregion *opregion = &i915->opregion;
+
+	if (!opregion->header)
+		return;
+
+	if (opregion->acpi) {
+		intel_didl_outputs(i915);
+		intel_setup_cadls(i915);
+
+		/* Notify BIOS we are ready to handle ACPI video ext notifs.
+		 * Right now, all the events are handled by the ACPI video module.
+		 * We don't actually need to do anything with them. */
+		opregion->acpi->csts = 0;
+		opregion->acpi->drdy = 1;
+	}
+
+	if (opregion->asle) {
+		opregion->asle->tche = ASLE_TCHE_BLC_EN;
+		opregion->asle->ardy = ASLE_ARDY_READY;
+	}
+
+	intel_opregion_notify_adapter(i915, PCI_D0);
+}
+
+void intel_opregion_suspend(struct drm_i915_private *i915, pci_power_t state)
+{
+	struct intel_opregion *opregion = &i915->opregion;
+
+	if (!opregion->header)
+		return;
+
+	if (opregion->asle)
+		opregion->asle->ardy = ASLE_ARDY_NOT_READY;
+
+	cancel_work_sync(&i915->opregion.asle_work);
+
+	if (opregion->acpi)
+		opregion->acpi->drdy = 0;
+
+	intel_opregion_notify_adapter(i915, state);
+}
+
+void intel_opregion_unregister(struct drm_i915_private *i915)
+{
+	struct intel_opregion *opregion = &i915->opregion;
+
+	intel_opregion_suspend(i915, PCI_D1);
+
+	if (!opregion->header)
+		return;
+
+	if (opregion->acpi_notifier.notifier_call) {
+		unregister_acpi_notifier(&opregion->acpi_notifier);
+		opregion->acpi_notifier.notifier_call = NULL;
+	}
+
+	/* just clear all opregion memory pointers now */
+	memunmap(opregion->header);
+	if (opregion->rvda) {
+		memunmap(opregion->rvda);
+		opregion->rvda = NULL;
+	}
+	if (opregion->vbt_firmware) {
+		kfree(opregion->vbt_firmware);
+		opregion->vbt_firmware = NULL;
+	}
+	opregion->header = NULL;
+	opregion->acpi = NULL;
+	opregion->swsci = NULL;
+	opregion->asle = NULL;
+	opregion->vbt = NULL;
+	opregion->lid_state = NULL;
+}
diff --git a/drivers/gpu/drm/i915/intel_opregion.h b/drivers/gpu/drm/i915/intel_opregion.h
index e8498a8cda3d..d84b6d2d2fae 100644
--- a/drivers/gpu/drm/i915/intel_opregion.h
+++ b/drivers/gpu/drm/i915/intel_opregion.h
@@ -57,8 +57,14 @@  struct intel_opregion {
 #ifdef CONFIG_ACPI
 
 int intel_opregion_setup(struct drm_i915_private *dev_priv);
+
 void intel_opregion_register(struct drm_i915_private *dev_priv);
 void intel_opregion_unregister(struct drm_i915_private *dev_priv);
+
+void intel_opregion_resume(struct drm_i915_private *dev_priv);
+void intel_opregion_suspend(struct drm_i915_private *dev_priv,
+			    pci_power_t state);
+
 void intel_opregion_asle_intr(struct drm_i915_private *dev_priv);
 int intel_opregion_notify_encoder(struct intel_encoder *intel_encoder,
 				  bool enable);
@@ -81,6 +87,15 @@  static inline void intel_opregion_unregister(struct drm_i915_private *dev_priv)
 {
 }
 
+void intel_opregion_resume(struct drm_i915_private *dev_priv)
+{
+}
+
+void intel_opregion_suspend(struct drm_i915_private *dev_priv,
+			    pci_power_t state)
+{
+}
+
 static inline void intel_opregion_asle_intr(struct drm_i915_private *dev_priv)
 {
 }