Commit 765425f5 authored by Luca Coelho's avatar Luca Coelho Committed by Jani Nikula
Browse files

drm/i915/display: add support for DMC wakelocks



In order to reduce the DC5->DC2 restore time, wakelocks have been
introduced in DMC so the driver can tell it when registers and other
memory areas are going to be accessed and keep their respective blocks
awake.

Implement this in the driver by adding the concept of DMC wakelocks.
When the driver needs to access memory which lies inside pre-defined
ranges, it will tell DMC to set the wakelock, access the memory, then
wait for a while and clear the wakelock.

The wakelock state is protected in the driver with spinlocks to
prevent concurrency issues.

BSpec: 71583
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Reviewed-by: default avatarUma Shankar <uma.shankar@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240412094148.808179-2-luciano.coelho@intel.com


Signed-off-by: default avatarJani Nikula <jani.nikula@intel.com>
parent 578ff984
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -204,6 +204,15 @@ DMC Firmware Support
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dmc.c
   :internal:

DMC wakelock support
--------------------

.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dmc_wl.c
   :doc: DMC wakelock support

.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dmc_wl.c
   :internal:

Video BIOS Table (VBT)
----------------------

+1 −0
Original line number Diff line number Diff line
@@ -265,6 +265,7 @@ i915-y += \
	display/intel_display_rps.o \
	display/intel_display_wa.o \
	display/intel_dmc.o \
	display/intel_dmc_wl.o \
	display/intel_dpio_phy.o \
	display/intel_dpll.o \
	display/intel_dpll_mgr.o \
+89 −8
Original line number Diff line number Diff line
@@ -13,52 +13,125 @@
static inline u32
intel_de_read(struct drm_i915_private *i915, i915_reg_t reg)
{
	return intel_uncore_read(&i915->uncore, reg);
	u32 val;

	intel_dmc_wl_get(i915, reg);

	val = intel_uncore_read(&i915->uncore, reg);

	intel_dmc_wl_put(i915, reg);

	return val;
}

static inline u8
intel_de_read8(struct drm_i915_private *i915, i915_reg_t reg)
{
	return intel_uncore_read8(&i915->uncore, reg);
	u8 val;

	intel_dmc_wl_get(i915, reg);

	val = intel_uncore_read8(&i915->uncore, reg);

	intel_dmc_wl_put(i915, reg);

	return val;
}

static inline u64
intel_de_read64_2x32(struct drm_i915_private *i915,
		     i915_reg_t lower_reg, i915_reg_t upper_reg)
{
	return intel_uncore_read64_2x32(&i915->uncore, lower_reg, upper_reg);
	u64 val;

	intel_dmc_wl_get(i915, lower_reg);
	intel_dmc_wl_get(i915, upper_reg);

	val = intel_uncore_read64_2x32(&i915->uncore, lower_reg, upper_reg);

	intel_dmc_wl_put(i915, upper_reg);
	intel_dmc_wl_put(i915, lower_reg);

	return val;
}

static inline void
intel_de_posting_read(struct drm_i915_private *i915, i915_reg_t reg)
{
	intel_dmc_wl_get(i915, reg);

	intel_uncore_posting_read(&i915->uncore, reg);

	intel_dmc_wl_put(i915, reg);
}

static inline void
intel_de_write(struct drm_i915_private *i915, i915_reg_t reg, u32 val)
{
	intel_dmc_wl_get(i915, reg);

	intel_uncore_write(&i915->uncore, reg, val);

	intel_dmc_wl_put(i915, reg);
}

static inline u32
intel_de_rmw(struct drm_i915_private *i915, i915_reg_t reg, u32 clear, u32 set)
__intel_de_rmw_nowl(struct drm_i915_private *i915, i915_reg_t reg,
		    u32 clear, u32 set)
{
	return intel_uncore_rmw(&i915->uncore, reg, clear, set);
}

static inline u32
intel_de_rmw(struct drm_i915_private *i915, i915_reg_t reg, u32 clear, u32 set)
{
	u32 val;

	intel_dmc_wl_get(i915, reg);

	val = __intel_de_rmw_nowl(i915, reg, clear, set);

	intel_dmc_wl_put(i915, reg);

	return val;
}

static inline int
__intel_wait_for_register_nowl(struct drm_i915_private *i915, i915_reg_t reg,
			       u32 mask, u32 value, unsigned int timeout)
{
	return intel_wait_for_register(&i915->uncore, reg, mask,
				       value, timeout);
}

static inline int
intel_de_wait(struct drm_i915_private *i915, i915_reg_t reg,
	      u32 mask, u32 value, unsigned int timeout)
{
	return intel_wait_for_register(&i915->uncore, reg, mask, value, timeout);
	int ret;

	intel_dmc_wl_get(i915, reg);

	ret = __intel_wait_for_register_nowl(i915, reg, mask, value, timeout);

	intel_dmc_wl_put(i915, reg);

	return ret;
}

static inline int
intel_de_wait_fw(struct drm_i915_private *i915, i915_reg_t reg,
		 u32 mask, u32 value, unsigned int timeout)
{
	return intel_wait_for_register_fw(&i915->uncore, reg, mask, value, timeout);
	int ret;

	intel_dmc_wl_get(i915, reg);

	ret = intel_wait_for_register_fw(&i915->uncore, reg, mask, value, timeout);

	intel_dmc_wl_put(i915, reg);

	return ret;
}

static inline int
@@ -67,8 +140,16 @@ intel_de_wait_custom(struct drm_i915_private *i915, i915_reg_t reg,
		     unsigned int fast_timeout_us,
		     unsigned int slow_timeout_ms, u32 *out_value)
{
	return __intel_wait_for_register(&i915->uncore, reg, mask, value,
	int ret;

	intel_dmc_wl_get(i915, reg);

	ret = __intel_wait_for_register(&i915->uncore, reg, mask, value,
					fast_timeout_us, slow_timeout_ms, out_value);

	intel_dmc_wl_put(i915, reg);

	return ret;
}

static inline int
+2 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "intel_global_state.h"
#include "intel_gmbus.h"
#include "intel_opregion.h"
#include "intel_dmc_wl.h"
#include "intel_wm_types.h"

struct task_struct;
@@ -546,6 +547,7 @@ struct intel_display {
	struct intel_overlay *overlay;
	struct intel_display_params params;
	struct intel_vbt_data vbt;
	struct intel_dmc_wl wl;
	struct intel_wm wm;
};

+6 −0
Original line number Diff line number Diff line
@@ -97,4 +97,10 @@
#define TGL_DMC_DEBUG3		_MMIO(0x101090)
#define DG1_DMC_DEBUG3		_MMIO(0x13415c)

#define DMC_WAKELOCK_CFG	_MMIO(0x8F1B0)
#define  DMC_WAKELOCK_CFG_ENABLE REG_BIT(31)
#define DMC_WAKELOCK1_CTL	_MMIO(0x8F140)
#define  DMC_WAKELOCK_CTL_REQ	 REG_BIT(31)
#define  DMC_WAKELOCK_CTL_ACK	 REG_BIT(15)

#endif /* __INTEL_DMC_REGS_H__ */
Loading