All of lore.kernel.org
 help / color / mirror / Atom feed
* [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux
@ 2021-01-08 17:44 Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 01/17] drm/i915/pps: abstract panel power sequencer from intel_dp.c Jani Nikula
                   ` (20 more replies)
  0 siblings, 21 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

This is v2 of [1], with comments from Anshuman addressed, and a few additional
patches at the end.

BR,
Jani.


[1] https://patchwork.freedesktop.org/series/85167/


Jani Nikula (17):
  drm/i915/pps: abstract panel power sequencer from intel_dp.c
  drm/i915/pps: rename pps_{,un}lock -> intel_pps_{,un}lock
  drm/i915/pps: rename intel_edp_backlight_* to intel_pps_backlight_*
  drm/i915/pps: rename intel_edp_panel_* to intel_pps_*
  drm/i915/pps: rename edp_panel_* to intel_pps_*_unlocked
  drm/i915/pps: abstract intel_pps_vdd_off_sync
  drm/i915/pps: add higher level intel_pps_init() call
  drm/i915/pps: abstract intel_pps_encoder_reset()
  drm/i915/pps: rename intel_dp_check_edp to
    intel_pps_check_power_unlocked
  drm/i915/pps: rename intel_power_sequencer_reset to
    intel_pps_reset_all
  drm/i915/pps: add locked intel_pps_wait_power_cycle
  drm/i915/pps: rename vlv_init_panel_power_sequencer to vlv_pps_init
  drm/i915/pps: rename intel_dp_init_panel_power_sequencer* functions
  drm/i915/pps: refactor init abstractions
  drm/i915/pps: move pps code over from intel_display.c and refactor
  drm/i915/dp: abstract struct intel_dp pps members to a sub-struct
  drm/i915/dp: split out aux functionality to intel_dp_aux.c

 drivers/gpu/drm/i915/Makefile                 |    2 +
 drivers/gpu/drm/i915/display/intel_ddi.c      |    9 +-
 drivers/gpu/drm/i915/display/intel_display.c  |   41 +-
 drivers/gpu/drm/i915/display/intel_display.h  |    1 -
 .../drm/i915/display/intel_display_debugfs.c  |    8 +-
 .../drm/i915/display/intel_display_power.c    |    6 +-
 .../drm/i915/display/intel_display_types.h    |   61 +-
 drivers/gpu/drm/i915/display/intel_dp.c       | 2249 +----------------
 drivers/gpu/drm/i915/display/intel_dp.h       |    5 +-
 drivers/gpu/drm/i915/display/intel_dp_aux.c   |  687 +++++
 drivers/gpu/drm/i915/display/intel_dp_aux.h   |   18 +
 drivers/gpu/drm/i915/display/intel_pps.c      | 1406 +++++++++++
 drivers/gpu/drm/i915/display/intel_pps.h      |   52 +
 drivers/gpu/drm/i915/i915_drv.c               |    1 +
 14 files changed, 2312 insertions(+), 2234 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_aux.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_aux.h
 create mode 100644 drivers/gpu/drm/i915/display/intel_pps.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_pps.h

-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 01/17] drm/i915/pps: abstract panel power sequencer from intel_dp.c
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-13 15:34   ` Jani Nikula
  2021-01-13 16:47   ` Anshuman Gupta
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 02/17] drm/i915/pps: rename pps_{, un}lock -> intel_pps_{, un}lock Jani Nikula
                   ` (19 subsequent siblings)
  20 siblings, 2 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

In a long overdue refactoring, split out all panel sequencer code from
intel_dp.c to new intel_pps.[ch].

The first part is mostly just code movement as-is, without cleanups or
functional changes.

We need to add a vlv_get_dpll() helper to get at the vlv/chv dpll from
pps code.

v2: Rebase.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/Makefile                 |    1 +
 drivers/gpu/drm/i915/display/intel_ddi.c      |    1 +
 .../drm/i915/display/intel_display_power.c    |    2 +-
 drivers/gpu/drm/i915/display/intel_dp.c       | 1436 +----------------
 drivers/gpu/drm/i915/display/intel_dp.h       |    5 +-
 drivers/gpu/drm/i915/display/intel_pps.c      | 1334 +++++++++++++++
 drivers/gpu/drm/i915/display/intel_pps.h      |   53 +
 7 files changed, 1443 insertions(+), 1389 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_pps.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_pps.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 4074d8cb0d6e..8a04403a11bb 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -251,6 +251,7 @@ i915-y += \
 	display/intel_lspcon.o \
 	display/intel_lvds.o \
 	display/intel_panel.o \
+	display/intel_pps.o \
 	display/intel_sdvo.o \
 	display/intel_tv.o \
 	display/intel_vdsc.o \
diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index 3df6913369bc..f09a597bf730 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -46,6 +46,7 @@
 #include "intel_hotplug.h"
 #include "intel_lspcon.h"
 #include "intel_panel.h"
+#include "intel_pps.h"
 #include "intel_psr.h"
 #include "intel_sprite.h"
 #include "intel_tc.h"
diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index d52374f01316..a11bd8213df4 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -4,7 +4,6 @@
  */
 
 #include "display/intel_crt.h"
-#include "display/intel_dp.h"
 
 #include "i915_drv.h"
 #include "i915_irq.h"
@@ -16,6 +15,7 @@
 #include "intel_dpio_phy.h"
 #include "intel_hotplug.h"
 #include "intel_pm.h"
+#include "intel_pps.h"
 #include "intel_sideband.h"
 #include "intel_tc.h"
 #include "intel_vga.h"
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 4f190a82d4ad..07279b10812e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -58,6 +58,7 @@
 #include "intel_lspcon.h"
 #include "intel_lvds.h"
 #include "intel_panel.h"
+#include "intel_pps.h"
 #include "intel_psr.h"
 #include "intel_sideband.h"
 #include "intel_tc.h"
@@ -121,6 +122,11 @@ static const struct dp_link_dpll chv_dpll[] = {
 		{ .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } },
 };
 
+const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
+{
+	return IS_CHERRYVIEW(i915) ? &chv_dpll[0].dpll : &vlv_dpll[0].dpll;
+}
+
 /* Constants for DP DSC configurations */
 static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15};
 
@@ -145,12 +151,6 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp)
 
 static void intel_dp_link_down(struct intel_encoder *encoder,
 			       const struct intel_crtc_state *old_crtc_state);
-static bool edp_panel_vdd_on(struct intel_dp *intel_dp);
-static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
-static void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
-					   const struct intel_crtc_state *crtc_state);
-static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
-				      enum pipe pipe);
 static void intel_dp_unset_edid(struct intel_dp *intel_dp);
 
 /* update sink rates from dpcd */
@@ -877,447 +877,6 @@ static void intel_dp_unpack_aux(u32 src, u8 *dst, int dst_bytes)
 		dst[i] = src >> ((3-i) * 8);
 }
 
-static void
-intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp);
-static void
-intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
-					      bool force_disable_vdd);
-static void
-intel_dp_pps_init(struct intel_dp *intel_dp);
-
-static intel_wakeref_t
-pps_lock(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	intel_wakeref_t wakeref;
-
-	/*
-	 * See intel_power_sequencer_reset() why we need
-	 * a power domain reference here.
-	 */
-	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
-	mutex_lock(&dev_priv->pps_mutex);
-
-	return wakeref;
-}
-
-static intel_wakeref_t
-pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-
-	mutex_unlock(&dev_priv->pps_mutex);
-	intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
-	return 0;
-}
-
-#define with_pps_lock(dp, wf) \
-	for ((wf) = pps_lock(dp); (wf); (wf) = pps_unlock((dp), (wf)))
-
-static void
-vlv_power_sequencer_kick(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum pipe pipe = intel_dp->pps_pipe;
-	bool pll_enabled, release_cl_override = false;
-	enum dpio_phy phy = DPIO_PHY(pipe);
-	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
-	u32 DP;
-
-	if (drm_WARN(&dev_priv->drm,
-		     intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN,
-		     "skipping pipe %c power sequencer kick due to [ENCODER:%d:%s] being active\n",
-		     pipe_name(pipe), dig_port->base.base.base.id,
-		     dig_port->base.base.name))
-		return;
-
-	drm_dbg_kms(&dev_priv->drm,
-		    "kicking pipe %c power sequencer for [ENCODER:%d:%s]\n",
-		    pipe_name(pipe), dig_port->base.base.base.id,
-		    dig_port->base.base.name);
-
-	/* Preserve the BIOS-computed detected bit. This is
-	 * supposed to be read-only.
-	 */
-	DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
-	DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
-	DP |= DP_PORT_WIDTH(1);
-	DP |= DP_LINK_TRAIN_PAT_1;
-
-	if (IS_CHERRYVIEW(dev_priv))
-		DP |= DP_PIPE_SEL_CHV(pipe);
-	else
-		DP |= DP_PIPE_SEL(pipe);
-
-	pll_enabled = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE;
-
-	/*
-	 * The DPLL for the pipe must be enabled for this to work.
-	 * So enable temporarily it if it's not already enabled.
-	 */
-	if (!pll_enabled) {
-		release_cl_override = IS_CHERRYVIEW(dev_priv) &&
-			!chv_phy_powergate_ch(dev_priv, phy, ch, true);
-
-		if (vlv_force_pll_on(dev_priv, pipe, IS_CHERRYVIEW(dev_priv) ?
-				     &chv_dpll[0].dpll : &vlv_dpll[0].dpll)) {
-			drm_err(&dev_priv->drm,
-				"Failed to force on pll for pipe %c!\n",
-				pipe_name(pipe));
-			return;
-		}
-	}
-
-	/*
-	 * Similar magic as in intel_dp_enable_port().
-	 * We _must_ do this port enable + disable trick
-	 * to make this power sequencer lock onto the port.
-	 * Otherwise even VDD force bit won't work.
-	 */
-	intel_de_write(dev_priv, intel_dp->output_reg, DP);
-	intel_de_posting_read(dev_priv, intel_dp->output_reg);
-
-	intel_de_write(dev_priv, intel_dp->output_reg, DP | DP_PORT_EN);
-	intel_de_posting_read(dev_priv, intel_dp->output_reg);
-
-	intel_de_write(dev_priv, intel_dp->output_reg, DP & ~DP_PORT_EN);
-	intel_de_posting_read(dev_priv, intel_dp->output_reg);
-
-	if (!pll_enabled) {
-		vlv_force_pll_off(dev_priv, pipe);
-
-		if (release_cl_override)
-			chv_phy_powergate_ch(dev_priv, phy, ch, false);
-	}
-}
-
-static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv)
-{
-	struct intel_encoder *encoder;
-	unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
-
-	/*
-	 * We don't have power sequencer currently.
-	 * Pick one that's not used by other ports.
-	 */
-	for_each_intel_dp(&dev_priv->drm, encoder) {
-		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
-		if (encoder->type == INTEL_OUTPUT_EDP) {
-			drm_WARN_ON(&dev_priv->drm,
-				    intel_dp->active_pipe != INVALID_PIPE &&
-				    intel_dp->active_pipe !=
-				    intel_dp->pps_pipe);
-
-			if (intel_dp->pps_pipe != INVALID_PIPE)
-				pipes &= ~(1 << intel_dp->pps_pipe);
-		} else {
-			drm_WARN_ON(&dev_priv->drm,
-				    intel_dp->pps_pipe != INVALID_PIPE);
-
-			if (intel_dp->active_pipe != INVALID_PIPE)
-				pipes &= ~(1 << intel_dp->active_pipe);
-		}
-	}
-
-	if (pipes == 0)
-		return INVALID_PIPE;
-
-	return ffs(pipes) - 1;
-}
-
-static enum pipe
-vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum pipe pipe;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	/* We should never land here with regular DP ports */
-	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
-
-	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE &&
-		    intel_dp->active_pipe != intel_dp->pps_pipe);
-
-	if (intel_dp->pps_pipe != INVALID_PIPE)
-		return intel_dp->pps_pipe;
-
-	pipe = vlv_find_free_pps(dev_priv);
-
-	/*
-	 * Didn't find one. This should not happen since there
-	 * are two power sequencers and up to two eDP ports.
-	 */
-	if (drm_WARN_ON(&dev_priv->drm, pipe == INVALID_PIPE))
-		pipe = PIPE_A;
-
-	vlv_steal_power_sequencer(dev_priv, pipe);
-	intel_dp->pps_pipe = pipe;
-
-	drm_dbg_kms(&dev_priv->drm,
-		    "picked pipe %c power sequencer for [ENCODER:%d:%s]\n",
-		    pipe_name(intel_dp->pps_pipe),
-		    dig_port->base.base.base.id,
-		    dig_port->base.base.name);
-
-	/* init power sequencer on this pipe and port */
-	intel_dp_init_panel_power_sequencer(intel_dp);
-	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
-
-	/*
-	 * Even vdd force doesn't work until we've made
-	 * the power sequencer lock in on the port.
-	 */
-	vlv_power_sequencer_kick(intel_dp);
-
-	return intel_dp->pps_pipe;
-}
-
-static int
-bxt_power_sequencer_idx(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	int backlight_controller = dev_priv->vbt.backlight.controller;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	/* We should never land here with regular DP ports */
-	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
-
-	if (!intel_dp->pps_reset)
-		return backlight_controller;
-
-	intel_dp->pps_reset = false;
-
-	/*
-	 * Only the HW needs to be reprogrammed, the SW state is fixed and
-	 * has been setup during connector init.
-	 */
-	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
-
-	return backlight_controller;
-}
-
-typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
-			       enum pipe pipe);
-
-static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
-			       enum pipe pipe)
-{
-	return intel_de_read(dev_priv, PP_STATUS(pipe)) & PP_ON;
-}
-
-static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
-				enum pipe pipe)
-{
-	return intel_de_read(dev_priv, PP_CONTROL(pipe)) & EDP_FORCE_VDD;
-}
-
-static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
-			 enum pipe pipe)
-{
-	return true;
-}
-
-static enum pipe
-vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
-		     enum port port,
-		     vlv_pipe_check pipe_check)
-{
-	enum pipe pipe;
-
-	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
-		u32 port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(pipe)) &
-			PANEL_PORT_SELECT_MASK;
-
-		if (port_sel != PANEL_PORT_SELECT_VLV(port))
-			continue;
-
-		if (!pipe_check(dev_priv, pipe))
-			continue;
-
-		return pipe;
-	}
-
-	return INVALID_PIPE;
-}
-
-static void
-vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum port port = dig_port->base.port;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	/* try to find a pipe with this port selected */
-	/* first pick one where the panel is on */
-	intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
-						  vlv_pipe_has_pp_on);
-	/* didn't find one? pick one where vdd is on */
-	if (intel_dp->pps_pipe == INVALID_PIPE)
-		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
-							  vlv_pipe_has_vdd_on);
-	/* didn't find one? pick one with just the correct port */
-	if (intel_dp->pps_pipe == INVALID_PIPE)
-		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
-							  vlv_pipe_any);
-
-	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
-	if (intel_dp->pps_pipe == INVALID_PIPE) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "no initial power sequencer for [ENCODER:%d:%s]\n",
-			    dig_port->base.base.base.id,
-			    dig_port->base.base.name);
-		return;
-	}
-
-	drm_dbg_kms(&dev_priv->drm,
-		    "initial power sequencer for [ENCODER:%d:%s]: pipe %c\n",
-		    dig_port->base.base.base.id,
-		    dig_port->base.base.name,
-		    pipe_name(intel_dp->pps_pipe));
-
-	intel_dp_init_panel_power_sequencer(intel_dp);
-	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
-}
-
-void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
-{
-	struct intel_encoder *encoder;
-
-	if (drm_WARN_ON(&dev_priv->drm,
-			!(IS_VALLEYVIEW(dev_priv) ||
-			  IS_CHERRYVIEW(dev_priv) ||
-			  IS_GEN9_LP(dev_priv))))
-		return;
-
-	/*
-	 * We can't grab pps_mutex here due to deadlock with power_domain
-	 * mutex when power_domain functions are called while holding pps_mutex.
-	 * That also means that in order to use pps_pipe the code needs to
-	 * hold both a power domain reference and pps_mutex, and the power domain
-	 * reference get/put must be done while _not_ holding pps_mutex.
-	 * pps_{lock,unlock}() do these steps in the correct order, so one
-	 * should use them always.
-	 */
-
-	for_each_intel_dp(&dev_priv->drm, encoder) {
-		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
-		drm_WARN_ON(&dev_priv->drm,
-			    intel_dp->active_pipe != INVALID_PIPE);
-
-		if (encoder->type != INTEL_OUTPUT_EDP)
-			continue;
-
-		if (IS_GEN9_LP(dev_priv))
-			intel_dp->pps_reset = true;
-		else
-			intel_dp->pps_pipe = INVALID_PIPE;
-	}
-}
-
-struct pps_registers {
-	i915_reg_t pp_ctrl;
-	i915_reg_t pp_stat;
-	i915_reg_t pp_on;
-	i915_reg_t pp_off;
-	i915_reg_t pp_div;
-};
-
-static void intel_pps_get_registers(struct intel_dp *intel_dp,
-				    struct pps_registers *regs)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	int pps_idx = 0;
-
-	memset(regs, 0, sizeof(*regs));
-
-	if (IS_GEN9_LP(dev_priv))
-		pps_idx = bxt_power_sequencer_idx(intel_dp);
-	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		pps_idx = vlv_power_sequencer_pipe(intel_dp);
-
-	regs->pp_ctrl = PP_CONTROL(pps_idx);
-	regs->pp_stat = PP_STATUS(pps_idx);
-	regs->pp_on = PP_ON_DELAYS(pps_idx);
-	regs->pp_off = PP_OFF_DELAYS(pps_idx);
-
-	/* Cycle delay moved from PP_DIVISOR to PP_CONTROL */
-	if (IS_GEN9_LP(dev_priv) || INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
-		regs->pp_div = INVALID_MMIO_REG;
-	else
-		regs->pp_div = PP_DIVISOR(pps_idx);
-}
-
-static i915_reg_t
-_pp_ctrl_reg(struct intel_dp *intel_dp)
-{
-	struct pps_registers regs;
-
-	intel_pps_get_registers(intel_dp, &regs);
-
-	return regs.pp_ctrl;
-}
-
-static i915_reg_t
-_pp_stat_reg(struct intel_dp *intel_dp)
-{
-	struct pps_registers regs;
-
-	intel_pps_get_registers(intel_dp, &regs);
-
-	return regs.pp_stat;
-}
-
-static bool edp_have_panel_power(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
-	    intel_dp->pps_pipe == INVALID_PIPE)
-		return false;
-
-	return (intel_de_read(dev_priv, _pp_stat_reg(intel_dp)) & PP_ON) != 0;
-}
-
-static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
-	    intel_dp->pps_pipe == INVALID_PIPE)
-		return false;
-
-	return intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
-}
-
-static void
-intel_dp_check_edp(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-
-	if (!intel_dp_is_edp(intel_dp))
-		return;
-
-	if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) {
-		drm_WARN(&dev_priv->drm, 1,
-			 "eDP powered off while attempting aux channel communication.\n");
-		drm_dbg_kms(&dev_priv->drm, "Status 0x%08x Control 0x%08x\n",
-			    intel_de_read(dev_priv, _pp_stat_reg(intel_dp)),
-			    intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)));
-	}
-}
-
 static u32
 intel_dp_aux_wait_done(struct intel_dp *intel_dp)
 {
@@ -2931,491 +2490,66 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
 	 * IBX PCH and CPU are the same for almost everything,
 	 * except that the CPU DP PLL is configured in this
 	 * register
-	 *
-	 * CPT PCH is quite different, having many bits moved
-	 * to the TRANS_DP_CTL register instead. That
-	 * configuration happens (oddly) in ilk_pch_enable
-	 */
-
-	/* Preserve the BIOS-computed detected bit. This is
-	 * supposed to be read-only.
-	 */
-	intel_dp->DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
-
-	/* Handle DP bits in common between all three register formats */
-	intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
-	intel_dp->DP |= DP_PORT_WIDTH(pipe_config->lane_count);
-
-	/* Split out the IBX/CPU vs CPT settings */
-
-	if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) {
-		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-			intel_dp->DP |= DP_SYNC_HS_HIGH;
-		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-			intel_dp->DP |= DP_SYNC_VS_HIGH;
-		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
-
-		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
-			intel_dp->DP |= DP_ENHANCED_FRAMING;
-
-		intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe);
-	} else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
-		u32 trans_dp;
-
-		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
-
-		trans_dp = intel_de_read(dev_priv, TRANS_DP_CTL(crtc->pipe));
-		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
-			trans_dp |= TRANS_DP_ENH_FRAMING;
-		else
-			trans_dp &= ~TRANS_DP_ENH_FRAMING;
-		intel_de_write(dev_priv, TRANS_DP_CTL(crtc->pipe), trans_dp);
-	} else {
-		if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
-			intel_dp->DP |= DP_COLOR_RANGE_16_235;
-
-		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
-			intel_dp->DP |= DP_SYNC_HS_HIGH;
-		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
-			intel_dp->DP |= DP_SYNC_VS_HIGH;
-		intel_dp->DP |= DP_LINK_TRAIN_OFF;
-
-		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
-			intel_dp->DP |= DP_ENHANCED_FRAMING;
-
-		if (IS_CHERRYVIEW(dev_priv))
-			intel_dp->DP |= DP_PIPE_SEL_CHV(crtc->pipe);
-		else
-			intel_dp->DP |= DP_PIPE_SEL(crtc->pipe);
-	}
-}
-
-#define IDLE_ON_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
-#define IDLE_ON_VALUE   	(PP_ON | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
-
-#define IDLE_OFF_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | 0)
-#define IDLE_OFF_VALUE		(0     | PP_SEQUENCE_NONE | 0                     | 0)
-
-#define IDLE_CYCLE_MASK		(PP_ON | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
-#define IDLE_CYCLE_VALUE	(0     | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
-
-static void intel_pps_verify_state(struct intel_dp *intel_dp);
-
-static void wait_panel_status(struct intel_dp *intel_dp,
-				       u32 mask,
-				       u32 value)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	i915_reg_t pp_stat_reg, pp_ctrl_reg;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	intel_pps_verify_state(intel_dp);
-
-	pp_stat_reg = _pp_stat_reg(intel_dp);
-	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
-
-	drm_dbg_kms(&dev_priv->drm,
-		    "mask %08x value %08x status %08x control %08x\n",
-		    mask, value,
-		    intel_de_read(dev_priv, pp_stat_reg),
-		    intel_de_read(dev_priv, pp_ctrl_reg));
-
-	if (intel_de_wait_for_register(dev_priv, pp_stat_reg,
-				       mask, value, 5000))
-		drm_err(&dev_priv->drm,
-			"Panel status timeout: status %08x control %08x\n",
-			intel_de_read(dev_priv, pp_stat_reg),
-			intel_de_read(dev_priv, pp_ctrl_reg));
-
-	drm_dbg_kms(&dev_priv->drm, "Wait complete\n");
-}
-
-static void wait_panel_on(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-
-	drm_dbg_kms(&i915->drm, "Wait for panel power on\n");
-	wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
-}
-
-static void wait_panel_off(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-
-	drm_dbg_kms(&i915->drm, "Wait for panel power off time\n");
-	wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
-}
-
-static void wait_panel_power_cycle(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-	ktime_t panel_power_on_time;
-	s64 panel_power_off_duration;
-
-	drm_dbg_kms(&i915->drm, "Wait for panel power cycle\n");
-
-	/* take the difference of currrent time and panel power off time
-	 * and then make panel wait for t11_t12 if needed. */
-	panel_power_on_time = ktime_get_boottime();
-	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->panel_power_off_time);
-
-	/* When we disable the VDD override bit last we have to do the manual
-	 * wait. */
-	if (panel_power_off_duration < (s64)intel_dp->panel_power_cycle_delay)
-		wait_remaining_ms_from_jiffies(jiffies,
-				       intel_dp->panel_power_cycle_delay - panel_power_off_duration);
-
-	wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
-}
-
-static void wait_backlight_on(struct intel_dp *intel_dp)
-{
-	wait_remaining_ms_from_jiffies(intel_dp->last_power_on,
-				       intel_dp->backlight_on_delay);
-}
-
-static void edp_wait_backlight_off(struct intel_dp *intel_dp)
-{
-	wait_remaining_ms_from_jiffies(intel_dp->last_backlight_off,
-				       intel_dp->backlight_off_delay);
-}
-
-/* Read the current pp_control value, unlocking the register if it
- * is locked
- */
-
-static  u32 ilk_get_pp_control(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	u32 control;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	control = intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp));
-	if (drm_WARN_ON(&dev_priv->drm, !HAS_DDI(dev_priv) &&
-			(control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
-		control &= ~PANEL_UNLOCK_MASK;
-		control |= PANEL_UNLOCK_REGS;
-	}
-	return control;
-}
-
-/*
- * Must be paired with edp_panel_vdd_off().
- * Must hold pps_mutex around the whole on/off sequence.
- * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
- */
-static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	u32 pp;
-	i915_reg_t pp_stat_reg, pp_ctrl_reg;
-	bool need_to_disable = !intel_dp->want_panel_vdd;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	if (!intel_dp_is_edp(intel_dp))
-		return false;
-
-	cancel_delayed_work(&intel_dp->panel_vdd_work);
-	intel_dp->want_panel_vdd = true;
-
-	if (edp_have_panel_vdd(intel_dp))
-		return need_to_disable;
-
-	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
-	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
-							intel_aux_power_domain(dig_port));
-
-	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n",
-		    dig_port->base.base.base.id,
-		    dig_port->base.base.name);
-
-	if (!edp_have_panel_power(intel_dp))
-		wait_panel_power_cycle(intel_dp);
-
-	pp = ilk_get_pp_control(intel_dp);
-	pp |= EDP_FORCE_VDD;
-
-	pp_stat_reg = _pp_stat_reg(intel_dp);
-	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
-
-	intel_de_write(dev_priv, pp_ctrl_reg, pp);
-	intel_de_posting_read(dev_priv, pp_ctrl_reg);
-	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
-		    intel_de_read(dev_priv, pp_stat_reg),
-		    intel_de_read(dev_priv, pp_ctrl_reg));
-	/*
-	 * If the panel wasn't on, delay before accessing aux channel
-	 */
-	if (!edp_have_panel_power(intel_dp)) {
-		drm_dbg_kms(&dev_priv->drm,
-			    "[ENCODER:%d:%s] panel power wasn't enabled\n",
-			    dig_port->base.base.base.id,
-			    dig_port->base.base.name);
-		msleep(intel_dp->panel_power_up_delay);
-	}
-
-	return need_to_disable;
-}
-
-/*
- * Must be paired with intel_edp_panel_vdd_off() or
- * intel_edp_panel_off().
- * Nested calls to these functions are not allowed since
- * we drop the lock. Caller must use some higher level
- * locking to prevent nested calls from other threads.
- */
-void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
-{
-	intel_wakeref_t wakeref;
-	bool vdd;
-
-	if (!intel_dp_is_edp(intel_dp))
-		return;
-
-	vdd = false;
-	with_pps_lock(intel_dp, wakeref)
-		vdd = edp_panel_vdd_on(intel_dp);
-	I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n",
-			dp_to_dig_port(intel_dp)->base.base.base.id,
-			dp_to_dig_port(intel_dp)->base.base.name);
-}
-
-static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port =
-		dp_to_dig_port(intel_dp);
-	u32 pp;
-	i915_reg_t pp_stat_reg, pp_ctrl_reg;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	drm_WARN_ON(&dev_priv->drm, intel_dp->want_panel_vdd);
-
-	if (!edp_have_panel_vdd(intel_dp))
-		return;
-
-	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD off\n",
-		    dig_port->base.base.base.id,
-		    dig_port->base.base.name);
-
-	pp = ilk_get_pp_control(intel_dp);
-	pp &= ~EDP_FORCE_VDD;
-
-	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
-	pp_stat_reg = _pp_stat_reg(intel_dp);
-
-	intel_de_write(dev_priv, pp_ctrl_reg, pp);
-	intel_de_posting_read(dev_priv, pp_ctrl_reg);
-
-	/* Make sure sequencer is idle before allowing subsequent activity */
-	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
-		    intel_de_read(dev_priv, pp_stat_reg),
-		    intel_de_read(dev_priv, pp_ctrl_reg));
-
-	if ((pp & PANEL_POWER_ON) == 0)
-		intel_dp->panel_power_off_time = ktime_get_boottime();
-
-	intel_display_power_put(dev_priv,
-				intel_aux_power_domain(dig_port),
-				fetch_and_zero(&intel_dp->vdd_wakeref));
-}
-
-static void edp_panel_vdd_work(struct work_struct *__work)
-{
-	struct intel_dp *intel_dp =
-		container_of(to_delayed_work(__work),
-			     struct intel_dp, panel_vdd_work);
-	intel_wakeref_t wakeref;
-
-	with_pps_lock(intel_dp, wakeref) {
-		if (!intel_dp->want_panel_vdd)
-			edp_panel_vdd_off_sync(intel_dp);
-	}
-}
-
-static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
-{
-	unsigned long delay;
-
-	/*
-	 * Queue the timer to fire a long time from now (relative to the power
-	 * down delay) to keep the panel power up across a sequence of
-	 * operations.
-	 */
-	delay = msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5);
-	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
-}
-
-/*
- * Must be paired with edp_panel_vdd_on().
- * Must hold pps_mutex around the whole on/off sequence.
- * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
- */
-static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	if (!intel_dp_is_edp(intel_dp))
-		return;
-
-	I915_STATE_WARN(!intel_dp->want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on",
-			dp_to_dig_port(intel_dp)->base.base.base.id,
-			dp_to_dig_port(intel_dp)->base.base.name);
-
-	intel_dp->want_panel_vdd = false;
-
-	if (sync)
-		edp_panel_vdd_off_sync(intel_dp);
-	else
-		edp_panel_vdd_schedule_off(intel_dp);
-}
-
-static void edp_panel_on(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	u32 pp;
-	i915_reg_t pp_ctrl_reg;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	if (!intel_dp_is_edp(intel_dp))
-		return;
-
-	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power on\n",
-		    dp_to_dig_port(intel_dp)->base.base.base.id,
-		    dp_to_dig_port(intel_dp)->base.base.name);
-
-	if (drm_WARN(&dev_priv->drm, edp_have_panel_power(intel_dp),
-		     "[ENCODER:%d:%s] panel power already on\n",
-		     dp_to_dig_port(intel_dp)->base.base.base.id,
-		     dp_to_dig_port(intel_dp)->base.base.name))
-		return;
-
-	wait_panel_power_cycle(intel_dp);
-
-	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
-	pp = ilk_get_pp_control(intel_dp);
-	if (IS_GEN(dev_priv, 5)) {
-		/* ILK workaround: disable reset around power sequence */
-		pp &= ~PANEL_POWER_RESET;
-		intel_de_write(dev_priv, pp_ctrl_reg, pp);
-		intel_de_posting_read(dev_priv, pp_ctrl_reg);
-	}
-
-	pp |= PANEL_POWER_ON;
-	if (!IS_GEN(dev_priv, 5))
-		pp |= PANEL_POWER_RESET;
-
-	intel_de_write(dev_priv, pp_ctrl_reg, pp);
-	intel_de_posting_read(dev_priv, pp_ctrl_reg);
-
-	wait_panel_on(intel_dp);
-	intel_dp->last_power_on = jiffies;
-
-	if (IS_GEN(dev_priv, 5)) {
-		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
-		intel_de_write(dev_priv, pp_ctrl_reg, pp);
-		intel_de_posting_read(dev_priv, pp_ctrl_reg);
-	}
-}
-
-void intel_edp_panel_on(struct intel_dp *intel_dp)
-{
-	intel_wakeref_t wakeref;
-
-	if (!intel_dp_is_edp(intel_dp))
-		return;
-
-	with_pps_lock(intel_dp, wakeref)
-		edp_panel_on(intel_dp);
-}
-
-
-static void edp_panel_off(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	u32 pp;
-	i915_reg_t pp_ctrl_reg;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	if (!intel_dp_is_edp(intel_dp))
-		return;
-
-	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power off\n",
-		    dig_port->base.base.base.id, dig_port->base.base.name);
-
-	drm_WARN(&dev_priv->drm, !intel_dp->want_panel_vdd,
-		 "Need [ENCODER:%d:%s] VDD to turn off panel\n",
-		 dig_port->base.base.base.id, dig_port->base.base.name);
-
-	pp = ilk_get_pp_control(intel_dp);
-	/* We need to switch off panel power _and_ force vdd, for otherwise some
-	 * panels get very unhappy and cease to work. */
-	pp &= ~(PANEL_POWER_ON | PANEL_POWER_RESET | EDP_FORCE_VDD |
-		EDP_BLC_ENABLE);
-
-	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
-
-	intel_dp->want_panel_vdd = false;
+	 *
+	 * CPT PCH is quite different, having many bits moved
+	 * to the TRANS_DP_CTL register instead. That
+	 * configuration happens (oddly) in ilk_pch_enable
+	 */
 
-	intel_de_write(dev_priv, pp_ctrl_reg, pp);
-	intel_de_posting_read(dev_priv, pp_ctrl_reg);
+	/* Preserve the BIOS-computed detected bit. This is
+	 * supposed to be read-only.
+	 */
+	intel_dp->DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
 
-	wait_panel_off(intel_dp);
-	intel_dp->panel_power_off_time = ktime_get_boottime();
+	/* Handle DP bits in common between all three register formats */
+	intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
+	intel_dp->DP |= DP_PORT_WIDTH(pipe_config->lane_count);
 
-	/* We got a reference when we enabled the VDD. */
-	intel_display_power_put(dev_priv,
-				intel_aux_power_domain(dig_port),
-				fetch_and_zero(&intel_dp->vdd_wakeref));
-}
+	/* Split out the IBX/CPU vs CPT settings */
 
-void intel_edp_panel_off(struct intel_dp *intel_dp)
-{
-	intel_wakeref_t wakeref;
+	if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) {
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+			intel_dp->DP |= DP_SYNC_HS_HIGH;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+			intel_dp->DP |= DP_SYNC_VS_HIGH;
+		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
 
-	if (!intel_dp_is_edp(intel_dp))
-		return;
+		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+			intel_dp->DP |= DP_ENHANCED_FRAMING;
 
-	with_pps_lock(intel_dp, wakeref)
-		edp_panel_off(intel_dp);
-}
+		intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe);
+	} else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
+		u32 trans_dp;
 
-/* Enable backlight in the panel power control. */
-static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	intel_wakeref_t wakeref;
+		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
 
-	/*
-	 * If we enable the backlight right away following a panel power
-	 * on, we may see slight flicker as the panel syncs with the eDP
-	 * link.  So delay a bit to make sure the image is solid before
-	 * allowing it to appear.
-	 */
-	wait_backlight_on(intel_dp);
+		trans_dp = intel_de_read(dev_priv, TRANS_DP_CTL(crtc->pipe));
+		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+			trans_dp |= TRANS_DP_ENH_FRAMING;
+		else
+			trans_dp &= ~TRANS_DP_ENH_FRAMING;
+		intel_de_write(dev_priv, TRANS_DP_CTL(crtc->pipe), trans_dp);
+	} else {
+		if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
+			intel_dp->DP |= DP_COLOR_RANGE_16_235;
 
-	with_pps_lock(intel_dp, wakeref) {
-		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
-		u32 pp;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
+			intel_dp->DP |= DP_SYNC_HS_HIGH;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
+			intel_dp->DP |= DP_SYNC_VS_HIGH;
+		intel_dp->DP |= DP_LINK_TRAIN_OFF;
 
-		pp = ilk_get_pp_control(intel_dp);
-		pp |= EDP_BLC_ENABLE;
+		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
+			intel_dp->DP |= DP_ENHANCED_FRAMING;
 
-		intel_de_write(dev_priv, pp_ctrl_reg, pp);
-		intel_de_posting_read(dev_priv, pp_ctrl_reg);
+		if (IS_CHERRYVIEW(dev_priv))
+			intel_dp->DP |= DP_PIPE_SEL_CHV(crtc->pipe);
+		else
+			intel_dp->DP |= DP_PIPE_SEL(crtc->pipe);
 	}
 }
 
+
 /* Enable backlight PWM and backlight PP control. */
 void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
 			    const struct drm_connector_state *conn_state)
@@ -3432,30 +2566,6 @@ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
 	_intel_edp_backlight_on(intel_dp);
 }
 
-/* Disable backlight in the panel power control. */
-static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	intel_wakeref_t wakeref;
-
-	if (!intel_dp_is_edp(intel_dp))
-		return;
-
-	with_pps_lock(intel_dp, wakeref) {
-		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
-		u32 pp;
-
-		pp = ilk_get_pp_control(intel_dp);
-		pp &= ~EDP_BLC_ENABLE;
-
-		intel_de_write(dev_priv, pp_ctrl_reg, pp);
-		intel_de_posting_read(dev_priv, pp_ctrl_reg);
-	}
-
-	intel_dp->last_backlight_off = jiffies;
-	edp_wait_backlight_off(intel_dp);
-}
-
 /* Disable backlight PP control and backlight PWM. */
 void intel_edp_backlight_off(const struct drm_connector_state *old_conn_state)
 {
@@ -3471,33 +2581,6 @@ void intel_edp_backlight_off(const struct drm_connector_state *old_conn_state)
 	intel_panel_disable_backlight(old_conn_state);
 }
 
-/*
- * Hook for controlling the panel power control backlight through the bl_power
- * sysfs attribute. Take care to handle multiple calls.
- */
-static void intel_edp_backlight_power(struct intel_connector *connector,
-				      bool enable)
-{
-	struct drm_i915_private *i915 = to_i915(connector->base.dev);
-	struct intel_dp *intel_dp = intel_attached_dp(connector);
-	intel_wakeref_t wakeref;
-	bool is_enabled;
-
-	is_enabled = false;
-	with_pps_lock(intel_dp, wakeref)
-		is_enabled = ilk_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
-	if (is_enabled == enable)
-		return;
-
-	drm_dbg_kms(&i915->drm, "panel power control backlight %s\n",
-		    enable ? "enable" : "disable");
-
-	if (enable)
-		_intel_edp_backlight_on(intel_dp);
-	else
-		_intel_edp_backlight_off(intel_dp);
-}
-
 static void assert_dp_port(struct intel_dp *intel_dp, bool state)
 {
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -4498,112 +3581,6 @@ static void g4x_pre_enable_dp(struct intel_atomic_state *state,
 		ilk_edp_pll_on(intel_dp, pipe_config);
 }
 
-static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
-{
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
-	enum pipe pipe = intel_dp->pps_pipe;
-	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
-
-	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
-
-	if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B))
-		return;
-
-	edp_panel_vdd_off_sync(intel_dp);
-
-	/*
-	 * VLV seems to get confused when multiple power sequencers
-	 * have the same port selected (even if only one has power/vdd
-	 * enabled). The failure manifests as vlv_wait_port_ready() failing
-	 * CHV on the other hand doesn't seem to mind having the same port
-	 * selected in multiple power sequencers, but let's clear the
-	 * port select always when logically disconnecting a power sequencer
-	 * from a port.
-	 */
-	drm_dbg_kms(&dev_priv->drm,
-		    "detaching pipe %c power sequencer from [ENCODER:%d:%s]\n",
-		    pipe_name(pipe), dig_port->base.base.base.id,
-		    dig_port->base.base.name);
-	intel_de_write(dev_priv, pp_on_reg, 0);
-	intel_de_posting_read(dev_priv, pp_on_reg);
-
-	intel_dp->pps_pipe = INVALID_PIPE;
-}
-
-static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
-				      enum pipe pipe)
-{
-	struct intel_encoder *encoder;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	for_each_intel_dp(&dev_priv->drm, encoder) {
-		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-
-		drm_WARN(&dev_priv->drm, intel_dp->active_pipe == pipe,
-			 "stealing pipe %c power sequencer from active [ENCODER:%d:%s]\n",
-			 pipe_name(pipe), encoder->base.base.id,
-			 encoder->base.name);
-
-		if (intel_dp->pps_pipe != pipe)
-			continue;
-
-		drm_dbg_kms(&dev_priv->drm,
-			    "stealing pipe %c power sequencer from [ENCODER:%d:%s]\n",
-			    pipe_name(pipe), encoder->base.base.id,
-			    encoder->base.name);
-
-		/* make sure vdd is off before we steal it */
-		vlv_detach_power_sequencer(intel_dp);
-	}
-}
-
-static void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
-					   const struct intel_crtc_state *crtc_state)
-{
-	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
-	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
-	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
-
-	if (intel_dp->pps_pipe != INVALID_PIPE &&
-	    intel_dp->pps_pipe != crtc->pipe) {
-		/*
-		 * If another power sequencer was being used on this
-		 * port previously make sure to turn off vdd there while
-		 * we still have control of it.
-		 */
-		vlv_detach_power_sequencer(intel_dp);
-	}
-
-	/*
-	 * We may be stealing the power
-	 * sequencer from another port.
-	 */
-	vlv_steal_power_sequencer(dev_priv, crtc->pipe);
-
-	intel_dp->active_pipe = crtc->pipe;
-
-	if (!intel_dp_is_edp(intel_dp))
-		return;
-
-	/* now it's all ours */
-	intel_dp->pps_pipe = crtc->pipe;
-
-	drm_dbg_kms(&dev_priv->drm,
-		    "initializing pipe %c power sequencer for [ENCODER:%d:%s]\n",
-		    pipe_name(intel_dp->pps_pipe), encoder->base.base.id,
-		    encoder->base.name);
-
-	/* init power sequencer on this pipe and port */
-	intel_dp_init_panel_power_sequencer(intel_dp);
-	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
-}
-
 static void vlv_pre_enable_dp(struct intel_atomic_state *state,
 			      struct intel_encoder *encoder,
 			      const struct intel_crtc_state *pipe_config,
@@ -7324,31 +6301,6 @@ void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
 		wait_panel_power_cycle(intel_dp);
 }
 
-static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	if (!edp_have_panel_vdd(intel_dp))
-		return;
-
-	/*
-	 * The VDD bit needs a power domain reference, so if the bit is
-	 * already enabled when we boot or resume, grab this reference and
-	 * schedule a vdd off, so we don't hold on to the reference
-	 * indefinitely.
-	 */
-	drm_dbg_kms(&dev_priv->drm,
-		    "VDD left on by BIOS, adjusting state tracking\n");
-	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
-	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
-							intel_aux_power_domain(dig_port));
-
-	edp_panel_vdd_schedule_off(intel_dp);
-}
-
 static enum pipe vlv_active_pipe(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
@@ -7554,19 +6506,6 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = {
 	.destroy = intel_dp_encoder_destroy,
 };
 
-static bool intel_edp_have_power(struct intel_dp *intel_dp)
-{
-	intel_wakeref_t wakeref;
-	bool have_power = false;
-
-	with_pps_lock(intel_dp, wakeref) {
-		have_power = edp_have_panel_power(intel_dp) &&
-						  edp_have_panel_vdd(intel_dp);
-	}
-
-	return have_power;
-}
-
 enum irqreturn
 intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd)
 {
@@ -7670,277 +6609,6 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 	}
 }
 
-static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
-{
-	intel_dp->panel_power_off_time = ktime_get_boottime();
-	intel_dp->last_power_on = jiffies;
-	intel_dp->last_backlight_off = jiffies;
-}
-
-static void
-intel_pps_readout_hw_state(struct intel_dp *intel_dp, struct edp_power_seq *seq)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	u32 pp_on, pp_off, pp_ctl;
-	struct pps_registers regs;
-
-	intel_pps_get_registers(intel_dp, &regs);
-
-	pp_ctl = ilk_get_pp_control(intel_dp);
-
-	/* Ensure PPS is unlocked */
-	if (!HAS_DDI(dev_priv))
-		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
-
-	pp_on = intel_de_read(dev_priv, regs.pp_on);
-	pp_off = intel_de_read(dev_priv, regs.pp_off);
-
-	/* Pull timing values out of registers */
-	seq->t1_t3 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, pp_on);
-	seq->t8 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, pp_on);
-	seq->t9 = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, pp_off);
-	seq->t10 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, pp_off);
-
-	if (i915_mmio_reg_valid(regs.pp_div)) {
-		u32 pp_div;
-
-		pp_div = intel_de_read(dev_priv, regs.pp_div);
-
-		seq->t11_t12 = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, pp_div) * 1000;
-	} else {
-		seq->t11_t12 = REG_FIELD_GET(BXT_POWER_CYCLE_DELAY_MASK, pp_ctl) * 1000;
-	}
-}
-
-static void
-intel_pps_dump_state(const char *state_name, const struct edp_power_seq *seq)
-{
-	DRM_DEBUG_KMS("%s t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
-		      state_name,
-		      seq->t1_t3, seq->t8, seq->t9, seq->t10, seq->t11_t12);
-}
-
-static void
-intel_pps_verify_state(struct intel_dp *intel_dp)
-{
-	struct edp_power_seq hw;
-	struct edp_power_seq *sw = &intel_dp->pps_delays;
-
-	intel_pps_readout_hw_state(intel_dp, &hw);
-
-	if (hw.t1_t3 != sw->t1_t3 || hw.t8 != sw->t8 || hw.t9 != sw->t9 ||
-	    hw.t10 != sw->t10 || hw.t11_t12 != sw->t11_t12) {
-		DRM_ERROR("PPS state mismatch\n");
-		intel_pps_dump_state("sw", sw);
-		intel_pps_dump_state("hw", &hw);
-	}
-}
-
-static void
-intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct edp_power_seq cur, vbt, spec,
-		*final = &intel_dp->pps_delays;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	/* already initialized? */
-	if (final->t11_t12 != 0)
-		return;
-
-	intel_pps_readout_hw_state(intel_dp, &cur);
-
-	intel_pps_dump_state("cur", &cur);
-
-	vbt = dev_priv->vbt.edp.pps;
-	/* On Toshiba Satellite P50-C-18C system the VBT T12 delay
-	 * of 500ms appears to be too short. Ocassionally the panel
-	 * just fails to power back on. Increasing the delay to 800ms
-	 * seems sufficient to avoid this problem.
-	 */
-	if (dev_priv->quirks & QUIRK_INCREASE_T12_DELAY) {
-		vbt.t11_t12 = max_t(u16, vbt.t11_t12, 1300 * 10);
-		drm_dbg_kms(&dev_priv->drm,
-			    "Increasing T12 panel delay as per the quirk to %d\n",
-			    vbt.t11_t12);
-	}
-	/* T11_T12 delay is special and actually in units of 100ms, but zero
-	 * based in the hw (so we need to add 100 ms). But the sw vbt
-	 * table multiplies it with 1000 to make it in units of 100usec,
-	 * too. */
-	vbt.t11_t12 += 100 * 10;
-
-	/* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
-	 * our hw here, which are all in 100usec. */
-	spec.t1_t3 = 210 * 10;
-	spec.t8 = 50 * 10; /* no limit for t8, use t7 instead */
-	spec.t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */
-	spec.t10 = 500 * 10;
-	/* This one is special and actually in units of 100ms, but zero
-	 * based in the hw (so we need to add 100 ms). But the sw vbt
-	 * table multiplies it with 1000 to make it in units of 100usec,
-	 * too. */
-	spec.t11_t12 = (510 + 100) * 10;
-
-	intel_pps_dump_state("vbt", &vbt);
-
-	/* Use the max of the register settings and vbt. If both are
-	 * unset, fall back to the spec limits. */
-#define assign_final(field)	final->field = (max(cur.field, vbt.field) == 0 ? \
-				       spec.field : \
-				       max(cur.field, vbt.field))
-	assign_final(t1_t3);
-	assign_final(t8);
-	assign_final(t9);
-	assign_final(t10);
-	assign_final(t11_t12);
-#undef assign_final
-
-#define get_delay(field)	(DIV_ROUND_UP(final->field, 10))
-	intel_dp->panel_power_up_delay = get_delay(t1_t3);
-	intel_dp->backlight_on_delay = get_delay(t8);
-	intel_dp->backlight_off_delay = get_delay(t9);
-	intel_dp->panel_power_down_delay = get_delay(t10);
-	intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
-#undef get_delay
-
-	drm_dbg_kms(&dev_priv->drm,
-		    "panel power up delay %d, power down delay %d, power cycle delay %d\n",
-		    intel_dp->panel_power_up_delay,
-		    intel_dp->panel_power_down_delay,
-		    intel_dp->panel_power_cycle_delay);
-
-	drm_dbg_kms(&dev_priv->drm, "backlight on delay %d, off delay %d\n",
-		    intel_dp->backlight_on_delay,
-		    intel_dp->backlight_off_delay);
-
-	/*
-	 * We override the HW backlight delays to 1 because we do manual waits
-	 * on them. For T8, even BSpec recommends doing it. For T9, if we
-	 * don't do this, we'll end up waiting for the backlight off delay
-	 * twice: once when we do the manual sleep, and once when we disable
-	 * the panel and wait for the PP_STATUS bit to become zero.
-	 */
-	final->t8 = 1;
-	final->t9 = 1;
-
-	/*
-	 * HW has only a 100msec granularity for t11_t12 so round it up
-	 * accordingly.
-	 */
-	final->t11_t12 = roundup(final->t11_t12, 100 * 10);
-}
-
-static void
-intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
-					      bool force_disable_vdd)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	u32 pp_on, pp_off, port_sel = 0;
-	int div = RUNTIME_INFO(dev_priv)->rawclk_freq / 1000;
-	struct pps_registers regs;
-	enum port port = dp_to_dig_port(intel_dp)->base.port;
-	const struct edp_power_seq *seq = &intel_dp->pps_delays;
-
-	lockdep_assert_held(&dev_priv->pps_mutex);
-
-	intel_pps_get_registers(intel_dp, &regs);
-
-	/*
-	 * On some VLV machines the BIOS can leave the VDD
-	 * enabled even on power sequencers which aren't
-	 * hooked up to any port. This would mess up the
-	 * power domain tracking the first time we pick
-	 * one of these power sequencers for use since
-	 * edp_panel_vdd_on() would notice that the VDD was
-	 * already on and therefore wouldn't grab the power
-	 * domain reference. Disable VDD first to avoid this.
-	 * This also avoids spuriously turning the VDD on as
-	 * soon as the new power sequencer gets initialized.
-	 */
-	if (force_disable_vdd) {
-		u32 pp = ilk_get_pp_control(intel_dp);
-
-		drm_WARN(&dev_priv->drm, pp & PANEL_POWER_ON,
-			 "Panel power already on\n");
-
-		if (pp & EDP_FORCE_VDD)
-			drm_dbg_kms(&dev_priv->drm,
-				    "VDD already on, disabling first\n");
-
-		pp &= ~EDP_FORCE_VDD;
-
-		intel_de_write(dev_priv, regs.pp_ctrl, pp);
-	}
-
-	pp_on = REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, seq->t1_t3) |
-		REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, seq->t8);
-	pp_off = REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, seq->t9) |
-		REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, seq->t10);
-
-	/* Haswell doesn't have any port selection bits for the panel
-	 * power sequencer any more. */
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		port_sel = PANEL_PORT_SELECT_VLV(port);
-	} else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
-		switch (port) {
-		case PORT_A:
-			port_sel = PANEL_PORT_SELECT_DPA;
-			break;
-		case PORT_C:
-			port_sel = PANEL_PORT_SELECT_DPC;
-			break;
-		case PORT_D:
-			port_sel = PANEL_PORT_SELECT_DPD;
-			break;
-		default:
-			MISSING_CASE(port);
-			break;
-		}
-	}
-
-	pp_on |= port_sel;
-
-	intel_de_write(dev_priv, regs.pp_on, pp_on);
-	intel_de_write(dev_priv, regs.pp_off, pp_off);
-
-	/*
-	 * Compute the divisor for the pp clock, simply match the Bspec formula.
-	 */
-	if (i915_mmio_reg_valid(regs.pp_div)) {
-		intel_de_write(dev_priv, regs.pp_div,
-			       REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, (100 * div) / 2 - 1) | REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000)));
-	} else {
-		u32 pp_ctl;
-
-		pp_ctl = intel_de_read(dev_priv, regs.pp_ctrl);
-		pp_ctl &= ~BXT_POWER_CYCLE_DELAY_MASK;
-		pp_ctl |= REG_FIELD_PREP(BXT_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000));
-		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
-	}
-
-	drm_dbg_kms(&dev_priv->drm,
-		    "panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
-		    intel_de_read(dev_priv, regs.pp_on),
-		    intel_de_read(dev_priv, regs.pp_off),
-		    i915_mmio_reg_valid(regs.pp_div) ?
-		    intel_de_read(dev_priv, regs.pp_div) :
-		    (intel_de_read(dev_priv, regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK));
-}
-
-static void intel_dp_pps_init(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		vlv_initial_power_sequencer_setup(intel_dp);
-	} else {
-		intel_dp_init_panel_power_sequencer(intel_dp);
-		intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
-	}
-}
-
 /**
  * intel_dp_set_drrs_state - program registers for RR switch to take effect
  * @dev_priv: i915 device
diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
index 4280a09fd8fd..d07bcdee9639 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.h
+++ b/drivers/gpu/drm/i915/display/intel_dp.h
@@ -70,15 +70,11 @@ enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *dig_port,
 void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
 			    const struct drm_connector_state *conn_state);
 void intel_edp_backlight_off(const struct drm_connector_state *conn_state);
-void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
-void intel_edp_panel_on(struct intel_dp *intel_dp);
-void intel_edp_panel_off(struct intel_dp *intel_dp);
 void intel_dp_mst_suspend(struct drm_i915_private *dev_priv);
 void intel_dp_mst_resume(struct drm_i915_private *dev_priv);
 int intel_dp_max_link_rate(struct intel_dp *intel_dp);
 int intel_dp_max_lane_count(struct intel_dp *intel_dp);
 int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
-void intel_power_sequencer_reset(struct drm_i915_private *dev_priv);
 u32 intel_dp_pack_aux(const u8 *src, int src_bytes);
 
 void intel_edp_drrs_enable(struct intel_dp *intel_dp,
@@ -144,6 +140,7 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
 				    struct intel_crtc_state *crtc_state);
 void intel_dp_sync_state(struct intel_encoder *encoder,
 			 const struct intel_crtc_state *crtc_state);
+const struct dpll *vlv_get_dpll(struct drm_i915_private *i915);
 
 void intel_dp_check_frl_training(struct intel_dp *intel_dp);
 void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp,
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
new file mode 100644
index 000000000000..83bd83b3e3c4
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -0,0 +1,1334 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "intel_display_types.h"
+#include "intel_dp.h"
+#include "intel_pps.h"
+
+static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
+				      enum pipe pipe);
+static void
+intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp);
+static void
+intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
+					      bool force_disable_vdd);
+
+intel_wakeref_t pps_lock(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	intel_wakeref_t wakeref;
+
+	/*
+	 * See intel_power_sequencer_reset() why we need
+	 * a power domain reference here.
+	 */
+	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
+	mutex_lock(&dev_priv->pps_mutex);
+
+	return wakeref;
+}
+
+intel_wakeref_t pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+	mutex_unlock(&dev_priv->pps_mutex);
+	intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
+
+	return 0;
+}
+
+static void
+vlv_power_sequencer_kick(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum pipe pipe = intel_dp->pps_pipe;
+	bool pll_enabled, release_cl_override = false;
+	enum dpio_phy phy = DPIO_PHY(pipe);
+	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
+	u32 DP;
+
+	if (drm_WARN(&dev_priv->drm,
+		     intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN,
+		     "skipping pipe %c power sequencer kick due to [ENCODER:%d:%s] being active\n",
+		     pipe_name(pipe), dig_port->base.base.base.id,
+		     dig_port->base.base.name))
+		return;
+
+	drm_dbg_kms(&dev_priv->drm,
+		    "kicking pipe %c power sequencer for [ENCODER:%d:%s]\n",
+		    pipe_name(pipe), dig_port->base.base.base.id,
+		    dig_port->base.base.name);
+
+	/* Preserve the BIOS-computed detected bit. This is
+	 * supposed to be read-only.
+	 */
+	DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
+	DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
+	DP |= DP_PORT_WIDTH(1);
+	DP |= DP_LINK_TRAIN_PAT_1;
+
+	if (IS_CHERRYVIEW(dev_priv))
+		DP |= DP_PIPE_SEL_CHV(pipe);
+	else
+		DP |= DP_PIPE_SEL(pipe);
+
+	pll_enabled = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE;
+
+	/*
+	 * The DPLL for the pipe must be enabled for this to work.
+	 * So enable temporarily it if it's not already enabled.
+	 */
+	if (!pll_enabled) {
+		release_cl_override = IS_CHERRYVIEW(dev_priv) &&
+			!chv_phy_powergate_ch(dev_priv, phy, ch, true);
+
+		if (vlv_force_pll_on(dev_priv, pipe, vlv_get_dpll(dev_priv))) {
+			drm_err(&dev_priv->drm,
+				"Failed to force on pll for pipe %c!\n",
+				pipe_name(pipe));
+			return;
+		}
+	}
+
+	/*
+	 * Similar magic as in intel_dp_enable_port().
+	 * We _must_ do this port enable + disable trick
+	 * to make this power sequencer lock onto the port.
+	 * Otherwise even VDD force bit won't work.
+	 */
+	intel_de_write(dev_priv, intel_dp->output_reg, DP);
+	intel_de_posting_read(dev_priv, intel_dp->output_reg);
+
+	intel_de_write(dev_priv, intel_dp->output_reg, DP | DP_PORT_EN);
+	intel_de_posting_read(dev_priv, intel_dp->output_reg);
+
+	intel_de_write(dev_priv, intel_dp->output_reg, DP & ~DP_PORT_EN);
+	intel_de_posting_read(dev_priv, intel_dp->output_reg);
+
+	if (!pll_enabled) {
+		vlv_force_pll_off(dev_priv, pipe);
+
+		if (release_cl_override)
+			chv_phy_powergate_ch(dev_priv, phy, ch, false);
+	}
+}
+
+static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv)
+{
+	struct intel_encoder *encoder;
+	unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
+
+	/*
+	 * We don't have power sequencer currently.
+	 * Pick one that's not used by other ports.
+	 */
+	for_each_intel_dp(&dev_priv->drm, encoder) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		if (encoder->type == INTEL_OUTPUT_EDP) {
+			drm_WARN_ON(&dev_priv->drm,
+				    intel_dp->active_pipe != INVALID_PIPE &&
+				    intel_dp->active_pipe !=
+				    intel_dp->pps_pipe);
+
+			if (intel_dp->pps_pipe != INVALID_PIPE)
+				pipes &= ~(1 << intel_dp->pps_pipe);
+		} else {
+			drm_WARN_ON(&dev_priv->drm,
+				    intel_dp->pps_pipe != INVALID_PIPE);
+
+			if (intel_dp->active_pipe != INVALID_PIPE)
+				pipes &= ~(1 << intel_dp->active_pipe);
+		}
+	}
+
+	if (pipes == 0)
+		return INVALID_PIPE;
+
+	return ffs(pipes) - 1;
+}
+
+static enum pipe
+vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum pipe pipe;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	/* We should never land here with regular DP ports */
+	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
+
+	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE &&
+		    intel_dp->active_pipe != intel_dp->pps_pipe);
+
+	if (intel_dp->pps_pipe != INVALID_PIPE)
+		return intel_dp->pps_pipe;
+
+	pipe = vlv_find_free_pps(dev_priv);
+
+	/*
+	 * Didn't find one. This should not happen since there
+	 * are two power sequencers and up to two eDP ports.
+	 */
+	if (drm_WARN_ON(&dev_priv->drm, pipe == INVALID_PIPE))
+		pipe = PIPE_A;
+
+	vlv_steal_power_sequencer(dev_priv, pipe);
+	intel_dp->pps_pipe = pipe;
+
+	drm_dbg_kms(&dev_priv->drm,
+		    "picked pipe %c power sequencer for [ENCODER:%d:%s]\n",
+		    pipe_name(intel_dp->pps_pipe),
+		    dig_port->base.base.base.id,
+		    dig_port->base.base.name);
+
+	/* init power sequencer on this pipe and port */
+	intel_dp_init_panel_power_sequencer(intel_dp);
+	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
+
+	/*
+	 * Even vdd force doesn't work until we've made
+	 * the power sequencer lock in on the port.
+	 */
+	vlv_power_sequencer_kick(intel_dp);
+
+	return intel_dp->pps_pipe;
+}
+
+static int
+bxt_power_sequencer_idx(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	int backlight_controller = dev_priv->vbt.backlight.controller;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	/* We should never land here with regular DP ports */
+	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
+
+	if (!intel_dp->pps_reset)
+		return backlight_controller;
+
+	intel_dp->pps_reset = false;
+
+	/*
+	 * Only the HW needs to be reprogrammed, the SW state is fixed and
+	 * has been setup during connector init.
+	 */
+	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
+
+	return backlight_controller;
+}
+
+typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
+			       enum pipe pipe);
+
+static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
+			       enum pipe pipe)
+{
+	return intel_de_read(dev_priv, PP_STATUS(pipe)) & PP_ON;
+}
+
+static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
+				enum pipe pipe)
+{
+	return intel_de_read(dev_priv, PP_CONTROL(pipe)) & EDP_FORCE_VDD;
+}
+
+static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
+			 enum pipe pipe)
+{
+	return true;
+}
+
+static enum pipe
+vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
+		     enum port port,
+		     vlv_pipe_check pipe_check)
+{
+	enum pipe pipe;
+
+	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
+		u32 port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(pipe)) &
+			PANEL_PORT_SELECT_MASK;
+
+		if (port_sel != PANEL_PORT_SELECT_VLV(port))
+			continue;
+
+		if (!pipe_check(dev_priv, pipe))
+			continue;
+
+		return pipe;
+	}
+
+	return INVALID_PIPE;
+}
+
+static void
+vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum port port = dig_port->base.port;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	/* try to find a pipe with this port selected */
+	/* first pick one where the panel is on */
+	intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+						  vlv_pipe_has_pp_on);
+	/* didn't find one? pick one where vdd is on */
+	if (intel_dp->pps_pipe == INVALID_PIPE)
+		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+							  vlv_pipe_has_vdd_on);
+	/* didn't find one? pick one with just the correct port */
+	if (intel_dp->pps_pipe == INVALID_PIPE)
+		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+							  vlv_pipe_any);
+
+	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
+	if (intel_dp->pps_pipe == INVALID_PIPE) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "no initial power sequencer for [ENCODER:%d:%s]\n",
+			    dig_port->base.base.base.id,
+			    dig_port->base.base.name);
+		return;
+	}
+
+	drm_dbg_kms(&dev_priv->drm,
+		    "initial power sequencer for [ENCODER:%d:%s]: pipe %c\n",
+		    dig_port->base.base.base.id,
+		    dig_port->base.base.name,
+		    pipe_name(intel_dp->pps_pipe));
+
+	intel_dp_init_panel_power_sequencer(intel_dp);
+	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
+}
+
+void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
+{
+	struct intel_encoder *encoder;
+
+	if (drm_WARN_ON(&dev_priv->drm,
+			!(IS_VALLEYVIEW(dev_priv) ||
+			  IS_CHERRYVIEW(dev_priv) ||
+			  IS_GEN9_LP(dev_priv))))
+		return;
+
+	/*
+	 * We can't grab pps_mutex here due to deadlock with power_domain
+	 * mutex when power_domain functions are called while holding pps_mutex.
+	 * That also means that in order to use pps_pipe the code needs to
+	 * hold both a power domain reference and pps_mutex, and the power domain
+	 * reference get/put must be done while _not_ holding pps_mutex.
+	 * pps_{lock,unlock}() do these steps in the correct order, so one
+	 * should use them always.
+	 */
+
+	for_each_intel_dp(&dev_priv->drm, encoder) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		drm_WARN_ON(&dev_priv->drm,
+			    intel_dp->active_pipe != INVALID_PIPE);
+
+		if (encoder->type != INTEL_OUTPUT_EDP)
+			continue;
+
+		if (IS_GEN9_LP(dev_priv))
+			intel_dp->pps_reset = true;
+		else
+			intel_dp->pps_pipe = INVALID_PIPE;
+	}
+}
+
+struct pps_registers {
+	i915_reg_t pp_ctrl;
+	i915_reg_t pp_stat;
+	i915_reg_t pp_on;
+	i915_reg_t pp_off;
+	i915_reg_t pp_div;
+};
+
+static void intel_pps_get_registers(struct intel_dp *intel_dp,
+				    struct pps_registers *regs)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	int pps_idx = 0;
+
+	memset(regs, 0, sizeof(*regs));
+
+	if (IS_GEN9_LP(dev_priv))
+		pps_idx = bxt_power_sequencer_idx(intel_dp);
+	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		pps_idx = vlv_power_sequencer_pipe(intel_dp);
+
+	regs->pp_ctrl = PP_CONTROL(pps_idx);
+	regs->pp_stat = PP_STATUS(pps_idx);
+	regs->pp_on = PP_ON_DELAYS(pps_idx);
+	regs->pp_off = PP_OFF_DELAYS(pps_idx);
+
+	/* Cycle delay moved from PP_DIVISOR to PP_CONTROL */
+	if (IS_GEN9_LP(dev_priv) || INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
+		regs->pp_div = INVALID_MMIO_REG;
+	else
+		regs->pp_div = PP_DIVISOR(pps_idx);
+}
+
+static i915_reg_t
+_pp_ctrl_reg(struct intel_dp *intel_dp)
+{
+	struct pps_registers regs;
+
+	intel_pps_get_registers(intel_dp, &regs);
+
+	return regs.pp_ctrl;
+}
+
+static i915_reg_t
+_pp_stat_reg(struct intel_dp *intel_dp)
+{
+	struct pps_registers regs;
+
+	intel_pps_get_registers(intel_dp, &regs);
+
+	return regs.pp_stat;
+}
+
+static bool edp_have_panel_power(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+	    intel_dp->pps_pipe == INVALID_PIPE)
+		return false;
+
+	return (intel_de_read(dev_priv, _pp_stat_reg(intel_dp)) & PP_ON) != 0;
+}
+
+static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
+	    intel_dp->pps_pipe == INVALID_PIPE)
+		return false;
+
+	return intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
+}
+
+void intel_dp_check_edp(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) {
+		drm_WARN(&dev_priv->drm, 1,
+			 "eDP powered off while attempting aux channel communication.\n");
+		drm_dbg_kms(&dev_priv->drm, "Status 0x%08x Control 0x%08x\n",
+			    intel_de_read(dev_priv, _pp_stat_reg(intel_dp)),
+			    intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)));
+	}
+}
+
+#define IDLE_ON_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
+#define IDLE_ON_VALUE   	(PP_ON | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
+
+#define IDLE_OFF_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | 0)
+#define IDLE_OFF_VALUE		(0     | PP_SEQUENCE_NONE | 0                     | 0)
+
+#define IDLE_CYCLE_MASK		(PP_ON | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
+#define IDLE_CYCLE_VALUE	(0     | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
+
+static void intel_pps_verify_state(struct intel_dp *intel_dp);
+
+static void wait_panel_status(struct intel_dp *intel_dp,
+				       u32 mask,
+				       u32 value)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	i915_reg_t pp_stat_reg, pp_ctrl_reg;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	intel_pps_verify_state(intel_dp);
+
+	pp_stat_reg = _pp_stat_reg(intel_dp);
+	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+
+	drm_dbg_kms(&dev_priv->drm,
+		    "mask %08x value %08x status %08x control %08x\n",
+		    mask, value,
+		    intel_de_read(dev_priv, pp_stat_reg),
+		    intel_de_read(dev_priv, pp_ctrl_reg));
+
+	if (intel_de_wait_for_register(dev_priv, pp_stat_reg,
+				       mask, value, 5000))
+		drm_err(&dev_priv->drm,
+			"Panel status timeout: status %08x control %08x\n",
+			intel_de_read(dev_priv, pp_stat_reg),
+			intel_de_read(dev_priv, pp_ctrl_reg));
+
+	drm_dbg_kms(&dev_priv->drm, "Wait complete\n");
+}
+
+static void wait_panel_on(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+	drm_dbg_kms(&i915->drm, "Wait for panel power on\n");
+	wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
+}
+
+static void wait_panel_off(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+
+	drm_dbg_kms(&i915->drm, "Wait for panel power off time\n");
+	wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
+}
+
+void wait_panel_power_cycle(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	ktime_t panel_power_on_time;
+	s64 panel_power_off_duration;
+
+	drm_dbg_kms(&i915->drm, "Wait for panel power cycle\n");
+
+	/* take the difference of currrent time and panel power off time
+	 * and then make panel wait for t11_t12 if needed. */
+	panel_power_on_time = ktime_get_boottime();
+	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->panel_power_off_time);
+
+	/* When we disable the VDD override bit last we have to do the manual
+	 * wait. */
+	if (panel_power_off_duration < (s64)intel_dp->panel_power_cycle_delay)
+		wait_remaining_ms_from_jiffies(jiffies,
+				       intel_dp->panel_power_cycle_delay - panel_power_off_duration);
+
+	wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
+}
+
+static void wait_backlight_on(struct intel_dp *intel_dp)
+{
+	wait_remaining_ms_from_jiffies(intel_dp->last_power_on,
+				       intel_dp->backlight_on_delay);
+}
+
+static void edp_wait_backlight_off(struct intel_dp *intel_dp)
+{
+	wait_remaining_ms_from_jiffies(intel_dp->last_backlight_off,
+				       intel_dp->backlight_off_delay);
+}
+
+/* Read the current pp_control value, unlocking the register if it
+ * is locked
+ */
+
+static  u32 ilk_get_pp_control(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	u32 control;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	control = intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp));
+	if (drm_WARN_ON(&dev_priv->drm, !HAS_DDI(dev_priv) &&
+			(control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
+		control &= ~PANEL_UNLOCK_MASK;
+		control |= PANEL_UNLOCK_REGS;
+	}
+	return control;
+}
+
+/*
+ * Must be paired with edp_panel_vdd_off().
+ * Must hold pps_mutex around the whole on/off sequence.
+ * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
+ */
+bool edp_panel_vdd_on(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	u32 pp;
+	i915_reg_t pp_stat_reg, pp_ctrl_reg;
+	bool need_to_disable = !intel_dp->want_panel_vdd;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	if (!intel_dp_is_edp(intel_dp))
+		return false;
+
+	cancel_delayed_work(&intel_dp->panel_vdd_work);
+	intel_dp->want_panel_vdd = true;
+
+	if (edp_have_panel_vdd(intel_dp))
+		return need_to_disable;
+
+	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
+	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
+							intel_aux_power_domain(dig_port));
+
+	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n",
+		    dig_port->base.base.base.id,
+		    dig_port->base.base.name);
+
+	if (!edp_have_panel_power(intel_dp))
+		wait_panel_power_cycle(intel_dp);
+
+	pp = ilk_get_pp_control(intel_dp);
+	pp |= EDP_FORCE_VDD;
+
+	pp_stat_reg = _pp_stat_reg(intel_dp);
+	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+
+	intel_de_write(dev_priv, pp_ctrl_reg, pp);
+	intel_de_posting_read(dev_priv, pp_ctrl_reg);
+	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
+		    intel_de_read(dev_priv, pp_stat_reg),
+		    intel_de_read(dev_priv, pp_ctrl_reg));
+	/*
+	 * If the panel wasn't on, delay before accessing aux channel
+	 */
+	if (!edp_have_panel_power(intel_dp)) {
+		drm_dbg_kms(&dev_priv->drm,
+			    "[ENCODER:%d:%s] panel power wasn't enabled\n",
+			    dig_port->base.base.base.id,
+			    dig_port->base.base.name);
+		msleep(intel_dp->panel_power_up_delay);
+	}
+
+	return need_to_disable;
+}
+
+/*
+ * Must be paired with intel_edp_panel_vdd_off() or
+ * intel_edp_panel_off().
+ * Nested calls to these functions are not allowed since
+ * we drop the lock. Caller must use some higher level
+ * locking to prevent nested calls from other threads.
+ */
+void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
+{
+	intel_wakeref_t wakeref;
+	bool vdd;
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	vdd = false;
+	with_pps_lock(intel_dp, wakeref)
+		vdd = edp_panel_vdd_on(intel_dp);
+	I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n",
+			dp_to_dig_port(intel_dp)->base.base.base.id,
+			dp_to_dig_port(intel_dp)->base.base.name);
+}
+
+void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port =
+		dp_to_dig_port(intel_dp);
+	u32 pp;
+	i915_reg_t pp_stat_reg, pp_ctrl_reg;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	drm_WARN_ON(&dev_priv->drm, intel_dp->want_panel_vdd);
+
+	if (!edp_have_panel_vdd(intel_dp))
+		return;
+
+	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD off\n",
+		    dig_port->base.base.base.id,
+		    dig_port->base.base.name);
+
+	pp = ilk_get_pp_control(intel_dp);
+	pp &= ~EDP_FORCE_VDD;
+
+	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+	pp_stat_reg = _pp_stat_reg(intel_dp);
+
+	intel_de_write(dev_priv, pp_ctrl_reg, pp);
+	intel_de_posting_read(dev_priv, pp_ctrl_reg);
+
+	/* Make sure sequencer is idle before allowing subsequent activity */
+	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
+		    intel_de_read(dev_priv, pp_stat_reg),
+		    intel_de_read(dev_priv, pp_ctrl_reg));
+
+	if ((pp & PANEL_POWER_ON) == 0)
+		intel_dp->panel_power_off_time = ktime_get_boottime();
+
+	intel_display_power_put(dev_priv,
+				intel_aux_power_domain(dig_port),
+				fetch_and_zero(&intel_dp->vdd_wakeref));
+}
+
+void edp_panel_vdd_work(struct work_struct *__work)
+{
+	struct intel_dp *intel_dp =
+		container_of(to_delayed_work(__work),
+			     struct intel_dp, panel_vdd_work);
+	intel_wakeref_t wakeref;
+
+	with_pps_lock(intel_dp, wakeref) {
+		if (!intel_dp->want_panel_vdd)
+			edp_panel_vdd_off_sync(intel_dp);
+	}
+}
+
+static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
+{
+	unsigned long delay;
+
+	/*
+	 * Queue the timer to fire a long time from now (relative to the power
+	 * down delay) to keep the panel power up across a sequence of
+	 * operations.
+	 */
+	delay = msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5);
+	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
+}
+
+/*
+ * Must be paired with edp_panel_vdd_on().
+ * Must hold pps_mutex around the whole on/off sequence.
+ * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
+ */
+void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	I915_STATE_WARN(!intel_dp->want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on",
+			dp_to_dig_port(intel_dp)->base.base.base.id,
+			dp_to_dig_port(intel_dp)->base.base.name);
+
+	intel_dp->want_panel_vdd = false;
+
+	if (sync)
+		edp_panel_vdd_off_sync(intel_dp);
+	else
+		edp_panel_vdd_schedule_off(intel_dp);
+}
+
+void edp_panel_on(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	u32 pp;
+	i915_reg_t pp_ctrl_reg;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power on\n",
+		    dp_to_dig_port(intel_dp)->base.base.base.id,
+		    dp_to_dig_port(intel_dp)->base.base.name);
+
+	if (drm_WARN(&dev_priv->drm, edp_have_panel_power(intel_dp),
+		     "[ENCODER:%d:%s] panel power already on\n",
+		     dp_to_dig_port(intel_dp)->base.base.base.id,
+		     dp_to_dig_port(intel_dp)->base.base.name))
+		return;
+
+	wait_panel_power_cycle(intel_dp);
+
+	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+	pp = ilk_get_pp_control(intel_dp);
+	if (IS_GEN(dev_priv, 5)) {
+		/* ILK workaround: disable reset around power sequence */
+		pp &= ~PANEL_POWER_RESET;
+		intel_de_write(dev_priv, pp_ctrl_reg, pp);
+		intel_de_posting_read(dev_priv, pp_ctrl_reg);
+	}
+
+	pp |= PANEL_POWER_ON;
+	if (!IS_GEN(dev_priv, 5))
+		pp |= PANEL_POWER_RESET;
+
+	intel_de_write(dev_priv, pp_ctrl_reg, pp);
+	intel_de_posting_read(dev_priv, pp_ctrl_reg);
+
+	wait_panel_on(intel_dp);
+	intel_dp->last_power_on = jiffies;
+
+	if (IS_GEN(dev_priv, 5)) {
+		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
+		intel_de_write(dev_priv, pp_ctrl_reg, pp);
+		intel_de_posting_read(dev_priv, pp_ctrl_reg);
+	}
+}
+
+void intel_edp_panel_on(struct intel_dp *intel_dp)
+{
+	intel_wakeref_t wakeref;
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	with_pps_lock(intel_dp, wakeref)
+		edp_panel_on(intel_dp);
+}
+
+void edp_panel_off(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	u32 pp;
+	i915_reg_t pp_ctrl_reg;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power off\n",
+		    dig_port->base.base.base.id, dig_port->base.base.name);
+
+	drm_WARN(&dev_priv->drm, !intel_dp->want_panel_vdd,
+		 "Need [ENCODER:%d:%s] VDD to turn off panel\n",
+		 dig_port->base.base.base.id, dig_port->base.base.name);
+
+	pp = ilk_get_pp_control(intel_dp);
+	/* We need to switch off panel power _and_ force vdd, for otherwise some
+	 * panels get very unhappy and cease to work. */
+	pp &= ~(PANEL_POWER_ON | PANEL_POWER_RESET | EDP_FORCE_VDD |
+		EDP_BLC_ENABLE);
+
+	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+
+	intel_dp->want_panel_vdd = false;
+
+	intel_de_write(dev_priv, pp_ctrl_reg, pp);
+	intel_de_posting_read(dev_priv, pp_ctrl_reg);
+
+	wait_panel_off(intel_dp);
+	intel_dp->panel_power_off_time = ktime_get_boottime();
+
+	/* We got a reference when we enabled the VDD. */
+	intel_display_power_put(dev_priv,
+				intel_aux_power_domain(dig_port),
+				fetch_and_zero(&intel_dp->vdd_wakeref));
+}
+
+void intel_edp_panel_off(struct intel_dp *intel_dp)
+{
+	intel_wakeref_t wakeref;
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	with_pps_lock(intel_dp, wakeref)
+		edp_panel_off(intel_dp);
+}
+
+/* Enable backlight in the panel power control. */
+void _intel_edp_backlight_on(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	intel_wakeref_t wakeref;
+
+	/*
+	 * If we enable the backlight right away following a panel power
+	 * on, we may see slight flicker as the panel syncs with the eDP
+	 * link.  So delay a bit to make sure the image is solid before
+	 * allowing it to appear.
+	 */
+	wait_backlight_on(intel_dp);
+
+	with_pps_lock(intel_dp, wakeref) {
+		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+		u32 pp;
+
+		pp = ilk_get_pp_control(intel_dp);
+		pp |= EDP_BLC_ENABLE;
+
+		intel_de_write(dev_priv, pp_ctrl_reg, pp);
+		intel_de_posting_read(dev_priv, pp_ctrl_reg);
+	}
+}
+
+/* Disable backlight in the panel power control. */
+void _intel_edp_backlight_off(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	intel_wakeref_t wakeref;
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	with_pps_lock(intel_dp, wakeref) {
+		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
+		u32 pp;
+
+		pp = ilk_get_pp_control(intel_dp);
+		pp &= ~EDP_BLC_ENABLE;
+
+		intel_de_write(dev_priv, pp_ctrl_reg, pp);
+		intel_de_posting_read(dev_priv, pp_ctrl_reg);
+	}
+
+	intel_dp->last_backlight_off = jiffies;
+	edp_wait_backlight_off(intel_dp);
+}
+
+/*
+ * Hook for controlling the panel power control backlight through the bl_power
+ * sysfs attribute. Take care to handle multiple calls.
+ */
+void intel_edp_backlight_power(struct intel_connector *connector, bool enable)
+{
+	struct drm_i915_private *i915 = to_i915(connector->base.dev);
+	struct intel_dp *intel_dp = intel_attached_dp(connector);
+	intel_wakeref_t wakeref;
+	bool is_enabled;
+
+	is_enabled = false;
+	with_pps_lock(intel_dp, wakeref)
+		is_enabled = ilk_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
+	if (is_enabled == enable)
+		return;
+
+	drm_dbg_kms(&i915->drm, "panel power control backlight %s\n",
+		    enable ? "enable" : "disable");
+
+	if (enable)
+		_intel_edp_backlight_on(intel_dp);
+	else
+		_intel_edp_backlight_off(intel_dp);
+}
+
+static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
+	enum pipe pipe = intel_dp->pps_pipe;
+	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
+
+	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
+
+	if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B))
+		return;
+
+	edp_panel_vdd_off_sync(intel_dp);
+
+	/*
+	 * VLV seems to get confused when multiple power sequencers
+	 * have the same port selected (even if only one has power/vdd
+	 * enabled). The failure manifests as vlv_wait_port_ready() failing
+	 * CHV on the other hand doesn't seem to mind having the same port
+	 * selected in multiple power sequencers, but let's clear the
+	 * port select always when logically disconnecting a power sequencer
+	 * from a port.
+	 */
+	drm_dbg_kms(&dev_priv->drm,
+		    "detaching pipe %c power sequencer from [ENCODER:%d:%s]\n",
+		    pipe_name(pipe), dig_port->base.base.base.id,
+		    dig_port->base.base.name);
+	intel_de_write(dev_priv, pp_on_reg, 0);
+	intel_de_posting_read(dev_priv, pp_on_reg);
+
+	intel_dp->pps_pipe = INVALID_PIPE;
+}
+
+static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
+				      enum pipe pipe)
+{
+	struct intel_encoder *encoder;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	for_each_intel_dp(&dev_priv->drm, encoder) {
+		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+
+		drm_WARN(&dev_priv->drm, intel_dp->active_pipe == pipe,
+			 "stealing pipe %c power sequencer from active [ENCODER:%d:%s]\n",
+			 pipe_name(pipe), encoder->base.base.id,
+			 encoder->base.name);
+
+		if (intel_dp->pps_pipe != pipe)
+			continue;
+
+		drm_dbg_kms(&dev_priv->drm,
+			    "stealing pipe %c power sequencer from [ENCODER:%d:%s]\n",
+			    pipe_name(pipe), encoder->base.base.id,
+			    encoder->base.name);
+
+		/* make sure vdd is off before we steal it */
+		vlv_detach_power_sequencer(intel_dp);
+	}
+}
+
+void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
+				    const struct intel_crtc_state *crtc_state)
+{
+	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
+
+	if (intel_dp->pps_pipe != INVALID_PIPE &&
+	    intel_dp->pps_pipe != crtc->pipe) {
+		/*
+		 * If another power sequencer was being used on this
+		 * port previously make sure to turn off vdd there while
+		 * we still have control of it.
+		 */
+		vlv_detach_power_sequencer(intel_dp);
+	}
+
+	/*
+	 * We may be stealing the power
+	 * sequencer from another port.
+	 */
+	vlv_steal_power_sequencer(dev_priv, crtc->pipe);
+
+	intel_dp->active_pipe = crtc->pipe;
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	/* now it's all ours */
+	intel_dp->pps_pipe = crtc->pipe;
+
+	drm_dbg_kms(&dev_priv->drm,
+		    "initializing pipe %c power sequencer for [ENCODER:%d:%s]\n",
+		    pipe_name(intel_dp->pps_pipe), encoder->base.base.id,
+		    encoder->base.name);
+
+	/* init power sequencer on this pipe and port */
+	intel_dp_init_panel_power_sequencer(intel_dp);
+	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
+}
+
+void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	if (!edp_have_panel_vdd(intel_dp))
+		return;
+
+	/*
+	 * The VDD bit needs a power domain reference, so if the bit is
+	 * already enabled when we boot or resume, grab this reference and
+	 * schedule a vdd off, so we don't hold on to the reference
+	 * indefinitely.
+	 */
+	drm_dbg_kms(&dev_priv->drm,
+		    "VDD left on by BIOS, adjusting state tracking\n");
+	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
+	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
+							intel_aux_power_domain(dig_port));
+
+	edp_panel_vdd_schedule_off(intel_dp);
+}
+
+bool intel_edp_have_power(struct intel_dp *intel_dp)
+{
+	intel_wakeref_t wakeref;
+	bool have_power = false;
+
+	with_pps_lock(intel_dp, wakeref) {
+		have_power = edp_have_panel_power(intel_dp) &&
+						  edp_have_panel_vdd(intel_dp);
+	}
+
+	return have_power;
+}
+
+void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
+{
+	intel_dp->panel_power_off_time = ktime_get_boottime();
+	intel_dp->last_power_on = jiffies;
+	intel_dp->last_backlight_off = jiffies;
+}
+
+static void
+intel_pps_readout_hw_state(struct intel_dp *intel_dp, struct edp_power_seq *seq)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	u32 pp_on, pp_off, pp_ctl;
+	struct pps_registers regs;
+
+	intel_pps_get_registers(intel_dp, &regs);
+
+	pp_ctl = ilk_get_pp_control(intel_dp);
+
+	/* Ensure PPS is unlocked */
+	if (!HAS_DDI(dev_priv))
+		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
+
+	pp_on = intel_de_read(dev_priv, regs.pp_on);
+	pp_off = intel_de_read(dev_priv, regs.pp_off);
+
+	/* Pull timing values out of registers */
+	seq->t1_t3 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, pp_on);
+	seq->t8 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, pp_on);
+	seq->t9 = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, pp_off);
+	seq->t10 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, pp_off);
+
+	if (i915_mmio_reg_valid(regs.pp_div)) {
+		u32 pp_div;
+
+		pp_div = intel_de_read(dev_priv, regs.pp_div);
+
+		seq->t11_t12 = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, pp_div) * 1000;
+	} else {
+		seq->t11_t12 = REG_FIELD_GET(BXT_POWER_CYCLE_DELAY_MASK, pp_ctl) * 1000;
+	}
+}
+
+static void
+intel_pps_dump_state(const char *state_name, const struct edp_power_seq *seq)
+{
+	DRM_DEBUG_KMS("%s t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
+		      state_name,
+		      seq->t1_t3, seq->t8, seq->t9, seq->t10, seq->t11_t12);
+}
+
+static void
+intel_pps_verify_state(struct intel_dp *intel_dp)
+{
+	struct edp_power_seq hw;
+	struct edp_power_seq *sw = &intel_dp->pps_delays;
+
+	intel_pps_readout_hw_state(intel_dp, &hw);
+
+	if (hw.t1_t3 != sw->t1_t3 || hw.t8 != sw->t8 || hw.t9 != sw->t9 ||
+	    hw.t10 != sw->t10 || hw.t11_t12 != sw->t11_t12) {
+		DRM_ERROR("PPS state mismatch\n");
+		intel_pps_dump_state("sw", sw);
+		intel_pps_dump_state("hw", &hw);
+	}
+}
+
+static void
+intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct edp_power_seq cur, vbt, spec,
+		*final = &intel_dp->pps_delays;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	/* already initialized? */
+	if (final->t11_t12 != 0)
+		return;
+
+	intel_pps_readout_hw_state(intel_dp, &cur);
+
+	intel_pps_dump_state("cur", &cur);
+
+	vbt = dev_priv->vbt.edp.pps;
+	/* On Toshiba Satellite P50-C-18C system the VBT T12 delay
+	 * of 500ms appears to be too short. Ocassionally the panel
+	 * just fails to power back on. Increasing the delay to 800ms
+	 * seems sufficient to avoid this problem.
+	 */
+	if (dev_priv->quirks & QUIRK_INCREASE_T12_DELAY) {
+		vbt.t11_t12 = max_t(u16, vbt.t11_t12, 1300 * 10);
+		drm_dbg_kms(&dev_priv->drm,
+			    "Increasing T12 panel delay as per the quirk to %d\n",
+			    vbt.t11_t12);
+	}
+	/* T11_T12 delay is special and actually in units of 100ms, but zero
+	 * based in the hw (so we need to add 100 ms). But the sw vbt
+	 * table multiplies it with 1000 to make it in units of 100usec,
+	 * too. */
+	vbt.t11_t12 += 100 * 10;
+
+	/* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
+	 * our hw here, which are all in 100usec. */
+	spec.t1_t3 = 210 * 10;
+	spec.t8 = 50 * 10; /* no limit for t8, use t7 instead */
+	spec.t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */
+	spec.t10 = 500 * 10;
+	/* This one is special and actually in units of 100ms, but zero
+	 * based in the hw (so we need to add 100 ms). But the sw vbt
+	 * table multiplies it with 1000 to make it in units of 100usec,
+	 * too. */
+	spec.t11_t12 = (510 + 100) * 10;
+
+	intel_pps_dump_state("vbt", &vbt);
+
+	/* Use the max of the register settings and vbt. If both are
+	 * unset, fall back to the spec limits. */
+#define assign_final(field)	final->field = (max(cur.field, vbt.field) == 0 ? \
+				       spec.field : \
+				       max(cur.field, vbt.field))
+	assign_final(t1_t3);
+	assign_final(t8);
+	assign_final(t9);
+	assign_final(t10);
+	assign_final(t11_t12);
+#undef assign_final
+
+#define get_delay(field)	(DIV_ROUND_UP(final->field, 10))
+	intel_dp->panel_power_up_delay = get_delay(t1_t3);
+	intel_dp->backlight_on_delay = get_delay(t8);
+	intel_dp->backlight_off_delay = get_delay(t9);
+	intel_dp->panel_power_down_delay = get_delay(t10);
+	intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
+#undef get_delay
+
+	drm_dbg_kms(&dev_priv->drm,
+		    "panel power up delay %d, power down delay %d, power cycle delay %d\n",
+		    intel_dp->panel_power_up_delay,
+		    intel_dp->panel_power_down_delay,
+		    intel_dp->panel_power_cycle_delay);
+
+	drm_dbg_kms(&dev_priv->drm, "backlight on delay %d, off delay %d\n",
+		    intel_dp->backlight_on_delay,
+		    intel_dp->backlight_off_delay);
+
+	/*
+	 * We override the HW backlight delays to 1 because we do manual waits
+	 * on them. For T8, even BSpec recommends doing it. For T9, if we
+	 * don't do this, we'll end up waiting for the backlight off delay
+	 * twice: once when we do the manual sleep, and once when we disable
+	 * the panel and wait for the PP_STATUS bit to become zero.
+	 */
+	final->t8 = 1;
+	final->t9 = 1;
+
+	/*
+	 * HW has only a 100msec granularity for t11_t12 so round it up
+	 * accordingly.
+	 */
+	final->t11_t12 = roundup(final->t11_t12, 100 * 10);
+}
+
+static void
+intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
+					      bool force_disable_vdd)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	u32 pp_on, pp_off, port_sel = 0;
+	int div = RUNTIME_INFO(dev_priv)->rawclk_freq / 1000;
+	struct pps_registers regs;
+	enum port port = dp_to_dig_port(intel_dp)->base.port;
+	const struct edp_power_seq *seq = &intel_dp->pps_delays;
+
+	lockdep_assert_held(&dev_priv->pps_mutex);
+
+	intel_pps_get_registers(intel_dp, &regs);
+
+	/*
+	 * On some VLV machines the BIOS can leave the VDD
+	 * enabled even on power sequencers which aren't
+	 * hooked up to any port. This would mess up the
+	 * power domain tracking the first time we pick
+	 * one of these power sequencers for use since
+	 * edp_panel_vdd_on() would notice that the VDD was
+	 * already on and therefore wouldn't grab the power
+	 * domain reference. Disable VDD first to avoid this.
+	 * This also avoids spuriously turning the VDD on as
+	 * soon as the new power sequencer gets initialized.
+	 */
+	if (force_disable_vdd) {
+		u32 pp = ilk_get_pp_control(intel_dp);
+
+		drm_WARN(&dev_priv->drm, pp & PANEL_POWER_ON,
+			 "Panel power already on\n");
+
+		if (pp & EDP_FORCE_VDD)
+			drm_dbg_kms(&dev_priv->drm,
+				    "VDD already on, disabling first\n");
+
+		pp &= ~EDP_FORCE_VDD;
+
+		intel_de_write(dev_priv, regs.pp_ctrl, pp);
+	}
+
+	pp_on = REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, seq->t1_t3) |
+		REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, seq->t8);
+	pp_off = REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, seq->t9) |
+		REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, seq->t10);
+
+	/* Haswell doesn't have any port selection bits for the panel
+	 * power sequencer any more. */
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+		port_sel = PANEL_PORT_SELECT_VLV(port);
+	} else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
+		switch (port) {
+		case PORT_A:
+			port_sel = PANEL_PORT_SELECT_DPA;
+			break;
+		case PORT_C:
+			port_sel = PANEL_PORT_SELECT_DPC;
+			break;
+		case PORT_D:
+			port_sel = PANEL_PORT_SELECT_DPD;
+			break;
+		default:
+			MISSING_CASE(port);
+			break;
+		}
+	}
+
+	pp_on |= port_sel;
+
+	intel_de_write(dev_priv, regs.pp_on, pp_on);
+	intel_de_write(dev_priv, regs.pp_off, pp_off);
+
+	/*
+	 * Compute the divisor for the pp clock, simply match the Bspec formula.
+	 */
+	if (i915_mmio_reg_valid(regs.pp_div)) {
+		intel_de_write(dev_priv, regs.pp_div,
+			       REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, (100 * div) / 2 - 1) | REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000)));
+	} else {
+		u32 pp_ctl;
+
+		pp_ctl = intel_de_read(dev_priv, regs.pp_ctrl);
+		pp_ctl &= ~BXT_POWER_CYCLE_DELAY_MASK;
+		pp_ctl |= REG_FIELD_PREP(BXT_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000));
+		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
+	}
+
+	drm_dbg_kms(&dev_priv->drm,
+		    "panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
+		    intel_de_read(dev_priv, regs.pp_on),
+		    intel_de_read(dev_priv, regs.pp_off),
+		    i915_mmio_reg_valid(regs.pp_div) ?
+		    intel_de_read(dev_priv, regs.pp_div) :
+		    (intel_de_read(dev_priv, regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK));
+}
+
+void intel_dp_pps_init(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+		vlv_initial_power_sequencer_setup(intel_dp);
+	} else {
+		intel_dp_init_panel_power_sequencer(intel_dp);
+		intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
+	}
+}
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
new file mode 100644
index 000000000000..76d5cc565501
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef __INTEL_PPS_H__
+#define __INTEL_PPS_H__
+
+#include <linux/types.h>
+
+#include "intel_wakeref.h"
+
+struct drm_i915_private;
+struct intel_connector;
+struct intel_crtc_state;
+struct intel_dp;
+struct intel_encoder;
+
+intel_wakeref_t pps_lock(struct intel_dp *intel_dp);
+intel_wakeref_t pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref);
+
+#define with_pps_lock(dp, wf)						\
+	for ((wf) = pps_lock(dp); (wf); (wf) = pps_unlock((dp), (wf)))
+
+void intel_dp_check_edp(struct intel_dp *intel_dp);
+void _intel_edp_backlight_on(struct intel_dp *intel_dp);
+void _intel_edp_backlight_off(struct intel_dp *intel_dp);
+void intel_edp_backlight_power(struct intel_connector *connector, bool enable);
+
+bool edp_panel_vdd_on(struct intel_dp *intel_dp);
+void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
+void edp_panel_vdd_off_sync(struct intel_dp *intel_dp);
+void edp_panel_on(struct intel_dp *intel_dp);
+void edp_panel_off(struct intel_dp *intel_dp);
+void edp_panel_vdd_work(struct work_struct *__work);
+
+void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
+void intel_edp_panel_on(struct intel_dp *intel_dp);
+void intel_edp_panel_off(struct intel_dp *intel_dp);
+bool intel_edp_have_power(struct intel_dp *intel_dp);
+
+void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp);
+
+void wait_panel_power_cycle(struct intel_dp *intel_dp);
+
+void intel_dp_pps_init(struct intel_dp *intel_dp);
+void intel_power_sequencer_reset(struct drm_i915_private *i915);
+void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp);
+
+void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
+				    const struct intel_crtc_state *crtc_state);
+
+#endif /* __INTEL_PPS_H__ */
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 02/17] drm/i915/pps: rename pps_{, un}lock -> intel_pps_{, un}lock
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 01/17] drm/i915/pps: abstract panel power sequencer from intel_dp.c Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 03/17] drm/i915/pps: rename intel_edp_backlight_* to intel_pps_backlight_* Jani Nikula
                   ` (18 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Start following the usual naming pattern for functions. No functional
changes.

Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c  | 20 ++++++++++----------
 drivers/gpu/drm/i915/display/intel_pps.c | 21 +++++++++++----------
 drivers/gpu/drm/i915/display/intel_pps.h |  8 ++++----
 3 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 07279b10812e..6e9b114171be 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1053,7 +1053,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
 	aux_domain = intel_aux_power_domain(dig_port);
 
 	aux_wakeref = intel_display_power_get(i915, aux_domain);
-	pps_wakeref = pps_lock(intel_dp);
+	pps_wakeref = intel_pps_lock(intel_dp);
 
 	/*
 	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
@@ -1205,7 +1205,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
 	if (vdd)
 		edp_panel_vdd_off(intel_dp, false);
 
-	pps_unlock(intel_dp, pps_wakeref);
+	intel_pps_unlock(intel_dp, pps_wakeref);
 	intel_display_power_put_async(i915, aux_domain, aux_wakeref);
 
 	if (is_tc_port)
@@ -3514,7 +3514,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
 	if (drm_WARN_ON(&dev_priv->drm, dp_reg & DP_PORT_EN))
 		return;
 
-	with_pps_lock(intel_dp, wakeref) {
+	with_intel_pps_lock(intel_dp, wakeref) {
 		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 			vlv_init_panel_power_sequencer(encoder, pipe_config);
 
@@ -4082,7 +4082,7 @@ intel_dp_link_down(struct intel_encoder *encoder,
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		intel_wakeref_t wakeref;
 
-		with_pps_lock(intel_dp, wakeref)
+		with_intel_pps_lock(intel_dp, wakeref)
 			intel_dp->active_pipe = INVALID_PIPE;
 	}
 }
@@ -6257,7 +6257,7 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder)
 		 * vdd might still be enabled do to the delayed vdd off.
 		 * Make sure vdd is actually turned off here.
 		 */
-		with_pps_lock(intel_dp, wakeref)
+		with_intel_pps_lock(intel_dp, wakeref)
 			edp_panel_vdd_off_sync(intel_dp);
 	}
 
@@ -6285,7 +6285,7 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 	 * Make sure vdd is actually turned off here.
 	 */
 	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-	with_pps_lock(intel_dp, wakeref)
+	with_intel_pps_lock(intel_dp, wakeref)
 		edp_panel_vdd_off_sync(intel_dp);
 }
 
@@ -6297,7 +6297,7 @@ void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
 	if (!intel_dp_is_edp(intel_dp))
 		return;
 
-	with_pps_lock(intel_dp, wakeref)
+	with_intel_pps_lock(intel_dp, wakeref)
 		wait_panel_power_cycle(intel_dp);
 }
 
@@ -6329,7 +6329,7 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
 	    !intel_dp_is_edp(intel_dp))
 		return;
 
-	with_pps_lock(intel_dp, wakeref) {
+	with_intel_pps_lock(intel_dp, wakeref) {
 		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
 			intel_dp->active_pipe = vlv_active_pipe(intel_dp);
 
@@ -7068,7 +7068,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 		return false;
 	}
 
-	with_pps_lock(intel_dp, wakeref) {
+	with_intel_pps_lock(intel_dp, wakeref) {
 		intel_dp_init_panel_power_timestamps(intel_dp);
 		intel_dp_pps_init(intel_dp);
 		intel_edp_panel_vdd_sanitize(intel_dp);
@@ -7145,7 +7145,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	 * vdd might still be enabled do to the delayed vdd off.
 	 * Make sure vdd is actually turned off here.
 	 */
-	with_pps_lock(intel_dp, wakeref)
+	with_intel_pps_lock(intel_dp, wakeref)
 		edp_panel_vdd_off_sync(intel_dp);
 
 	return false;
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 83bd83b3e3c4..1a05f2c7f690 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -16,7 +16,7 @@ static void
 intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
 					      bool force_disable_vdd);
 
-intel_wakeref_t pps_lock(struct intel_dp *intel_dp)
+intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	intel_wakeref_t wakeref;
@@ -31,7 +31,8 @@ intel_wakeref_t pps_lock(struct intel_dp *intel_dp)
 	return wakeref;
 }
 
-intel_wakeref_t pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref)
+intel_wakeref_t intel_pps_unlock(struct intel_dp *intel_dp,
+				 intel_wakeref_t wakeref)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
@@ -630,7 +631,7 @@ void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
 		return;
 
 	vdd = false;
-	with_pps_lock(intel_dp, wakeref)
+	with_intel_pps_lock(intel_dp, wakeref)
 		vdd = edp_panel_vdd_on(intel_dp);
 	I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n",
 			dp_to_dig_port(intel_dp)->base.base.base.id,
@@ -685,7 +686,7 @@ void edp_panel_vdd_work(struct work_struct *__work)
 			     struct intel_dp, panel_vdd_work);
 	intel_wakeref_t wakeref;
 
-	with_pps_lock(intel_dp, wakeref) {
+	with_intel_pps_lock(intel_dp, wakeref) {
 		if (!intel_dp->want_panel_vdd)
 			edp_panel_vdd_off_sync(intel_dp);
 	}
@@ -786,7 +787,7 @@ void intel_edp_panel_on(struct intel_dp *intel_dp)
 	if (!intel_dp_is_edp(intel_dp))
 		return;
 
-	with_pps_lock(intel_dp, wakeref)
+	with_intel_pps_lock(intel_dp, wakeref)
 		edp_panel_on(intel_dp);
 }
 
@@ -838,7 +839,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 	if (!intel_dp_is_edp(intel_dp))
 		return;
 
-	with_pps_lock(intel_dp, wakeref)
+	with_intel_pps_lock(intel_dp, wakeref)
 		edp_panel_off(intel_dp);
 }
 
@@ -856,7 +857,7 @@ void _intel_edp_backlight_on(struct intel_dp *intel_dp)
 	 */
 	wait_backlight_on(intel_dp);
 
-	with_pps_lock(intel_dp, wakeref) {
+	with_intel_pps_lock(intel_dp, wakeref) {
 		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 		u32 pp;
 
@@ -877,7 +878,7 @@ void _intel_edp_backlight_off(struct intel_dp *intel_dp)
 	if (!intel_dp_is_edp(intel_dp))
 		return;
 
-	with_pps_lock(intel_dp, wakeref) {
+	with_intel_pps_lock(intel_dp, wakeref) {
 		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 		u32 pp;
 
@@ -904,7 +905,7 @@ void intel_edp_backlight_power(struct intel_connector *connector, bool enable)
 	bool is_enabled;
 
 	is_enabled = false;
-	with_pps_lock(intel_dp, wakeref)
+	with_intel_pps_lock(intel_dp, wakeref)
 		is_enabled = ilk_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
 	if (is_enabled == enable)
 		return;
@@ -1054,7 +1055,7 @@ bool intel_edp_have_power(struct intel_dp *intel_dp)
 	intel_wakeref_t wakeref;
 	bool have_power = false;
 
-	with_pps_lock(intel_dp, wakeref) {
+	with_intel_pps_lock(intel_dp, wakeref) {
 		have_power = edp_have_panel_power(intel_dp) &&
 						  edp_have_panel_vdd(intel_dp);
 	}
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index 76d5cc565501..f44e6ce9e8c1 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -16,11 +16,11 @@ struct intel_crtc_state;
 struct intel_dp;
 struct intel_encoder;
 
-intel_wakeref_t pps_lock(struct intel_dp *intel_dp);
-intel_wakeref_t pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref);
+intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp);
+intel_wakeref_t intel_pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref);
 
-#define with_pps_lock(dp, wf)						\
-	for ((wf) = pps_lock(dp); (wf); (wf) = pps_unlock((dp), (wf)))
+#define with_intel_pps_lock(dp, wf)						\
+	for ((wf) = intel_pps_lock(dp); (wf); (wf) = intel_pps_unlock((dp), (wf)))
 
 void intel_dp_check_edp(struct intel_dp *intel_dp);
 void _intel_edp_backlight_on(struct intel_dp *intel_dp);
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 03/17] drm/i915/pps: rename intel_edp_backlight_* to intel_pps_backlight_*
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 01/17] drm/i915/pps: abstract panel power sequencer from intel_dp.c Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 02/17] drm/i915/pps: rename pps_{, un}lock -> intel_pps_{, un}lock Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 04/17] drm/i915/pps: rename intel_edp_panel_* to intel_pps_* Jani Nikula
                   ` (17 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Follow the usual naming pattern for functions. No functional changes.

Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c  |  6 +++---
 drivers/gpu/drm/i915/display/intel_pps.c | 10 +++++-----
 drivers/gpu/drm/i915/display/intel_pps.h |  6 +++---
 3 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 6e9b114171be..421e68bb436f 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -2563,7 +2563,7 @@ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
 	drm_dbg_kms(&i915->drm, "\n");
 
 	intel_panel_enable_backlight(crtc_state, conn_state);
-	_intel_edp_backlight_on(intel_dp);
+	intel_pps_backlight_on(intel_dp);
 }
 
 /* Disable backlight PP control and backlight PWM. */
@@ -2577,7 +2577,7 @@ void intel_edp_backlight_off(const struct drm_connector_state *old_conn_state)
 
 	drm_dbg_kms(&i915->drm, "\n");
 
-	_intel_edp_backlight_off(intel_dp);
+	intel_pps_backlight_off(intel_dp);
 	intel_panel_disable_backlight(old_conn_state);
 }
 
@@ -7128,7 +7128,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	}
 
 	intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode);
-	intel_connector->panel.backlight.power = intel_edp_backlight_power;
+	intel_connector->panel.backlight.power = intel_pps_backlight_power;
 	intel_panel_setup_backlight(connector, pipe);
 
 	if (fixed_mode) {
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 1a05f2c7f690..36d8782d8df1 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -844,7 +844,7 @@ void intel_edp_panel_off(struct intel_dp *intel_dp)
 }
 
 /* Enable backlight in the panel power control. */
-void _intel_edp_backlight_on(struct intel_dp *intel_dp)
+void intel_pps_backlight_on(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	intel_wakeref_t wakeref;
@@ -870,7 +870,7 @@ void _intel_edp_backlight_on(struct intel_dp *intel_dp)
 }
 
 /* Disable backlight in the panel power control. */
-void _intel_edp_backlight_off(struct intel_dp *intel_dp)
+void intel_pps_backlight_off(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	intel_wakeref_t wakeref;
@@ -897,7 +897,7 @@ void _intel_edp_backlight_off(struct intel_dp *intel_dp)
  * Hook for controlling the panel power control backlight through the bl_power
  * sysfs attribute. Take care to handle multiple calls.
  */
-void intel_edp_backlight_power(struct intel_connector *connector, bool enable)
+void intel_pps_backlight_power(struct intel_connector *connector, bool enable)
 {
 	struct drm_i915_private *i915 = to_i915(connector->base.dev);
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
@@ -914,9 +914,9 @@ void intel_edp_backlight_power(struct intel_connector *connector, bool enable)
 		    enable ? "enable" : "disable");
 
 	if (enable)
-		_intel_edp_backlight_on(intel_dp);
+		intel_pps_backlight_on(intel_dp);
 	else
-		_intel_edp_backlight_off(intel_dp);
+		intel_pps_backlight_off(intel_dp);
 }
 
 static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index f44e6ce9e8c1..81e4e9fc3cf5 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -23,9 +23,9 @@ intel_wakeref_t intel_pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wake
 	for ((wf) = intel_pps_lock(dp); (wf); (wf) = intel_pps_unlock((dp), (wf)))
 
 void intel_dp_check_edp(struct intel_dp *intel_dp);
-void _intel_edp_backlight_on(struct intel_dp *intel_dp);
-void _intel_edp_backlight_off(struct intel_dp *intel_dp);
-void intel_edp_backlight_power(struct intel_connector *connector, bool enable);
+void intel_pps_backlight_on(struct intel_dp *intel_dp);
+void intel_pps_backlight_off(struct intel_dp *intel_dp);
+void intel_pps_backlight_power(struct intel_connector *connector, bool enable);
 
 bool edp_panel_vdd_on(struct intel_dp *intel_dp);
 void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 04/17] drm/i915/pps: rename intel_edp_panel_* to intel_pps_*
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (2 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 03/17] drm/i915/pps: rename intel_edp_backlight_* to intel_pps_backlight_* Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-13 10:39   ` Anshuman Gupta
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 05/17] drm/i915/pps: rename edp_panel_* to intel_pps_*_unlocked Jani Nikula
                   ` (16 subsequent siblings)
  20 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Follow the usual naming pattern for functions. We don't need to repeat
"panel" here. No functional changes.

v2: Fix comment (Anshuman)

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_ddi.c |  8 ++++----
 drivers/gpu/drm/i915/display/intel_dp.c  | 10 +++++-----
 drivers/gpu/drm/i915/display/intel_pps.c | 17 ++++++++---------
 drivers/gpu/drm/i915/display/intel_pps.h | 11 +++++------
 4 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
index f09a597bf730..243ab635aa34 100644
--- a/drivers/gpu/drm/i915/display/intel_ddi.c
+++ b/drivers/gpu/drm/i915/display/intel_ddi.c
@@ -3592,7 +3592,7 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
 	 */
 
 	/* 2. Enable Panel Power if PPS is required */
-	intel_edp_panel_on(intel_dp);
+	intel_pps_on(intel_dp);
 
 	/*
 	 * 3. For non-TBT Type-C ports, set FIA lane count
@@ -3735,7 +3735,7 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
 				 crtc_state->port_clock,
 				 crtc_state->lane_count);
 
-	intel_edp_panel_on(intel_dp);
+	intel_pps_on(intel_dp);
 
 	intel_ddi_clk_select(encoder, crtc_state);
 
@@ -3977,8 +3977,8 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
 	if (INTEL_GEN(dev_priv) >= 12)
 		intel_ddi_disable_pipe_clock(old_crtc_state);
 
-	intel_edp_panel_vdd_on(intel_dp);
-	intel_edp_panel_off(intel_dp);
+	intel_pps_vdd_on(intel_dp);
+	intel_pps_off(intel_dp);
 
 	if (!intel_phy_is_tc(dev_priv, phy) ||
 	    dig_port->tc_mode != TC_PORT_TBT_ALT)
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 421e68bb436f..eac674ad91c8 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -3001,10 +3001,10 @@ static void intel_disable_dp(struct intel_atomic_state *state,
 
 	/* Make sure the panel is off before trying to change the mode. But also
 	 * ensure that we have vdd while we switch off the panel. */
-	intel_edp_panel_vdd_on(intel_dp);
+	intel_pps_vdd_on(intel_dp);
 	intel_edp_backlight_off(old_conn_state);
 	intel_dp_set_power(intel_dp, DP_SET_POWER_D3);
-	intel_edp_panel_off(intel_dp);
+	intel_pps_off(intel_dp);
 	intel_dp->frl.is_trained = false;
 	intel_dp->frl.trained_rate_gbps = 0;
 }
@@ -6339,7 +6339,7 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
 			 * something nasty with it.
 			 */
 			intel_dp_pps_init(intel_dp);
-			intel_edp_panel_vdd_sanitize(intel_dp);
+			intel_pps_vdd_sanitize(intel_dp);
 		}
 	}
 }
@@ -6513,7 +6513,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd)
 	struct intel_dp *intel_dp = &dig_port->dp;
 
 	if (dig_port->base.type == INTEL_OUTPUT_EDP &&
-	    (long_hpd || !intel_edp_have_power(intel_dp))) {
+	    (long_hpd || !intel_pps_have_power(intel_dp))) {
 		/*
 		 * vdd off can generate a long/short pulse on eDP which
 		 * would require vdd on to handle it, and thus we
@@ -7071,7 +7071,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	with_intel_pps_lock(intel_dp, wakeref) {
 		intel_dp_init_panel_power_timestamps(intel_dp);
 		intel_dp_pps_init(intel_dp);
-		intel_edp_panel_vdd_sanitize(intel_dp);
+		intel_pps_vdd_sanitize(intel_dp);
 	}
 
 	/* Cache DPCD and EDID for edp. */
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 36d8782d8df1..59215cfd7d97 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -558,7 +558,7 @@ static  u32 ilk_get_pp_control(struct intel_dp *intel_dp)
 /*
  * Must be paired with edp_panel_vdd_off().
  * Must hold pps_mutex around the whole on/off sequence.
- * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
+ * Can be nested with intel_pps_vdd_{on,off}() calls.
  */
 bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 {
@@ -616,13 +616,12 @@ bool edp_panel_vdd_on(struct intel_dp *intel_dp)
 }
 
 /*
- * Must be paired with intel_edp_panel_vdd_off() or
- * intel_edp_panel_off().
+ * Must be paired with intel_pps_off().
  * Nested calls to these functions are not allowed since
  * we drop the lock. Caller must use some higher level
  * locking to prevent nested calls from other threads.
  */
-void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
+void intel_pps_vdd_on(struct intel_dp *intel_dp)
 {
 	intel_wakeref_t wakeref;
 	bool vdd;
@@ -708,7 +707,7 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
 /*
  * Must be paired with edp_panel_vdd_on().
  * Must hold pps_mutex around the whole on/off sequence.
- * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
+ * Can be nested with intel_pps_vdd_{on,off}() calls.
  */
 void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 {
@@ -780,7 +779,7 @@ void edp_panel_on(struct intel_dp *intel_dp)
 	}
 }
 
-void intel_edp_panel_on(struct intel_dp *intel_dp)
+void intel_pps_on(struct intel_dp *intel_dp)
 {
 	intel_wakeref_t wakeref;
 
@@ -832,7 +831,7 @@ void edp_panel_off(struct intel_dp *intel_dp)
 				fetch_and_zero(&intel_dp->vdd_wakeref));
 }
 
-void intel_edp_panel_off(struct intel_dp *intel_dp)
+void intel_pps_off(struct intel_dp *intel_dp)
 {
 	intel_wakeref_t wakeref;
 
@@ -1025,7 +1024,7 @@ void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
 	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
 }
 
-void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
+void intel_pps_vdd_sanitize(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -1050,7 +1049,7 @@ void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
 	edp_panel_vdd_schedule_off(intel_dp);
 }
 
-bool intel_edp_have_power(struct intel_dp *intel_dp)
+bool intel_pps_have_power(struct intel_dp *intel_dp)
 {
 	intel_wakeref_t wakeref;
 	bool have_power = false;
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index 81e4e9fc3cf5..69f670678d0e 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -34,12 +34,11 @@ void edp_panel_on(struct intel_dp *intel_dp);
 void edp_panel_off(struct intel_dp *intel_dp);
 void edp_panel_vdd_work(struct work_struct *__work);
 
-void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
-void intel_edp_panel_on(struct intel_dp *intel_dp);
-void intel_edp_panel_off(struct intel_dp *intel_dp);
-bool intel_edp_have_power(struct intel_dp *intel_dp);
-
-void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp);
+void intel_pps_vdd_sanitize(struct intel_dp *intel_dp);
+void intel_pps_vdd_on(struct intel_dp *intel_dp);
+void intel_pps_on(struct intel_dp *intel_dp);
+void intel_pps_off(struct intel_dp *intel_dp);
+bool intel_pps_have_power(struct intel_dp *intel_dp);
 
 void wait_panel_power_cycle(struct intel_dp *intel_dp);
 
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 05/17] drm/i915/pps: rename edp_panel_* to intel_pps_*_unlocked
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (3 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 04/17] drm/i915/pps: rename intel_edp_panel_* to intel_pps_* Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-13 10:41   ` Anshuman Gupta
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 06/17] drm/i915/pps: abstract intel_pps_vdd_off_sync Jani Nikula
                   ` (15 subsequent siblings)
  20 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Follow the usual naming pattern for functions, both for the prefix and
the _unlocked suffix for functions that expect the lock to be held when
calling. No functional changes.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c  | 16 +++++++--------
 drivers/gpu/drm/i915/display/intel_pps.c | 26 ++++++++++++------------
 drivers/gpu/drm/i915/display/intel_pps.h | 10 ++++-----
 3 files changed, 26 insertions(+), 26 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index eac674ad91c8..1384f1d3a9cf 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1061,7 +1061,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
 	 * to turn it off. But for eg. i2c-dev access we need to turn it on/off
 	 * ourselves.
 	 */
-	vdd = edp_panel_vdd_on(intel_dp);
+	vdd = intel_pps_vdd_on_unlocked(intel_dp);
 
 	/* dp aux is extremely sensitive to irq latency, hence request the
 	 * lowest possible wakeup latency and so prevent the cpu from going into
@@ -1203,7 +1203,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
 	cpu_latency_qos_update_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
 
 	if (vdd)
-		edp_panel_vdd_off(intel_dp, false);
+		intel_pps_vdd_off_unlocked(intel_dp, false);
 
 	intel_pps_unlock(intel_dp, pps_wakeref);
 	intel_display_power_put_async(i915, aux_domain, aux_wakeref);
@@ -3520,9 +3520,9 @@ static void intel_enable_dp(struct intel_atomic_state *state,
 
 		intel_dp_enable_port(intel_dp, pipe_config);
 
-		edp_panel_vdd_on(intel_dp);
-		edp_panel_on(intel_dp);
-		edp_panel_vdd_off(intel_dp, true);
+		intel_pps_vdd_on_unlocked(intel_dp);
+		intel_pps_on_unlocked(intel_dp);
+		intel_pps_vdd_off_unlocked(intel_dp, true);
 	}
 
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
@@ -6258,7 +6258,7 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder)
 		 * Make sure vdd is actually turned off here.
 		 */
 		with_intel_pps_lock(intel_dp, wakeref)
-			edp_panel_vdd_off_sync(intel_dp);
+			intel_pps_vdd_off_sync_unlocked(intel_dp);
 	}
 
 	intel_dp_aux_fini(intel_dp);
@@ -6286,7 +6286,7 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 	 */
 	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
 	with_intel_pps_lock(intel_dp, wakeref)
-		edp_panel_vdd_off_sync(intel_dp);
+		intel_pps_vdd_off_sync_unlocked(intel_dp);
 }
 
 void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
@@ -7146,7 +7146,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	 * Make sure vdd is actually turned off here.
 	 */
 	with_intel_pps_lock(intel_dp, wakeref)
-		edp_panel_vdd_off_sync(intel_dp);
+		intel_pps_vdd_off_sync_unlocked(intel_dp);
 
 	return false;
 }
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 59215cfd7d97..fd3677948800 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -556,11 +556,11 @@ static  u32 ilk_get_pp_control(struct intel_dp *intel_dp)
 }
 
 /*
- * Must be paired with edp_panel_vdd_off().
+ * Must be paired with intel_pps_vdd_off_unlocked().
  * Must hold pps_mutex around the whole on/off sequence.
  * Can be nested with intel_pps_vdd_{on,off}() calls.
  */
-bool edp_panel_vdd_on(struct intel_dp *intel_dp)
+bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -631,13 +631,13 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp)
 
 	vdd = false;
 	with_intel_pps_lock(intel_dp, wakeref)
-		vdd = edp_panel_vdd_on(intel_dp);
+		vdd = intel_pps_vdd_on_unlocked(intel_dp);
 	I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n",
 			dp_to_dig_port(intel_dp)->base.base.base.id,
 			dp_to_dig_port(intel_dp)->base.base.name);
 }
 
-void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
+void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_digital_port *dig_port =
@@ -687,7 +687,7 @@ void edp_panel_vdd_work(struct work_struct *__work)
 
 	with_intel_pps_lock(intel_dp, wakeref) {
 		if (!intel_dp->want_panel_vdd)
-			edp_panel_vdd_off_sync(intel_dp);
+			intel_pps_vdd_off_sync_unlocked(intel_dp);
 	}
 }
 
@@ -709,7 +709,7 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
  * Must hold pps_mutex around the whole on/off sequence.
  * Can be nested with intel_pps_vdd_{on,off}() calls.
  */
-void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
+void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
@@ -725,12 +725,12 @@ void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
 	intel_dp->want_panel_vdd = false;
 
 	if (sync)
-		edp_panel_vdd_off_sync(intel_dp);
+		intel_pps_vdd_off_sync_unlocked(intel_dp);
 	else
 		edp_panel_vdd_schedule_off(intel_dp);
 }
 
-void edp_panel_on(struct intel_dp *intel_dp)
+void intel_pps_on_unlocked(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	u32 pp;
@@ -787,10 +787,10 @@ void intel_pps_on(struct intel_dp *intel_dp)
 		return;
 
 	with_intel_pps_lock(intel_dp, wakeref)
-		edp_panel_on(intel_dp);
+		intel_pps_on_unlocked(intel_dp);
 }
 
-void edp_panel_off(struct intel_dp *intel_dp)
+void intel_pps_off_unlocked(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -839,7 +839,7 @@ void intel_pps_off(struct intel_dp *intel_dp)
 		return;
 
 	with_intel_pps_lock(intel_dp, wakeref)
-		edp_panel_off(intel_dp);
+		intel_pps_off_unlocked(intel_dp);
 }
 
 /* Enable backlight in the panel power control. */
@@ -930,7 +930,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
 	if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B))
 		return;
 
-	edp_panel_vdd_off_sync(intel_dp);
+	intel_pps_vdd_off_sync_unlocked(intel_dp);
 
 	/*
 	 * VLV seems to get confused when multiple power sequencers
@@ -1245,7 +1245,7 @@ intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
 	 * hooked up to any port. This would mess up the
 	 * power domain tracking the first time we pick
 	 * one of these power sequencers for use since
-	 * edp_panel_vdd_on() would notice that the VDD was
+	 * intel_pps_vdd_on_unlocked() would notice that the VDD was
 	 * already on and therefore wouldn't grab the power
 	 * domain reference. Disable VDD first to avoid this.
 	 * This also avoids spuriously turning the VDD on as
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index 69f670678d0e..e7f0473be9a7 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -27,11 +27,11 @@ void intel_pps_backlight_on(struct intel_dp *intel_dp);
 void intel_pps_backlight_off(struct intel_dp *intel_dp);
 void intel_pps_backlight_power(struct intel_connector *connector, bool enable);
 
-bool edp_panel_vdd_on(struct intel_dp *intel_dp);
-void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
-void edp_panel_vdd_off_sync(struct intel_dp *intel_dp);
-void edp_panel_on(struct intel_dp *intel_dp);
-void edp_panel_off(struct intel_dp *intel_dp);
+bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp);
+void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync);
+void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp);
+void intel_pps_on_unlocked(struct intel_dp *intel_dp);
+void intel_pps_off_unlocked(struct intel_dp *intel_dp);
 void edp_panel_vdd_work(struct work_struct *__work);
 
 void intel_pps_vdd_sanitize(struct intel_dp *intel_dp);
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 06/17] drm/i915/pps: abstract intel_pps_vdd_off_sync
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (4 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 05/17] drm/i915/pps: rename edp_panel_* to intel_pps_*_unlocked Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-13 10:42   ` Anshuman Gupta
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 07/17] drm/i915/pps: add higher level intel_pps_init() call Jani Nikula
                   ` (14 subsequent siblings)
  20 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Add a locked version of intel_pps_vdd_off_sync_unlocked() that does
everything the callers expect it to. No functional changes.

v2: Fix typo (Anshuman)

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c  | 31 +++---------------------
 drivers/gpu/drm/i915/display/intel_pps.c | 18 +++++++++++++-
 drivers/gpu/drm/i915/display/intel_pps.h |  2 +-
 3 files changed, 21 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 1384f1d3a9cf..bff5e735a92e 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6249,17 +6249,8 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder)
 	struct intel_dp *intel_dp = &dig_port->dp;
 
 	intel_dp_mst_encoder_cleanup(dig_port);
-	if (intel_dp_is_edp(intel_dp)) {
-		intel_wakeref_t wakeref;
 
-		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-		/*
-		 * vdd might still be enabled do to the delayed vdd off.
-		 * Make sure vdd is actually turned off here.
-		 */
-		with_intel_pps_lock(intel_dp, wakeref)
-			intel_pps_vdd_off_sync_unlocked(intel_dp);
-	}
+	intel_pps_vdd_off_sync(intel_dp);
 
 	intel_dp_aux_fini(intel_dp);
 }
@@ -6275,18 +6266,8 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
 void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
-	intel_wakeref_t wakeref;
-
-	if (!intel_dp_is_edp(intel_dp))
-		return;
 
-	/*
-	 * vdd might still be enabled do to the delayed vdd off.
-	 * Make sure vdd is actually turned off here.
-	 */
-	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-	with_intel_pps_lock(intel_dp, wakeref)
-		intel_pps_vdd_off_sync_unlocked(intel_dp);
+	intel_pps_vdd_off_sync(intel_dp);
 }
 
 void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
@@ -7140,13 +7121,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	return true;
 
 out_vdd_off:
-	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
-	/*
-	 * vdd might still be enabled do to the delayed vdd off.
-	 * Make sure vdd is actually turned off here.
-	 */
-	with_intel_pps_lock(intel_dp, wakeref)
-		intel_pps_vdd_off_sync_unlocked(intel_dp);
+	intel_pps_vdd_off_sync(intel_dp);
 
 	return false;
 }
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index fd3677948800..b6c07694ae9d 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -637,7 +637,7 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp)
 			dp_to_dig_port(intel_dp)->base.base.name);
 }
 
-void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
+static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_digital_port *dig_port =
@@ -678,6 +678,22 @@ void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
 				fetch_and_zero(&intel_dp->vdd_wakeref));
 }
 
+void intel_pps_vdd_off_sync(struct intel_dp *intel_dp)
+{
+	intel_wakeref_t wakeref;
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+	/*
+	 * vdd might still be enabled due to the delayed vdd off.
+	 * Make sure vdd is actually turned off here.
+	 */
+	with_intel_pps_lock(intel_dp, wakeref)
+		intel_pps_vdd_off_sync_unlocked(intel_dp);
+}
+
 void edp_panel_vdd_work(struct work_struct *__work)
 {
 	struct intel_dp *intel_dp =
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index e7f0473be9a7..3cab183658c6 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -29,7 +29,6 @@ void intel_pps_backlight_power(struct intel_connector *connector, bool enable);
 
 bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp);
 void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync);
-void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp);
 void intel_pps_on_unlocked(struct intel_dp *intel_dp);
 void intel_pps_off_unlocked(struct intel_dp *intel_dp);
 void edp_panel_vdd_work(struct work_struct *__work);
@@ -38,6 +37,7 @@ void intel_pps_vdd_sanitize(struct intel_dp *intel_dp);
 void intel_pps_vdd_on(struct intel_dp *intel_dp);
 void intel_pps_on(struct intel_dp *intel_dp);
 void intel_pps_off(struct intel_dp *intel_dp);
+void intel_pps_vdd_off_sync(struct intel_dp *intel_dp);
 bool intel_pps_have_power(struct intel_dp *intel_dp);
 
 void wait_panel_power_cycle(struct intel_dp *intel_dp);
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 07/17] drm/i915/pps: add higher level intel_pps_init() call
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (5 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 06/17] drm/i915/pps: abstract intel_pps_vdd_off_sync Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 08/17] drm/i915/pps: abstract intel_pps_encoder_reset() Jani Nikula
                   ` (13 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Add a new init call to be called only once, unlike some of the other
various init calls. This lets us hide more functions within
intel_pps.c. No functional changes.

Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c  |  9 +--------
 drivers/gpu/drm/i915/display/intel_pps.c | 17 +++++++++++++++--
 drivers/gpu/drm/i915/display/intel_pps.h |  3 +--
 3 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index bff5e735a92e..31c5474f85d6 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -7026,14 +7026,11 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 	struct drm_display_mode *downclock_mode = NULL;
 	bool has_dpcd;
 	enum pipe pipe = INVALID_PIPE;
-	intel_wakeref_t wakeref;
 	struct edid *edid;
 
 	if (!intel_dp_is_edp(intel_dp))
 		return true;
 
-	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work);
-
 	/*
 	 * On IBX/CPT we may get here with LVDS already registered. Since the
 	 * driver uses the only internal power sequencer available for both
@@ -7049,11 +7046,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 		return false;
 	}
 
-	with_intel_pps_lock(intel_dp, wakeref) {
-		intel_dp_init_panel_power_timestamps(intel_dp);
-		intel_dp_pps_init(intel_dp);
-		intel_pps_vdd_sanitize(intel_dp);
-	}
+	intel_pps_init(intel_dp);
 
 	/* Cache DPCD and EDID for edp. */
 	has_dpcd = intel_edp_init_dpcd(intel_dp);
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index b6c07694ae9d..799190fafa4f 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -694,7 +694,7 @@ void intel_pps_vdd_off_sync(struct intel_dp *intel_dp)
 		intel_pps_vdd_off_sync_unlocked(intel_dp);
 }
 
-void edp_panel_vdd_work(struct work_struct *__work)
+static void edp_panel_vdd_work(struct work_struct *__work)
 {
 	struct intel_dp *intel_dp =
 		container_of(to_delayed_work(__work),
@@ -1078,7 +1078,7 @@ bool intel_pps_have_power(struct intel_dp *intel_dp)
 	return have_power;
 }
 
-void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
+static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
 {
 	intel_dp->panel_power_off_time = ktime_get_boottime();
 	intel_dp->last_power_on = jiffies;
@@ -1348,3 +1348,16 @@ void intel_dp_pps_init(struct intel_dp *intel_dp)
 		intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
 	}
 }
+
+void intel_pps_init(struct intel_dp *intel_dp)
+{
+	intel_wakeref_t wakeref;
+
+	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work);
+
+	with_intel_pps_lock(intel_dp, wakeref) {
+		intel_dp_init_panel_power_timestamps(intel_dp);
+		intel_dp_pps_init(intel_dp);
+		intel_pps_vdd_sanitize(intel_dp);
+	}
+}
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index 3cab183658c6..53c0fafd1440 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -31,7 +31,6 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp);
 void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync);
 void intel_pps_on_unlocked(struct intel_dp *intel_dp);
 void intel_pps_off_unlocked(struct intel_dp *intel_dp);
-void edp_panel_vdd_work(struct work_struct *__work);
 
 void intel_pps_vdd_sanitize(struct intel_dp *intel_dp);
 void intel_pps_vdd_on(struct intel_dp *intel_dp);
@@ -42,9 +41,9 @@ bool intel_pps_have_power(struct intel_dp *intel_dp);
 
 void wait_panel_power_cycle(struct intel_dp *intel_dp);
 
+void intel_pps_init(struct intel_dp *intel_dp);
 void intel_dp_pps_init(struct intel_dp *intel_dp);
 void intel_power_sequencer_reset(struct drm_i915_private *i915);
-void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp);
 
 void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
 				    const struct intel_crtc_state *crtc_state);
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 08/17] drm/i915/pps: abstract intel_pps_encoder_reset()
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (6 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 07/17] drm/i915/pps: add higher level intel_pps_init() call Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 09/17] drm/i915/pps: rename intel_dp_check_edp to intel_pps_check_power_unlocked Jani Nikula
                   ` (12 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Add an "encoder reset" call to hide some more pps functions, and clean
up the callers. A minor functional change is not holding the pps lock
across the whole operation in intel_dp_encoder_reset, but instead doing
it in two steps.

v2: rename intel_pps_reinit to intel_pps_encoder_reset for clarity

Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c  | 20 +++++---------------
 drivers/gpu/drm/i915/display/intel_pps.c | 21 +++++++++++++++++++--
 drivers/gpu/drm/i915/display/intel_pps.h |  3 +--
 3 files changed, 25 insertions(+), 19 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 31c5474f85d6..cfaadeaf9f00 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6299,30 +6299,20 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->dev);
 	struct intel_dp *intel_dp = enc_to_intel_dp(to_intel_encoder(encoder));
-	intel_wakeref_t wakeref;
 
 	if (!HAS_DDI(dev_priv))
 		intel_dp->DP = intel_de_read(dev_priv, intel_dp->output_reg);
 
 	intel_dp->reset_link_params = true;
 
-	if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv) &&
-	    !intel_dp_is_edp(intel_dp))
-		return;
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
+		intel_wakeref_t wakeref;
 
-	with_intel_pps_lock(intel_dp, wakeref) {
-		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		with_intel_pps_lock(intel_dp, wakeref)
 			intel_dp->active_pipe = vlv_active_pipe(intel_dp);
-
-		if (intel_dp_is_edp(intel_dp)) {
-			/*
-			 * Reinit the power sequencer, in case BIOS did
-			 * something nasty with it.
-			 */
-			intel_dp_pps_init(intel_dp);
-			intel_pps_vdd_sanitize(intel_dp);
-		}
 	}
+
+	intel_pps_encoder_reset(intel_dp);
 }
 
 static int intel_modeset_tile_group(struct intel_atomic_state *state,
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 799190fafa4f..3b962be4f4c0 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -1040,7 +1040,7 @@ void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
 	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
 }
 
-void intel_pps_vdd_sanitize(struct intel_dp *intel_dp)
+static void intel_pps_vdd_sanitize(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
@@ -1337,7 +1337,7 @@ intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
 		    (intel_de_read(dev_priv, regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK));
 }
 
-void intel_dp_pps_init(struct intel_dp *intel_dp)
+static void intel_dp_pps_init(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
@@ -1349,6 +1349,23 @@ void intel_dp_pps_init(struct intel_dp *intel_dp)
 	}
 }
 
+void intel_pps_encoder_reset(struct intel_dp *intel_dp)
+{
+	intel_wakeref_t wakeref;
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	with_intel_pps_lock(intel_dp, wakeref) {
+		/*
+		 * Reinit the power sequencer, in case BIOS did something nasty
+		 * with it.
+		 */
+		intel_dp_pps_init(intel_dp);
+		intel_pps_vdd_sanitize(intel_dp);
+	}
+}
+
 void intel_pps_init(struct intel_dp *intel_dp)
 {
 	intel_wakeref_t wakeref;
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index 53c0fafd1440..7c3b5ea4f47b 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -32,7 +32,6 @@ void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync);
 void intel_pps_on_unlocked(struct intel_dp *intel_dp);
 void intel_pps_off_unlocked(struct intel_dp *intel_dp);
 
-void intel_pps_vdd_sanitize(struct intel_dp *intel_dp);
 void intel_pps_vdd_on(struct intel_dp *intel_dp);
 void intel_pps_on(struct intel_dp *intel_dp);
 void intel_pps_off(struct intel_dp *intel_dp);
@@ -42,7 +41,7 @@ bool intel_pps_have_power(struct intel_dp *intel_dp);
 void wait_panel_power_cycle(struct intel_dp *intel_dp);
 
 void intel_pps_init(struct intel_dp *intel_dp);
-void intel_dp_pps_init(struct intel_dp *intel_dp);
+void intel_pps_encoder_reset(struct intel_dp *intel_dp);
 void intel_power_sequencer_reset(struct drm_i915_private *i915);
 
 void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 09/17] drm/i915/pps: rename intel_dp_check_edp to intel_pps_check_power_unlocked
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (7 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 08/17] drm/i915/pps: abstract intel_pps_encoder_reset() Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 10/17] drm/i915/pps: rename intel_power_sequencer_reset to intel_pps_reset_all Jani Nikula
                   ` (11 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Follow the usual naming pattern for functions. No functional changes.

Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c  | 2 +-
 drivers/gpu/drm/i915/display/intel_pps.c | 2 +-
 drivers/gpu/drm/i915/display/intel_pps.h | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index cfaadeaf9f00..1685e48b17cd 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -1069,7 +1069,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
 	 */
 	cpu_latency_qos_update_request(&intel_dp->pm_qos, 0);
 
-	intel_dp_check_edp(intel_dp);
+	intel_pps_check_power_unlocked(intel_dp);
 
 	/* Try to wait for any previous AUX channel activity */
 	for (try = 0; try < 3; try++) {
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 3b962be4f4c0..9e5744578b26 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -428,7 +428,7 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
 	return intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
 }
 
-void intel_dp_check_edp(struct intel_dp *intel_dp)
+void intel_pps_check_power_unlocked(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index 7c3b5ea4f47b..e0391c9c8383 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -22,7 +22,6 @@ intel_wakeref_t intel_pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wake
 #define with_intel_pps_lock(dp, wf)						\
 	for ((wf) = intel_pps_lock(dp); (wf); (wf) = intel_pps_unlock((dp), (wf)))
 
-void intel_dp_check_edp(struct intel_dp *intel_dp);
 void intel_pps_backlight_on(struct intel_dp *intel_dp);
 void intel_pps_backlight_off(struct intel_dp *intel_dp);
 void intel_pps_backlight_power(struct intel_connector *connector, bool enable);
@@ -31,6 +30,7 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp);
 void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync);
 void intel_pps_on_unlocked(struct intel_dp *intel_dp);
 void intel_pps_off_unlocked(struct intel_dp *intel_dp);
+void intel_pps_check_power_unlocked(struct intel_dp *intel_dp);
 
 void intel_pps_vdd_on(struct intel_dp *intel_dp);
 void intel_pps_on(struct intel_dp *intel_dp);
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 10/17] drm/i915/pps: rename intel_power_sequencer_reset to intel_pps_reset_all
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (8 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 09/17] drm/i915/pps: rename intel_dp_check_edp to intel_pps_check_power_unlocked Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 11/17] drm/i915/pps: add locked intel_pps_wait_power_cycle Jani Nikula
                   ` (10 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Follow the usual naming pattern for functions. "reset all" because it
iterates over all DP encoders. No functional changes.

Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display_power.c | 4 ++--
 drivers/gpu/drm/i915/display/intel_pps.c           | 5 ++---
 drivers/gpu/drm/i915/display/intel_pps.h           | 2 +-
 3 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
index a11bd8213df4..c11c37c65d86 100644
--- a/drivers/gpu/drm/i915/display/intel_display_power.c
+++ b/drivers/gpu/drm/i915/display/intel_display_power.c
@@ -936,7 +936,7 @@ static void bxt_enable_dc9(struct drm_i915_private *dev_priv)
 	 * because PPS registers are always on.
 	 */
 	if (!HAS_PCH_SPLIT(dev_priv))
-		intel_power_sequencer_reset(dev_priv);
+		intel_pps_reset_all(dev_priv);
 	gen9_set_dc_state(dev_priv, DC_STATE_EN_DC9);
 }
 
@@ -1446,7 +1446,7 @@ static void vlv_display_power_well_deinit(struct drm_i915_private *dev_priv)
 	/* make sure we're done processing display irqs */
 	intel_synchronize_irq(dev_priv);
 
-	intel_power_sequencer_reset(dev_priv);
+	intel_pps_reset_all(dev_priv);
 
 	/* Prevent us from re-enabling polling on accident in late suspend */
 	if (!dev_priv->drm.dev->power.is_suspended)
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 9e5744578b26..d396ee5f6f69 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -22,8 +22,7 @@ intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp)
 	intel_wakeref_t wakeref;
 
 	/*
-	 * See intel_power_sequencer_reset() why we need
-	 * a power domain reference here.
+	 * See intel_pps_reset_all() why we need a power domain reference here.
 	 */
 	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
 	mutex_lock(&dev_priv->pps_mutex);
@@ -313,7 +312,7 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
 	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
 }
 
-void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
+void intel_pps_reset_all(struct drm_i915_private *dev_priv)
 {
 	struct intel_encoder *encoder;
 
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index e0391c9c8383..ecd9ea2a095c 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -42,7 +42,7 @@ void wait_panel_power_cycle(struct intel_dp *intel_dp);
 
 void intel_pps_init(struct intel_dp *intel_dp);
 void intel_pps_encoder_reset(struct intel_dp *intel_dp);
-void intel_power_sequencer_reset(struct drm_i915_private *i915);
+void intel_pps_reset_all(struct drm_i915_private *i915);
 
 void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
 				    const struct intel_crtc_state *crtc_state);
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 11/17] drm/i915/pps: add locked intel_pps_wait_power_cycle
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (9 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 10/17] drm/i915/pps: rename intel_power_sequencer_reset to intel_pps_reset_all Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 12/17] drm/i915/pps: rename vlv_init_panel_power_sequencer to vlv_pps_init Jani Nikula
                   ` (9 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Prefer keeping the unlocked variants hidden if possible. No functional
changes.

Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c  |  7 +------
 drivers/gpu/drm/i915/display/intel_pps.c | 13 ++++++++++++-
 drivers/gpu/drm/i915/display/intel_pps.h |  3 +--
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index 1685e48b17cd..ffb6f6c9b858 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -6273,13 +6273,8 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
 void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
 {
 	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
-	intel_wakeref_t wakeref;
-
-	if (!intel_dp_is_edp(intel_dp))
-		return;
 
-	with_intel_pps_lock(intel_dp, wakeref)
-		wait_panel_power_cycle(intel_dp);
+	intel_pps_wait_power_cycle(intel_dp);
 }
 
 static enum pipe vlv_active_pipe(struct intel_dp *intel_dp)
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index d396ee5f6f69..79276ab20c75 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -500,7 +500,7 @@ static void wait_panel_off(struct intel_dp *intel_dp)
 	wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
 }
 
-void wait_panel_power_cycle(struct intel_dp *intel_dp)
+static void wait_panel_power_cycle(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 	ktime_t panel_power_on_time;
@@ -522,6 +522,17 @@ void wait_panel_power_cycle(struct intel_dp *intel_dp)
 	wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
 }
 
+void intel_pps_wait_power_cycle(struct intel_dp *intel_dp)
+{
+	intel_wakeref_t wakeref;
+
+	if (!intel_dp_is_edp(intel_dp))
+		return;
+
+	with_intel_pps_lock(intel_dp, wakeref)
+		wait_panel_power_cycle(intel_dp);
+}
+
 static void wait_backlight_on(struct intel_dp *intel_dp)
 {
 	wait_remaining_ms_from_jiffies(intel_dp->last_power_on,
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index ecd9ea2a095c..fdf7a17e2dfa 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -37,8 +37,7 @@ void intel_pps_on(struct intel_dp *intel_dp);
 void intel_pps_off(struct intel_dp *intel_dp);
 void intel_pps_vdd_off_sync(struct intel_dp *intel_dp);
 bool intel_pps_have_power(struct intel_dp *intel_dp);
-
-void wait_panel_power_cycle(struct intel_dp *intel_dp);
+void intel_pps_wait_power_cycle(struct intel_dp *intel_dp);
 
 void intel_pps_init(struct intel_dp *intel_dp);
 void intel_pps_encoder_reset(struct intel_dp *intel_dp);
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 12/17] drm/i915/pps: rename vlv_init_panel_power_sequencer to vlv_pps_init
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (10 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 11/17] drm/i915/pps: add locked intel_pps_wait_power_cycle Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 13/17] drm/i915/pps: rename intel_dp_init_panel_power_sequencer* functions Jani Nikula
                   ` (8 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

This function is a bit of an outlier, but try to change to a name that
is more in line with the rest of the intel_pps functions. No functional
changes.

Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_dp.c  | 2 +-
 drivers/gpu/drm/i915/display/intel_pps.c | 4 ++--
 drivers/gpu/drm/i915/display/intel_pps.h | 4 ++--
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index ffb6f6c9b858..a8835e3b1ac1 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -3516,7 +3516,7 @@ static void intel_enable_dp(struct intel_atomic_state *state,
 
 	with_intel_pps_lock(intel_dp, wakeref) {
 		if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-			vlv_init_panel_power_sequencer(encoder, pipe_config);
+			vlv_pps_init(encoder, pipe_config);
 
 		intel_dp_enable_port(intel_dp, pipe_config);
 
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 79276ab20c75..8925df55e22e 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -1005,8 +1005,8 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
 	}
 }
 
-void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
-				    const struct intel_crtc_state *crtc_state)
+void vlv_pps_init(struct intel_encoder *encoder,
+		  const struct intel_crtc_state *crtc_state)
 {
 	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index fdf7a17e2dfa..22045c5cdc86 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -43,7 +43,7 @@ void intel_pps_init(struct intel_dp *intel_dp);
 void intel_pps_encoder_reset(struct intel_dp *intel_dp);
 void intel_pps_reset_all(struct drm_i915_private *i915);
 
-void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
-				    const struct intel_crtc_state *crtc_state);
+void vlv_pps_init(struct intel_encoder *encoder,
+		  const struct intel_crtc_state *crtc_state);
 
 #endif /* __INTEL_PPS_H__ */
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 13/17] drm/i915/pps: rename intel_dp_init_panel_power_sequencer* functions
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (11 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 12/17] drm/i915/pps: rename vlv_init_panel_power_sequencer to vlv_pps_init Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-13 11:02   ` Anshuman Gupta
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 14/17] drm/i915/pps: refactor init abstractions Jani Nikula
                   ` (7 subsequent siblings)
  20 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

There are a number of functions that "init" pps in various ways. Try to
find some more consistency in the naming.

Rename:
 - intel_dp_init_panel_power_sequencer -> pps_init_delays
 - intel_dp_init_panel_power_sequencer_registers -> pps_init_registers
 - intel_dp_init_panel_power_timestamps -> pps_init_timestamps

as this is what the functions do. Skip the intel_ prefix here to
emphasize these are static and not exported.

No functional changes.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_pps.c | 37 ++++++++++--------------
 1 file changed, 16 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 8925df55e22e..58eff6289d12 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -10,11 +10,9 @@
 
 static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
 				      enum pipe pipe);
-static void
-intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp);
-static void
-intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
-					      bool force_disable_vdd);
+
+static void pps_init_delays(struct intel_dp *intel_dp);
+static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd);
 
 intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp)
 {
@@ -190,8 +188,8 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 		    dig_port->base.base.name);
 
 	/* init power sequencer on this pipe and port */
-	intel_dp_init_panel_power_sequencer(intel_dp);
-	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
+	pps_init_delays(intel_dp);
+	pps_init_registers(intel_dp, true);
 
 	/*
 	 * Even vdd force doesn't work until we've made
@@ -222,7 +220,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp)
 	 * Only the HW needs to be reprogrammed, the SW state is fixed and
 	 * has been setup during connector init.
 	 */
-	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
+	pps_init_registers(intel_dp, false);
 
 	return backlight_controller;
 }
@@ -308,8 +306,8 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
 		    dig_port->base.base.name,
 		    pipe_name(intel_dp->pps_pipe));
 
-	intel_dp_init_panel_power_sequencer(intel_dp);
-	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
+	pps_init_delays(intel_dp);
+	pps_init_registers(intel_dp, false);
 }
 
 void intel_pps_reset_all(struct drm_i915_private *dev_priv)
@@ -1046,8 +1044,8 @@ void vlv_pps_init(struct intel_encoder *encoder,
 		    encoder->base.name);
 
 	/* init power sequencer on this pipe and port */
-	intel_dp_init_panel_power_sequencer(intel_dp);
-	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
+	pps_init_delays(intel_dp);
+	pps_init_registers(intel_dp, true);
 }
 
 static void intel_pps_vdd_sanitize(struct intel_dp *intel_dp)
@@ -1088,7 +1086,7 @@ bool intel_pps_have_power(struct intel_dp *intel_dp)
 	return have_power;
 }
 
-static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
+static void pps_init_timestamps(struct intel_dp *intel_dp)
 {
 	intel_dp->panel_power_off_time = ktime_get_boottime();
 	intel_dp->last_power_on = jiffies;
@@ -1154,8 +1152,7 @@ intel_pps_verify_state(struct intel_dp *intel_dp)
 	}
 }
 
-static void
-intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp)
+static void pps_init_delays(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct edp_power_seq cur, vbt, spec,
@@ -1250,9 +1247,7 @@ intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp)
 	final->t11_t12 = roundup(final->t11_t12, 100 * 10);
 }
 
-static void
-intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
-					      bool force_disable_vdd)
+static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	u32 pp_on, pp_off, port_sel = 0;
@@ -1354,8 +1349,8 @@ static void intel_dp_pps_init(struct intel_dp *intel_dp)
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
 		vlv_initial_power_sequencer_setup(intel_dp);
 	} else {
-		intel_dp_init_panel_power_sequencer(intel_dp);
-		intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
+		pps_init_delays(intel_dp);
+		pps_init_registers(intel_dp, false);
 	}
 }
 
@@ -1383,7 +1378,7 @@ void intel_pps_init(struct intel_dp *intel_dp)
 	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work);
 
 	with_intel_pps_lock(intel_dp, wakeref) {
-		intel_dp_init_panel_power_timestamps(intel_dp);
+		pps_init_timestamps(intel_dp);
 		intel_dp_pps_init(intel_dp);
 		intel_pps_vdd_sanitize(intel_dp);
 	}
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 14/17] drm/i915/pps: refactor init abstractions
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (12 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 13/17] drm/i915/pps: rename intel_dp_init_panel_power_sequencer* functions Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-13 11:44   ` Anshuman Gupta
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 15/17] drm/i915/pps: move pps code over from intel_display.c and refactor Jani Nikula
                   ` (6 subsequent siblings)
  20 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Once you realize there is no need to hold the pps mutex when calling
pps_init_timestamps() in intel_pps_init(), we can reuse
intel_pps_encoder_reset() which has the same code.

Since intel_dp_pps_init() is only called from one place now, move it
inline to remove one "init" function altogether.

Finally, remove some initialization from
vlv_initial_power_sequencer_setup() and do it in the caller to highlight
the similarity, not the difference, in the platforms.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_pps.c | 33 +++++++-----------------
 1 file changed, 10 insertions(+), 23 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index 58eff6289d12..b4d026ca3313 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -305,9 +305,6 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
 		    dig_port->base.base.base.id,
 		    dig_port->base.base.name,
 		    pipe_name(intel_dp->pps_pipe));
-
-	pps_init_delays(intel_dp);
-	pps_init_registers(intel_dp, false);
 }
 
 void intel_pps_reset_all(struct drm_i915_private *dev_priv)
@@ -1342,20 +1339,9 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
 		    (intel_de_read(dev_priv, regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK));
 }
 
-static void intel_dp_pps_init(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
-		vlv_initial_power_sequencer_setup(intel_dp);
-	} else {
-		pps_init_delays(intel_dp);
-		pps_init_registers(intel_dp, false);
-	}
-}
-
 void intel_pps_encoder_reset(struct intel_dp *intel_dp)
 {
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
 	intel_wakeref_t wakeref;
 
 	if (!intel_dp_is_edp(intel_dp))
@@ -1366,20 +1352,21 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp)
 		 * Reinit the power sequencer, in case BIOS did something nasty
 		 * with it.
 		 */
-		intel_dp_pps_init(intel_dp);
+		if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
+			vlv_initial_power_sequencer_setup(intel_dp);
+
+		pps_init_delays(intel_dp);
+		pps_init_registers(intel_dp, false);
+
 		intel_pps_vdd_sanitize(intel_dp);
 	}
 }
 
 void intel_pps_init(struct intel_dp *intel_dp)
 {
-	intel_wakeref_t wakeref;
-
 	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work);
 
-	with_intel_pps_lock(intel_dp, wakeref) {
-		pps_init_timestamps(intel_dp);
-		intel_dp_pps_init(intel_dp);
-		intel_pps_vdd_sanitize(intel_dp);
-	}
+	pps_init_timestamps(intel_dp);
+
+	intel_pps_encoder_reset(intel_dp);
 }
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 15/17] drm/i915/pps: move pps code over from intel_display.c and refactor
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (13 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 14/17] drm/i915/pps: refactor init abstractions Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-13 11:55   ` Anshuman Gupta
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 16/17] drm/i915/dp: abstract struct intel_dp pps members to a sub-struct Jani Nikula
                   ` (5 subsequent siblings)
  20 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

intel_display.c has some pps functions that belong to intel_pps.c. Move
them over.

While at it, refactor the duplicate intel_pps_init() in intel_display.c
into an orthogonal intel_pps_setup() in intel_pps.c, and call it earlier
in intel_modeset_init_nogem().

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/display/intel_display.c | 41 ++------------------
 drivers/gpu/drm/i915/display/intel_display.h |  1 -
 drivers/gpu/drm/i915/display/intel_pps.c     | 34 ++++++++++++++++
 drivers/gpu/drm/i915/display/intel_pps.h     |  3 ++
 drivers/gpu/drm/i915/i915_drv.c              |  1 +
 5 files changed, 42 insertions(+), 38 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
index 0189d379a55e..f8806c4ecb21 100644
--- a/drivers/gpu/drm/i915/display/intel_display.c
+++ b/drivers/gpu/drm/i915/display/intel_display.c
@@ -81,6 +81,7 @@
 #include "intel_overlay.h"
 #include "intel_pipe_crc.h"
 #include "intel_pm.h"
+#include "intel_pps.h"
 #include "intel_psr.h"
 #include "intel_quirks.h"
 #include "intel_sideband.h"
@@ -16100,48 +16101,12 @@ static bool intel_ddi_crt_present(struct drm_i915_private *dev_priv)
 	return true;
 }
 
-void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
-{
-	int pps_num;
-	int pps_idx;
-
-	if (HAS_DDI(dev_priv))
-		return;
-	/*
-	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
-	 * everywhere where registers can be write protected.
-	 */
-	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		pps_num = 2;
-	else
-		pps_num = 1;
-
-	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
-		u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx));
-
-		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
-		intel_de_write(dev_priv, PP_CONTROL(pps_idx), val);
-	}
-}
-
-static void intel_pps_init(struct drm_i915_private *dev_priv)
-{
-	if (HAS_PCH_SPLIT(dev_priv) || IS_GEN9_LP(dev_priv))
-		dev_priv->pps_mmio_base = PCH_PPS_BASE;
-	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		dev_priv->pps_mmio_base = VLV_PPS_BASE;
-	else
-		dev_priv->pps_mmio_base = PPS_BASE;
-
-	intel_pps_unlock_regs_wa(dev_priv);
-}
-
 static void intel_setup_outputs(struct drm_i915_private *dev_priv)
 {
 	struct intel_encoder *encoder;
 	bool dpd_is_edp = false;
 
-	intel_pps_init(dev_priv);
+	intel_pps_unlock_regs_wa(dev_priv);
 
 	if (!HAS_DISPLAY(dev_priv))
 		return;
@@ -17199,6 +17164,8 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)
 
 	intel_panel_sanitize_ssc(i915);
 
+	intel_pps_setup(i915);
+
 	intel_gmbus_setup(i915);
 
 	drm_dbg_kms(&i915->drm, "%d display pipe%s available.\n",
diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
index 7ddbc00a0f41..bbd5dbc61ce9 100644
--- a/drivers/gpu/drm/i915/display/intel_display.h
+++ b/drivers/gpu/drm/i915/display/intel_display.h
@@ -546,7 +546,6 @@ unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info
 unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info);
 bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv);
 int intel_display_suspend(struct drm_device *dev);
-void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
 void intel_encoder_destroy(struct drm_encoder *encoder);
 struct drm_display_mode *
 intel_encoder_current_mode(struct intel_encoder *encoder);
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index b4d026ca3313..c3a0fc933500 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -1370,3 +1370,37 @@ void intel_pps_init(struct intel_dp *intel_dp)
 
 	intel_pps_encoder_reset(intel_dp);
 }
+
+void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
+{
+	int pps_num;
+	int pps_idx;
+
+	if (HAS_DDI(dev_priv))
+		return;
+	/*
+	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
+	 * everywhere where registers can be write protected.
+	 */
+	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
+		pps_num = 2;
+	else
+		pps_num = 1;
+
+	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
+		u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx));
+
+		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
+		intel_de_write(dev_priv, PP_CONTROL(pps_idx), val);
+	}
+}
+
+void intel_pps_setup(struct drm_i915_private *i915)
+{
+	if (HAS_PCH_SPLIT(i915) || IS_GEN9_LP(i915))
+		i915->pps_mmio_base = PCH_PPS_BASE;
+	else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
+		i915->pps_mmio_base = VLV_PPS_BASE;
+	else
+		i915->pps_mmio_base = PPS_BASE;
+}
diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
index 22045c5cdc86..fbbcca782e7b 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.h
+++ b/drivers/gpu/drm/i915/display/intel_pps.h
@@ -46,4 +46,7 @@ void intel_pps_reset_all(struct drm_i915_private *i915);
 void vlv_pps_init(struct intel_encoder *encoder,
 		  const struct intel_crtc_state *crtc_state);
 
+void intel_pps_unlock_regs_wa(struct drm_i915_private *i915);
+void intel_pps_setup(struct drm_i915_private *i915);
+
 #endif /* __INTEL_PPS_H__ */
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 3e504247f2da..7282c8f08318 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -58,6 +58,7 @@
 #include "display/intel_hotplug.h"
 #include "display/intel_overlay.h"
 #include "display/intel_pipe_crc.h"
+#include "display/intel_pps.h"
 #include "display/intel_sprite.h"
 #include "display/intel_vga.h"
 
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 16/17] drm/i915/dp: abstract struct intel_dp pps members to a sub-struct
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (14 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 15/17] drm/i915/pps: move pps code over from intel_display.c and refactor Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-13 11:58   ` Anshuman Gupta
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 17/17] drm/i915/dp: split out aux functionality to intel_dp_aux.c Jani Nikula
                   ` (4 subsequent siblings)
  20 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Add some namespacing to highlight what belongs where. No functional
changes.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 .../drm/i915/display/intel_display_debugfs.c  |   8 +-
 .../drm/i915/display/intel_display_types.h    |  61 +++---
 drivers/gpu/drm/i915/display/intel_dp.c       |  14 +-
 drivers/gpu/drm/i915/display/intel_pps.c      | 192 +++++++++---------
 4 files changed, 140 insertions(+), 135 deletions(-)

diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
index cd7e5519ee7d..885d2d3c91a3 100644
--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
@@ -2155,13 +2155,13 @@ static int i915_panel_show(struct seq_file *m, void *data)
 		return -ENODEV;
 
 	seq_printf(m, "Panel power up delay: %d\n",
-		   intel_dp->panel_power_up_delay);
+		   intel_dp->pps.panel_power_up_delay);
 	seq_printf(m, "Panel power down delay: %d\n",
-		   intel_dp->panel_power_down_delay);
+		   intel_dp->pps.panel_power_down_delay);
 	seq_printf(m, "Backlight on delay: %d\n",
-		   intel_dp->backlight_on_delay);
+		   intel_dp->pps.backlight_on_delay);
 	seq_printf(m, "Backlight off delay: %d\n",
-		   intel_dp->backlight_off_delay);
+		   intel_dp->pps.backlight_off_delay);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
index 1067bd073c95..69b34378cc6e 100644
--- a/drivers/gpu/drm/i915/display/intel_display_types.h
+++ b/drivers/gpu/drm/i915/display/intel_display_types.h
@@ -1344,6 +1344,38 @@ struct intel_dp_pcon_frl {
 	int trained_rate_gbps;
 };
 
+struct intel_pps {
+	int panel_power_up_delay;
+	int panel_power_down_delay;
+	int panel_power_cycle_delay;
+	int backlight_on_delay;
+	int backlight_off_delay;
+	struct delayed_work panel_vdd_work;
+	bool want_panel_vdd;
+	unsigned long last_power_on;
+	unsigned long last_backlight_off;
+	ktime_t panel_power_off_time;
+	intel_wakeref_t vdd_wakeref;
+
+	/*
+	 * Pipe whose power sequencer is currently locked into
+	 * this port. Only relevant on VLV/CHV.
+	 */
+	enum pipe pps_pipe;
+	/*
+	 * Pipe currently driving the port. Used for preventing
+	 * the use of the PPS for any pipe currentrly driving
+	 * external DP as that will mess things up on VLV.
+	 */
+	enum pipe active_pipe;
+	/*
+	 * Set if the sequencer may be reset due to a power transition,
+	 * requiring a reinitialization. Only relevant on BXT.
+	 */
+	bool pps_reset;
+	struct edp_power_seq pps_delays;
+};
+
 struct intel_dp {
 	i915_reg_t output_reg;
 	u32 DP;
@@ -1383,35 +1415,8 @@ struct intel_dp {
 	struct drm_dp_aux aux;
 	u32 aux_busy_last_status;
 	u8 train_set[4];
-	int panel_power_up_delay;
-	int panel_power_down_delay;
-	int panel_power_cycle_delay;
-	int backlight_on_delay;
-	int backlight_off_delay;
-	struct delayed_work panel_vdd_work;
-	bool want_panel_vdd;
-	unsigned long last_power_on;
-	unsigned long last_backlight_off;
-	ktime_t panel_power_off_time;
-	intel_wakeref_t vdd_wakeref;
 
-	/*
-	 * Pipe whose power sequencer is currently locked into
-	 * this port. Only relevant on VLV/CHV.
-	 */
-	enum pipe pps_pipe;
-	/*
-	 * Pipe currently driving the port. Used for preventing
-	 * the use of the PPS for any pipe currentrly driving
-	 * external DP as that will mess things up on VLV.
-	 */
-	enum pipe active_pipe;
-	/*
-	 * Set if the sequencer may be reset due to a power transition,
-	 * requiring a reinitialization. Only relevant on BXT.
-	 */
-	bool pps_reset;
-	struct edp_power_seq pps_delays;
+	struct intel_pps pps;
 
 	bool can_mst; /* this port supports mst */
 	bool is_mst;
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index a8835e3b1ac1..e6859b9925b9 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -4075,7 +4075,7 @@ intel_dp_link_down(struct intel_encoder *encoder,
 		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
 	}
 
-	msleep(intel_dp->panel_power_down_delay);
+	msleep(intel_dp->pps.panel_power_down_delay);
 
 	intel_dp->DP = DP;
 
@@ -4083,7 +4083,7 @@ intel_dp_link_down(struct intel_encoder *encoder,
 		intel_wakeref_t wakeref;
 
 		with_intel_pps_lock(intel_dp, wakeref)
-			intel_dp->active_pipe = INVALID_PIPE;
+			intel_dp->pps.active_pipe = INVALID_PIPE;
 	}
 }
 
@@ -6304,7 +6304,7 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
 		intel_wakeref_t wakeref;
 
 		with_intel_pps_lock(intel_dp, wakeref)
-			intel_dp->active_pipe = vlv_active_pipe(intel_dp);
+			intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp);
 	}
 
 	intel_pps_encoder_reset(intel_dp);
@@ -7076,7 +7076,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
 		pipe = vlv_active_pipe(intel_dp);
 
 		if (pipe != PIPE_A && pipe != PIPE_B)
-			pipe = intel_dp->pps_pipe;
+			pipe = intel_dp->pps.pps_pipe;
 
 		if (pipe != PIPE_A && pipe != PIPE_B)
 			pipe = PIPE_A;
@@ -7153,8 +7153,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
 	intel_dp_set_source_rates(intel_dp);
 
 	intel_dp->reset_link_params = true;
-	intel_dp->pps_pipe = INVALID_PIPE;
-	intel_dp->active_pipe = INVALID_PIPE;
+	intel_dp->pps.pps_pipe = INVALID_PIPE;
+	intel_dp->pps.active_pipe = INVALID_PIPE;
 
 	/* Preserve the current hw state. */
 	intel_dp->DP = intel_de_read(dev_priv, intel_dp->output_reg);
@@ -7172,7 +7172,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
 	}
 
 	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
-		intel_dp->active_pipe = vlv_active_pipe(intel_dp);
+		intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp);
 
 	/*
 	 * For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but
diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
index c3a0fc933500..6bf807173ed3 100644
--- a/drivers/gpu/drm/i915/display/intel_pps.c
+++ b/drivers/gpu/drm/i915/display/intel_pps.c
@@ -44,7 +44,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum pipe pipe = intel_dp->pps_pipe;
+	enum pipe pipe = intel_dp->pps.pps_pipe;
 	bool pll_enabled, release_cl_override = false;
 	enum dpio_phy phy = DPIO_PHY(pipe);
 	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
@@ -130,18 +130,18 @@ static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv)
 
 		if (encoder->type == INTEL_OUTPUT_EDP) {
 			drm_WARN_ON(&dev_priv->drm,
-				    intel_dp->active_pipe != INVALID_PIPE &&
-				    intel_dp->active_pipe !=
-				    intel_dp->pps_pipe);
+				    intel_dp->pps.active_pipe != INVALID_PIPE &&
+				    intel_dp->pps.active_pipe !=
+				    intel_dp->pps.pps_pipe);
 
-			if (intel_dp->pps_pipe != INVALID_PIPE)
-				pipes &= ~(1 << intel_dp->pps_pipe);
+			if (intel_dp->pps.pps_pipe != INVALID_PIPE)
+				pipes &= ~(1 << intel_dp->pps.pps_pipe);
 		} else {
 			drm_WARN_ON(&dev_priv->drm,
-				    intel_dp->pps_pipe != INVALID_PIPE);
+				    intel_dp->pps.pps_pipe != INVALID_PIPE);
 
-			if (intel_dp->active_pipe != INVALID_PIPE)
-				pipes &= ~(1 << intel_dp->active_pipe);
+			if (intel_dp->pps.active_pipe != INVALID_PIPE)
+				pipes &= ~(1 << intel_dp->pps.active_pipe);
 		}
 	}
 
@@ -163,11 +163,11 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 	/* We should never land here with regular DP ports */
 	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
 
-	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE &&
-		    intel_dp->active_pipe != intel_dp->pps_pipe);
+	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.active_pipe != INVALID_PIPE &&
+		    intel_dp->pps.active_pipe != intel_dp->pps.pps_pipe);
 
-	if (intel_dp->pps_pipe != INVALID_PIPE)
-		return intel_dp->pps_pipe;
+	if (intel_dp->pps.pps_pipe != INVALID_PIPE)
+		return intel_dp->pps.pps_pipe;
 
 	pipe = vlv_find_free_pps(dev_priv);
 
@@ -179,11 +179,11 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 		pipe = PIPE_A;
 
 	vlv_steal_power_sequencer(dev_priv, pipe);
-	intel_dp->pps_pipe = pipe;
+	intel_dp->pps.pps_pipe = pipe;
 
 	drm_dbg_kms(&dev_priv->drm,
 		    "picked pipe %c power sequencer for [ENCODER:%d:%s]\n",
-		    pipe_name(intel_dp->pps_pipe),
+		    pipe_name(intel_dp->pps.pps_pipe),
 		    dig_port->base.base.base.id,
 		    dig_port->base.base.name);
 
@@ -197,7 +197,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
 	 */
 	vlv_power_sequencer_kick(intel_dp);
 
-	return intel_dp->pps_pipe;
+	return intel_dp->pps.pps_pipe;
 }
 
 static int
@@ -211,10 +211,10 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp)
 	/* We should never land here with regular DP ports */
 	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
 
-	if (!intel_dp->pps_reset)
+	if (!intel_dp->pps.pps_reset)
 		return backlight_controller;
 
-	intel_dp->pps_reset = false;
+	intel_dp->pps.pps_reset = false;
 
 	/*
 	 * Only the HW needs to be reprogrammed, the SW state is fixed and
@@ -280,19 +280,19 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
 
 	/* try to find a pipe with this port selected */
 	/* first pick one where the panel is on */
-	intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
-						  vlv_pipe_has_pp_on);
+	intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+						      vlv_pipe_has_pp_on);
 	/* didn't find one? pick one where vdd is on */
-	if (intel_dp->pps_pipe == INVALID_PIPE)
-		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
-							  vlv_pipe_has_vdd_on);
+	if (intel_dp->pps.pps_pipe == INVALID_PIPE)
+		intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+							      vlv_pipe_has_vdd_on);
 	/* didn't find one? pick one with just the correct port */
-	if (intel_dp->pps_pipe == INVALID_PIPE)
-		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
-							  vlv_pipe_any);
+	if (intel_dp->pps.pps_pipe == INVALID_PIPE)
+		intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
+							      vlv_pipe_any);
 
 	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
-	if (intel_dp->pps_pipe == INVALID_PIPE) {
+	if (intel_dp->pps.pps_pipe == INVALID_PIPE) {
 		drm_dbg_kms(&dev_priv->drm,
 			    "no initial power sequencer for [ENCODER:%d:%s]\n",
 			    dig_port->base.base.base.id,
@@ -304,7 +304,7 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
 		    "initial power sequencer for [ENCODER:%d:%s]: pipe %c\n",
 		    dig_port->base.base.base.id,
 		    dig_port->base.base.name,
-		    pipe_name(intel_dp->pps_pipe));
+		    pipe_name(intel_dp->pps.pps_pipe));
 }
 
 void intel_pps_reset_all(struct drm_i915_private *dev_priv)
@@ -331,15 +331,15 @@ void intel_pps_reset_all(struct drm_i915_private *dev_priv)
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
 		drm_WARN_ON(&dev_priv->drm,
-			    intel_dp->active_pipe != INVALID_PIPE);
+			    intel_dp->pps.active_pipe != INVALID_PIPE);
 
 		if (encoder->type != INTEL_OUTPUT_EDP)
 			continue;
 
 		if (IS_GEN9_LP(dev_priv))
-			intel_dp->pps_reset = true;
+			intel_dp->pps.pps_reset = true;
 		else
-			intel_dp->pps_pipe = INVALID_PIPE;
+			intel_dp->pps.pps_pipe = INVALID_PIPE;
 	}
 }
 
@@ -403,7 +403,7 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp)
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
 	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
-	    intel_dp->pps_pipe == INVALID_PIPE)
+	    intel_dp->pps.pps_pipe == INVALID_PIPE)
 		return false;
 
 	return (intel_de_read(dev_priv, _pp_stat_reg(intel_dp)) & PP_ON) != 0;
@@ -416,7 +416,7 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
 	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
-	    intel_dp->pps_pipe == INVALID_PIPE)
+	    intel_dp->pps.pps_pipe == INVALID_PIPE)
 		return false;
 
 	return intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
@@ -506,13 +506,13 @@ static void wait_panel_power_cycle(struct intel_dp *intel_dp)
 	/* take the difference of currrent time and panel power off time
 	 * and then make panel wait for t11_t12 if needed. */
 	panel_power_on_time = ktime_get_boottime();
-	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->panel_power_off_time);
+	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->pps.panel_power_off_time);
 
 	/* When we disable the VDD override bit last we have to do the manual
 	 * wait. */
-	if (panel_power_off_duration < (s64)intel_dp->panel_power_cycle_delay)
+	if (panel_power_off_duration < (s64)intel_dp->pps.panel_power_cycle_delay)
 		wait_remaining_ms_from_jiffies(jiffies,
-				       intel_dp->panel_power_cycle_delay - panel_power_off_duration);
+				       intel_dp->pps.panel_power_cycle_delay - panel_power_off_duration);
 
 	wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
 }
@@ -530,14 +530,14 @@ void intel_pps_wait_power_cycle(struct intel_dp *intel_dp)
 
 static void wait_backlight_on(struct intel_dp *intel_dp)
 {
-	wait_remaining_ms_from_jiffies(intel_dp->last_power_on,
-				       intel_dp->backlight_on_delay);
+	wait_remaining_ms_from_jiffies(intel_dp->pps.last_power_on,
+				       intel_dp->pps.backlight_on_delay);
 }
 
 static void edp_wait_backlight_off(struct intel_dp *intel_dp)
 {
-	wait_remaining_ms_from_jiffies(intel_dp->last_backlight_off,
-				       intel_dp->backlight_off_delay);
+	wait_remaining_ms_from_jiffies(intel_dp->pps.last_backlight_off,
+				       intel_dp->pps.backlight_off_delay);
 }
 
 /* Read the current pp_control value, unlocking the register if it
@@ -571,22 +571,22 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
 	u32 pp;
 	i915_reg_t pp_stat_reg, pp_ctrl_reg;
-	bool need_to_disable = !intel_dp->want_panel_vdd;
+	bool need_to_disable = !intel_dp->pps.want_panel_vdd;
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
 	if (!intel_dp_is_edp(intel_dp))
 		return false;
 
-	cancel_delayed_work(&intel_dp->panel_vdd_work);
-	intel_dp->want_panel_vdd = true;
+	cancel_delayed_work(&intel_dp->pps.panel_vdd_work);
+	intel_dp->pps.want_panel_vdd = true;
 
 	if (edp_have_panel_vdd(intel_dp))
 		return need_to_disable;
 
-	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
-	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
-							intel_aux_power_domain(dig_port));
+	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.vdd_wakeref);
+	intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv,
+							    intel_aux_power_domain(dig_port));
 
 	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n",
 		    dig_port->base.base.base.id,
@@ -614,7 +614,7 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
 			    "[ENCODER:%d:%s] panel power wasn't enabled\n",
 			    dig_port->base.base.base.id,
 			    dig_port->base.base.name);
-		msleep(intel_dp->panel_power_up_delay);
+		msleep(intel_dp->pps.panel_power_up_delay);
 	}
 
 	return need_to_disable;
@@ -652,7 +652,7 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
-	drm_WARN_ON(&dev_priv->drm, intel_dp->want_panel_vdd);
+	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.want_panel_vdd);
 
 	if (!edp_have_panel_vdd(intel_dp))
 		return;
@@ -676,11 +676,11 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
 		    intel_de_read(dev_priv, pp_ctrl_reg));
 
 	if ((pp & PANEL_POWER_ON) == 0)
-		intel_dp->panel_power_off_time = ktime_get_boottime();
+		intel_dp->pps.panel_power_off_time = ktime_get_boottime();
 
 	intel_display_power_put(dev_priv,
 				intel_aux_power_domain(dig_port),
-				fetch_and_zero(&intel_dp->vdd_wakeref));
+				fetch_and_zero(&intel_dp->pps.vdd_wakeref));
 }
 
 void intel_pps_vdd_off_sync(struct intel_dp *intel_dp)
@@ -690,7 +690,7 @@ void intel_pps_vdd_off_sync(struct intel_dp *intel_dp)
 	if (!intel_dp_is_edp(intel_dp))
 		return;
 
-	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
+	cancel_delayed_work_sync(&intel_dp->pps.panel_vdd_work);
 	/*
 	 * vdd might still be enabled due to the delayed vdd off.
 	 * Make sure vdd is actually turned off here.
@@ -701,13 +701,13 @@ void intel_pps_vdd_off_sync(struct intel_dp *intel_dp)
 
 static void edp_panel_vdd_work(struct work_struct *__work)
 {
-	struct intel_dp *intel_dp =
-		container_of(to_delayed_work(__work),
-			     struct intel_dp, panel_vdd_work);
+	struct intel_pps *pps = container_of(to_delayed_work(__work),
+					     struct intel_pps, panel_vdd_work);
+	struct intel_dp *intel_dp = container_of(pps, struct intel_dp, pps);
 	intel_wakeref_t wakeref;
 
 	with_intel_pps_lock(intel_dp, wakeref) {
-		if (!intel_dp->want_panel_vdd)
+		if (!intel_dp->pps.want_panel_vdd)
 			intel_pps_vdd_off_sync_unlocked(intel_dp);
 	}
 }
@@ -721,8 +721,8 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
 	 * down delay) to keep the panel power up across a sequence of
 	 * operations.
 	 */
-	delay = msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5);
-	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
+	delay = msecs_to_jiffies(intel_dp->pps.panel_power_cycle_delay * 5);
+	schedule_delayed_work(&intel_dp->pps.panel_vdd_work, delay);
 }
 
 /*
@@ -739,11 +739,11 @@ void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync)
 	if (!intel_dp_is_edp(intel_dp))
 		return;
 
-	I915_STATE_WARN(!intel_dp->want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on",
+	I915_STATE_WARN(!intel_dp->pps.want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on",
 			dp_to_dig_port(intel_dp)->base.base.base.id,
 			dp_to_dig_port(intel_dp)->base.base.name);
 
-	intel_dp->want_panel_vdd = false;
+	intel_dp->pps.want_panel_vdd = false;
 
 	if (sync)
 		intel_pps_vdd_off_sync_unlocked(intel_dp);
@@ -791,7 +791,7 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp)
 	intel_de_posting_read(dev_priv, pp_ctrl_reg);
 
 	wait_panel_on(intel_dp);
-	intel_dp->last_power_on = jiffies;
+	intel_dp->pps.last_power_on = jiffies;
 
 	if (IS_GEN(dev_priv, 5)) {
 		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
@@ -826,7 +826,7 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp)
 	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power off\n",
 		    dig_port->base.base.base.id, dig_port->base.base.name);
 
-	drm_WARN(&dev_priv->drm, !intel_dp->want_panel_vdd,
+	drm_WARN(&dev_priv->drm, !intel_dp->pps.want_panel_vdd,
 		 "Need [ENCODER:%d:%s] VDD to turn off panel\n",
 		 dig_port->base.base.base.id, dig_port->base.base.name);
 
@@ -838,18 +838,18 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp)
 
 	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
 
-	intel_dp->want_panel_vdd = false;
+	intel_dp->pps.want_panel_vdd = false;
 
 	intel_de_write(dev_priv, pp_ctrl_reg, pp);
 	intel_de_posting_read(dev_priv, pp_ctrl_reg);
 
 	wait_panel_off(intel_dp);
-	intel_dp->panel_power_off_time = ktime_get_boottime();
+	intel_dp->pps.panel_power_off_time = ktime_get_boottime();
 
 	/* We got a reference when we enabled the VDD. */
 	intel_display_power_put(dev_priv,
 				intel_aux_power_domain(dig_port),
-				fetch_and_zero(&intel_dp->vdd_wakeref));
+				fetch_and_zero(&intel_dp->pps.vdd_wakeref));
 }
 
 void intel_pps_off(struct intel_dp *intel_dp)
@@ -909,7 +909,7 @@ void intel_pps_backlight_off(struct intel_dp *intel_dp)
 		intel_de_posting_read(dev_priv, pp_ctrl_reg);
 	}
 
-	intel_dp->last_backlight_off = jiffies;
+	intel_dp->pps.last_backlight_off = jiffies;
 	edp_wait_backlight_off(intel_dp);
 }
 
@@ -943,10 +943,10 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
 {
 	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
 	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
-	enum pipe pipe = intel_dp->pps_pipe;
+	enum pipe pipe = intel_dp->pps.pps_pipe;
 	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
 
-	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
+	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.active_pipe != INVALID_PIPE);
 
 	if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B))
 		return;
@@ -969,7 +969,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
 	intel_de_write(dev_priv, pp_on_reg, 0);
 	intel_de_posting_read(dev_priv, pp_on_reg);
 
-	intel_dp->pps_pipe = INVALID_PIPE;
+	intel_dp->pps.pps_pipe = INVALID_PIPE;
 }
 
 static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
@@ -982,12 +982,12 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
 	for_each_intel_dp(&dev_priv->drm, encoder) {
 		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 
-		drm_WARN(&dev_priv->drm, intel_dp->active_pipe == pipe,
+		drm_WARN(&dev_priv->drm, intel_dp->pps.active_pipe == pipe,
 			 "stealing pipe %c power sequencer from active [ENCODER:%d:%s]\n",
 			 pipe_name(pipe), encoder->base.base.id,
 			 encoder->base.name);
 
-		if (intel_dp->pps_pipe != pipe)
+		if (intel_dp->pps.pps_pipe != pipe)
 			continue;
 
 		drm_dbg_kms(&dev_priv->drm,
@@ -1009,10 +1009,10 @@ void vlv_pps_init(struct intel_encoder *encoder,
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
-	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
+	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.active_pipe != INVALID_PIPE);
 
-	if (intel_dp->pps_pipe != INVALID_PIPE &&
-	    intel_dp->pps_pipe != crtc->pipe) {
+	if (intel_dp->pps.pps_pipe != INVALID_PIPE &&
+	    intel_dp->pps.pps_pipe != crtc->pipe) {
 		/*
 		 * If another power sequencer was being used on this
 		 * port previously make sure to turn off vdd there while
@@ -1027,17 +1027,17 @@ void vlv_pps_init(struct intel_encoder *encoder,
 	 */
 	vlv_steal_power_sequencer(dev_priv, crtc->pipe);
 
-	intel_dp->active_pipe = crtc->pipe;
+	intel_dp->pps.active_pipe = crtc->pipe;
 
 	if (!intel_dp_is_edp(intel_dp))
 		return;
 
 	/* now it's all ours */
-	intel_dp->pps_pipe = crtc->pipe;
+	intel_dp->pps.pps_pipe = crtc->pipe;
 
 	drm_dbg_kms(&dev_priv->drm,
 		    "initializing pipe %c power sequencer for [ENCODER:%d:%s]\n",
-		    pipe_name(intel_dp->pps_pipe), encoder->base.base.id,
+		    pipe_name(intel_dp->pps.pps_pipe), encoder->base.base.id,
 		    encoder->base.name);
 
 	/* init power sequencer on this pipe and port */
@@ -1063,9 +1063,9 @@ static void intel_pps_vdd_sanitize(struct intel_dp *intel_dp)
 	 */
 	drm_dbg_kms(&dev_priv->drm,
 		    "VDD left on by BIOS, adjusting state tracking\n");
-	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
-	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
-							intel_aux_power_domain(dig_port));
+	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.vdd_wakeref);
+	intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv,
+							    intel_aux_power_domain(dig_port));
 
 	edp_panel_vdd_schedule_off(intel_dp);
 }
@@ -1085,9 +1085,9 @@ bool intel_pps_have_power(struct intel_dp *intel_dp)
 
 static void pps_init_timestamps(struct intel_dp *intel_dp)
 {
-	intel_dp->panel_power_off_time = ktime_get_boottime();
-	intel_dp->last_power_on = jiffies;
-	intel_dp->last_backlight_off = jiffies;
+	intel_dp->pps.panel_power_off_time = ktime_get_boottime();
+	intel_dp->pps.last_power_on = jiffies;
+	intel_dp->pps.last_backlight_off = jiffies;
 }
 
 static void
@@ -1137,7 +1137,7 @@ static void
 intel_pps_verify_state(struct intel_dp *intel_dp)
 {
 	struct edp_power_seq hw;
-	struct edp_power_seq *sw = &intel_dp->pps_delays;
+	struct edp_power_seq *sw = &intel_dp->pps.pps_delays;
 
 	intel_pps_readout_hw_state(intel_dp, &hw);
 
@@ -1153,7 +1153,7 @@ static void pps_init_delays(struct intel_dp *intel_dp)
 {
 	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
 	struct edp_power_seq cur, vbt, spec,
-		*final = &intel_dp->pps_delays;
+		*final = &intel_dp->pps.pps_delays;
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
@@ -1210,22 +1210,22 @@ static void pps_init_delays(struct intel_dp *intel_dp)
 #undef assign_final
 
 #define get_delay(field)	(DIV_ROUND_UP(final->field, 10))
-	intel_dp->panel_power_up_delay = get_delay(t1_t3);
-	intel_dp->backlight_on_delay = get_delay(t8);
-	intel_dp->backlight_off_delay = get_delay(t9);
-	intel_dp->panel_power_down_delay = get_delay(t10);
-	intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
+	intel_dp->pps.panel_power_up_delay = get_delay(t1_t3);
+	intel_dp->pps.backlight_on_delay = get_delay(t8);
+	intel_dp->pps.backlight_off_delay = get_delay(t9);
+	intel_dp->pps.panel_power_down_delay = get_delay(t10);
+	intel_dp->pps.panel_power_cycle_delay = get_delay(t11_t12);
 #undef get_delay
 
 	drm_dbg_kms(&dev_priv->drm,
 		    "panel power up delay %d, power down delay %d, power cycle delay %d\n",
-		    intel_dp->panel_power_up_delay,
-		    intel_dp->panel_power_down_delay,
-		    intel_dp->panel_power_cycle_delay);
+		    intel_dp->pps.panel_power_up_delay,
+		    intel_dp->pps.panel_power_down_delay,
+		    intel_dp->pps.panel_power_cycle_delay);
 
 	drm_dbg_kms(&dev_priv->drm, "backlight on delay %d, off delay %d\n",
-		    intel_dp->backlight_on_delay,
-		    intel_dp->backlight_off_delay);
+		    intel_dp->pps.backlight_on_delay,
+		    intel_dp->pps.backlight_off_delay);
 
 	/*
 	 * We override the HW backlight delays to 1 because we do manual waits
@@ -1251,7 +1251,7 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
 	int div = RUNTIME_INFO(dev_priv)->rawclk_freq / 1000;
 	struct pps_registers regs;
 	enum port port = dp_to_dig_port(intel_dp)->base.port;
-	const struct edp_power_seq *seq = &intel_dp->pps_delays;
+	const struct edp_power_seq *seq = &intel_dp->pps.pps_delays;
 
 	lockdep_assert_held(&dev_priv->pps_mutex);
 
@@ -1364,7 +1364,7 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp)
 
 void intel_pps_init(struct intel_dp *intel_dp)
 {
-	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work);
+	INIT_DELAYED_WORK(&intel_dp->pps.panel_vdd_work, edp_panel_vdd_work);
 
 	pps_init_timestamps(intel_dp);
 
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] [PATCH v2 17/17] drm/i915/dp: split out aux functionality to intel_dp_aux.c
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (15 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 16/17] drm/i915/dp: abstract struct intel_dp pps members to a sub-struct Jani Nikula
@ 2021-01-08 17:44 ` Jani Nikula
  2021-01-20  4:44   ` Gupta, Anshuman
  2021-01-08 19:23 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/dp: split out pps and aux (rev2) Patchwork
                   ` (3 subsequent siblings)
  20 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2021-01-08 17:44 UTC (permalink / raw)
  To: intel-gfx; +Cc: jani.nikula

Split out the DP aux functionality to a new intel_dp_aux.[ch]. This is a
surprisingly clean cut.

Signed-off-by: Jani Nikula <jani.nikula@intel.com>
---
 drivers/gpu/drm/i915/Makefile               |   1 +
 drivers/gpu/drm/i915/display/intel_dp.c     | 680 +------------------
 drivers/gpu/drm/i915/display/intel_dp_aux.c | 687 ++++++++++++++++++++
 drivers/gpu/drm/i915/display/intel_dp_aux.h |  18 +
 4 files changed, 707 insertions(+), 679 deletions(-)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_aux.c
 create mode 100644 drivers/gpu/drm/i915/display/intel_dp_aux.h

diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
index 8a04403a11bb..71df8cbd63bc 100644
--- a/drivers/gpu/drm/i915/Makefile
+++ b/drivers/gpu/drm/i915/Makefile
@@ -238,6 +238,7 @@ i915-y += \
 	display/intel_crt.o \
 	display/intel_ddi.o \
 	display/intel_dp.o \
+	display/intel_dp_aux.o \
 	display/intel_dp_aux_backlight.o \
 	display/intel_dp_hdcp.o \
 	display/intel_dp_link_training.o \
diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
index e6859b9925b9..1705d58bf64c 100644
--- a/drivers/gpu/drm/i915/display/intel_dp.c
+++ b/drivers/gpu/drm/i915/display/intel_dp.c
@@ -41,13 +41,13 @@
 
 #include "i915_debugfs.h"
 #include "i915_drv.h"
-#include "i915_trace.h"
 #include "intel_atomic.h"
 #include "intel_audio.h"
 #include "intel_connector.h"
 #include "intel_ddi.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
+#include "intel_dp_aux.h"
 #include "intel_dp_link_training.h"
 #include "intel_dp_mst.h"
 #include "intel_dpio_phy.h"
@@ -856,684 +856,6 @@ intel_dp_mode_valid(struct drm_connector *connector,
 	return intel_mode_valid_max_plane_size(dev_priv, mode, bigjoiner);
 }
 
-u32 intel_dp_pack_aux(const u8 *src, int src_bytes)
-{
-	int i;
-	u32 v = 0;
-
-	if (src_bytes > 4)
-		src_bytes = 4;
-	for (i = 0; i < src_bytes; i++)
-		v |= ((u32)src[i]) << ((3 - i) * 8);
-	return v;
-}
-
-static void intel_dp_unpack_aux(u32 src, u8 *dst, int dst_bytes)
-{
-	int i;
-	if (dst_bytes > 4)
-		dst_bytes = 4;
-	for (i = 0; i < dst_bytes; i++)
-		dst[i] = src >> ((3-i) * 8);
-}
-
-static u32
-intel_dp_aux_wait_done(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-	i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
-	const unsigned int timeout_ms = 10;
-	u32 status;
-	bool done;
-
-#define C (((status = intel_uncore_read_notrace(&i915->uncore, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
-	done = wait_event_timeout(i915->gmbus_wait_queue, C,
-				  msecs_to_jiffies_timeout(timeout_ms));
-
-	/* just trace the final value */
-	trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);
-
-	if (!done)
-		drm_err(&i915->drm,
-			"%s: did not complete or timeout within %ums (status 0x%08x)\n",
-			intel_dp->aux.name, timeout_ms, status);
-#undef C
-
-	return status;
-}
-
-static u32 g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-
-	if (index)
-		return 0;
-
-	/*
-	 * The clock divider is based off the hrawclk, and would like to run at
-	 * 2MHz.  So, take the hrawclk value and divide by 2000 and use that
-	 */
-	return DIV_ROUND_CLOSEST(RUNTIME_INFO(dev_priv)->rawclk_freq, 2000);
-}
-
-static u32 ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	u32 freq;
-
-	if (index)
-		return 0;
-
-	/*
-	 * The clock divider is based off the cdclk or PCH rawclk, and would
-	 * like to run at 2MHz.  So, take the cdclk or PCH rawclk value and
-	 * divide by 2000 and use that
-	 */
-	if (dig_port->aux_ch == AUX_CH_A)
-		freq = dev_priv->cdclk.hw.cdclk;
-	else
-		freq = RUNTIME_INFO(dev_priv)->rawclk_freq;
-	return DIV_ROUND_CLOSEST(freq, 2000);
-}
-
-static u32 hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-
-	if (dig_port->aux_ch != AUX_CH_A && HAS_PCH_LPT_H(dev_priv)) {
-		/* Workaround for non-ULT HSW */
-		switch (index) {
-		case 0: return 63;
-		case 1: return 72;
-		default: return 0;
-		}
-	}
-
-	return ilk_get_aux_clock_divider(intel_dp, index);
-}
-
-static u32 skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
-{
-	/*
-	 * SKL doesn't need us to program the AUX clock divider (Hardware will
-	 * derive the clock from CDCLK automatically). We still implement the
-	 * get_aux_clock_divider vfunc to plug-in into the existing code.
-	 */
-	return index ? 0 : 1;
-}
-
-static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
-				int send_bytes,
-				u32 aux_clock_divider)
-{
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_i915_private *dev_priv =
-			to_i915(dig_port->base.base.dev);
-	u32 precharge, timeout;
-
-	if (IS_GEN(dev_priv, 6))
-		precharge = 3;
-	else
-		precharge = 5;
-
-	if (IS_BROADWELL(dev_priv))
-		timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
-	else
-		timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
-
-	return DP_AUX_CH_CTL_SEND_BUSY |
-	       DP_AUX_CH_CTL_DONE |
-	       DP_AUX_CH_CTL_INTERRUPT |
-	       DP_AUX_CH_CTL_TIME_OUT_ERROR |
-	       timeout |
-	       DP_AUX_CH_CTL_RECEIVE_ERROR |
-	       (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
-	       (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
-	       (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT);
-}
-
-static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
-				int send_bytes,
-				u32 unused)
-{
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_i915_private *i915 =
-			to_i915(dig_port->base.base.dev);
-	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
-	u32 ret;
-
-	ret = DP_AUX_CH_CTL_SEND_BUSY |
-	      DP_AUX_CH_CTL_DONE |
-	      DP_AUX_CH_CTL_INTERRUPT |
-	      DP_AUX_CH_CTL_TIME_OUT_ERROR |
-	      DP_AUX_CH_CTL_TIME_OUT_MAX |
-	      DP_AUX_CH_CTL_RECEIVE_ERROR |
-	      (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
-	      DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) |
-	      DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
-
-	if (intel_phy_is_tc(i915, phy) &&
-	    dig_port->tc_mode == TC_PORT_TBT_ALT)
-		ret |= DP_AUX_CH_CTL_TBT_IO;
-
-	return ret;
-}
-
-static int
-intel_dp_aux_xfer(struct intel_dp *intel_dp,
-		  const u8 *send, int send_bytes,
-		  u8 *recv, int recv_size,
-		  u32 aux_send_ctl_flags)
-{
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct drm_i915_private *i915 =
-			to_i915(dig_port->base.base.dev);
-	struct intel_uncore *uncore = &i915->uncore;
-	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
-	bool is_tc_port = intel_phy_is_tc(i915, phy);
-	i915_reg_t ch_ctl, ch_data[5];
-	u32 aux_clock_divider;
-	enum intel_display_power_domain aux_domain;
-	intel_wakeref_t aux_wakeref;
-	intel_wakeref_t pps_wakeref;
-	int i, ret, recv_bytes;
-	int try, clock = 0;
-	u32 status;
-	bool vdd;
-
-	ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
-	for (i = 0; i < ARRAY_SIZE(ch_data); i++)
-		ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
-
-	if (is_tc_port)
-		intel_tc_port_lock(dig_port);
-
-	aux_domain = intel_aux_power_domain(dig_port);
-
-	aux_wakeref = intel_display_power_get(i915, aux_domain);
-	pps_wakeref = intel_pps_lock(intel_dp);
-
-	/*
-	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
-	 * In such cases we want to leave VDD enabled and it's up to upper layers
-	 * to turn it off. But for eg. i2c-dev access we need to turn it on/off
-	 * ourselves.
-	 */
-	vdd = intel_pps_vdd_on_unlocked(intel_dp);
-
-	/* dp aux is extremely sensitive to irq latency, hence request the
-	 * lowest possible wakeup latency and so prevent the cpu from going into
-	 * deep sleep states.
-	 */
-	cpu_latency_qos_update_request(&intel_dp->pm_qos, 0);
-
-	intel_pps_check_power_unlocked(intel_dp);
-
-	/* Try to wait for any previous AUX channel activity */
-	for (try = 0; try < 3; try++) {
-		status = intel_uncore_read_notrace(uncore, ch_ctl);
-		if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
-			break;
-		msleep(1);
-	}
-	/* just trace the final value */
-	trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);
-
-	if (try == 3) {
-		const u32 status = intel_uncore_read(uncore, ch_ctl);
-
-		if (status != intel_dp->aux_busy_last_status) {
-			drm_WARN(&i915->drm, 1,
-				 "%s: not started (status 0x%08x)\n",
-				 intel_dp->aux.name, status);
-			intel_dp->aux_busy_last_status = status;
-		}
-
-		ret = -EBUSY;
-		goto out;
-	}
-
-	/* Only 5 data registers! */
-	if (drm_WARN_ON(&i915->drm, send_bytes > 20 || recv_size > 20)) {
-		ret = -E2BIG;
-		goto out;
-	}
-
-	while ((aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, clock++))) {
-		u32 send_ctl = intel_dp->get_aux_send_ctl(intel_dp,
-							  send_bytes,
-							  aux_clock_divider);
-
-		send_ctl |= aux_send_ctl_flags;
-
-		/* Must try at least 3 times according to DP spec */
-		for (try = 0; try < 5; try++) {
-			/* Load the send data into the aux channel data registers */
-			for (i = 0; i < send_bytes; i += 4)
-				intel_uncore_write(uncore,
-						   ch_data[i >> 2],
-						   intel_dp_pack_aux(send + i,
-								     send_bytes - i));
-
-			/* Send the command and wait for it to complete */
-			intel_uncore_write(uncore, ch_ctl, send_ctl);
-
-			status = intel_dp_aux_wait_done(intel_dp);
-
-			/* Clear done status and any errors */
-			intel_uncore_write(uncore,
-					   ch_ctl,
-					   status |
-					   DP_AUX_CH_CTL_DONE |
-					   DP_AUX_CH_CTL_TIME_OUT_ERROR |
-					   DP_AUX_CH_CTL_RECEIVE_ERROR);
-
-			/* DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2
-			 *   400us delay required for errors and timeouts
-			 *   Timeout errors from the HW already meet this
-			 *   requirement so skip to next iteration
-			 */
-			if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR)
-				continue;
-
-			if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
-				usleep_range(400, 500);
-				continue;
-			}
-			if (status & DP_AUX_CH_CTL_DONE)
-				goto done;
-		}
-	}
-
-	if ((status & DP_AUX_CH_CTL_DONE) == 0) {
-		drm_err(&i915->drm, "%s: not done (status 0x%08x)\n",
-			intel_dp->aux.name, status);
-		ret = -EBUSY;
-		goto out;
-	}
-
-done:
-	/* Check for timeout or receive error.
-	 * Timeouts occur when the sink is not connected
-	 */
-	if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
-		drm_err(&i915->drm, "%s: receive error (status 0x%08x)\n",
-			intel_dp->aux.name, status);
-		ret = -EIO;
-		goto out;
-	}
-
-	/* Timeouts occur when the device isn't connected, so they're
-	 * "normal" -- don't fill the kernel log with these */
-	if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
-		drm_dbg_kms(&i915->drm, "%s: timeout (status 0x%08x)\n",
-			    intel_dp->aux.name, status);
-		ret = -ETIMEDOUT;
-		goto out;
-	}
-
-	/* Unload any bytes sent back from the other side */
-	recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
-		      DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
-
-	/*
-	 * By BSpec: "Message sizes of 0 or >20 are not allowed."
-	 * We have no idea of what happened so we return -EBUSY so
-	 * drm layer takes care for the necessary retries.
-	 */
-	if (recv_bytes == 0 || recv_bytes > 20) {
-		drm_dbg_kms(&i915->drm,
-			    "%s: Forbidden recv_bytes = %d on aux transaction\n",
-			    intel_dp->aux.name, recv_bytes);
-		ret = -EBUSY;
-		goto out;
-	}
-
-	if (recv_bytes > recv_size)
-		recv_bytes = recv_size;
-
-	for (i = 0; i < recv_bytes; i += 4)
-		intel_dp_unpack_aux(intel_uncore_read(uncore, ch_data[i >> 2]),
-				    recv + i, recv_bytes - i);
-
-	ret = recv_bytes;
-out:
-	cpu_latency_qos_update_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
-
-	if (vdd)
-		intel_pps_vdd_off_unlocked(intel_dp, false);
-
-	intel_pps_unlock(intel_dp, pps_wakeref);
-	intel_display_power_put_async(i915, aux_domain, aux_wakeref);
-
-	if (is_tc_port)
-		intel_tc_port_unlock(dig_port);
-
-	return ret;
-}
-
-#define BARE_ADDRESS_SIZE	3
-#define HEADER_SIZE		(BARE_ADDRESS_SIZE + 1)
-
-static void
-intel_dp_aux_header(u8 txbuf[HEADER_SIZE],
-		    const struct drm_dp_aux_msg *msg)
-{
-	txbuf[0] = (msg->request << 4) | ((msg->address >> 16) & 0xf);
-	txbuf[1] = (msg->address >> 8) & 0xff;
-	txbuf[2] = msg->address & 0xff;
-	txbuf[3] = msg->size - 1;
-}
-
-static u32 intel_dp_aux_xfer_flags(const struct drm_dp_aux_msg *msg)
-{
-	/*
-	 * If we're trying to send the HDCP Aksv, we need to set a the Aksv
-	 * select bit to inform the hardware to send the Aksv after our header
-	 * since we can't access that data from software.
-	 */
-	if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE &&
-	    msg->address == DP_AUX_HDCP_AKSV)
-		return DP_AUX_CH_CTL_AUX_AKSV_SELECT;
-
-	return 0;
-}
-
-static ssize_t
-intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
-{
-	struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux);
-	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
-	u8 txbuf[20], rxbuf[20];
-	size_t txsize, rxsize;
-	u32 flags = intel_dp_aux_xfer_flags(msg);
-	int ret;
-
-	intel_dp_aux_header(txbuf, msg);
-
-	switch (msg->request & ~DP_AUX_I2C_MOT) {
-	case DP_AUX_NATIVE_WRITE:
-	case DP_AUX_I2C_WRITE:
-	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
-		txsize = msg->size ? HEADER_SIZE + msg->size : BARE_ADDRESS_SIZE;
-		rxsize = 2; /* 0 or 1 data bytes */
-
-		if (drm_WARN_ON(&i915->drm, txsize > 20))
-			return -E2BIG;
-
-		drm_WARN_ON(&i915->drm, !msg->buffer != !msg->size);
-
-		if (msg->buffer)
-			memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size);
-
-		ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize,
-					rxbuf, rxsize, flags);
-		if (ret > 0) {
-			msg->reply = rxbuf[0] >> 4;
-
-			if (ret > 1) {
-				/* Number of bytes written in a short write. */
-				ret = clamp_t(int, rxbuf[1], 0, msg->size);
-			} else {
-				/* Return payload size. */
-				ret = msg->size;
-			}
-		}
-		break;
-
-	case DP_AUX_NATIVE_READ:
-	case DP_AUX_I2C_READ:
-		txsize = msg->size ? HEADER_SIZE : BARE_ADDRESS_SIZE;
-		rxsize = msg->size + 1;
-
-		if (drm_WARN_ON(&i915->drm, rxsize > 20))
-			return -E2BIG;
-
-		ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize,
-					rxbuf, rxsize, flags);
-		if (ret > 0) {
-			msg->reply = rxbuf[0] >> 4;
-			/*
-			 * Assume happy day, and copy the data. The caller is
-			 * expected to check msg->reply before touching it.
-			 *
-			 * Return payload size.
-			 */
-			ret--;
-			memcpy(msg->buffer, rxbuf + 1, ret);
-		}
-		break;
-
-	default:
-		ret = -EINVAL;
-		break;
-	}
-
-	return ret;
-}
-
-
-static i915_reg_t g4x_aux_ctl_reg(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum aux_ch aux_ch = dig_port->aux_ch;
-
-	switch (aux_ch) {
-	case AUX_CH_B:
-	case AUX_CH_C:
-	case AUX_CH_D:
-		return DP_AUX_CH_CTL(aux_ch);
-	default:
-		MISSING_CASE(aux_ch);
-		return DP_AUX_CH_CTL(AUX_CH_B);
-	}
-}
-
-static i915_reg_t g4x_aux_data_reg(struct intel_dp *intel_dp, int index)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum aux_ch aux_ch = dig_port->aux_ch;
-
-	switch (aux_ch) {
-	case AUX_CH_B:
-	case AUX_CH_C:
-	case AUX_CH_D:
-		return DP_AUX_CH_DATA(aux_ch, index);
-	default:
-		MISSING_CASE(aux_ch);
-		return DP_AUX_CH_DATA(AUX_CH_B, index);
-	}
-}
-
-static i915_reg_t ilk_aux_ctl_reg(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum aux_ch aux_ch = dig_port->aux_ch;
-
-	switch (aux_ch) {
-	case AUX_CH_A:
-		return DP_AUX_CH_CTL(aux_ch);
-	case AUX_CH_B:
-	case AUX_CH_C:
-	case AUX_CH_D:
-		return PCH_DP_AUX_CH_CTL(aux_ch);
-	default:
-		MISSING_CASE(aux_ch);
-		return DP_AUX_CH_CTL(AUX_CH_A);
-	}
-}
-
-static i915_reg_t ilk_aux_data_reg(struct intel_dp *intel_dp, int index)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum aux_ch aux_ch = dig_port->aux_ch;
-
-	switch (aux_ch) {
-	case AUX_CH_A:
-		return DP_AUX_CH_DATA(aux_ch, index);
-	case AUX_CH_B:
-	case AUX_CH_C:
-	case AUX_CH_D:
-		return PCH_DP_AUX_CH_DATA(aux_ch, index);
-	default:
-		MISSING_CASE(aux_ch);
-		return DP_AUX_CH_DATA(AUX_CH_A, index);
-	}
-}
-
-static i915_reg_t skl_aux_ctl_reg(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum aux_ch aux_ch = dig_port->aux_ch;
-
-	switch (aux_ch) {
-	case AUX_CH_A:
-	case AUX_CH_B:
-	case AUX_CH_C:
-	case AUX_CH_D:
-	case AUX_CH_E:
-	case AUX_CH_F:
-		return DP_AUX_CH_CTL(aux_ch);
-	default:
-		MISSING_CASE(aux_ch);
-		return DP_AUX_CH_CTL(AUX_CH_A);
-	}
-}
-
-static i915_reg_t skl_aux_data_reg(struct intel_dp *intel_dp, int index)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum aux_ch aux_ch = dig_port->aux_ch;
-
-	switch (aux_ch) {
-	case AUX_CH_A:
-	case AUX_CH_B:
-	case AUX_CH_C:
-	case AUX_CH_D:
-	case AUX_CH_E:
-	case AUX_CH_F:
-		return DP_AUX_CH_DATA(aux_ch, index);
-	default:
-		MISSING_CASE(aux_ch);
-		return DP_AUX_CH_DATA(AUX_CH_A, index);
-	}
-}
-
-static i915_reg_t tgl_aux_ctl_reg(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum aux_ch aux_ch = dig_port->aux_ch;
-
-	switch (aux_ch) {
-	case AUX_CH_A:
-	case AUX_CH_B:
-	case AUX_CH_C:
-	case AUX_CH_USBC1:
-	case AUX_CH_USBC2:
-	case AUX_CH_USBC3:
-	case AUX_CH_USBC4:
-	case AUX_CH_USBC5:
-	case AUX_CH_USBC6:
-		return DP_AUX_CH_CTL(aux_ch);
-	default:
-		MISSING_CASE(aux_ch);
-		return DP_AUX_CH_CTL(AUX_CH_A);
-	}
-}
-
-static i915_reg_t tgl_aux_data_reg(struct intel_dp *intel_dp, int index)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	enum aux_ch aux_ch = dig_port->aux_ch;
-
-	switch (aux_ch) {
-	case AUX_CH_A:
-	case AUX_CH_B:
-	case AUX_CH_C:
-	case AUX_CH_USBC1:
-	case AUX_CH_USBC2:
-	case AUX_CH_USBC3:
-	case AUX_CH_USBC4:
-	case AUX_CH_USBC5:
-	case AUX_CH_USBC6:
-		return DP_AUX_CH_DATA(aux_ch, index);
-	default:
-		MISSING_CASE(aux_ch);
-		return DP_AUX_CH_DATA(AUX_CH_A, index);
-	}
-}
-
-static void
-intel_dp_aux_fini(struct intel_dp *intel_dp)
-{
-	if (cpu_latency_qos_request_active(&intel_dp->pm_qos))
-		cpu_latency_qos_remove_request(&intel_dp->pm_qos);
-
-	kfree(intel_dp->aux.name);
-}
-
-static void
-intel_dp_aux_init(struct intel_dp *intel_dp)
-{
-	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
-	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
-	struct intel_encoder *encoder = &dig_port->base;
-	enum aux_ch aux_ch = dig_port->aux_ch;
-
-	if (INTEL_GEN(dev_priv) >= 12) {
-		intel_dp->aux_ch_ctl_reg = tgl_aux_ctl_reg;
-		intel_dp->aux_ch_data_reg = tgl_aux_data_reg;
-	} else if (INTEL_GEN(dev_priv) >= 9) {
-		intel_dp->aux_ch_ctl_reg = skl_aux_ctl_reg;
-		intel_dp->aux_ch_data_reg = skl_aux_data_reg;
-	} else if (HAS_PCH_SPLIT(dev_priv)) {
-		intel_dp->aux_ch_ctl_reg = ilk_aux_ctl_reg;
-		intel_dp->aux_ch_data_reg = ilk_aux_data_reg;
-	} else {
-		intel_dp->aux_ch_ctl_reg = g4x_aux_ctl_reg;
-		intel_dp->aux_ch_data_reg = g4x_aux_data_reg;
-	}
-
-	if (INTEL_GEN(dev_priv) >= 9)
-		intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
-	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
-		intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
-	else if (HAS_PCH_SPLIT(dev_priv))
-		intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
-	else
-		intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider;
-
-	if (INTEL_GEN(dev_priv) >= 9)
-		intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
-	else
-		intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
-
-	drm_dp_aux_init(&intel_dp->aux);
-
-	/* Failure to allocate our preferred name is not critical */
-	if (INTEL_GEN(dev_priv) >= 12 && aux_ch >= AUX_CH_USBC1)
-		intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX USBC%c/%s",
-					       aux_ch - AUX_CH_USBC1 + '1',
-					       encoder->base.name);
-	else
-		intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %c/%s",
-					       aux_ch_name(aux_ch),
-					       encoder->base.name);
-
-	intel_dp->aux.transfer = intel_dp_aux_transfer;
-	cpu_latency_qos_add_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
-}
-
 bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp)
 {
 	int max_rate = intel_dp->source_rates[intel_dp->num_source_rates - 1];
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.c b/drivers/gpu/drm/i915/display/intel_dp_aux.c
new file mode 100644
index 000000000000..3d96ab5851df
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
@@ -0,0 +1,687 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#include "i915_drv.h"
+#include "i915_trace.h"
+#include "intel_display_types.h"
+#include "intel_dp_aux.h"
+#include "intel_pps.h"
+#include "intel_tc.h"
+
+u32 intel_dp_pack_aux(const u8 *src, int src_bytes)
+{
+	int i;
+	u32 v = 0;
+
+	if (src_bytes > 4)
+		src_bytes = 4;
+	for (i = 0; i < src_bytes; i++)
+		v |= ((u32)src[i]) << ((3 - i) * 8);
+	return v;
+}
+
+static void intel_dp_unpack_aux(u32 src, u8 *dst, int dst_bytes)
+{
+	int i;
+	if (dst_bytes > 4)
+		dst_bytes = 4;
+	for (i = 0; i < dst_bytes; i++)
+		dst[i] = src >> ((3-i) * 8);
+}
+
+static u32
+intel_dp_aux_wait_done(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
+	const unsigned int timeout_ms = 10;
+	u32 status;
+	bool done;
+
+#define C (((status = intel_uncore_read_notrace(&i915->uncore, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)
+	done = wait_event_timeout(i915->gmbus_wait_queue, C,
+				  msecs_to_jiffies_timeout(timeout_ms));
+
+	/* just trace the final value */
+	trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);
+
+	if (!done)
+		drm_err(&i915->drm,
+			"%s: did not complete or timeout within %ums (status 0x%08x)\n",
+			intel_dp->aux.name, timeout_ms, status);
+#undef C
+
+	return status;
+}
+
+static u32 g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+
+	if (index)
+		return 0;
+
+	/*
+	 * The clock divider is based off the hrawclk, and would like to run at
+	 * 2MHz.  So, take the hrawclk value and divide by 2000 and use that
+	 */
+	return DIV_ROUND_CLOSEST(RUNTIME_INFO(dev_priv)->rawclk_freq, 2000);
+}
+
+static u32 ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	u32 freq;
+
+	if (index)
+		return 0;
+
+	/*
+	 * The clock divider is based off the cdclk or PCH rawclk, and would
+	 * like to run at 2MHz.  So, take the cdclk or PCH rawclk value and
+	 * divide by 2000 and use that
+	 */
+	if (dig_port->aux_ch == AUX_CH_A)
+		freq = dev_priv->cdclk.hw.cdclk;
+	else
+		freq = RUNTIME_INFO(dev_priv)->rawclk_freq;
+	return DIV_ROUND_CLOSEST(freq, 2000);
+}
+
+static u32 hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+
+	if (dig_port->aux_ch != AUX_CH_A && HAS_PCH_LPT_H(dev_priv)) {
+		/* Workaround for non-ULT HSW */
+		switch (index) {
+		case 0: return 63;
+		case 1: return 72;
+		default: return 0;
+		}
+	}
+
+	return ilk_get_aux_clock_divider(intel_dp, index);
+}
+
+static u32 skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
+{
+	/*
+	 * SKL doesn't need us to program the AUX clock divider (Hardware will
+	 * derive the clock from CDCLK automatically). We still implement the
+	 * get_aux_clock_divider vfunc to plug-in into the existing code.
+	 */
+	return index ? 0 : 1;
+}
+
+static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
+				int send_bytes,
+				u32 aux_clock_divider)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct drm_i915_private *dev_priv =
+			to_i915(dig_port->base.base.dev);
+	u32 precharge, timeout;
+
+	if (IS_GEN(dev_priv, 6))
+		precharge = 3;
+	else
+		precharge = 5;
+
+	if (IS_BROADWELL(dev_priv))
+		timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
+	else
+		timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
+
+	return DP_AUX_CH_CTL_SEND_BUSY |
+	       DP_AUX_CH_CTL_DONE |
+	       DP_AUX_CH_CTL_INTERRUPT |
+	       DP_AUX_CH_CTL_TIME_OUT_ERROR |
+	       timeout |
+	       DP_AUX_CH_CTL_RECEIVE_ERROR |
+	       (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+	       (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
+	       (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT);
+}
+
+static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
+				int send_bytes,
+				u32 unused)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct drm_i915_private *i915 =
+			to_i915(dig_port->base.base.dev);
+	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
+	u32 ret;
+
+	ret = DP_AUX_CH_CTL_SEND_BUSY |
+	      DP_AUX_CH_CTL_DONE |
+	      DP_AUX_CH_CTL_INTERRUPT |
+	      DP_AUX_CH_CTL_TIME_OUT_ERROR |
+	      DP_AUX_CH_CTL_TIME_OUT_MAX |
+	      DP_AUX_CH_CTL_RECEIVE_ERROR |
+	      (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
+	      DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) |
+	      DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
+
+	if (intel_phy_is_tc(i915, phy) &&
+	    dig_port->tc_mode == TC_PORT_TBT_ALT)
+		ret |= DP_AUX_CH_CTL_TBT_IO;
+
+	return ret;
+}
+
+static int
+intel_dp_aux_xfer(struct intel_dp *intel_dp,
+		  const u8 *send, int send_bytes,
+		  u8 *recv, int recv_size,
+		  u32 aux_send_ctl_flags)
+{
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct drm_i915_private *i915 =
+			to_i915(dig_port->base.base.dev);
+	struct intel_uncore *uncore = &i915->uncore;
+	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
+	bool is_tc_port = intel_phy_is_tc(i915, phy);
+	i915_reg_t ch_ctl, ch_data[5];
+	u32 aux_clock_divider;
+	enum intel_display_power_domain aux_domain;
+	intel_wakeref_t aux_wakeref;
+	intel_wakeref_t pps_wakeref;
+	int i, ret, recv_bytes;
+	int try, clock = 0;
+	u32 status;
+	bool vdd;
+
+	ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
+	for (i = 0; i < ARRAY_SIZE(ch_data); i++)
+		ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
+
+	if (is_tc_port)
+		intel_tc_port_lock(dig_port);
+
+	aux_domain = intel_aux_power_domain(dig_port);
+
+	aux_wakeref = intel_display_power_get(i915, aux_domain);
+	pps_wakeref = intel_pps_lock(intel_dp);
+
+	/*
+	 * We will be called with VDD already enabled for dpcd/edid/oui reads.
+	 * In such cases we want to leave VDD enabled and it's up to upper layers
+	 * to turn it off. But for eg. i2c-dev access we need to turn it on/off
+	 * ourselves.
+	 */
+	vdd = intel_pps_vdd_on_unlocked(intel_dp);
+
+	/* dp aux is extremely sensitive to irq latency, hence request the
+	 * lowest possible wakeup latency and so prevent the cpu from going into
+	 * deep sleep states.
+	 */
+	cpu_latency_qos_update_request(&intel_dp->pm_qos, 0);
+
+	intel_pps_check_power_unlocked(intel_dp);
+
+	/* Try to wait for any previous AUX channel activity */
+	for (try = 0; try < 3; try++) {
+		status = intel_uncore_read_notrace(uncore, ch_ctl);
+		if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
+			break;
+		msleep(1);
+	}
+	/* just trace the final value */
+	trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);
+
+	if (try == 3) {
+		const u32 status = intel_uncore_read(uncore, ch_ctl);
+
+		if (status != intel_dp->aux_busy_last_status) {
+			drm_WARN(&i915->drm, 1,
+				 "%s: not started (status 0x%08x)\n",
+				 intel_dp->aux.name, status);
+			intel_dp->aux_busy_last_status = status;
+		}
+
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/* Only 5 data registers! */
+	if (drm_WARN_ON(&i915->drm, send_bytes > 20 || recv_size > 20)) {
+		ret = -E2BIG;
+		goto out;
+	}
+
+	while ((aux_clock_divider = intel_dp->get_aux_clock_divider(intel_dp, clock++))) {
+		u32 send_ctl = intel_dp->get_aux_send_ctl(intel_dp,
+							  send_bytes,
+							  aux_clock_divider);
+
+		send_ctl |= aux_send_ctl_flags;
+
+		/* Must try at least 3 times according to DP spec */
+		for (try = 0; try < 5; try++) {
+			/* Load the send data into the aux channel data registers */
+			for (i = 0; i < send_bytes; i += 4)
+				intel_uncore_write(uncore,
+						   ch_data[i >> 2],
+						   intel_dp_pack_aux(send + i,
+								     send_bytes - i));
+
+			/* Send the command and wait for it to complete */
+			intel_uncore_write(uncore, ch_ctl, send_ctl);
+
+			status = intel_dp_aux_wait_done(intel_dp);
+
+			/* Clear done status and any errors */
+			intel_uncore_write(uncore,
+					   ch_ctl,
+					   status |
+					   DP_AUX_CH_CTL_DONE |
+					   DP_AUX_CH_CTL_TIME_OUT_ERROR |
+					   DP_AUX_CH_CTL_RECEIVE_ERROR);
+
+			/* DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2
+			 *   400us delay required for errors and timeouts
+			 *   Timeout errors from the HW already meet this
+			 *   requirement so skip to next iteration
+			 */
+			if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR)
+				continue;
+
+			if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
+				usleep_range(400, 500);
+				continue;
+			}
+			if (status & DP_AUX_CH_CTL_DONE)
+				goto done;
+		}
+	}
+
+	if ((status & DP_AUX_CH_CTL_DONE) == 0) {
+		drm_err(&i915->drm, "%s: not done (status 0x%08x)\n",
+			intel_dp->aux.name, status);
+		ret = -EBUSY;
+		goto out;
+	}
+
+done:
+	/* Check for timeout or receive error.
+	 * Timeouts occur when the sink is not connected
+	 */
+	if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
+		drm_err(&i915->drm, "%s: receive error (status 0x%08x)\n",
+			intel_dp->aux.name, status);
+		ret = -EIO;
+		goto out;
+	}
+
+	/* Timeouts occur when the device isn't connected, so they're
+	 * "normal" -- don't fill the kernel log with these */
+	if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
+		drm_dbg_kms(&i915->drm, "%s: timeout (status 0x%08x)\n",
+			    intel_dp->aux.name, status);
+		ret = -ETIMEDOUT;
+		goto out;
+	}
+
+	/* Unload any bytes sent back from the other side */
+	recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK) >>
+		      DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
+
+	/*
+	 * By BSpec: "Message sizes of 0 or >20 are not allowed."
+	 * We have no idea of what happened so we return -EBUSY so
+	 * drm layer takes care for the necessary retries.
+	 */
+	if (recv_bytes == 0 || recv_bytes > 20) {
+		drm_dbg_kms(&i915->drm,
+			    "%s: Forbidden recv_bytes = %d on aux transaction\n",
+			    intel_dp->aux.name, recv_bytes);
+		ret = -EBUSY;
+		goto out;
+	}
+
+	if (recv_bytes > recv_size)
+		recv_bytes = recv_size;
+
+	for (i = 0; i < recv_bytes; i += 4)
+		intel_dp_unpack_aux(intel_uncore_read(uncore, ch_data[i >> 2]),
+				    recv + i, recv_bytes - i);
+
+	ret = recv_bytes;
+out:
+	cpu_latency_qos_update_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
+
+	if (vdd)
+		intel_pps_vdd_off_unlocked(intel_dp, false);
+
+	intel_pps_unlock(intel_dp, pps_wakeref);
+	intel_display_power_put_async(i915, aux_domain, aux_wakeref);
+
+	if (is_tc_port)
+		intel_tc_port_unlock(dig_port);
+
+	return ret;
+}
+
+#define BARE_ADDRESS_SIZE	3
+#define HEADER_SIZE		(BARE_ADDRESS_SIZE + 1)
+
+static void
+intel_dp_aux_header(u8 txbuf[HEADER_SIZE],
+		    const struct drm_dp_aux_msg *msg)
+{
+	txbuf[0] = (msg->request << 4) | ((msg->address >> 16) & 0xf);
+	txbuf[1] = (msg->address >> 8) & 0xff;
+	txbuf[2] = msg->address & 0xff;
+	txbuf[3] = msg->size - 1;
+}
+
+static u32 intel_dp_aux_xfer_flags(const struct drm_dp_aux_msg *msg)
+{
+	/*
+	 * If we're trying to send the HDCP Aksv, we need to set a the Aksv
+	 * select bit to inform the hardware to send the Aksv after our header
+	 * since we can't access that data from software.
+	 */
+	if ((msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_WRITE &&
+	    msg->address == DP_AUX_HDCP_AKSV)
+		return DP_AUX_CH_CTL_AUX_AKSV_SELECT;
+
+	return 0;
+}
+
+static ssize_t
+intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
+{
+	struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux);
+	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
+	u8 txbuf[20], rxbuf[20];
+	size_t txsize, rxsize;
+	u32 flags = intel_dp_aux_xfer_flags(msg);
+	int ret;
+
+	intel_dp_aux_header(txbuf, msg);
+
+	switch (msg->request & ~DP_AUX_I2C_MOT) {
+	case DP_AUX_NATIVE_WRITE:
+	case DP_AUX_I2C_WRITE:
+	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
+		txsize = msg->size ? HEADER_SIZE + msg->size : BARE_ADDRESS_SIZE;
+		rxsize = 2; /* 0 or 1 data bytes */
+
+		if (drm_WARN_ON(&i915->drm, txsize > 20))
+			return -E2BIG;
+
+		drm_WARN_ON(&i915->drm, !msg->buffer != !msg->size);
+
+		if (msg->buffer)
+			memcpy(txbuf + HEADER_SIZE, msg->buffer, msg->size);
+
+		ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize,
+					rxbuf, rxsize, flags);
+		if (ret > 0) {
+			msg->reply = rxbuf[0] >> 4;
+
+			if (ret > 1) {
+				/* Number of bytes written in a short write. */
+				ret = clamp_t(int, rxbuf[1], 0, msg->size);
+			} else {
+				/* Return payload size. */
+				ret = msg->size;
+			}
+		}
+		break;
+
+	case DP_AUX_NATIVE_READ:
+	case DP_AUX_I2C_READ:
+		txsize = msg->size ? HEADER_SIZE : BARE_ADDRESS_SIZE;
+		rxsize = msg->size + 1;
+
+		if (drm_WARN_ON(&i915->drm, rxsize > 20))
+			return -E2BIG;
+
+		ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize,
+					rxbuf, rxsize, flags);
+		if (ret > 0) {
+			msg->reply = rxbuf[0] >> 4;
+			/*
+			 * Assume happy day, and copy the data. The caller is
+			 * expected to check msg->reply before touching it.
+			 *
+			 * Return payload size.
+			 */
+			ret--;
+			memcpy(msg->buffer, rxbuf + 1, ret);
+		}
+		break;
+
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+
+static i915_reg_t g4x_aux_ctl_reg(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum aux_ch aux_ch = dig_port->aux_ch;
+
+	switch (aux_ch) {
+	case AUX_CH_B:
+	case AUX_CH_C:
+	case AUX_CH_D:
+		return DP_AUX_CH_CTL(aux_ch);
+	default:
+		MISSING_CASE(aux_ch);
+		return DP_AUX_CH_CTL(AUX_CH_B);
+	}
+}
+
+static i915_reg_t g4x_aux_data_reg(struct intel_dp *intel_dp, int index)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum aux_ch aux_ch = dig_port->aux_ch;
+
+	switch (aux_ch) {
+	case AUX_CH_B:
+	case AUX_CH_C:
+	case AUX_CH_D:
+		return DP_AUX_CH_DATA(aux_ch, index);
+	default:
+		MISSING_CASE(aux_ch);
+		return DP_AUX_CH_DATA(AUX_CH_B, index);
+	}
+}
+
+static i915_reg_t ilk_aux_ctl_reg(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum aux_ch aux_ch = dig_port->aux_ch;
+
+	switch (aux_ch) {
+	case AUX_CH_A:
+		return DP_AUX_CH_CTL(aux_ch);
+	case AUX_CH_B:
+	case AUX_CH_C:
+	case AUX_CH_D:
+		return PCH_DP_AUX_CH_CTL(aux_ch);
+	default:
+		MISSING_CASE(aux_ch);
+		return DP_AUX_CH_CTL(AUX_CH_A);
+	}
+}
+
+static i915_reg_t ilk_aux_data_reg(struct intel_dp *intel_dp, int index)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum aux_ch aux_ch = dig_port->aux_ch;
+
+	switch (aux_ch) {
+	case AUX_CH_A:
+		return DP_AUX_CH_DATA(aux_ch, index);
+	case AUX_CH_B:
+	case AUX_CH_C:
+	case AUX_CH_D:
+		return PCH_DP_AUX_CH_DATA(aux_ch, index);
+	default:
+		MISSING_CASE(aux_ch);
+		return DP_AUX_CH_DATA(AUX_CH_A, index);
+	}
+}
+
+static i915_reg_t skl_aux_ctl_reg(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum aux_ch aux_ch = dig_port->aux_ch;
+
+	switch (aux_ch) {
+	case AUX_CH_A:
+	case AUX_CH_B:
+	case AUX_CH_C:
+	case AUX_CH_D:
+	case AUX_CH_E:
+	case AUX_CH_F:
+		return DP_AUX_CH_CTL(aux_ch);
+	default:
+		MISSING_CASE(aux_ch);
+		return DP_AUX_CH_CTL(AUX_CH_A);
+	}
+}
+
+static i915_reg_t skl_aux_data_reg(struct intel_dp *intel_dp, int index)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum aux_ch aux_ch = dig_port->aux_ch;
+
+	switch (aux_ch) {
+	case AUX_CH_A:
+	case AUX_CH_B:
+	case AUX_CH_C:
+	case AUX_CH_D:
+	case AUX_CH_E:
+	case AUX_CH_F:
+		return DP_AUX_CH_DATA(aux_ch, index);
+	default:
+		MISSING_CASE(aux_ch);
+		return DP_AUX_CH_DATA(AUX_CH_A, index);
+	}
+}
+
+static i915_reg_t tgl_aux_ctl_reg(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum aux_ch aux_ch = dig_port->aux_ch;
+
+	switch (aux_ch) {
+	case AUX_CH_A:
+	case AUX_CH_B:
+	case AUX_CH_C:
+	case AUX_CH_USBC1:
+	case AUX_CH_USBC2:
+	case AUX_CH_USBC3:
+	case AUX_CH_USBC4:
+	case AUX_CH_USBC5:
+	case AUX_CH_USBC6:
+		return DP_AUX_CH_CTL(aux_ch);
+	default:
+		MISSING_CASE(aux_ch);
+		return DP_AUX_CH_CTL(AUX_CH_A);
+	}
+}
+
+static i915_reg_t tgl_aux_data_reg(struct intel_dp *intel_dp, int index)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	enum aux_ch aux_ch = dig_port->aux_ch;
+
+	switch (aux_ch) {
+	case AUX_CH_A:
+	case AUX_CH_B:
+	case AUX_CH_C:
+	case AUX_CH_USBC1:
+	case AUX_CH_USBC2:
+	case AUX_CH_USBC3:
+	case AUX_CH_USBC4:
+	case AUX_CH_USBC5:
+	case AUX_CH_USBC6:
+		return DP_AUX_CH_DATA(aux_ch, index);
+	default:
+		MISSING_CASE(aux_ch);
+		return DP_AUX_CH_DATA(AUX_CH_A, index);
+	}
+}
+
+void intel_dp_aux_fini(struct intel_dp *intel_dp)
+{
+	if (cpu_latency_qos_request_active(&intel_dp->pm_qos))
+		cpu_latency_qos_remove_request(&intel_dp->pm_qos);
+
+	kfree(intel_dp->aux.name);
+}
+
+void intel_dp_aux_init(struct intel_dp *intel_dp)
+{
+	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
+	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+	struct intel_encoder *encoder = &dig_port->base;
+	enum aux_ch aux_ch = dig_port->aux_ch;
+
+	if (INTEL_GEN(dev_priv) >= 12) {
+		intel_dp->aux_ch_ctl_reg = tgl_aux_ctl_reg;
+		intel_dp->aux_ch_data_reg = tgl_aux_data_reg;
+	} else if (INTEL_GEN(dev_priv) >= 9) {
+		intel_dp->aux_ch_ctl_reg = skl_aux_ctl_reg;
+		intel_dp->aux_ch_data_reg = skl_aux_data_reg;
+	} else if (HAS_PCH_SPLIT(dev_priv)) {
+		intel_dp->aux_ch_ctl_reg = ilk_aux_ctl_reg;
+		intel_dp->aux_ch_data_reg = ilk_aux_data_reg;
+	} else {
+		intel_dp->aux_ch_ctl_reg = g4x_aux_ctl_reg;
+		intel_dp->aux_ch_data_reg = g4x_aux_data_reg;
+	}
+
+	if (INTEL_GEN(dev_priv) >= 9)
+		intel_dp->get_aux_clock_divider = skl_get_aux_clock_divider;
+	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
+		intel_dp->get_aux_clock_divider = hsw_get_aux_clock_divider;
+	else if (HAS_PCH_SPLIT(dev_priv))
+		intel_dp->get_aux_clock_divider = ilk_get_aux_clock_divider;
+	else
+		intel_dp->get_aux_clock_divider = g4x_get_aux_clock_divider;
+
+	if (INTEL_GEN(dev_priv) >= 9)
+		intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
+	else
+		intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
+
+	drm_dp_aux_init(&intel_dp->aux);
+
+	/* Failure to allocate our preferred name is not critical */
+	if (INTEL_GEN(dev_priv) >= 12 && aux_ch >= AUX_CH_USBC1)
+		intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX USBC%c/%s",
+					       aux_ch - AUX_CH_USBC1 + '1',
+					       encoder->base.name);
+	else
+		intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %c/%s",
+					       aux_ch_name(aux_ch),
+					       encoder->base.name);
+
+	intel_dp->aux.transfer = intel_dp_aux_transfer;
+	cpu_latency_qos_add_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
+}
diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.h b/drivers/gpu/drm/i915/display/intel_dp_aux.h
new file mode 100644
index 000000000000..cea58dd86c49
--- /dev/null
+++ b/drivers/gpu/drm/i915/display/intel_dp_aux.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2020 Intel Corporation
+ */
+
+#ifndef __INTEL_DP_AUX_H__
+#define __INTEL_DP_AUX_H__
+
+#include <linux/types.h>
+
+struct intel_dp;
+
+u32 intel_dp_pack_aux(const u8 *src, int src_bytes);
+
+void intel_dp_aux_fini(struct intel_dp *intel_dp);
+void intel_dp_aux_init(struct intel_dp *intel_dp);
+
+#endif /* __INTEL_DP_AUX_H__ */
-- 
2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/dp: split out pps and aux (rev2)
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (16 preceding siblings ...)
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 17/17] drm/i915/dp: split out aux functionality to intel_dp_aux.c Jani Nikula
@ 2021-01-08 19:23 ` Patchwork
  2021-01-08 19:24 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
                   ` (2 subsequent siblings)
  20 siblings, 0 replies; 37+ messages in thread
From: Patchwork @ 2021-01-08 19:23 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/dp: split out pps and aux (rev2)
URL   : https://patchwork.freedesktop.org/series/85167/
State : warning

== Summary ==

$ dim checkpatch origin/drm-tip
1d7a1bfde18c drm/i915/pps: abstract panel power sequencer from intel_dp.c
-:1082: CHECK:LINE_SPACING: Please don't use multiple blank lines
#1082: FILE: drivers/gpu/drm/i915/display/intel_dp.c:2552:
 
+

-:1623: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#1623: 
new file mode 100644

-:2073: WARNING:LONG_LINE: line length of 107 exceeds 100 columns
#2073: FILE: drivers/gpu/drm/i915/display/intel_pps.c:446:
+#define IDLE_ON_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)

-:2074: WARNING:LONG_LINE: line length of 110 exceeds 100 columns
#2074: FILE: drivers/gpu/drm/i915/display/intel_pps.c:447:
+#define IDLE_ON_VALUE   	(PP_ON | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)

-:2074: WARNING:SPACE_BEFORE_TAB: please, no space before tabs
#2074: FILE: drivers/gpu/drm/i915/display/intel_pps.c:447:
+#define IDLE_ON_VALUE   ^I(PP_ON | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)$

-:2079: WARNING:LONG_LINE: line length of 107 exceeds 100 columns
#2079: FILE: drivers/gpu/drm/i915/display/intel_pps.c:452:
+#define IDLE_CYCLE_MASK		(PP_ON | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)

-:2080: WARNING:LONG_LINE: line length of 111 exceeds 100 columns
#2080: FILE: drivers/gpu/drm/i915/display/intel_pps.c:453:
+#define IDLE_CYCLE_VALUE	(0     | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)

-:2085: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2085: FILE: drivers/gpu/drm/i915/display/intel_pps.c:458:
+static void wait_panel_status(struct intel_dp *intel_dp,
+				       u32 mask,

-:2139: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#2139: FILE: drivers/gpu/drm/i915/display/intel_pps.c:512:
+	 * and then make panel wait for t11_t12 if needed. */

-:2141: WARNING:LONG_LINE: line length of 103 exceeds 100 columns
#2141: FILE: drivers/gpu/drm/i915/display/intel_pps.c:514:
+	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->panel_power_off_time);

-:2144: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#2144: FILE: drivers/gpu/drm/i915/display/intel_pps.c:517:
+	 * wait. */

-:2147: WARNING:LONG_LINE: line length of 101 exceeds 100 columns
#2147: FILE: drivers/gpu/drm/i915/display/intel_pps.c:520:
+				       intel_dp->panel_power_cycle_delay - panel_power_off_duration);

-:2147: CHECK:PARENTHESIS_ALIGNMENT: Alignment should match open parenthesis
#2147: FILE: drivers/gpu/drm/i915/display/intel_pps.c:520:
+		wait_remaining_ms_from_jiffies(jiffies,
+				       intel_dp->panel_power_cycle_delay - panel_power_off_duration);

-:2441: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#2441: FILE: drivers/gpu/drm/i915/display/intel_pps.c:814:
+	 * panels get very unhappy and cease to work. */

-:2790: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#2790: FILE: drivers/gpu/drm/i915/display/intel_pps.c:1163:
+	 * too. */

-:2794: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#2794: FILE: drivers/gpu/drm/i915/display/intel_pps.c:1167:
+	 * our hw here, which are all in 100usec. */

-:2802: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#2802: FILE: drivers/gpu/drm/i915/display/intel_pps.c:1175:
+	 * too. */

-:2808: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#2808: FILE: drivers/gpu/drm/i915/display/intel_pps.c:1181:
+	 * unset, fall back to the spec limits. */

-:2809: ERROR:COMPLEX_MACRO: Macros with complex values should be enclosed in parentheses
#2809: FILE: drivers/gpu/drm/i915/display/intel_pps.c:1182:
+#define assign_final(field)	final->field = (max(cur.field, vbt.field) == 0 ? \
+				       spec.field : \
+				       max(cur.field, vbt.field))

-:2809: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'field' - possible side-effects?
#2809: FILE: drivers/gpu/drm/i915/display/intel_pps.c:1182:
+#define assign_final(field)	final->field = (max(cur.field, vbt.field) == 0 ? \
+				       spec.field : \
+				       max(cur.field, vbt.field))

-:2809: CHECK:MACRO_ARG_PRECEDENCE: Macro argument 'field' may be better as '(field)' to avoid precedence issues
#2809: FILE: drivers/gpu/drm/i915/display/intel_pps.c:1182:
+#define assign_final(field)	final->field = (max(cur.field, vbt.field) == 0 ? \
+				       spec.field : \
+				       max(cur.field, vbt.field))

-:2819: CHECK:MACRO_ARG_PRECEDENCE: Macro argument 'field' may be better as '(field)' to avoid precedence issues
#2819: FILE: drivers/gpu/drm/i915/display/intel_pps.c:1192:
+#define get_delay(field)	(DIV_ROUND_UP(final->field, 10))

-:2902: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#2902: FILE: drivers/gpu/drm/i915/display/intel_pps.c:1275:
+	 * power sequencer any more. */

-:2932: WARNING:LONG_LINE: line length of 176 exceeds 100 columns
#2932: FILE: drivers/gpu/drm/i915/display/intel_pps.c:1305:
+			       REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, (100 * div) / 2 - 1) | REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000)));

-:2938: WARNING:LONG_LINE: line length of 103 exceeds 100 columns
#2938: FILE: drivers/gpu/drm/i915/display/intel_pps.c:1311:
+		pp_ctl |= REG_FIELD_PREP(BXT_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000));

-:2989: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'dp' - possible side-effects?
#2989: FILE: drivers/gpu/drm/i915/display/intel_pps.h:22:
+#define with_pps_lock(dp, wf)						\
+	for ((wf) = pps_lock(dp); (wf); (wf) = pps_unlock((dp), (wf)))

-:2989: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'wf' - possible side-effects?
#2989: FILE: drivers/gpu/drm/i915/display/intel_pps.h:22:
+#define with_pps_lock(dp, wf)						\
+	for ((wf) = pps_lock(dp); (wf); (wf) = pps_unlock((dp), (wf)))

total: 1 errors, 18 warnings, 8 checks, 2953 lines checked
84bd85deaf0b drm/i915/pps: rename pps_{, un}lock -> intel_pps_{, un}lock
-:216: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'dp' - possible side-effects?
#216: FILE: drivers/gpu/drm/i915/display/intel_pps.h:22:
+#define with_intel_pps_lock(dp, wf)						\
+	for ((wf) = intel_pps_lock(dp); (wf); (wf) = intel_pps_unlock((dp), (wf)))

-:216: CHECK:MACRO_ARG_REUSE: Macro argument reuse 'wf' - possible side-effects?
#216: FILE: drivers/gpu/drm/i915/display/intel_pps.h:22:
+#define with_intel_pps_lock(dp, wf)						\
+	for ((wf) = intel_pps_lock(dp); (wf); (wf) = intel_pps_unlock((dp), (wf)))

total: 0 errors, 0 warnings, 2 checks, 176 lines checked
9de69e6f8cbd drm/i915/pps: rename intel_edp_backlight_* to intel_pps_backlight_*
67bedb793872 drm/i915/pps: rename intel_edp_panel_* to intel_pps_*
4c39d047e6a5 drm/i915/pps: rename edp_panel_* to intel_pps_*_unlocked
13979e877fa3 drm/i915/pps: abstract intel_pps_vdd_off_sync
b0c7e08de7bc drm/i915/pps: add higher level intel_pps_init() call
fcd60022bd6d drm/i915/pps: abstract intel_pps_encoder_reset()
46024084caf5 drm/i915/pps: rename intel_dp_check_edp to intel_pps_check_power_unlocked
4c5d95f01d72 drm/i915/pps: rename intel_power_sequencer_reset to intel_pps_reset_all
cb6cf18c5623 drm/i915/pps: add locked intel_pps_wait_power_cycle
eaad3ef82888 drm/i915/pps: rename vlv_init_panel_power_sequencer to vlv_pps_init
ca6b78cc5788 drm/i915/pps: rename intel_dp_init_panel_power_sequencer* functions
f57fa5d3bb5d drm/i915/pps: refactor init abstractions
d50dad330043 drm/i915/pps: move pps code over from intel_display.c and refactor
d7a14085a159 drm/i915/dp: abstract struct intel_dp pps members to a sub-struct
-:346: WARNING:LONG_LINE: line length of 107 exceeds 100 columns
#346: FILE: drivers/gpu/drm/i915/display/intel_pps.c:509:
+	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->pps.panel_power_off_time);

-:354: WARNING:LONG_LINE: line length of 105 exceeds 100 columns
#354: FILE: drivers/gpu/drm/i915/display/intel_pps.c:515:
+				       intel_dp->pps.panel_power_cycle_delay - panel_power_off_duration);

total: 0 errors, 2 warnings, 0 checks, 632 lines checked
d6be48f10987 drm/i915/dp: split out aux functionality to intel_dp_aux.c
-:728: WARNING:FILE_PATH_CHANGES: added, moved or deleted file(s), does MAINTAINERS need updating?
#728: 
new file mode 100644

-:760: WARNING:LINE_SPACING: Missing a blank line after declarations
#760: FILE: drivers/gpu/drm/i915/display/intel_dp_aux.c:28:
+	int i;
+	if (dst_bytes > 4)

-:763: CHECK:SPACING: spaces preferred around that '-' (ctx:VxV)
#763: FILE: drivers/gpu/drm/i915/display/intel_dp_aux.c:31:
+		dst[i] = src >> ((3-i) * 8);
 		                   ^

-:775: WARNING:LONG_LINE: line length of 104 exceeds 100 columns
#775: FILE: drivers/gpu/drm/i915/display/intel_dp_aux.c:43:
+#define C (((status = intel_uncore_read_notrace(&i915->uncore, ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0)

-:965: WARNING:MSLEEP: msleep < 20ms can sleep for up to 20ms; see Documentation/timers/timers-howto.rst
#965: FILE: drivers/gpu/drm/i915/display/intel_dp_aux.c:233:
+		msleep(1);

-:1055: WARNING:BLOCK_COMMENT_STYLE: Block comments use a trailing */ on a separate line
#1055: FILE: drivers/gpu/drm/i915/display/intel_dp_aux.c:323:
+	 * "normal" -- don't fill the kernel log with these */

-:1203: CHECK:LINE_SPACING: Please don't use multiple blank lines
#1203: FILE: drivers/gpu/drm/i915/display/intel_dp_aux.c:471:
+
+

total: 0 errors, 5 warnings, 2 checks, 1410 lines checked


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Intel-gfx] ✗ Fi.CI.SPARSE: warning for drm/i915/dp: split out pps and aux (rev2)
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (17 preceding siblings ...)
  2021-01-08 19:23 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/dp: split out pps and aux (rev2) Patchwork
@ 2021-01-08 19:24 ` Patchwork
  2021-01-08 19:52 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
  2021-01-09  1:05 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
  20 siblings, 0 replies; 37+ messages in thread
From: Patchwork @ 2021-01-08 19:24 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

== Series Details ==

Series: drm/i915/dp: split out pps and aux (rev2)
URL   : https://patchwork.freedesktop.org/series/85167/
State : warning

== Summary ==

$ dim sparse --fast origin/drm-tip
Sparse version: v0.6.2
Fast mode used, each commit won't be checked separately.
-
+drivers/gpu/drm/i915/gt/intel_reset.c:1329:5: warning: context imbalance in 'intel_gt_reset_trylock' - different lock contexts for basic block
+drivers/gpu/drm/i915/gvt/mmio.c:295:23: warning: memcpy with byte count of 279040
+drivers/gpu/drm/i915/i915_perf.c:1450:15: warning: memset with byte count of 16777216
+drivers/gpu/drm/i915/i915_perf.c:1504:15: warning: memset with byte count of 16777216
+drivers/gpu/drm/i915/intel_wakeref.c:137:19: warning: context imbalance in 'wakeref_auto_timeout' - unexpected unlock
+./include/linux/seqlock.h:843:24: warning: trying to copy expression type 31
+./include/linux/seqlock.h:843:24: warning: trying to copy expression type 31
+./include/linux/seqlock.h:869:16: warning: trying to copy expression type 31
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'fwtable_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen11_fwtable_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen12_fwtable_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read64' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_read8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen6_write8' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen8_write16' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen8_write32' - different lock contexts for basic block
+./include/linux/spinlock.h:409:9: warning: context imbalance in 'gen8_write8' - different lock contexts for basic block


_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Intel-gfx] ✓ Fi.CI.BAT: success for drm/i915/dp: split out pps and aux (rev2)
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (18 preceding siblings ...)
  2021-01-08 19:24 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
@ 2021-01-08 19:52 ` Patchwork
  2021-01-09  1:05 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork
  20 siblings, 0 replies; 37+ messages in thread
From: Patchwork @ 2021-01-08 19:52 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 4597 bytes --]

== Series Details ==

Series: drm/i915/dp: split out pps and aux (rev2)
URL   : https://patchwork.freedesktop.org/series/85167/
State : success

== Summary ==

CI Bug Log - changes from CI_DRM_9567 -> Patchwork_19296
====================================================

Summary
-------

  **SUCCESS**

  No regressions found.

  External URL: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/index.html

Known issues
------------

  Here are the changes found in Patchwork_19296 that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@amdgpu/amd_basic@cs-gfx:
    - fi-kbl-soraka:      NOTRUN -> [SKIP][1] ([fdo#109271]) +17 similar issues
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/fi-kbl-soraka/igt@amdgpu/amd_basic@cs-gfx.html

  * igt@amdgpu/amd_cs_nop@nop-compute0:
    - fi-tgl-y:           NOTRUN -> [SKIP][2] ([fdo#109315] / [i915#2575]) +8 similar issues
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/fi-tgl-y/igt@amdgpu/amd_cs_nop@nop-compute0.html

  * igt@prime_vgem@basic-fence-flip:
    - fi-tgl-y:           [PASS][3] -> [DMESG-WARN][4] ([i915#402]) +1 similar issue
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/fi-tgl-y/igt@prime_vgem@basic-fence-flip.html
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/fi-tgl-y/igt@prime_vgem@basic-fence-flip.html

  
#### Possible fixes ####

  * igt@debugfs_test@read_all_entries:
    - fi-tgl-y:           [DMESG-WARN][5] ([i915#402]) -> [PASS][6] +2 similar issues
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/fi-tgl-y/igt@debugfs_test@read_all_entries.html
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/fi-tgl-y/igt@debugfs_test@read_all_entries.html

  * igt@i915_selftest@live@gem:
    - fi-kbl-soraka:      [DMESG-FAIL][7] -> [PASS][8]
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/fi-kbl-soraka/igt@i915_selftest@live@gem.html
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/fi-kbl-soraka/igt@i915_selftest@live@gem.html

  * igt@i915_selftest@live@reset:
    - fi-kbl-soraka:      [SKIP][9] ([fdo#109271]) -> [PASS][10] +12 similar issues
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/fi-kbl-soraka/igt@i915_selftest@live@reset.html
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/fi-kbl-soraka/igt@i915_selftest@live@reset.html

  
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109315]: https://bugs.freedesktop.org/show_bug.cgi?id=109315
  [i915#2575]: https://gitlab.freedesktop.org/drm/intel/issues/2575
  [i915#402]: https://gitlab.freedesktop.org/drm/intel/issues/402


Participating hosts (43 -> 38)
------------------------------

  Missing    (5): fi-ilk-m540 fi-hsw-4200u fi-bsw-cyan fi-ctg-p8600 fi-bdw-samus 


Build changes
-------------

  * Linux: CI_DRM_9567 -> Patchwork_19296

  CI-20190529: 20190529
  CI_DRM_9567: 9fc1f6dac2ec9339e390931322768a0286f01f71 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5951: fec3b9c7d88357144f0d7a1447b9316a1c81da1a @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_19296: d6be48f109873e9857af7afab7f34224b92f57b0 @ git://anongit.freedesktop.org/gfx-ci/linux


== Linux commits ==

d6be48f10987 drm/i915/dp: split out aux functionality to intel_dp_aux.c
d7a14085a159 drm/i915/dp: abstract struct intel_dp pps members to a sub-struct
d50dad330043 drm/i915/pps: move pps code over from intel_display.c and refactor
f57fa5d3bb5d drm/i915/pps: refactor init abstractions
ca6b78cc5788 drm/i915/pps: rename intel_dp_init_panel_power_sequencer* functions
eaad3ef82888 drm/i915/pps: rename vlv_init_panel_power_sequencer to vlv_pps_init
cb6cf18c5623 drm/i915/pps: add locked intel_pps_wait_power_cycle
4c5d95f01d72 drm/i915/pps: rename intel_power_sequencer_reset to intel_pps_reset_all
46024084caf5 drm/i915/pps: rename intel_dp_check_edp to intel_pps_check_power_unlocked
fcd60022bd6d drm/i915/pps: abstract intel_pps_encoder_reset()
b0c7e08de7bc drm/i915/pps: add higher level intel_pps_init() call
13979e877fa3 drm/i915/pps: abstract intel_pps_vdd_off_sync
4c39d047e6a5 drm/i915/pps: rename edp_panel_* to intel_pps_*_unlocked
67bedb793872 drm/i915/pps: rename intel_edp_panel_* to intel_pps_*
9de69e6f8cbd drm/i915/pps: rename intel_edp_backlight_* to intel_pps_backlight_*
84bd85deaf0b drm/i915/pps: rename pps_{, un}lock -> intel_pps_{, un}lock
1d7a1bfde18c drm/i915/pps: abstract panel power sequencer from intel_dp.c

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/index.html

[-- Attachment #1.2: Type: text/html, Size: 5605 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Intel-gfx] ✗ Fi.CI.IGT: failure for drm/i915/dp: split out pps and aux (rev2)
  2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
                   ` (19 preceding siblings ...)
  2021-01-08 19:52 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
@ 2021-01-09  1:05 ` Patchwork
  20 siblings, 0 replies; 37+ messages in thread
From: Patchwork @ 2021-01-09  1:05 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx


[-- Attachment #1.1: Type: text/plain, Size: 20377 bytes --]

== Series Details ==

Series: drm/i915/dp: split out pps and aux (rev2)
URL   : https://patchwork.freedesktop.org/series/85167/
State : failure

== Summary ==

CI Bug Log - changes from CI_DRM_9567_full -> Patchwork_19296_full
====================================================

Summary
-------

  **FAILURE**

  Serious unknown changes coming with Patchwork_19296_full absolutely need to be
  verified manually.
  
  If you think the reported changes have nothing to do with the changes
  introduced in Patchwork_19296_full, please notify your bug team to allow them
  to document this new failure mode, which will reduce false positives in CI.

  

Possible new issues
-------------------

  Here are the unknown changes that may have been introduced in Patchwork_19296_full:

### IGT changes ###

#### Possible regressions ####

  * igt@gem_eio@in-flight-immediate:
    - shard-skl:          NOTRUN -> [FAIL][1]
   [1]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl8/igt@gem_eio@in-flight-immediate.html

  
#### Suppressed ####

  The following results come from untrusted machines, tests, or statuses.
  They do not affect the overall result.

  * {igt@gem_exec_schedule@u-fairslice@rcs0}:
    - shard-apl:          [DMESG-WARN][2] ([i915#1610]) -> [DMESG-WARN][3]
   [2]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-apl4/igt@gem_exec_schedule@u-fairslice@rcs0.html
   [3]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-apl3/igt@gem_exec_schedule@u-fairslice@rcs0.html

  * {igt@kms_psr2_sf@primary-plane-update-sf-dmg-area-2}:
    - shard-iclb:         [SKIP][4] ([i915#2920]) -> [SKIP][5] +2 similar issues
   [4]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-iclb2/igt@kms_psr2_sf@primary-plane-update-sf-dmg-area-2.html
   [5]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-iclb7/igt@kms_psr2_sf@primary-plane-update-sf-dmg-area-2.html

  
Known issues
------------

  Here are the changes found in Patchwork_19296_full that come from known issues:

### IGT changes ###

#### Issues hit ####

  * igt@gem_ctx_persistence@engines-mixed:
    - shard-hsw:          NOTRUN -> [SKIP][6] ([fdo#109271] / [i915#1099]) +3 similar issues
   [6]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-hsw6/igt@gem_ctx_persistence@engines-mixed.html
    - shard-snb:          NOTRUN -> [SKIP][7] ([fdo#109271] / [i915#1099]) +1 similar issue
   [7]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-snb7/igt@gem_ctx_persistence@engines-mixed.html

  * igt@gem_exec_reloc@basic-many-active@rcs0:
    - shard-apl:          [PASS][8] -> [FAIL][9] ([i915#2389])
   [8]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-apl7/igt@gem_exec_reloc@basic-many-active@rcs0.html
   [9]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-apl4/igt@gem_exec_reloc@basic-many-active@rcs0.html

  * igt@gem_exec_reloc@basic-wide-active@bcs0:
    - shard-skl:          NOTRUN -> [FAIL][10] ([i915#2389]) +3 similar issues
   [10]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl7/igt@gem_exec_reloc@basic-wide-active@bcs0.html

  * igt@gem_media_vme:
    - shard-skl:          NOTRUN -> [SKIP][11] ([fdo#109271]) +151 similar issues
   [11]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl8/igt@gem_media_vme.html

  * igt@gem_pread@exhaustion:
    - shard-hsw:          NOTRUN -> [WARN][12] ([i915#2658])
   [12]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-hsw7/igt@gem_pread@exhaustion.html

  * igt@gem_userptr_blits@process-exit-mmap-busy@uc:
    - shard-skl:          NOTRUN -> [SKIP][13] ([fdo#109271] / [i915#1699]) +3 similar issues
   [13]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl8/igt@gem_userptr_blits@process-exit-mmap-busy@uc.html

  * igt@gem_userptr_blits@process-exit-mmap@wc:
    - shard-hsw:          NOTRUN -> [SKIP][14] ([fdo#109271]) +203 similar issues
   [14]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-hsw7/igt@gem_userptr_blits@process-exit-mmap@wc.html

  * igt@gen7_exec_parse@basic-allocation:
    - shard-glk:          NOTRUN -> [SKIP][15] ([fdo#109271]) +4 similar issues
   [15]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-glk4/igt@gen7_exec_parse@basic-allocation.html

  * igt@i915_pm_dc@dc3co-vpb-simulation:
    - shard-kbl:          NOTRUN -> [SKIP][16] ([fdo#109271] / [i915#658])
   [16]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-kbl1/igt@i915_pm_dc@dc3co-vpb-simulation.html

  * igt@i915_pm_dc@dc6-dpms:
    - shard-skl:          NOTRUN -> [FAIL][17] ([i915#454])
   [17]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl8/igt@i915_pm_dc@dc6-dpms.html

  * igt@kms_chamelium@hdmi-aspect-ratio:
    - shard-skl:          NOTRUN -> [SKIP][18] ([fdo#109271] / [fdo#111827]) +15 similar issues
   [18]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl8/igt@kms_chamelium@hdmi-aspect-ratio.html

  * igt@kms_color_chamelium@pipe-d-gamma:
    - shard-hsw:          NOTRUN -> [SKIP][19] ([fdo#109271] / [fdo#111827]) +15 similar issues
   [19]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-hsw7/igt@kms_color_chamelium@pipe-d-gamma.html

  * igt@kms_cursor_crc@pipe-b-cursor-128x128-onscreen:
    - shard-skl:          NOTRUN -> [FAIL][20] ([i915#54]) +3 similar issues
   [20]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl7/igt@kms_cursor_crc@pipe-b-cursor-128x128-onscreen.html

  * igt@kms_cursor_crc@pipe-c-cursor-64x21-random:
    - shard-skl:          [PASS][21] -> [FAIL][22] ([i915#54]) +5 similar issues
   [21]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-skl2/igt@kms_cursor_crc@pipe-c-cursor-64x21-random.html
   [22]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl7/igt@kms_cursor_crc@pipe-c-cursor-64x21-random.html

  * igt@kms_cursor_legacy@2x-cursor-vs-flip-atomic:
    - shard-snb:          NOTRUN -> [SKIP][23] ([fdo#109271]) +41 similar issues
   [23]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-snb7/igt@kms_cursor_legacy@2x-cursor-vs-flip-atomic.html

  * igt@kms_flip@flip-vs-expired-vblank@a-edp1:
    - shard-tglb:         [PASS][24] -> [FAIL][25] ([i915#2598])
   [24]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-tglb3/igt@kms_flip@flip-vs-expired-vblank@a-edp1.html
   [25]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-tglb2/igt@kms_flip@flip-vs-expired-vblank@a-edp1.html

  * igt@kms_flip@plain-flip-ts-check-interruptible@c-edp1:
    - shard-skl:          [PASS][26] -> [FAIL][27] ([i915#2122])
   [26]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-skl5/igt@kms_flip@plain-flip-ts-check-interruptible@c-edp1.html
   [27]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl8/igt@kms_flip@plain-flip-ts-check-interruptible@c-edp1.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs:
    - shard-skl:          NOTRUN -> [SKIP][28] ([fdo#109271] / [i915#2672])
   [28]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl9/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-32bpp-ytilegen12rcccs.html

  * igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile:
    - shard-skl:          NOTRUN -> [SKIP][29] ([fdo#109271] / [i915#2642])
   [29]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl7/igt@kms_flip_scaled_crc@flip-32bpp-ytile-to-64bpp-ytile.html

  * igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-mmap-gtt:
    - shard-kbl:          NOTRUN -> [SKIP][30] ([fdo#109271]) +12 similar issues
   [30]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-kbl1/igt@kms_frontbuffer_tracking@fbcpsr-2p-scndscrn-pri-shrfb-draw-mmap-gtt.html

  * igt@kms_frontbuffer_tracking@psr-1p-primscrn-indfb-plflip-blt:
    - shard-skl:          NOTRUN -> [FAIL][31] ([i915#49])
   [31]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl10/igt@kms_frontbuffer_tracking@psr-1p-primscrn-indfb-plflip-blt.html

  * igt@kms_pipe_crc_basic@hang-read-crc-pipe-d:
    - shard-skl:          NOTRUN -> [SKIP][32] ([fdo#109271] / [i915#533])
   [32]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl7/igt@kms_pipe_crc_basic@hang-read-crc-pipe-d.html

  * igt@kms_plane@plane-panning-bottom-right-suspend-pipe-a-planes:
    - shard-kbl:          [PASS][33] -> [DMESG-WARN][34] ([i915#180] / [i915#533])
   [33]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-kbl2/igt@kms_plane@plane-panning-bottom-right-suspend-pipe-a-planes.html
   [34]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-kbl7/igt@kms_plane@plane-panning-bottom-right-suspend-pipe-a-planes.html

  * igt@kms_plane_alpha_blend@pipe-a-alpha-7efc:
    - shard-skl:          NOTRUN -> [FAIL][35] ([fdo#108145] / [i915#265]) +3 similar issues
   [35]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl10/igt@kms_plane_alpha_blend@pipe-a-alpha-7efc.html

  * igt@kms_plane_alpha_blend@pipe-b-alpha-opaque-fb:
    - shard-kbl:          NOTRUN -> [FAIL][36] ([fdo#108145] / [i915#265])
   [36]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-kbl1/igt@kms_plane_alpha_blend@pipe-b-alpha-opaque-fb.html

  * igt@kms_plane_alpha_blend@pipe-b-alpha-transparent-fb:
    - shard-skl:          NOTRUN -> [FAIL][37] ([i915#265])
   [37]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl7/igt@kms_plane_alpha_blend@pipe-b-alpha-transparent-fb.html

  * igt@kms_psr@psr2_suspend:
    - shard-iclb:         [PASS][38] -> [SKIP][39] ([fdo#109441]) +2 similar issues
   [38]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-iclb2/igt@kms_psr@psr2_suspend.html
   [39]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-iclb7/igt@kms_psr@psr2_suspend.html

  
#### Possible fixes ####

  * {igt@gem_exec_fair@basic-none@vcs0}:
    - shard-kbl:          [FAIL][40] ([i915#2842]) -> [PASS][41] +3 similar issues
   [40]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-kbl7/igt@gem_exec_fair@basic-none@vcs0.html
   [41]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-kbl4/igt@gem_exec_fair@basic-none@vcs0.html

  * igt@gem_exec_whisper@basic-contexts-priority-all:
    - shard-glk:          [DMESG-WARN][42] ([i915#118] / [i915#95]) -> [PASS][43]
   [42]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-glk2/igt@gem_exec_whisper@basic-contexts-priority-all.html
   [43]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-glk5/igt@gem_exec_whisper@basic-contexts-priority-all.html

  * igt@gem_linear_blits@interruptible:
    - shard-glk:          [INCOMPLETE][44] -> [PASS][45]
   [44]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-glk5/igt@gem_linear_blits@interruptible.html
   [45]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-glk4/igt@gem_linear_blits@interruptible.html

  * igt@i915_module_load@reload-with-fault-injection:
    - shard-snb:          [INCOMPLETE][46] ([i915#2880]) -> [PASS][47]
   [46]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-snb5/igt@i915_module_load@reload-with-fault-injection.html
   [47]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-snb7/igt@i915_module_load@reload-with-fault-injection.html

  * igt@i915_pm_dc@dc6-psr:
    - shard-iclb:         [FAIL][48] ([i915#454]) -> [PASS][49]
   [48]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-iclb6/igt@i915_pm_dc@dc6-psr.html
   [49]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-iclb3/igt@i915_pm_dc@dc6-psr.html

  * igt@i915_pm_rpm@system-suspend-execbuf:
    - shard-skl:          [INCOMPLETE][50] ([i915#151]) -> [PASS][51]
   [50]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-skl5/igt@i915_pm_rpm@system-suspend-execbuf.html
   [51]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl8/igt@i915_pm_rpm@system-suspend-execbuf.html

  * igt@i915_suspend@sysfs-reader:
    - shard-kbl:          [DMESG-WARN][52] ([i915#180]) -> [PASS][53]
   [52]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-kbl7/igt@i915_suspend@sysfs-reader.html
   [53]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-kbl1/igt@i915_suspend@sysfs-reader.html

  * igt@kms_cursor_crc@pipe-b-cursor-64x64-offscreen:
    - shard-skl:          [FAIL][54] ([i915#54]) -> [PASS][55] +2 similar issues
   [54]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-skl10/igt@kms_cursor_crc@pipe-b-cursor-64x64-offscreen.html
   [55]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl7/igt@kms_cursor_crc@pipe-b-cursor-64x64-offscreen.html

  * igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions:
    - shard-skl:          [FAIL][56] ([i915#2346]) -> [PASS][57]
   [56]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-skl4/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html
   [57]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl5/igt@kms_cursor_legacy@flip-vs-cursor-atomic-transitions.html

  * igt@kms_hdr@bpc-switch:
    - shard-skl:          [FAIL][58] ([i915#1188]) -> [PASS][59]
   [58]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-skl9/igt@kms_hdr@bpc-switch.html
   [59]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl1/igt@kms_hdr@bpc-switch.html

  * igt@kms_psr@psr2_cursor_render:
    - shard-iclb:         [SKIP][60] ([fdo#109441]) -> [PASS][61] +2 similar issues
   [60]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-iclb7/igt@kms_psr@psr2_cursor_render.html
   [61]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-iclb2/igt@kms_psr@psr2_cursor_render.html

  * igt@perf@polling-parameterized:
    - shard-skl:          [FAIL][62] ([i915#1542]) -> [PASS][63]
   [62]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-skl9/igt@perf@polling-parameterized.html
   [63]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl8/igt@perf@polling-parameterized.html

  
#### Warnings ####

  * igt@i915_pm_dc@dc3co-vpb-simulation:
    - shard-iclb:         [SKIP][64] ([i915#658]) -> [SKIP][65] ([i915#588])
   [64]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-iclb3/igt@i915_pm_dc@dc3co-vpb-simulation.html
   [65]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-iclb2/igt@i915_pm_dc@dc3co-vpb-simulation.html

  * igt@i915_pm_dc@dc6-psr:
    - shard-skl:          [INCOMPLETE][66] ([i915#198]) -> [FAIL][67] ([i915#454])
   [66]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-skl10/igt@i915_pm_dc@dc6-psr.html
   [67]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl7/igt@i915_pm_dc@dc6-psr.html

  * igt@i915_pm_rc6_residency@rc6-fence:
    - shard-iclb:         [WARN][68] ([i915#1804] / [i915#2684]) -> [WARN][69] ([i915#2681] / [i915#2684])
   [68]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-iclb4/igt@i915_pm_rc6_residency@rc6-fence.html
   [69]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-iclb8/igt@i915_pm_rc6_residency@rc6-fence.html

  * igt@runner@aborted:
    - shard-kbl:          ([FAIL][70], [FAIL][71]) ([i915#2295]) -> ([FAIL][72], [FAIL][73], [FAIL][74]) ([i915#1814] / [i915#2295] / [i915#2426] / [i915#2505])
   [70]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-kbl4/igt@runner@aborted.html
   [71]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-kbl7/igt@runner@aborted.html
   [72]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-kbl2/igt@runner@aborted.html
   [73]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-kbl7/igt@runner@aborted.html
   [74]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-kbl6/igt@runner@aborted.html
    - shard-glk:          [FAIL][75] ([i915#2295] / [k.org#202321]) -> ([FAIL][76], [FAIL][77]) ([i915#2295] / [i915#2426] / [k.org#202321])
   [75]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-glk3/igt@runner@aborted.html
   [76]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-glk6/igt@runner@aborted.html
   [77]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-glk1/igt@runner@aborted.html
    - shard-skl:          [FAIL][78] ([i915#2295]) -> ([FAIL][79], [FAIL][80]) ([i915#2295] / [i915#2426])
   [78]: https://intel-gfx-ci.01.org/tree/drm-tip/CI_DRM_9567/shard-skl8/igt@runner@aborted.html
   [79]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl1/igt@runner@aborted.html
   [80]: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/shard-skl9/igt@runner@aborted.html

  
  {name}: This element is suppressed. This means it is ignored when computing
          the status of the difference (SUCCESS, WARNING, or FAILURE).

  [fdo#108145]: https://bugs.freedesktop.org/show_bug.cgi?id=108145
  [fdo#109271]: https://bugs.freedesktop.org/show_bug.cgi?id=109271
  [fdo#109441]: https://bugs.freedesktop.org/show_bug.cgi?id=109441
  [fdo#111827]: https://bugs.freedesktop.org/show_bug.cgi?id=111827
  [i915#1099]: https://gitlab.freedesktop.org/drm/intel/issues/1099
  [i915#118]: https://gitlab.freedesktop.org/drm/intel/issues/118
  [i915#1188]: https://gitlab.freedesktop.org/drm/intel/issues/1188
  [i915#151]: https://gitlab.freedesktop.org/drm/intel/issues/151
  [i915#1542]: https://gitlab.freedesktop.org/drm/intel/issues/1542
  [i915#1610]: https://gitlab.freedesktop.org/drm/intel/issues/1610
  [i915#1699]: https://gitlab.freedesktop.org/drm/intel/issues/1699
  [i915#180]: https://gitlab.freedesktop.org/drm/intel/issues/180
  [i915#1804]: https://gitlab.freedesktop.org/drm/intel/issues/1804
  [i915#1814]: https://gitlab.freedesktop.org/drm/intel/issues/1814
  [i915#198]: https://gitlab.freedesktop.org/drm/intel/issues/198
  [i915#2122]: https://gitlab.freedesktop.org/drm/intel/issues/2122
  [i915#2295]: https://gitlab.freedesktop.org/drm/intel/issues/2295
  [i915#2346]: https://gitlab.freedesktop.org/drm/intel/issues/2346
  [i915#2389]: https://gitlab.freedesktop.org/drm/intel/issues/2389
  [i915#2426]: https://gitlab.freedesktop.org/drm/intel/issues/2426
  [i915#2505]: https://gitlab.freedesktop.org/drm/intel/issues/2505
  [i915#2598]: https://gitlab.freedesktop.org/drm/intel/issues/2598
  [i915#2642]: https://gitlab.freedesktop.org/drm/intel/issues/2642
  [i915#265]: https://gitlab.freedesktop.org/drm/intel/issues/265
  [i915#2658]: https://gitlab.freedesktop.org/drm/intel/issues/2658
  [i915#2672]: https://gitlab.freedesktop.org/drm/intel/issues/2672
  [i915#2681]: https://gitlab.freedesktop.org/drm/intel/issues/2681
  [i915#2684]: https://gitlab.freedesktop.org/drm/intel/issues/2684
  [i915#2803]: https://gitlab.freedesktop.org/drm/intel/issues/2803
  [i915#2842]: https://gitlab.freedesktop.org/drm/intel/issues/2842
  [i915#2849]: https://gitlab.freedesktop.org/drm/intel/issues/2849
  [i915#2880]: https://gitlab.freedesktop.org/drm/intel/issues/2880
  [i915#2920]: https://gitlab.freedesktop.org/drm/intel/issues/2920
  [i915#454]: https://gitlab.freedesktop.org/drm/intel/issues/454
  [i915#49]: https://gitlab.freedesktop.org/drm/intel/issues/49
  [i915#533]: https://gitlab.freedesktop.org/drm/intel/issues/533
  [i915#54]: https://gitlab.freedesktop.org/drm/intel/issues/54
  [i915#588]: https://gitlab.freedesktop.org/drm/intel/issues/588
  [i915#658]: https://gitlab.freedesktop.org/drm/intel/issues/658
  [i915#95]: https://gitlab.freedesktop.org/drm/intel/issues/95
  [k.org#202321]: https://bugzilla.kernel.org/show_bug.cgi?id=202321


Participating hosts (10 -> 10)
------------------------------

  No changes in participating hosts


Build changes
-------------

  * Linux: CI_DRM_9567 -> Patchwork_19296

  CI-20190529: 20190529
  CI_DRM_9567: 9fc1f6dac2ec9339e390931322768a0286f01f71 @ git://anongit.freedesktop.org/gfx-ci/linux
  IGT_5951: fec3b9c7d88357144f0d7a1447b9316a1c81da1a @ git://anongit.freedesktop.org/xorg/app/intel-gpu-tools
  Patchwork_19296: d6be48f109873e9857af7afab7f34224b92f57b0 @ git://anongit.freedesktop.org/gfx-ci/linux
  piglit_4509: fdc5a4ca11124ab8413c7988896eec4c97336694 @ git://anongit.freedesktop.org/piglit

== Logs ==

For more details see: https://intel-gfx-ci.01.org/tree/drm-tip/Patchwork_19296/index.html

[-- Attachment #1.2: Type: text/html, Size: 24430 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 04/17] drm/i915/pps: rename intel_edp_panel_* to intel_pps_*
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 04/17] drm/i915/pps: rename intel_edp_panel_* to intel_pps_* Jani Nikula
@ 2021-01-13 10:39   ` Anshuman Gupta
  0 siblings, 0 replies; 37+ messages in thread
From: Anshuman Gupta @ 2021-01-13 10:39 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On 2021-01-08 at 19:44:12 +0200, Jani Nikula wrote:
> Follow the usual naming pattern for functions. We don't need to repeat
> "panel" here. No functional changes.
> 
> v2: Fix comment (Anshuman)
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
LGTM.
Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_ddi.c |  8 ++++----
>  drivers/gpu/drm/i915/display/intel_dp.c  | 10 +++++-----
>  drivers/gpu/drm/i915/display/intel_pps.c | 17 ++++++++---------
>  drivers/gpu/drm/i915/display/intel_pps.h | 11 +++++------
>  4 files changed, 22 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> index f09a597bf730..243ab635aa34 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -3592,7 +3592,7 @@ static void tgl_ddi_pre_enable_dp(struct intel_atomic_state *state,
>  	 */
>  
>  	/* 2. Enable Panel Power if PPS is required */
> -	intel_edp_panel_on(intel_dp);
> +	intel_pps_on(intel_dp);
>  
>  	/*
>  	 * 3. For non-TBT Type-C ports, set FIA lane count
> @@ -3735,7 +3735,7 @@ static void hsw_ddi_pre_enable_dp(struct intel_atomic_state *state,
>  				 crtc_state->port_clock,
>  				 crtc_state->lane_count);
>  
> -	intel_edp_panel_on(intel_dp);
> +	intel_pps_on(intel_dp);
>  
>  	intel_ddi_clk_select(encoder, crtc_state);
>  
> @@ -3977,8 +3977,8 @@ static void intel_ddi_post_disable_dp(struct intel_atomic_state *state,
>  	if (INTEL_GEN(dev_priv) >= 12)
>  		intel_ddi_disable_pipe_clock(old_crtc_state);
>  
> -	intel_edp_panel_vdd_on(intel_dp);
> -	intel_edp_panel_off(intel_dp);
> +	intel_pps_vdd_on(intel_dp);
> +	intel_pps_off(intel_dp);
>  
>  	if (!intel_phy_is_tc(dev_priv, phy) ||
>  	    dig_port->tc_mode != TC_PORT_TBT_ALT)
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 421e68bb436f..eac674ad91c8 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -3001,10 +3001,10 @@ static void intel_disable_dp(struct intel_atomic_state *state,
>  
>  	/* Make sure the panel is off before trying to change the mode. But also
>  	 * ensure that we have vdd while we switch off the panel. */
> -	intel_edp_panel_vdd_on(intel_dp);
> +	intel_pps_vdd_on(intel_dp);
>  	intel_edp_backlight_off(old_conn_state);
>  	intel_dp_set_power(intel_dp, DP_SET_POWER_D3);
> -	intel_edp_panel_off(intel_dp);
> +	intel_pps_off(intel_dp);
>  	intel_dp->frl.is_trained = false;
>  	intel_dp->frl.trained_rate_gbps = 0;
>  }
> @@ -6339,7 +6339,7 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
>  			 * something nasty with it.
>  			 */
>  			intel_dp_pps_init(intel_dp);
> -			intel_edp_panel_vdd_sanitize(intel_dp);
> +			intel_pps_vdd_sanitize(intel_dp);
>  		}
>  	}
>  }
> @@ -6513,7 +6513,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd)
>  	struct intel_dp *intel_dp = &dig_port->dp;
>  
>  	if (dig_port->base.type == INTEL_OUTPUT_EDP &&
> -	    (long_hpd || !intel_edp_have_power(intel_dp))) {
> +	    (long_hpd || !intel_pps_have_power(intel_dp))) {
>  		/*
>  		 * vdd off can generate a long/short pulse on eDP which
>  		 * would require vdd on to handle it, and thus we
> @@ -7071,7 +7071,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	with_intel_pps_lock(intel_dp, wakeref) {
>  		intel_dp_init_panel_power_timestamps(intel_dp);
>  		intel_dp_pps_init(intel_dp);
> -		intel_edp_panel_vdd_sanitize(intel_dp);
> +		intel_pps_vdd_sanitize(intel_dp);
>  	}
>  
>  	/* Cache DPCD and EDID for edp. */
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
> index 36d8782d8df1..59215cfd7d97 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.c
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -558,7 +558,7 @@ static  u32 ilk_get_pp_control(struct intel_dp *intel_dp)
>  /*
>   * Must be paired with edp_panel_vdd_off().
>   * Must hold pps_mutex around the whole on/off sequence.
> - * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> + * Can be nested with intel_pps_vdd_{on,off}() calls.
>   */
>  bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>  {
> @@ -616,13 +616,12 @@ bool edp_panel_vdd_on(struct intel_dp *intel_dp)
>  }
>  
>  /*
> - * Must be paired with intel_edp_panel_vdd_off() or
> - * intel_edp_panel_off().
> + * Must be paired with intel_pps_off().
>   * Nested calls to these functions are not allowed since
>   * we drop the lock. Caller must use some higher level
>   * locking to prevent nested calls from other threads.
>   */
> -void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
> +void intel_pps_vdd_on(struct intel_dp *intel_dp)
>  {
>  	intel_wakeref_t wakeref;
>  	bool vdd;
> @@ -708,7 +707,7 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
>  /*
>   * Must be paired with edp_panel_vdd_on().
>   * Must hold pps_mutex around the whole on/off sequence.
> - * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> + * Can be nested with intel_pps_vdd_{on,off}() calls.
>   */
>  void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  {
> @@ -780,7 +779,7 @@ void edp_panel_on(struct intel_dp *intel_dp)
>  	}
>  }
>  
> -void intel_edp_panel_on(struct intel_dp *intel_dp)
> +void intel_pps_on(struct intel_dp *intel_dp)
>  {
>  	intel_wakeref_t wakeref;
>  
> @@ -832,7 +831,7 @@ void edp_panel_off(struct intel_dp *intel_dp)
>  				fetch_and_zero(&intel_dp->vdd_wakeref));
>  }
>  
> -void intel_edp_panel_off(struct intel_dp *intel_dp)
> +void intel_pps_off(struct intel_dp *intel_dp)
>  {
>  	intel_wakeref_t wakeref;
>  
> @@ -1025,7 +1024,7 @@ void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
>  	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
>  }
>  
> -void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
> +void intel_pps_vdd_sanitize(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> @@ -1050,7 +1049,7 @@ void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
>  	edp_panel_vdd_schedule_off(intel_dp);
>  }
>  
> -bool intel_edp_have_power(struct intel_dp *intel_dp)
> +bool intel_pps_have_power(struct intel_dp *intel_dp)
>  {
>  	intel_wakeref_t wakeref;
>  	bool have_power = false;
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
> index 81e4e9fc3cf5..69f670678d0e 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.h
> +++ b/drivers/gpu/drm/i915/display/intel_pps.h
> @@ -34,12 +34,11 @@ void edp_panel_on(struct intel_dp *intel_dp);
>  void edp_panel_off(struct intel_dp *intel_dp);
>  void edp_panel_vdd_work(struct work_struct *__work);
>  
> -void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
> -void intel_edp_panel_on(struct intel_dp *intel_dp);
> -void intel_edp_panel_off(struct intel_dp *intel_dp);
> -bool intel_edp_have_power(struct intel_dp *intel_dp);
> -
> -void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp);
> +void intel_pps_vdd_sanitize(struct intel_dp *intel_dp);
> +void intel_pps_vdd_on(struct intel_dp *intel_dp);
> +void intel_pps_on(struct intel_dp *intel_dp);
> +void intel_pps_off(struct intel_dp *intel_dp);
> +bool intel_pps_have_power(struct intel_dp *intel_dp);
>  
>  void wait_panel_power_cycle(struct intel_dp *intel_dp);
>  
> -- 
> 2.20.1
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 05/17] drm/i915/pps: rename edp_panel_* to intel_pps_*_unlocked
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 05/17] drm/i915/pps: rename edp_panel_* to intel_pps_*_unlocked Jani Nikula
@ 2021-01-13 10:41   ` Anshuman Gupta
  0 siblings, 0 replies; 37+ messages in thread
From: Anshuman Gupta @ 2021-01-13 10:41 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On 2021-01-08 at 19:44:13 +0200, Jani Nikula wrote:
> Follow the usual naming pattern for functions, both for the prefix and
> the _unlocked suffix for functions that expect the lock to be held when
> calling. No functional changes.
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
LGTM.
Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c  | 16 +++++++--------
>  drivers/gpu/drm/i915/display/intel_pps.c | 26 ++++++++++++------------
>  drivers/gpu/drm/i915/display/intel_pps.h | 10 ++++-----
>  3 files changed, 26 insertions(+), 26 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index eac674ad91c8..1384f1d3a9cf 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -1061,7 +1061,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
>  	 * to turn it off. But for eg. i2c-dev access we need to turn it on/off
>  	 * ourselves.
>  	 */
> -	vdd = edp_panel_vdd_on(intel_dp);
> +	vdd = intel_pps_vdd_on_unlocked(intel_dp);
>  
>  	/* dp aux is extremely sensitive to irq latency, hence request the
>  	 * lowest possible wakeup latency and so prevent the cpu from going into
> @@ -1203,7 +1203,7 @@ intel_dp_aux_xfer(struct intel_dp *intel_dp,
>  	cpu_latency_qos_update_request(&intel_dp->pm_qos, PM_QOS_DEFAULT_VALUE);
>  
>  	if (vdd)
> -		edp_panel_vdd_off(intel_dp, false);
> +		intel_pps_vdd_off_unlocked(intel_dp, false);
>  
>  	intel_pps_unlock(intel_dp, pps_wakeref);
>  	intel_display_power_put_async(i915, aux_domain, aux_wakeref);
> @@ -3520,9 +3520,9 @@ static void intel_enable_dp(struct intel_atomic_state *state,
>  
>  		intel_dp_enable_port(intel_dp, pipe_config);
>  
> -		edp_panel_vdd_on(intel_dp);
> -		edp_panel_on(intel_dp);
> -		edp_panel_vdd_off(intel_dp, true);
> +		intel_pps_vdd_on_unlocked(intel_dp);
> +		intel_pps_on_unlocked(intel_dp);
> +		intel_pps_vdd_off_unlocked(intel_dp, true);
>  	}
>  
>  	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> @@ -6258,7 +6258,7 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder)
>  		 * Make sure vdd is actually turned off here.
>  		 */
>  		with_intel_pps_lock(intel_dp, wakeref)
> -			edp_panel_vdd_off_sync(intel_dp);
> +			intel_pps_vdd_off_sync_unlocked(intel_dp);
>  	}
>  
>  	intel_dp_aux_fini(intel_dp);
> @@ -6286,7 +6286,7 @@ void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
>  	 */
>  	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
>  	with_intel_pps_lock(intel_dp, wakeref)
> -		edp_panel_vdd_off_sync(intel_dp);
> +		intel_pps_vdd_off_sync_unlocked(intel_dp);
>  }
>  
>  void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
> @@ -7146,7 +7146,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	 * Make sure vdd is actually turned off here.
>  	 */
>  	with_intel_pps_lock(intel_dp, wakeref)
> -		edp_panel_vdd_off_sync(intel_dp);
> +		intel_pps_vdd_off_sync_unlocked(intel_dp);
>  
>  	return false;
>  }
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
> index 59215cfd7d97..fd3677948800 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.c
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -556,11 +556,11 @@ static  u32 ilk_get_pp_control(struct intel_dp *intel_dp)
>  }
>  
>  /*
> - * Must be paired with edp_panel_vdd_off().
> + * Must be paired with intel_pps_vdd_off_unlocked().
>   * Must hold pps_mutex around the whole on/off sequence.
>   * Can be nested with intel_pps_vdd_{on,off}() calls.
>   */
> -bool edp_panel_vdd_on(struct intel_dp *intel_dp)
> +bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> @@ -631,13 +631,13 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp)
>  
>  	vdd = false;
>  	with_intel_pps_lock(intel_dp, wakeref)
> -		vdd = edp_panel_vdd_on(intel_dp);
> +		vdd = intel_pps_vdd_on_unlocked(intel_dp);
>  	I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n",
>  			dp_to_dig_port(intel_dp)->base.base.base.id,
>  			dp_to_dig_port(intel_dp)->base.base.name);
>  }
>  
> -void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
> +void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	struct intel_digital_port *dig_port =
> @@ -687,7 +687,7 @@ void edp_panel_vdd_work(struct work_struct *__work)
>  
>  	with_intel_pps_lock(intel_dp, wakeref) {
>  		if (!intel_dp->want_panel_vdd)
> -			edp_panel_vdd_off_sync(intel_dp);
> +			intel_pps_vdd_off_sync_unlocked(intel_dp);
>  	}
>  }
>  
> @@ -709,7 +709,7 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
>   * Must hold pps_mutex around the whole on/off sequence.
>   * Can be nested with intel_pps_vdd_{on,off}() calls.
>   */
> -void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
> +void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  
> @@ -725,12 +725,12 @@ void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
>  	intel_dp->want_panel_vdd = false;
>  
>  	if (sync)
> -		edp_panel_vdd_off_sync(intel_dp);
> +		intel_pps_vdd_off_sync_unlocked(intel_dp);
>  	else
>  		edp_panel_vdd_schedule_off(intel_dp);
>  }
>  
> -void edp_panel_on(struct intel_dp *intel_dp)
> +void intel_pps_on_unlocked(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	u32 pp;
> @@ -787,10 +787,10 @@ void intel_pps_on(struct intel_dp *intel_dp)
>  		return;
>  
>  	with_intel_pps_lock(intel_dp, wakeref)
> -		edp_panel_on(intel_dp);
> +		intel_pps_on_unlocked(intel_dp);
>  }
>  
> -void edp_panel_off(struct intel_dp *intel_dp)
> +void intel_pps_off_unlocked(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> @@ -839,7 +839,7 @@ void intel_pps_off(struct intel_dp *intel_dp)
>  		return;
>  
>  	with_intel_pps_lock(intel_dp, wakeref)
> -		edp_panel_off(intel_dp);
> +		intel_pps_off_unlocked(intel_dp);
>  }
>  
>  /* Enable backlight in the panel power control. */
> @@ -930,7 +930,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
>  	if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B))
>  		return;
>  
> -	edp_panel_vdd_off_sync(intel_dp);
> +	intel_pps_vdd_off_sync_unlocked(intel_dp);
>  
>  	/*
>  	 * VLV seems to get confused when multiple power sequencers
> @@ -1245,7 +1245,7 @@ intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
>  	 * hooked up to any port. This would mess up the
>  	 * power domain tracking the first time we pick
>  	 * one of these power sequencers for use since
> -	 * edp_panel_vdd_on() would notice that the VDD was
> +	 * intel_pps_vdd_on_unlocked() would notice that the VDD was
>  	 * already on and therefore wouldn't grab the power
>  	 * domain reference. Disable VDD first to avoid this.
>  	 * This also avoids spuriously turning the VDD on as
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
> index 69f670678d0e..e7f0473be9a7 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.h
> +++ b/drivers/gpu/drm/i915/display/intel_pps.h
> @@ -27,11 +27,11 @@ void intel_pps_backlight_on(struct intel_dp *intel_dp);
>  void intel_pps_backlight_off(struct intel_dp *intel_dp);
>  void intel_pps_backlight_power(struct intel_connector *connector, bool enable);
>  
> -bool edp_panel_vdd_on(struct intel_dp *intel_dp);
> -void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
> -void edp_panel_vdd_off_sync(struct intel_dp *intel_dp);
> -void edp_panel_on(struct intel_dp *intel_dp);
> -void edp_panel_off(struct intel_dp *intel_dp);
> +bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp);
> +void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync);
> +void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp);
> +void intel_pps_on_unlocked(struct intel_dp *intel_dp);
> +void intel_pps_off_unlocked(struct intel_dp *intel_dp);
>  void edp_panel_vdd_work(struct work_struct *__work);
>  
>  void intel_pps_vdd_sanitize(struct intel_dp *intel_dp);
> -- 
> 2.20.1
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 06/17] drm/i915/pps: abstract intel_pps_vdd_off_sync
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 06/17] drm/i915/pps: abstract intel_pps_vdd_off_sync Jani Nikula
@ 2021-01-13 10:42   ` Anshuman Gupta
  0 siblings, 0 replies; 37+ messages in thread
From: Anshuman Gupta @ 2021-01-13 10:42 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On 2021-01-08 at 19:44:14 +0200, Jani Nikula wrote:
> Add a locked version of intel_pps_vdd_off_sync_unlocked() that does
> everything the callers expect it to. No functional changes.
> 
> v2: Fix typo (Anshuman)
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
LGTM.
Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_dp.c  | 31 +++---------------------
>  drivers/gpu/drm/i915/display/intel_pps.c | 18 +++++++++++++-
>  drivers/gpu/drm/i915/display/intel_pps.h |  2 +-
>  3 files changed, 21 insertions(+), 30 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 1384f1d3a9cf..bff5e735a92e 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -6249,17 +6249,8 @@ void intel_dp_encoder_flush_work(struct drm_encoder *encoder)
>  	struct intel_dp *intel_dp = &dig_port->dp;
>  
>  	intel_dp_mst_encoder_cleanup(dig_port);
> -	if (intel_dp_is_edp(intel_dp)) {
> -		intel_wakeref_t wakeref;
>  
> -		cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> -		/*
> -		 * vdd might still be enabled do to the delayed vdd off.
> -		 * Make sure vdd is actually turned off here.
> -		 */
> -		with_intel_pps_lock(intel_dp, wakeref)
> -			intel_pps_vdd_off_sync_unlocked(intel_dp);
> -	}
> +	intel_pps_vdd_off_sync(intel_dp);
>  
>  	intel_dp_aux_fini(intel_dp);
>  }
> @@ -6275,18 +6266,8 @@ static void intel_dp_encoder_destroy(struct drm_encoder *encoder)
>  void intel_dp_encoder_suspend(struct intel_encoder *intel_encoder)
>  {
>  	struct intel_dp *intel_dp = enc_to_intel_dp(intel_encoder);
> -	intel_wakeref_t wakeref;
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
>  
> -	/*
> -	 * vdd might still be enabled do to the delayed vdd off.
> -	 * Make sure vdd is actually turned off here.
> -	 */
> -	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> -	with_intel_pps_lock(intel_dp, wakeref)
> -		intel_pps_vdd_off_sync_unlocked(intel_dp);
> +	intel_pps_vdd_off_sync(intel_dp);
>  }
>  
>  void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
> @@ -7140,13 +7121,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  	return true;
>  
>  out_vdd_off:
> -	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> -	/*
> -	 * vdd might still be enabled do to the delayed vdd off.
> -	 * Make sure vdd is actually turned off here.
> -	 */
> -	with_intel_pps_lock(intel_dp, wakeref)
> -		intel_pps_vdd_off_sync_unlocked(intel_dp);
> +	intel_pps_vdd_off_sync(intel_dp);
>  
>  	return false;
>  }
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
> index fd3677948800..b6c07694ae9d 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.c
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -637,7 +637,7 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp)
>  			dp_to_dig_port(intel_dp)->base.base.name);
>  }
>  
> -void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
> +static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	struct intel_digital_port *dig_port =
> @@ -678,6 +678,22 @@ void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
>  				fetch_and_zero(&intel_dp->vdd_wakeref));
>  }
>  
> +void intel_pps_vdd_off_sync(struct intel_dp *intel_dp)
> +{
> +	intel_wakeref_t wakeref;
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> +	/*
> +	 * vdd might still be enabled due to the delayed vdd off.
> +	 * Make sure vdd is actually turned off here.
> +	 */
> +	with_intel_pps_lock(intel_dp, wakeref)
> +		intel_pps_vdd_off_sync_unlocked(intel_dp);
> +}
> +
>  void edp_panel_vdd_work(struct work_struct *__work)
>  {
>  	struct intel_dp *intel_dp =
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
> index e7f0473be9a7..3cab183658c6 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.h
> +++ b/drivers/gpu/drm/i915/display/intel_pps.h
> @@ -29,7 +29,6 @@ void intel_pps_backlight_power(struct intel_connector *connector, bool enable);
>  
>  bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp);
>  void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync);
> -void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp);
>  void intel_pps_on_unlocked(struct intel_dp *intel_dp);
>  void intel_pps_off_unlocked(struct intel_dp *intel_dp);
>  void edp_panel_vdd_work(struct work_struct *__work);
> @@ -38,6 +37,7 @@ void intel_pps_vdd_sanitize(struct intel_dp *intel_dp);
>  void intel_pps_vdd_on(struct intel_dp *intel_dp);
>  void intel_pps_on(struct intel_dp *intel_dp);
>  void intel_pps_off(struct intel_dp *intel_dp);
> +void intel_pps_vdd_off_sync(struct intel_dp *intel_dp);
>  bool intel_pps_have_power(struct intel_dp *intel_dp);
>  
>  void wait_panel_power_cycle(struct intel_dp *intel_dp);
> -- 
> 2.20.1
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 13/17] drm/i915/pps: rename intel_dp_init_panel_power_sequencer* functions
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 13/17] drm/i915/pps: rename intel_dp_init_panel_power_sequencer* functions Jani Nikula
@ 2021-01-13 11:02   ` Anshuman Gupta
  2021-01-14  8:31     ` Jani Nikula
  0 siblings, 1 reply; 37+ messages in thread
From: Anshuman Gupta @ 2021-01-13 11:02 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On 2021-01-08 at 19:44:21 +0200, Jani Nikula wrote:
> There are a number of functions that "init" pps in various ways. Try to
> find some more consistency in the naming.
> 
> Rename:
>  - intel_dp_init_panel_power_sequencer -> pps_init_delays
>  - intel_dp_init_panel_power_sequencer_registers -> pps_init_registers
>  - intel_dp_init_panel_power_timestamps -> pps_init_timestamps
> 
> as this is what the functions do. Skip the intel_ prefix here to
> emphasize these are static and not exported.
> 
> No functional changes.
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
LGTM.
Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_pps.c | 37 ++++++++++--------------
>  1 file changed, 16 insertions(+), 21 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
> index 8925df55e22e..58eff6289d12 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.c
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -10,11 +10,9 @@
>  
>  static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
>  				      enum pipe pipe);
> -static void
> -intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp);
> -static void
> -intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
> -					      bool force_disable_vdd);
> +
> +static void pps_init_delays(struct intel_dp *intel_dp);
> +static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd);
>  
>  intel_wakeref_t intel_pps_lock(struct intel_dp *intel_dp)
>  {
> @@ -190,8 +188,8 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
>  		    dig_port->base.base.name);
>  
>  	/* init power sequencer on this pipe and port */
> -	intel_dp_init_panel_power_sequencer(intel_dp);
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
> +	pps_init_delays(intel_dp);
> +	pps_init_registers(intel_dp, true);
>  
>  	/*
>  	 * Even vdd force doesn't work until we've made
> @@ -222,7 +220,7 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp)
>  	 * Only the HW needs to be reprogrammed, the SW state is fixed and
>  	 * has been setup during connector init.
>  	 */
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> +	pps_init_registers(intel_dp, false);
>  
>  	return backlight_controller;
>  }
> @@ -308,8 +306,8 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
>  		    dig_port->base.base.name,
>  		    pipe_name(intel_dp->pps_pipe));
>  
> -	intel_dp_init_panel_power_sequencer(intel_dp);
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> +	pps_init_delays(intel_dp);
> +	pps_init_registers(intel_dp, false);
>  }
>  
>  void intel_pps_reset_all(struct drm_i915_private *dev_priv)
> @@ -1046,8 +1044,8 @@ void vlv_pps_init(struct intel_encoder *encoder,
>  		    encoder->base.name);
>  
>  	/* init power sequencer on this pipe and port */
> -	intel_dp_init_panel_power_sequencer(intel_dp);
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
> +	pps_init_delays(intel_dp);
> +	pps_init_registers(intel_dp, true);
>  }
>  
>  static void intel_pps_vdd_sanitize(struct intel_dp *intel_dp)
> @@ -1088,7 +1086,7 @@ bool intel_pps_have_power(struct intel_dp *intel_dp)
>  	return have_power;
>  }
>  
> -static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
> +static void pps_init_timestamps(struct intel_dp *intel_dp)
>  {
>  	intel_dp->panel_power_off_time = ktime_get_boottime();
>  	intel_dp->last_power_on = jiffies;
> @@ -1154,8 +1152,7 @@ intel_pps_verify_state(struct intel_dp *intel_dp)
>  	}
>  }
>  
> -static void
> -intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp)
> +static void pps_init_delays(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	struct edp_power_seq cur, vbt, spec,
> @@ -1250,9 +1247,7 @@ intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp)
>  	final->t11_t12 = roundup(final->t11_t12, 100 * 10);
>  }
>  
> -static void
> -intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
> -					      bool force_disable_vdd)
> +static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	u32 pp_on, pp_off, port_sel = 0;
> @@ -1354,8 +1349,8 @@ static void intel_dp_pps_init(struct intel_dp *intel_dp)
>  	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
>  		vlv_initial_power_sequencer_setup(intel_dp);
>  	} else {
> -		intel_dp_init_panel_power_sequencer(intel_dp);
> -		intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> +		pps_init_delays(intel_dp);
> +		pps_init_registers(intel_dp, false);
>  	}
>  }
>  
> @@ -1383,7 +1378,7 @@ void intel_pps_init(struct intel_dp *intel_dp)
>  	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work);
>  
>  	with_intel_pps_lock(intel_dp, wakeref) {
> -		intel_dp_init_panel_power_timestamps(intel_dp);
> +		pps_init_timestamps(intel_dp);
>  		intel_dp_pps_init(intel_dp);
>  		intel_pps_vdd_sanitize(intel_dp);
>  	}
> -- 
> 2.20.1
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 14/17] drm/i915/pps: refactor init abstractions
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 14/17] drm/i915/pps: refactor init abstractions Jani Nikula
@ 2021-01-13 11:44   ` Anshuman Gupta
  2021-01-14  8:46     ` Jani Nikula
  0 siblings, 1 reply; 37+ messages in thread
From: Anshuman Gupta @ 2021-01-13 11:44 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On 2021-01-08 at 19:44:22 +0200, Jani Nikula wrote:
> Once you realize there is no need to hold the pps mutex when calling
> pps_init_timestamps() in intel_pps_init(), we can reuse
> intel_pps_encoder_reset() which has the same code.
> 
> Since intel_dp_pps_init() is only called from one place now, move it
> inline to remove one "init" function altogether.
> 
> Finally, remove some initialization from
> vlv_initial_power_sequencer_setup() and do it in the caller to highlight
> the similarity, not the difference, in the platforms.
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_pps.c | 33 +++++++-----------------
>  1 file changed, 10 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
> index 58eff6289d12..b4d026ca3313 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.c
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -305,9 +305,6 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
>  		    dig_port->base.base.base.id,
>  		    dig_port->base.base.name,
>  		    pipe_name(intel_dp->pps_pipe));
> -
> -	pps_init_delays(intel_dp);
> -	pps_init_registers(intel_dp, false);
>  }
>  
>  void intel_pps_reset_all(struct drm_i915_private *dev_priv)
> @@ -1342,20 +1339,9 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
>  		    (intel_de_read(dev_priv, regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK));
>  }
>  
> -static void intel_dp_pps_init(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -		vlv_initial_power_sequencer_setup(intel_dp);
> -	} else {
> -		pps_init_delays(intel_dp);
> -		pps_init_registers(intel_dp, false);
> -	}
> -}
> -
>  void intel_pps_encoder_reset(struct intel_dp *intel_dp)
>  {
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
>  	intel_wakeref_t wakeref;
>  
>  	if (!intel_dp_is_edp(intel_dp))
> @@ -1366,20 +1352,21 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp)
>  		 * Reinit the power sequencer, in case BIOS did something nasty
		IMHO above comment would need a improvement, or nuke it ?
		as intel_pps_encoder_reset() will also get called from intel_pps_init()	
		unlike only while resuming from suspend.
		Thanks,
		Anshuman Gupta.
>  		 * with it.
>  		 */
> -		intel_dp_pps_init(intel_dp);
> +		if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
> +			vlv_initial_power_sequencer_setup(intel_dp);
> +
> +		pps_init_delays(intel_dp);
> +		pps_init_registers(intel_dp, false);
> +
>  		intel_pps_vdd_sanitize(intel_dp);
>  	}
>  }
>  
>  void intel_pps_init(struct intel_dp *intel_dp)
>  {
> -	intel_wakeref_t wakeref;
> -
>  	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work);
>  
> -	with_intel_pps_lock(intel_dp, wakeref) {
> -		pps_init_timestamps(intel_dp);
> -		intel_dp_pps_init(intel_dp);
> -		intel_pps_vdd_sanitize(intel_dp);
> -	}
> +	pps_init_timestamps(intel_dp);
> +
> +	intel_pps_encoder_reset(intel_dp);
>  }
> -- 
> 2.20.1
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 15/17] drm/i915/pps: move pps code over from intel_display.c and refactor
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 15/17] drm/i915/pps: move pps code over from intel_display.c and refactor Jani Nikula
@ 2021-01-13 11:55   ` Anshuman Gupta
  2021-01-14  8:56     ` Jani Nikula
  0 siblings, 1 reply; 37+ messages in thread
From: Anshuman Gupta @ 2021-01-13 11:55 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On 2021-01-08 at 19:44:23 +0200, Jani Nikula wrote:
> intel_display.c has some pps functions that belong to intel_pps.c. Move
> them over.
> 
> While at it, refactor the duplicate intel_pps_init() in intel_display.c
> into an orthogonal intel_pps_setup() in intel_pps.c, and call it earlier
> in intel_modeset_init_nogem().
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/display/intel_display.c | 41 ++------------------
>  drivers/gpu/drm/i915/display/intel_display.h |  1 -
>  drivers/gpu/drm/i915/display/intel_pps.c     | 34 ++++++++++++++++
>  drivers/gpu/drm/i915/display/intel_pps.h     |  3 ++
>  drivers/gpu/drm/i915/i915_drv.c              |  1 +
>  5 files changed, 42 insertions(+), 38 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
> index 0189d379a55e..f8806c4ecb21 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.c
> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> @@ -81,6 +81,7 @@
>  #include "intel_overlay.h"
>  #include "intel_pipe_crc.h"
>  #include "intel_pm.h"
> +#include "intel_pps.h"
>  #include "intel_psr.h"
>  #include "intel_quirks.h"
>  #include "intel_sideband.h"
> @@ -16100,48 +16101,12 @@ static bool intel_ddi_crt_present(struct drm_i915_private *dev_priv)
>  	return true;
>  }
>  
> -void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
> -{
> -	int pps_num;
> -	int pps_idx;
> -
> -	if (HAS_DDI(dev_priv))
> -		return;
> -	/*
> -	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
> -	 * everywhere where registers can be write protected.
> -	 */
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		pps_num = 2;
> -	else
> -		pps_num = 1;
> -
> -	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
> -		u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx));
> -
> -		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
> -		intel_de_write(dev_priv, PP_CONTROL(pps_idx), val);
> -	}
> -}
> -
> -static void intel_pps_init(struct drm_i915_private *dev_priv)
> -{
> -	if (HAS_PCH_SPLIT(dev_priv) || IS_GEN9_LP(dev_priv))
> -		dev_priv->pps_mmio_base = PCH_PPS_BASE;
> -	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		dev_priv->pps_mmio_base = VLV_PPS_BASE;
> -	else
> -		dev_priv->pps_mmio_base = PPS_BASE;
> -
> -	intel_pps_unlock_regs_wa(dev_priv);
> -}
> -
>  static void intel_setup_outputs(struct drm_i915_private *dev_priv)
>  {
>  	struct intel_encoder *encoder;
>  	bool dpd_is_edp = false;
>  
> -	intel_pps_init(dev_priv);
> +	intel_pps_unlock_regs_wa(dev_priv);
>  
>  	if (!HAS_DISPLAY(dev_priv))
>  		return;
> @@ -17199,6 +17164,8 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)
>  
>  	intel_panel_sanitize_ssc(i915);
>  
> +	intel_pps_setup(i915);
> +
This is mmio init, could you please guide me why i915_driver_mmio_probe()
has not chosen to call intel_pps_setup() ?
>  	intel_gmbus_setup(i915);
>  
>  	drm_dbg_kms(&i915->drm, "%d display pipe%s available.\n",
> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
> index 7ddbc00a0f41..bbd5dbc61ce9 100644
> --- a/drivers/gpu/drm/i915/display/intel_display.h
> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> @@ -546,7 +546,6 @@ unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info
>  unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info);
>  bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv);
>  int intel_display_suspend(struct drm_device *dev);
> -void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
>  void intel_encoder_destroy(struct drm_encoder *encoder);
>  struct drm_display_mode *
>  intel_encoder_current_mode(struct intel_encoder *encoder);
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
> index b4d026ca3313..c3a0fc933500 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.c
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -1370,3 +1370,37 @@ void intel_pps_init(struct intel_dp *intel_dp)
>  
>  	intel_pps_encoder_reset(intel_dp);
>  }
> +
> +void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
> +{
> +	int pps_num;
> +	int pps_idx;
> +
> +	if (HAS_DDI(dev_priv))
> +		return;
> +	/*
> +	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
> +	 * everywhere where registers can be write protected.
> +	 */
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		pps_num = 2;
> +	else
> +		pps_num = 1;
> +
> +	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
> +		u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx));
> +
> +		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
> +		intel_de_write(dev_priv, PP_CONTROL(pps_idx), val);
> +	}
> +}
> +
> +void intel_pps_setup(struct drm_i915_private *i915)
> +{
> +	if (HAS_PCH_SPLIT(i915) || IS_GEN9_LP(i915))
> +		i915->pps_mmio_base = PCH_PPS_BASE;
> +	else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
> +		i915->pps_mmio_base = VLV_PPS_BASE;
> +	else
> +		i915->pps_mmio_base = PPS_BASE;
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
> index 22045c5cdc86..fbbcca782e7b 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.h
> +++ b/drivers/gpu/drm/i915/display/intel_pps.h
> @@ -46,4 +46,7 @@ void intel_pps_reset_all(struct drm_i915_private *i915);
>  void vlv_pps_init(struct intel_encoder *encoder,
>  		  const struct intel_crtc_state *crtc_state);
>  
> +void intel_pps_unlock_regs_wa(struct drm_i915_private *i915);
> +void intel_pps_setup(struct drm_i915_private *i915);
> +
>  #endif /* __INTEL_PPS_H__ */
> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
> index 3e504247f2da..7282c8f08318 100644
> --- a/drivers/gpu/drm/i915/i915_drv.c
> +++ b/drivers/gpu/drm/i915/i915_drv.c
> @@ -58,6 +58,7 @@
>  #include "display/intel_hotplug.h"
>  #include "display/intel_overlay.h"
>  #include "display/intel_pipe_crc.h"
> +#include "display/intel_pps.h"
>  #include "display/intel_sprite.h"
>  #include "display/intel_vga.h"
>  
> -- 
> 2.20.1
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 16/17] drm/i915/dp: abstract struct intel_dp pps members to a sub-struct
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 16/17] drm/i915/dp: abstract struct intel_dp pps members to a sub-struct Jani Nikula
@ 2021-01-13 11:58   ` Anshuman Gupta
  0 siblings, 0 replies; 37+ messages in thread
From: Anshuman Gupta @ 2021-01-13 11:58 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On 2021-01-08 at 19:44:24 +0200, Jani Nikula wrote:
> Add some namespacing to highlight what belongs where. No functional
> changes.
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> ---
>  .../drm/i915/display/intel_display_debugfs.c  |   8 +-
>  .../drm/i915/display/intel_display_types.h    |  61 +++---
>  drivers/gpu/drm/i915/display/intel_dp.c       |  14 +-
>  drivers/gpu/drm/i915/display/intel_pps.c      | 192 +++++++++---------
>  4 files changed, 140 insertions(+), 135 deletions(-)
> 
> diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> index cd7e5519ee7d..885d2d3c91a3 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
> @@ -2155,13 +2155,13 @@ static int i915_panel_show(struct seq_file *m, void *data)
>  		return -ENODEV;
>  
>  	seq_printf(m, "Panel power up delay: %d\n",
> -		   intel_dp->panel_power_up_delay);
> +		   intel_dp->pps.panel_power_up_delay);
>  	seq_printf(m, "Panel power down delay: %d\n",
> -		   intel_dp->panel_power_down_delay);
> +		   intel_dp->pps.panel_power_down_delay);
>  	seq_printf(m, "Backlight on delay: %d\n",
> -		   intel_dp->backlight_on_delay);
> +		   intel_dp->pps.backlight_on_delay);
>  	seq_printf(m, "Backlight off delay: %d\n",
> -		   intel_dp->backlight_off_delay);
> +		   intel_dp->pps.backlight_off_delay);
Not related to this patch but can we add panel_power_cycle_delay too
in the debugfs, that is also useful to debug some issues.
Thanks,
Anshuman Gupta. 
>  
>  	return 0;
>  }
> diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h
> index 1067bd073c95..69b34378cc6e 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_types.h
> +++ b/drivers/gpu/drm/i915/display/intel_display_types.h
> @@ -1344,6 +1344,38 @@ struct intel_dp_pcon_frl {
>  	int trained_rate_gbps;
>  };
>  
> +struct intel_pps {
> +	int panel_power_up_delay;
> +	int panel_power_down_delay;
> +	int panel_power_cycle_delay;
> +	int backlight_on_delay;
> +	int backlight_off_delay;
> +	struct delayed_work panel_vdd_work;
> +	bool want_panel_vdd;
> +	unsigned long last_power_on;
> +	unsigned long last_backlight_off;
> +	ktime_t panel_power_off_time;
> +	intel_wakeref_t vdd_wakeref;
> +
> +	/*
> +	 * Pipe whose power sequencer is currently locked into
> +	 * this port. Only relevant on VLV/CHV.
> +	 */
> +	enum pipe pps_pipe;
> +	/*
> +	 * Pipe currently driving the port. Used for preventing
> +	 * the use of the PPS for any pipe currentrly driving
> +	 * external DP as that will mess things up on VLV.
> +	 */
> +	enum pipe active_pipe;
> +	/*
> +	 * Set if the sequencer may be reset due to a power transition,
> +	 * requiring a reinitialization. Only relevant on BXT.
> +	 */
> +	bool pps_reset;
> +	struct edp_power_seq pps_delays;
> +};
> +
>  struct intel_dp {
>  	i915_reg_t output_reg;
>  	u32 DP;
> @@ -1383,35 +1415,8 @@ struct intel_dp {
>  	struct drm_dp_aux aux;
>  	u32 aux_busy_last_status;
>  	u8 train_set[4];
> -	int panel_power_up_delay;
> -	int panel_power_down_delay;
> -	int panel_power_cycle_delay;
> -	int backlight_on_delay;
> -	int backlight_off_delay;
> -	struct delayed_work panel_vdd_work;
> -	bool want_panel_vdd;
> -	unsigned long last_power_on;
> -	unsigned long last_backlight_off;
> -	ktime_t panel_power_off_time;
> -	intel_wakeref_t vdd_wakeref;
>  
> -	/*
> -	 * Pipe whose power sequencer is currently locked into
> -	 * this port. Only relevant on VLV/CHV.
> -	 */
> -	enum pipe pps_pipe;
> -	/*
> -	 * Pipe currently driving the port. Used for preventing
> -	 * the use of the PPS for any pipe currentrly driving
> -	 * external DP as that will mess things up on VLV.
> -	 */
> -	enum pipe active_pipe;
> -	/*
> -	 * Set if the sequencer may be reset due to a power transition,
> -	 * requiring a reinitialization. Only relevant on BXT.
> -	 */
> -	bool pps_reset;
> -	struct edp_power_seq pps_delays;
> +	struct intel_pps pps;
>  
>  	bool can_mst; /* this port supports mst */
>  	bool is_mst;
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index a8835e3b1ac1..e6859b9925b9 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -4075,7 +4075,7 @@ intel_dp_link_down(struct intel_encoder *encoder,
>  		intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true);
>  	}
>  
> -	msleep(intel_dp->panel_power_down_delay);
> +	msleep(intel_dp->pps.panel_power_down_delay);
>  
>  	intel_dp->DP = DP;
>  
> @@ -4083,7 +4083,7 @@ intel_dp_link_down(struct intel_encoder *encoder,
>  		intel_wakeref_t wakeref;
>  
>  		with_intel_pps_lock(intel_dp, wakeref)
> -			intel_dp->active_pipe = INVALID_PIPE;
> +			intel_dp->pps.active_pipe = INVALID_PIPE;
>  	}
>  }
>  
> @@ -6304,7 +6304,7 @@ void intel_dp_encoder_reset(struct drm_encoder *encoder)
>  		intel_wakeref_t wakeref;
>  
>  		with_intel_pps_lock(intel_dp, wakeref)
> -			intel_dp->active_pipe = vlv_active_pipe(intel_dp);
> +			intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp);
>  	}
>  
>  	intel_pps_encoder_reset(intel_dp);
> @@ -7076,7 +7076,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp,
>  		pipe = vlv_active_pipe(intel_dp);
>  
>  		if (pipe != PIPE_A && pipe != PIPE_B)
> -			pipe = intel_dp->pps_pipe;
> +			pipe = intel_dp->pps.pps_pipe;
>  
>  		if (pipe != PIPE_A && pipe != PIPE_B)
>  			pipe = PIPE_A;
> @@ -7153,8 +7153,8 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
>  	intel_dp_set_source_rates(intel_dp);
>  
>  	intel_dp->reset_link_params = true;
> -	intel_dp->pps_pipe = INVALID_PIPE;
> -	intel_dp->active_pipe = INVALID_PIPE;
> +	intel_dp->pps.pps_pipe = INVALID_PIPE;
> +	intel_dp->pps.active_pipe = INVALID_PIPE;
>  
>  	/* Preserve the current hw state. */
>  	intel_dp->DP = intel_de_read(dev_priv, intel_dp->output_reg);
> @@ -7172,7 +7172,7 @@ intel_dp_init_connector(struct intel_digital_port *dig_port,
>  	}
>  
>  	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		intel_dp->active_pipe = vlv_active_pipe(intel_dp);
> +		intel_dp->pps.active_pipe = vlv_active_pipe(intel_dp);
>  
>  	/*
>  	 * For eDP we always set the encoder type to INTEL_OUTPUT_EDP, but
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
> index c3a0fc933500..6bf807173ed3 100644
> --- a/drivers/gpu/drm/i915/display/intel_pps.c
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -44,7 +44,7 @@ vlv_power_sequencer_kick(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum pipe pipe = intel_dp->pps_pipe;
> +	enum pipe pipe = intel_dp->pps.pps_pipe;
>  	bool pll_enabled, release_cl_override = false;
>  	enum dpio_phy phy = DPIO_PHY(pipe);
>  	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
> @@ -130,18 +130,18 @@ static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv)
>  
>  		if (encoder->type == INTEL_OUTPUT_EDP) {
>  			drm_WARN_ON(&dev_priv->drm,
> -				    intel_dp->active_pipe != INVALID_PIPE &&
> -				    intel_dp->active_pipe !=
> -				    intel_dp->pps_pipe);
> +				    intel_dp->pps.active_pipe != INVALID_PIPE &&
> +				    intel_dp->pps.active_pipe !=
> +				    intel_dp->pps.pps_pipe);
>  
> -			if (intel_dp->pps_pipe != INVALID_PIPE)
> -				pipes &= ~(1 << intel_dp->pps_pipe);
> +			if (intel_dp->pps.pps_pipe != INVALID_PIPE)
> +				pipes &= ~(1 << intel_dp->pps.pps_pipe);
>  		} else {
>  			drm_WARN_ON(&dev_priv->drm,
> -				    intel_dp->pps_pipe != INVALID_PIPE);
> +				    intel_dp->pps.pps_pipe != INVALID_PIPE);
>  
> -			if (intel_dp->active_pipe != INVALID_PIPE)
> -				pipes &= ~(1 << intel_dp->active_pipe);
> +			if (intel_dp->pps.active_pipe != INVALID_PIPE)
> +				pipes &= ~(1 << intel_dp->pps.active_pipe);
>  		}
>  	}
>  
> @@ -163,11 +163,11 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
>  	/* We should never land here with regular DP ports */
>  	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
>  
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE &&
> -		    intel_dp->active_pipe != intel_dp->pps_pipe);
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.active_pipe != INVALID_PIPE &&
> +		    intel_dp->pps.active_pipe != intel_dp->pps.pps_pipe);
>  
> -	if (intel_dp->pps_pipe != INVALID_PIPE)
> -		return intel_dp->pps_pipe;
> +	if (intel_dp->pps.pps_pipe != INVALID_PIPE)
> +		return intel_dp->pps.pps_pipe;
>  
>  	pipe = vlv_find_free_pps(dev_priv);
>  
> @@ -179,11 +179,11 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
>  		pipe = PIPE_A;
>  
>  	vlv_steal_power_sequencer(dev_priv, pipe);
> -	intel_dp->pps_pipe = pipe;
> +	intel_dp->pps.pps_pipe = pipe;
>  
>  	drm_dbg_kms(&dev_priv->drm,
>  		    "picked pipe %c power sequencer for [ENCODER:%d:%s]\n",
> -		    pipe_name(intel_dp->pps_pipe),
> +		    pipe_name(intel_dp->pps.pps_pipe),
>  		    dig_port->base.base.base.id,
>  		    dig_port->base.base.name);
>  
> @@ -197,7 +197,7 @@ vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
>  	 */
>  	vlv_power_sequencer_kick(intel_dp);
>  
> -	return intel_dp->pps_pipe;
> +	return intel_dp->pps.pps_pipe;
>  }
>  
>  static int
> @@ -211,10 +211,10 @@ bxt_power_sequencer_idx(struct intel_dp *intel_dp)
>  	/* We should never land here with regular DP ports */
>  	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
>  
> -	if (!intel_dp->pps_reset)
> +	if (!intel_dp->pps.pps_reset)
>  		return backlight_controller;
>  
> -	intel_dp->pps_reset = false;
> +	intel_dp->pps.pps_reset = false;
>  
>  	/*
>  	 * Only the HW needs to be reprogrammed, the SW state is fixed and
> @@ -280,19 +280,19 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
>  
>  	/* try to find a pipe with this port selected */
>  	/* first pick one where the panel is on */
> -	intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> -						  vlv_pipe_has_pp_on);
> +	intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> +						      vlv_pipe_has_pp_on);
>  	/* didn't find one? pick one where vdd is on */
> -	if (intel_dp->pps_pipe == INVALID_PIPE)
> -		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> -							  vlv_pipe_has_vdd_on);
> +	if (intel_dp->pps.pps_pipe == INVALID_PIPE)
> +		intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> +							      vlv_pipe_has_vdd_on);
>  	/* didn't find one? pick one with just the correct port */
> -	if (intel_dp->pps_pipe == INVALID_PIPE)
> -		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> -							  vlv_pipe_any);
> +	if (intel_dp->pps.pps_pipe == INVALID_PIPE)
> +		intel_dp->pps.pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> +							      vlv_pipe_any);
>  
>  	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
> -	if (intel_dp->pps_pipe == INVALID_PIPE) {
> +	if (intel_dp->pps.pps_pipe == INVALID_PIPE) {
>  		drm_dbg_kms(&dev_priv->drm,
>  			    "no initial power sequencer for [ENCODER:%d:%s]\n",
>  			    dig_port->base.base.base.id,
> @@ -304,7 +304,7 @@ vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
>  		    "initial power sequencer for [ENCODER:%d:%s]: pipe %c\n",
>  		    dig_port->base.base.base.id,
>  		    dig_port->base.base.name,
> -		    pipe_name(intel_dp->pps_pipe));
> +		    pipe_name(intel_dp->pps.pps_pipe));
>  }
>  
>  void intel_pps_reset_all(struct drm_i915_private *dev_priv)
> @@ -331,15 +331,15 @@ void intel_pps_reset_all(struct drm_i915_private *dev_priv)
>  		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>  
>  		drm_WARN_ON(&dev_priv->drm,
> -			    intel_dp->active_pipe != INVALID_PIPE);
> +			    intel_dp->pps.active_pipe != INVALID_PIPE);
>  
>  		if (encoder->type != INTEL_OUTPUT_EDP)
>  			continue;
>  
>  		if (IS_GEN9_LP(dev_priv))
> -			intel_dp->pps_reset = true;
> +			intel_dp->pps.pps_reset = true;
>  		else
> -			intel_dp->pps_pipe = INVALID_PIPE;
> +			intel_dp->pps.pps_pipe = INVALID_PIPE;
>  	}
>  }
>  
> @@ -403,7 +403,7 @@ static bool edp_have_panel_power(struct intel_dp *intel_dp)
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
>  	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> -	    intel_dp->pps_pipe == INVALID_PIPE)
> +	    intel_dp->pps.pps_pipe == INVALID_PIPE)
>  		return false;
>  
>  	return (intel_de_read(dev_priv, _pp_stat_reg(intel_dp)) & PP_ON) != 0;
> @@ -416,7 +416,7 @@ static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
>  	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> -	    intel_dp->pps_pipe == INVALID_PIPE)
> +	    intel_dp->pps.pps_pipe == INVALID_PIPE)
>  		return false;
>  
>  	return intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
> @@ -506,13 +506,13 @@ static void wait_panel_power_cycle(struct intel_dp *intel_dp)
>  	/* take the difference of currrent time and panel power off time
>  	 * and then make panel wait for t11_t12 if needed. */
>  	panel_power_on_time = ktime_get_boottime();
> -	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->panel_power_off_time);
> +	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->pps.panel_power_off_time);
>  
>  	/* When we disable the VDD override bit last we have to do the manual
>  	 * wait. */
> -	if (panel_power_off_duration < (s64)intel_dp->panel_power_cycle_delay)
> +	if (panel_power_off_duration < (s64)intel_dp->pps.panel_power_cycle_delay)
>  		wait_remaining_ms_from_jiffies(jiffies,
> -				       intel_dp->panel_power_cycle_delay - panel_power_off_duration);
> +				       intel_dp->pps.panel_power_cycle_delay - panel_power_off_duration);
>  
>  	wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
>  }
> @@ -530,14 +530,14 @@ void intel_pps_wait_power_cycle(struct intel_dp *intel_dp)
>  
>  static void wait_backlight_on(struct intel_dp *intel_dp)
>  {
> -	wait_remaining_ms_from_jiffies(intel_dp->last_power_on,
> -				       intel_dp->backlight_on_delay);
> +	wait_remaining_ms_from_jiffies(intel_dp->pps.last_power_on,
> +				       intel_dp->pps.backlight_on_delay);
>  }
>  
>  static void edp_wait_backlight_off(struct intel_dp *intel_dp)
>  {
> -	wait_remaining_ms_from_jiffies(intel_dp->last_backlight_off,
> -				       intel_dp->backlight_off_delay);
> +	wait_remaining_ms_from_jiffies(intel_dp->pps.last_backlight_off,
> +				       intel_dp->pps.backlight_off_delay);
>  }
>  
>  /* Read the current pp_control value, unlocking the register if it
> @@ -571,22 +571,22 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
>  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
>  	u32 pp;
>  	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> -	bool need_to_disable = !intel_dp->want_panel_vdd;
> +	bool need_to_disable = !intel_dp->pps.want_panel_vdd;
>  
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
>  	if (!intel_dp_is_edp(intel_dp))
>  		return false;
>  
> -	cancel_delayed_work(&intel_dp->panel_vdd_work);
> -	intel_dp->want_panel_vdd = true;
> +	cancel_delayed_work(&intel_dp->pps.panel_vdd_work);
> +	intel_dp->pps.want_panel_vdd = true;
>  
>  	if (edp_have_panel_vdd(intel_dp))
>  		return need_to_disable;
>  
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
> -	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
> -							intel_aux_power_domain(dig_port));
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.vdd_wakeref);
> +	intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv,
> +							    intel_aux_power_domain(dig_port));
>  
>  	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n",
>  		    dig_port->base.base.base.id,
> @@ -614,7 +614,7 @@ bool intel_pps_vdd_on_unlocked(struct intel_dp *intel_dp)
>  			    "[ENCODER:%d:%s] panel power wasn't enabled\n",
>  			    dig_port->base.base.base.id,
>  			    dig_port->base.base.name);
> -		msleep(intel_dp->panel_power_up_delay);
> +		msleep(intel_dp->pps.panel_power_up_delay);
>  	}
>  
>  	return need_to_disable;
> @@ -652,7 +652,7 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
>  
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->want_panel_vdd);
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.want_panel_vdd);
>  
>  	if (!edp_have_panel_vdd(intel_dp))
>  		return;
> @@ -676,11 +676,11 @@ static void intel_pps_vdd_off_sync_unlocked(struct intel_dp *intel_dp)
>  		    intel_de_read(dev_priv, pp_ctrl_reg));
>  
>  	if ((pp & PANEL_POWER_ON) == 0)
> -		intel_dp->panel_power_off_time = ktime_get_boottime();
> +		intel_dp->pps.panel_power_off_time = ktime_get_boottime();
>  
>  	intel_display_power_put(dev_priv,
>  				intel_aux_power_domain(dig_port),
> -				fetch_and_zero(&intel_dp->vdd_wakeref));
> +				fetch_and_zero(&intel_dp->pps.vdd_wakeref));
>  }
>  
>  void intel_pps_vdd_off_sync(struct intel_dp *intel_dp)
> @@ -690,7 +690,7 @@ void intel_pps_vdd_off_sync(struct intel_dp *intel_dp)
>  	if (!intel_dp_is_edp(intel_dp))
>  		return;
>  
> -	cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> +	cancel_delayed_work_sync(&intel_dp->pps.panel_vdd_work);
>  	/*
>  	 * vdd might still be enabled due to the delayed vdd off.
>  	 * Make sure vdd is actually turned off here.
> @@ -701,13 +701,13 @@ void intel_pps_vdd_off_sync(struct intel_dp *intel_dp)
>  
>  static void edp_panel_vdd_work(struct work_struct *__work)
>  {
> -	struct intel_dp *intel_dp =
> -		container_of(to_delayed_work(__work),
> -			     struct intel_dp, panel_vdd_work);
> +	struct intel_pps *pps = container_of(to_delayed_work(__work),
> +					     struct intel_pps, panel_vdd_work);
> +	struct intel_dp *intel_dp = container_of(pps, struct intel_dp, pps);
>  	intel_wakeref_t wakeref;
>  
>  	with_intel_pps_lock(intel_dp, wakeref) {
> -		if (!intel_dp->want_panel_vdd)
> +		if (!intel_dp->pps.want_panel_vdd)
>  			intel_pps_vdd_off_sync_unlocked(intel_dp);
>  	}
>  }
> @@ -721,8 +721,8 @@ static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
>  	 * down delay) to keep the panel power up across a sequence of
>  	 * operations.
>  	 */
> -	delay = msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5);
> -	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
> +	delay = msecs_to_jiffies(intel_dp->pps.panel_power_cycle_delay * 5);
> +	schedule_delayed_work(&intel_dp->pps.panel_vdd_work, delay);
>  }
>  
>  /*
> @@ -739,11 +739,11 @@ void intel_pps_vdd_off_unlocked(struct intel_dp *intel_dp, bool sync)
>  	if (!intel_dp_is_edp(intel_dp))
>  		return;
>  
> -	I915_STATE_WARN(!intel_dp->want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on",
> +	I915_STATE_WARN(!intel_dp->pps.want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on",
>  			dp_to_dig_port(intel_dp)->base.base.base.id,
>  			dp_to_dig_port(intel_dp)->base.base.name);
>  
> -	intel_dp->want_panel_vdd = false;
> +	intel_dp->pps.want_panel_vdd = false;
>  
>  	if (sync)
>  		intel_pps_vdd_off_sync_unlocked(intel_dp);
> @@ -791,7 +791,7 @@ void intel_pps_on_unlocked(struct intel_dp *intel_dp)
>  	intel_de_posting_read(dev_priv, pp_ctrl_reg);
>  
>  	wait_panel_on(intel_dp);
> -	intel_dp->last_power_on = jiffies;
> +	intel_dp->pps.last_power_on = jiffies;
>  
>  	if (IS_GEN(dev_priv, 5)) {
>  		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
> @@ -826,7 +826,7 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp)
>  	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power off\n",
>  		    dig_port->base.base.base.id, dig_port->base.base.name);
>  
> -	drm_WARN(&dev_priv->drm, !intel_dp->want_panel_vdd,
> +	drm_WARN(&dev_priv->drm, !intel_dp->pps.want_panel_vdd,
>  		 "Need [ENCODER:%d:%s] VDD to turn off panel\n",
>  		 dig_port->base.base.base.id, dig_port->base.base.name);
>  
> @@ -838,18 +838,18 @@ void intel_pps_off_unlocked(struct intel_dp *intel_dp)
>  
>  	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
>  
> -	intel_dp->want_panel_vdd = false;
> +	intel_dp->pps.want_panel_vdd = false;
>  
>  	intel_de_write(dev_priv, pp_ctrl_reg, pp);
>  	intel_de_posting_read(dev_priv, pp_ctrl_reg);
>  
>  	wait_panel_off(intel_dp);
> -	intel_dp->panel_power_off_time = ktime_get_boottime();
> +	intel_dp->pps.panel_power_off_time = ktime_get_boottime();
>  
>  	/* We got a reference when we enabled the VDD. */
>  	intel_display_power_put(dev_priv,
>  				intel_aux_power_domain(dig_port),
> -				fetch_and_zero(&intel_dp->vdd_wakeref));
> +				fetch_and_zero(&intel_dp->pps.vdd_wakeref));
>  }
>  
>  void intel_pps_off(struct intel_dp *intel_dp)
> @@ -909,7 +909,7 @@ void intel_pps_backlight_off(struct intel_dp *intel_dp)
>  		intel_de_posting_read(dev_priv, pp_ctrl_reg);
>  	}
>  
> -	intel_dp->last_backlight_off = jiffies;
> +	intel_dp->pps.last_backlight_off = jiffies;
>  	edp_wait_backlight_off(intel_dp);
>  }
>  
> @@ -943,10 +943,10 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
>  {
>  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
>  	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> -	enum pipe pipe = intel_dp->pps_pipe;
> +	enum pipe pipe = intel_dp->pps.pps_pipe;
>  	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
>  
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.active_pipe != INVALID_PIPE);
>  
>  	if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B))
>  		return;
> @@ -969,7 +969,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
>  	intel_de_write(dev_priv, pp_on_reg, 0);
>  	intel_de_posting_read(dev_priv, pp_on_reg);
>  
> -	intel_dp->pps_pipe = INVALID_PIPE;
> +	intel_dp->pps.pps_pipe = INVALID_PIPE;
>  }
>  
>  static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
> @@ -982,12 +982,12 @@ static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
>  	for_each_intel_dp(&dev_priv->drm, encoder) {
>  		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
>  
> -		drm_WARN(&dev_priv->drm, intel_dp->active_pipe == pipe,
> +		drm_WARN(&dev_priv->drm, intel_dp->pps.active_pipe == pipe,
>  			 "stealing pipe %c power sequencer from active [ENCODER:%d:%s]\n",
>  			 pipe_name(pipe), encoder->base.base.id,
>  			 encoder->base.name);
>  
> -		if (intel_dp->pps_pipe != pipe)
> +		if (intel_dp->pps.pps_pipe != pipe)
>  			continue;
>  
>  		drm_dbg_kms(&dev_priv->drm,
> @@ -1009,10 +1009,10 @@ void vlv_pps_init(struct intel_encoder *encoder,
>  
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.active_pipe != INVALID_PIPE);
>  
> -	if (intel_dp->pps_pipe != INVALID_PIPE &&
> -	    intel_dp->pps_pipe != crtc->pipe) {
> +	if (intel_dp->pps.pps_pipe != INVALID_PIPE &&
> +	    intel_dp->pps.pps_pipe != crtc->pipe) {
>  		/*
>  		 * If another power sequencer was being used on this
>  		 * port previously make sure to turn off vdd there while
> @@ -1027,17 +1027,17 @@ void vlv_pps_init(struct intel_encoder *encoder,
>  	 */
>  	vlv_steal_power_sequencer(dev_priv, crtc->pipe);
>  
> -	intel_dp->active_pipe = crtc->pipe;
> +	intel_dp->pps.active_pipe = crtc->pipe;
>  
>  	if (!intel_dp_is_edp(intel_dp))
>  		return;
>  
>  	/* now it's all ours */
> -	intel_dp->pps_pipe = crtc->pipe;
> +	intel_dp->pps.pps_pipe = crtc->pipe;
>  
>  	drm_dbg_kms(&dev_priv->drm,
>  		    "initializing pipe %c power sequencer for [ENCODER:%d:%s]\n",
> -		    pipe_name(intel_dp->pps_pipe), encoder->base.base.id,
> +		    pipe_name(intel_dp->pps.pps_pipe), encoder->base.base.id,
>  		    encoder->base.name);
>  
>  	/* init power sequencer on this pipe and port */
> @@ -1063,9 +1063,9 @@ static void intel_pps_vdd_sanitize(struct intel_dp *intel_dp)
>  	 */
>  	drm_dbg_kms(&dev_priv->drm,
>  		    "VDD left on by BIOS, adjusting state tracking\n");
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
> -	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
> -							intel_aux_power_domain(dig_port));
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->pps.vdd_wakeref);
> +	intel_dp->pps.vdd_wakeref = intel_display_power_get(dev_priv,
> +							    intel_aux_power_domain(dig_port));
>  
>  	edp_panel_vdd_schedule_off(intel_dp);
>  }
> @@ -1085,9 +1085,9 @@ bool intel_pps_have_power(struct intel_dp *intel_dp)
>  
>  static void pps_init_timestamps(struct intel_dp *intel_dp)
>  {
> -	intel_dp->panel_power_off_time = ktime_get_boottime();
> -	intel_dp->last_power_on = jiffies;
> -	intel_dp->last_backlight_off = jiffies;
> +	intel_dp->pps.panel_power_off_time = ktime_get_boottime();
> +	intel_dp->pps.last_power_on = jiffies;
> +	intel_dp->pps.last_backlight_off = jiffies;
>  }
>  
>  static void
> @@ -1137,7 +1137,7 @@ static void
>  intel_pps_verify_state(struct intel_dp *intel_dp)
>  {
>  	struct edp_power_seq hw;
> -	struct edp_power_seq *sw = &intel_dp->pps_delays;
> +	struct edp_power_seq *sw = &intel_dp->pps.pps_delays;
>  
>  	intel_pps_readout_hw_state(intel_dp, &hw);
>  
> @@ -1153,7 +1153,7 @@ static void pps_init_delays(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
>  	struct edp_power_seq cur, vbt, spec,
> -		*final = &intel_dp->pps_delays;
> +		*final = &intel_dp->pps.pps_delays;
>  
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
> @@ -1210,22 +1210,22 @@ static void pps_init_delays(struct intel_dp *intel_dp)
>  #undef assign_final
>  
>  #define get_delay(field)	(DIV_ROUND_UP(final->field, 10))
> -	intel_dp->panel_power_up_delay = get_delay(t1_t3);
> -	intel_dp->backlight_on_delay = get_delay(t8);
> -	intel_dp->backlight_off_delay = get_delay(t9);
> -	intel_dp->panel_power_down_delay = get_delay(t10);
> -	intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
> +	intel_dp->pps.panel_power_up_delay = get_delay(t1_t3);
> +	intel_dp->pps.backlight_on_delay = get_delay(t8);
> +	intel_dp->pps.backlight_off_delay = get_delay(t9);
> +	intel_dp->pps.panel_power_down_delay = get_delay(t10);
> +	intel_dp->pps.panel_power_cycle_delay = get_delay(t11_t12);
>  #undef get_delay
>  
>  	drm_dbg_kms(&dev_priv->drm,
>  		    "panel power up delay %d, power down delay %d, power cycle delay %d\n",
> -		    intel_dp->panel_power_up_delay,
> -		    intel_dp->panel_power_down_delay,
> -		    intel_dp->panel_power_cycle_delay);
> +		    intel_dp->pps.panel_power_up_delay,
> +		    intel_dp->pps.panel_power_down_delay,
> +		    intel_dp->pps.panel_power_cycle_delay);
>  
>  	drm_dbg_kms(&dev_priv->drm, "backlight on delay %d, off delay %d\n",
> -		    intel_dp->backlight_on_delay,
> -		    intel_dp->backlight_off_delay);
> +		    intel_dp->pps.backlight_on_delay,
> +		    intel_dp->pps.backlight_off_delay);
>  
>  	/*
>  	 * We override the HW backlight delays to 1 because we do manual waits
> @@ -1251,7 +1251,7 @@ static void pps_init_registers(struct intel_dp *intel_dp, bool force_disable_vdd
>  	int div = RUNTIME_INFO(dev_priv)->rawclk_freq / 1000;
>  	struct pps_registers regs;
>  	enum port port = dp_to_dig_port(intel_dp)->base.port;
> -	const struct edp_power_seq *seq = &intel_dp->pps_delays;
> +	const struct edp_power_seq *seq = &intel_dp->pps.pps_delays;
>  
>  	lockdep_assert_held(&dev_priv->pps_mutex);
>  
> @@ -1364,7 +1364,7 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp)
>  
>  void intel_pps_init(struct intel_dp *intel_dp)
>  {
> -	INIT_DELAYED_WORK(&intel_dp->panel_vdd_work, edp_panel_vdd_work);
> +	INIT_DELAYED_WORK(&intel_dp->pps.panel_vdd_work, edp_panel_vdd_work);
>  
>  	pps_init_timestamps(intel_dp);
>  
> -- 
> 2.20.1
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 01/17] drm/i915/pps: abstract panel power sequencer from intel_dp.c
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 01/17] drm/i915/pps: abstract panel power sequencer from intel_dp.c Jani Nikula
@ 2021-01-13 15:34   ` Jani Nikula
  2021-01-13 16:47   ` Anshuman Gupta
  1 sibling, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-13 15:34 UTC (permalink / raw)
  To: intel-gfx


Anshuman, thanks a bunch for the reviews, much appreciated!

...but may I ask for reviews on this one too, as starting to push the
patches hinges on the first one. I'd rather start pushing the ready ones
than repost the entire series for the required changes.

Thanks,
Jani.


On Fri, 08 Jan 2021, Jani Nikula <jani.nikula@intel.com> wrote:
> In a long overdue refactoring, split out all panel sequencer code from
> intel_dp.c to new intel_pps.[ch].
>
> The first part is mostly just code movement as-is, without cleanups or
> functional changes.
>
> We need to add a vlv_get_dpll() helper to get at the vlv/chv dpll from
> pps code.
>
> v2: Rebase.
>
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile                 |    1 +
>  drivers/gpu/drm/i915/display/intel_ddi.c      |    1 +
>  .../drm/i915/display/intel_display_power.c    |    2 +-
>  drivers/gpu/drm/i915/display/intel_dp.c       | 1436 +----------------
>  drivers/gpu/drm/i915/display/intel_dp.h       |    5 +-
>  drivers/gpu/drm/i915/display/intel_pps.c      | 1334 +++++++++++++++
>  drivers/gpu/drm/i915/display/intel_pps.h      |   53 +
>  7 files changed, 1443 insertions(+), 1389 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_pps.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_pps.h
>
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 4074d8cb0d6e..8a04403a11bb 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -251,6 +251,7 @@ i915-y += \
>  	display/intel_lspcon.o \
>  	display/intel_lvds.o \
>  	display/intel_panel.o \
> +	display/intel_pps.o \
>  	display/intel_sdvo.o \
>  	display/intel_tv.o \
>  	display/intel_vdsc.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 3df6913369bc..f09a597bf730 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -46,6 +46,7 @@
>  #include "intel_hotplug.h"
>  #include "intel_lspcon.h"
>  #include "intel_panel.h"
> +#include "intel_pps.h"
>  #include "intel_psr.h"
>  #include "intel_sprite.h"
>  #include "intel_tc.h"
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
> index d52374f01316..a11bd8213df4 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> @@ -4,7 +4,6 @@
>   */
>  
>  #include "display/intel_crt.h"
> -#include "display/intel_dp.h"
>  
>  #include "i915_drv.h"
>  #include "i915_irq.h"
> @@ -16,6 +15,7 @@
>  #include "intel_dpio_phy.h"
>  #include "intel_hotplug.h"
>  #include "intel_pm.h"
> +#include "intel_pps.h"
>  #include "intel_sideband.h"
>  #include "intel_tc.h"
>  #include "intel_vga.h"
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 4f190a82d4ad..07279b10812e 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -58,6 +58,7 @@
>  #include "intel_lspcon.h"
>  #include "intel_lvds.h"
>  #include "intel_panel.h"
> +#include "intel_pps.h"
>  #include "intel_psr.h"
>  #include "intel_sideband.h"
>  #include "intel_tc.h"
> @@ -121,6 +122,11 @@ static const struct dp_link_dpll chv_dpll[] = {
>  		{ .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } },
>  };
>  
> +const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
> +{
> +	return IS_CHERRYVIEW(i915) ? &chv_dpll[0].dpll : &vlv_dpll[0].dpll;
> +}
> +
>  /* Constants for DP DSC configurations */
>  static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15};
>  
> @@ -145,12 +151,6 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp)
>  
>  static void intel_dp_link_down(struct intel_encoder *encoder,
>  			       const struct intel_crtc_state *old_crtc_state);
> -static bool edp_panel_vdd_on(struct intel_dp *intel_dp);
> -static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
> -static void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
> -					   const struct intel_crtc_state *crtc_state);
> -static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
> -				      enum pipe pipe);
>  static void intel_dp_unset_edid(struct intel_dp *intel_dp);
>  
>  /* update sink rates from dpcd */
> @@ -877,447 +877,6 @@ static void intel_dp_unpack_aux(u32 src, u8 *dst, int dst_bytes)
>  		dst[i] = src >> ((3-i) * 8);
>  }
>  
> -static void
> -intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp);
> -static void
> -intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
> -					      bool force_disable_vdd);
> -static void
> -intel_dp_pps_init(struct intel_dp *intel_dp);
> -
> -static intel_wakeref_t
> -pps_lock(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	intel_wakeref_t wakeref;
> -
> -	/*
> -	 * See intel_power_sequencer_reset() why we need
> -	 * a power domain reference here.
> -	 */
> -	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
> -	mutex_lock(&dev_priv->pps_mutex);
> -
> -	return wakeref;
> -}
> -
> -static intel_wakeref_t
> -pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	mutex_unlock(&dev_priv->pps_mutex);
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
> -	return 0;
> -}
> -
> -#define with_pps_lock(dp, wf) \
> -	for ((wf) = pps_lock(dp); (wf); (wf) = pps_unlock((dp), (wf)))
> -
> -static void
> -vlv_power_sequencer_kick(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum pipe pipe = intel_dp->pps_pipe;
> -	bool pll_enabled, release_cl_override = false;
> -	enum dpio_phy phy = DPIO_PHY(pipe);
> -	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
> -	u32 DP;
> -
> -	if (drm_WARN(&dev_priv->drm,
> -		     intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN,
> -		     "skipping pipe %c power sequencer kick due to [ENCODER:%d:%s] being active\n",
> -		     pipe_name(pipe), dig_port->base.base.base.id,
> -		     dig_port->base.base.name))
> -		return;
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "kicking pipe %c power sequencer for [ENCODER:%d:%s]\n",
> -		    pipe_name(pipe), dig_port->base.base.base.id,
> -		    dig_port->base.base.name);
> -
> -	/* Preserve the BIOS-computed detected bit. This is
> -	 * supposed to be read-only.
> -	 */
> -	DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
> -	DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
> -	DP |= DP_PORT_WIDTH(1);
> -	DP |= DP_LINK_TRAIN_PAT_1;
> -
> -	if (IS_CHERRYVIEW(dev_priv))
> -		DP |= DP_PIPE_SEL_CHV(pipe);
> -	else
> -		DP |= DP_PIPE_SEL(pipe);
> -
> -	pll_enabled = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE;
> -
> -	/*
> -	 * The DPLL for the pipe must be enabled for this to work.
> -	 * So enable temporarily it if it's not already enabled.
> -	 */
> -	if (!pll_enabled) {
> -		release_cl_override = IS_CHERRYVIEW(dev_priv) &&
> -			!chv_phy_powergate_ch(dev_priv, phy, ch, true);
> -
> -		if (vlv_force_pll_on(dev_priv, pipe, IS_CHERRYVIEW(dev_priv) ?
> -				     &chv_dpll[0].dpll : &vlv_dpll[0].dpll)) {
> -			drm_err(&dev_priv->drm,
> -				"Failed to force on pll for pipe %c!\n",
> -				pipe_name(pipe));
> -			return;
> -		}
> -	}
> -
> -	/*
> -	 * Similar magic as in intel_dp_enable_port().
> -	 * We _must_ do this port enable + disable trick
> -	 * to make this power sequencer lock onto the port.
> -	 * Otherwise even VDD force bit won't work.
> -	 */
> -	intel_de_write(dev_priv, intel_dp->output_reg, DP);
> -	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> -
> -	intel_de_write(dev_priv, intel_dp->output_reg, DP | DP_PORT_EN);
> -	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> -
> -	intel_de_write(dev_priv, intel_dp->output_reg, DP & ~DP_PORT_EN);
> -	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> -
> -	if (!pll_enabled) {
> -		vlv_force_pll_off(dev_priv, pipe);
> -
> -		if (release_cl_override)
> -			chv_phy_powergate_ch(dev_priv, phy, ch, false);
> -	}
> -}
> -
> -static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv)
> -{
> -	struct intel_encoder *encoder;
> -	unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
> -
> -	/*
> -	 * We don't have power sequencer currently.
> -	 * Pick one that's not used by other ports.
> -	 */
> -	for_each_intel_dp(&dev_priv->drm, encoder) {
> -		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -
> -		if (encoder->type == INTEL_OUTPUT_EDP) {
> -			drm_WARN_ON(&dev_priv->drm,
> -				    intel_dp->active_pipe != INVALID_PIPE &&
> -				    intel_dp->active_pipe !=
> -				    intel_dp->pps_pipe);
> -
> -			if (intel_dp->pps_pipe != INVALID_PIPE)
> -				pipes &= ~(1 << intel_dp->pps_pipe);
> -		} else {
> -			drm_WARN_ON(&dev_priv->drm,
> -				    intel_dp->pps_pipe != INVALID_PIPE);
> -
> -			if (intel_dp->active_pipe != INVALID_PIPE)
> -				pipes &= ~(1 << intel_dp->active_pipe);
> -		}
> -	}
> -
> -	if (pipes == 0)
> -		return INVALID_PIPE;
> -
> -	return ffs(pipes) - 1;
> -}
> -
> -static enum pipe
> -vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum pipe pipe;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	/* We should never land here with regular DP ports */
> -	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
> -
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE &&
> -		    intel_dp->active_pipe != intel_dp->pps_pipe);
> -
> -	if (intel_dp->pps_pipe != INVALID_PIPE)
> -		return intel_dp->pps_pipe;
> -
> -	pipe = vlv_find_free_pps(dev_priv);
> -
> -	/*
> -	 * Didn't find one. This should not happen since there
> -	 * are two power sequencers and up to two eDP ports.
> -	 */
> -	if (drm_WARN_ON(&dev_priv->drm, pipe == INVALID_PIPE))
> -		pipe = PIPE_A;
> -
> -	vlv_steal_power_sequencer(dev_priv, pipe);
> -	intel_dp->pps_pipe = pipe;
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "picked pipe %c power sequencer for [ENCODER:%d:%s]\n",
> -		    pipe_name(intel_dp->pps_pipe),
> -		    dig_port->base.base.base.id,
> -		    dig_port->base.base.name);
> -
> -	/* init power sequencer on this pipe and port */
> -	intel_dp_init_panel_power_sequencer(intel_dp);
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
> -
> -	/*
> -	 * Even vdd force doesn't work until we've made
> -	 * the power sequencer lock in on the port.
> -	 */
> -	vlv_power_sequencer_kick(intel_dp);
> -
> -	return intel_dp->pps_pipe;
> -}
> -
> -static int
> -bxt_power_sequencer_idx(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	int backlight_controller = dev_priv->vbt.backlight.controller;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	/* We should never land here with regular DP ports */
> -	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
> -
> -	if (!intel_dp->pps_reset)
> -		return backlight_controller;
> -
> -	intel_dp->pps_reset = false;
> -
> -	/*
> -	 * Only the HW needs to be reprogrammed, the SW state is fixed and
> -	 * has been setup during connector init.
> -	 */
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> -
> -	return backlight_controller;
> -}
> -
> -typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
> -			       enum pipe pipe);
> -
> -static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
> -			       enum pipe pipe)
> -{
> -	return intel_de_read(dev_priv, PP_STATUS(pipe)) & PP_ON;
> -}
> -
> -static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
> -				enum pipe pipe)
> -{
> -	return intel_de_read(dev_priv, PP_CONTROL(pipe)) & EDP_FORCE_VDD;
> -}
> -
> -static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
> -			 enum pipe pipe)
> -{
> -	return true;
> -}
> -
> -static enum pipe
> -vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
> -		     enum port port,
> -		     vlv_pipe_check pipe_check)
> -{
> -	enum pipe pipe;
> -
> -	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
> -		u32 port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(pipe)) &
> -			PANEL_PORT_SELECT_MASK;
> -
> -		if (port_sel != PANEL_PORT_SELECT_VLV(port))
> -			continue;
> -
> -		if (!pipe_check(dev_priv, pipe))
> -			continue;
> -
> -		return pipe;
> -	}
> -
> -	return INVALID_PIPE;
> -}
> -
> -static void
> -vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum port port = dig_port->base.port;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	/* try to find a pipe with this port selected */
> -	/* first pick one where the panel is on */
> -	intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> -						  vlv_pipe_has_pp_on);
> -	/* didn't find one? pick one where vdd is on */
> -	if (intel_dp->pps_pipe == INVALID_PIPE)
> -		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> -							  vlv_pipe_has_vdd_on);
> -	/* didn't find one? pick one with just the correct port */
> -	if (intel_dp->pps_pipe == INVALID_PIPE)
> -		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> -							  vlv_pipe_any);
> -
> -	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
> -	if (intel_dp->pps_pipe == INVALID_PIPE) {
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "no initial power sequencer for [ENCODER:%d:%s]\n",
> -			    dig_port->base.base.base.id,
> -			    dig_port->base.base.name);
> -		return;
> -	}
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "initial power sequencer for [ENCODER:%d:%s]: pipe %c\n",
> -		    dig_port->base.base.base.id,
> -		    dig_port->base.base.name,
> -		    pipe_name(intel_dp->pps_pipe));
> -
> -	intel_dp_init_panel_power_sequencer(intel_dp);
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> -}
> -
> -void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
> -{
> -	struct intel_encoder *encoder;
> -
> -	if (drm_WARN_ON(&dev_priv->drm,
> -			!(IS_VALLEYVIEW(dev_priv) ||
> -			  IS_CHERRYVIEW(dev_priv) ||
> -			  IS_GEN9_LP(dev_priv))))
> -		return;
> -
> -	/*
> -	 * We can't grab pps_mutex here due to deadlock with power_domain
> -	 * mutex when power_domain functions are called while holding pps_mutex.
> -	 * That also means that in order to use pps_pipe the code needs to
> -	 * hold both a power domain reference and pps_mutex, and the power domain
> -	 * reference get/put must be done while _not_ holding pps_mutex.
> -	 * pps_{lock,unlock}() do these steps in the correct order, so one
> -	 * should use them always.
> -	 */
> -
> -	for_each_intel_dp(&dev_priv->drm, encoder) {
> -		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -
> -		drm_WARN_ON(&dev_priv->drm,
> -			    intel_dp->active_pipe != INVALID_PIPE);
> -
> -		if (encoder->type != INTEL_OUTPUT_EDP)
> -			continue;
> -
> -		if (IS_GEN9_LP(dev_priv))
> -			intel_dp->pps_reset = true;
> -		else
> -			intel_dp->pps_pipe = INVALID_PIPE;
> -	}
> -}
> -
> -struct pps_registers {
> -	i915_reg_t pp_ctrl;
> -	i915_reg_t pp_stat;
> -	i915_reg_t pp_on;
> -	i915_reg_t pp_off;
> -	i915_reg_t pp_div;
> -};
> -
> -static void intel_pps_get_registers(struct intel_dp *intel_dp,
> -				    struct pps_registers *regs)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	int pps_idx = 0;
> -
> -	memset(regs, 0, sizeof(*regs));
> -
> -	if (IS_GEN9_LP(dev_priv))
> -		pps_idx = bxt_power_sequencer_idx(intel_dp);
> -	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		pps_idx = vlv_power_sequencer_pipe(intel_dp);
> -
> -	regs->pp_ctrl = PP_CONTROL(pps_idx);
> -	regs->pp_stat = PP_STATUS(pps_idx);
> -	regs->pp_on = PP_ON_DELAYS(pps_idx);
> -	regs->pp_off = PP_OFF_DELAYS(pps_idx);
> -
> -	/* Cycle delay moved from PP_DIVISOR to PP_CONTROL */
> -	if (IS_GEN9_LP(dev_priv) || INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
> -		regs->pp_div = INVALID_MMIO_REG;
> -	else
> -		regs->pp_div = PP_DIVISOR(pps_idx);
> -}
> -
> -static i915_reg_t
> -_pp_ctrl_reg(struct intel_dp *intel_dp)
> -{
> -	struct pps_registers regs;
> -
> -	intel_pps_get_registers(intel_dp, &regs);
> -
> -	return regs.pp_ctrl;
> -}
> -
> -static i915_reg_t
> -_pp_stat_reg(struct intel_dp *intel_dp)
> -{
> -	struct pps_registers regs;
> -
> -	intel_pps_get_registers(intel_dp, &regs);
> -
> -	return regs.pp_stat;
> -}
> -
> -static bool edp_have_panel_power(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> -	    intel_dp->pps_pipe == INVALID_PIPE)
> -		return false;
> -
> -	return (intel_de_read(dev_priv, _pp_stat_reg(intel_dp)) & PP_ON) != 0;
> -}
> -
> -static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> -	    intel_dp->pps_pipe == INVALID_PIPE)
> -		return false;
> -
> -	return intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
> -}
> -
> -static void
> -intel_dp_check_edp(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) {
> -		drm_WARN(&dev_priv->drm, 1,
> -			 "eDP powered off while attempting aux channel communication.\n");
> -		drm_dbg_kms(&dev_priv->drm, "Status 0x%08x Control 0x%08x\n",
> -			    intel_de_read(dev_priv, _pp_stat_reg(intel_dp)),
> -			    intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)));
> -	}
> -}
> -
>  static u32
>  intel_dp_aux_wait_done(struct intel_dp *intel_dp)
>  {
> @@ -2931,491 +2490,66 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
>  	 * IBX PCH and CPU are the same for almost everything,
>  	 * except that the CPU DP PLL is configured in this
>  	 * register
> -	 *
> -	 * CPT PCH is quite different, having many bits moved
> -	 * to the TRANS_DP_CTL register instead. That
> -	 * configuration happens (oddly) in ilk_pch_enable
> -	 */
> -
> -	/* Preserve the BIOS-computed detected bit. This is
> -	 * supposed to be read-only.
> -	 */
> -	intel_dp->DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
> -
> -	/* Handle DP bits in common between all three register formats */
> -	intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
> -	intel_dp->DP |= DP_PORT_WIDTH(pipe_config->lane_count);
> -
> -	/* Split out the IBX/CPU vs CPT settings */
> -
> -	if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) {
> -		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
> -			intel_dp->DP |= DP_SYNC_HS_HIGH;
> -		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
> -			intel_dp->DP |= DP_SYNC_VS_HIGH;
> -		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
> -
> -		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> -			intel_dp->DP |= DP_ENHANCED_FRAMING;
> -
> -		intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe);
> -	} else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
> -		u32 trans_dp;
> -
> -		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
> -
> -		trans_dp = intel_de_read(dev_priv, TRANS_DP_CTL(crtc->pipe));
> -		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> -			trans_dp |= TRANS_DP_ENH_FRAMING;
> -		else
> -			trans_dp &= ~TRANS_DP_ENH_FRAMING;
> -		intel_de_write(dev_priv, TRANS_DP_CTL(crtc->pipe), trans_dp);
> -	} else {
> -		if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
> -			intel_dp->DP |= DP_COLOR_RANGE_16_235;
> -
> -		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
> -			intel_dp->DP |= DP_SYNC_HS_HIGH;
> -		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
> -			intel_dp->DP |= DP_SYNC_VS_HIGH;
> -		intel_dp->DP |= DP_LINK_TRAIN_OFF;
> -
> -		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> -			intel_dp->DP |= DP_ENHANCED_FRAMING;
> -
> -		if (IS_CHERRYVIEW(dev_priv))
> -			intel_dp->DP |= DP_PIPE_SEL_CHV(crtc->pipe);
> -		else
> -			intel_dp->DP |= DP_PIPE_SEL(crtc->pipe);
> -	}
> -}
> -
> -#define IDLE_ON_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
> -#define IDLE_ON_VALUE   	(PP_ON | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
> -
> -#define IDLE_OFF_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | 0)
> -#define IDLE_OFF_VALUE		(0     | PP_SEQUENCE_NONE | 0                     | 0)
> -
> -#define IDLE_CYCLE_MASK		(PP_ON | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
> -#define IDLE_CYCLE_VALUE	(0     | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
> -
> -static void intel_pps_verify_state(struct intel_dp *intel_dp);
> -
> -static void wait_panel_status(struct intel_dp *intel_dp,
> -				       u32 mask,
> -				       u32 value)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	intel_pps_verify_state(intel_dp);
> -
> -	pp_stat_reg = _pp_stat_reg(intel_dp);
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "mask %08x value %08x status %08x control %08x\n",
> -		    mask, value,
> -		    intel_de_read(dev_priv, pp_stat_reg),
> -		    intel_de_read(dev_priv, pp_ctrl_reg));
> -
> -	if (intel_de_wait_for_register(dev_priv, pp_stat_reg,
> -				       mask, value, 5000))
> -		drm_err(&dev_priv->drm,
> -			"Panel status timeout: status %08x control %08x\n",
> -			intel_de_read(dev_priv, pp_stat_reg),
> -			intel_de_read(dev_priv, pp_ctrl_reg));
> -
> -	drm_dbg_kms(&dev_priv->drm, "Wait complete\n");
> -}
> -
> -static void wait_panel_on(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> -
> -	drm_dbg_kms(&i915->drm, "Wait for panel power on\n");
> -	wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
> -}
> -
> -static void wait_panel_off(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> -
> -	drm_dbg_kms(&i915->drm, "Wait for panel power off time\n");
> -	wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
> -}
> -
> -static void wait_panel_power_cycle(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> -	ktime_t panel_power_on_time;
> -	s64 panel_power_off_duration;
> -
> -	drm_dbg_kms(&i915->drm, "Wait for panel power cycle\n");
> -
> -	/* take the difference of currrent time and panel power off time
> -	 * and then make panel wait for t11_t12 if needed. */
> -	panel_power_on_time = ktime_get_boottime();
> -	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->panel_power_off_time);
> -
> -	/* When we disable the VDD override bit last we have to do the manual
> -	 * wait. */
> -	if (panel_power_off_duration < (s64)intel_dp->panel_power_cycle_delay)
> -		wait_remaining_ms_from_jiffies(jiffies,
> -				       intel_dp->panel_power_cycle_delay - panel_power_off_duration);
> -
> -	wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
> -}
> -
> -static void wait_backlight_on(struct intel_dp *intel_dp)
> -{
> -	wait_remaining_ms_from_jiffies(intel_dp->last_power_on,
> -				       intel_dp->backlight_on_delay);
> -}
> -
> -static void edp_wait_backlight_off(struct intel_dp *intel_dp)
> -{
> -	wait_remaining_ms_from_jiffies(intel_dp->last_backlight_off,
> -				       intel_dp->backlight_off_delay);
> -}
> -
> -/* Read the current pp_control value, unlocking the register if it
> - * is locked
> - */
> -
> -static  u32 ilk_get_pp_control(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	u32 control;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	control = intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp));
> -	if (drm_WARN_ON(&dev_priv->drm, !HAS_DDI(dev_priv) &&
> -			(control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
> -		control &= ~PANEL_UNLOCK_MASK;
> -		control |= PANEL_UNLOCK_REGS;
> -	}
> -	return control;
> -}
> -
> -/*
> - * Must be paired with edp_panel_vdd_off().
> - * Must hold pps_mutex around the whole on/off sequence.
> - * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> - */
> -static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	u32 pp;
> -	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> -	bool need_to_disable = !intel_dp->want_panel_vdd;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return false;
> -
> -	cancel_delayed_work(&intel_dp->panel_vdd_work);
> -	intel_dp->want_panel_vdd = true;
> -
> -	if (edp_have_panel_vdd(intel_dp))
> -		return need_to_disable;
> -
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
> -	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
> -							intel_aux_power_domain(dig_port));
> -
> -	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n",
> -		    dig_port->base.base.base.id,
> -		    dig_port->base.base.name);
> -
> -	if (!edp_have_panel_power(intel_dp))
> -		wait_panel_power_cycle(intel_dp);
> -
> -	pp = ilk_get_pp_control(intel_dp);
> -	pp |= EDP_FORCE_VDD;
> -
> -	pp_stat_reg = _pp_stat_reg(intel_dp);
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -
> -	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
> -		    intel_de_read(dev_priv, pp_stat_reg),
> -		    intel_de_read(dev_priv, pp_ctrl_reg));
> -	/*
> -	 * If the panel wasn't on, delay before accessing aux channel
> -	 */
> -	if (!edp_have_panel_power(intel_dp)) {
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "[ENCODER:%d:%s] panel power wasn't enabled\n",
> -			    dig_port->base.base.base.id,
> -			    dig_port->base.base.name);
> -		msleep(intel_dp->panel_power_up_delay);
> -	}
> -
> -	return need_to_disable;
> -}
> -
> -/*
> - * Must be paired with intel_edp_panel_vdd_off() or
> - * intel_edp_panel_off().
> - * Nested calls to these functions are not allowed since
> - * we drop the lock. Caller must use some higher level
> - * locking to prevent nested calls from other threads.
> - */
> -void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
> -{
> -	intel_wakeref_t wakeref;
> -	bool vdd;
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	vdd = false;
> -	with_pps_lock(intel_dp, wakeref)
> -		vdd = edp_panel_vdd_on(intel_dp);
> -	I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n",
> -			dp_to_dig_port(intel_dp)->base.base.base.id,
> -			dp_to_dig_port(intel_dp)->base.base.name);
> -}
> -
> -static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port =
> -		dp_to_dig_port(intel_dp);
> -	u32 pp;
> -	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->want_panel_vdd);
> -
> -	if (!edp_have_panel_vdd(intel_dp))
> -		return;
> -
> -	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD off\n",
> -		    dig_port->base.base.base.id,
> -		    dig_port->base.base.name);
> -
> -	pp = ilk_get_pp_control(intel_dp);
> -	pp &= ~EDP_FORCE_VDD;
> -
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -	pp_stat_reg = _pp_stat_reg(intel_dp);
> -
> -	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -
> -	/* Make sure sequencer is idle before allowing subsequent activity */
> -	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
> -		    intel_de_read(dev_priv, pp_stat_reg),
> -		    intel_de_read(dev_priv, pp_ctrl_reg));
> -
> -	if ((pp & PANEL_POWER_ON) == 0)
> -		intel_dp->panel_power_off_time = ktime_get_boottime();
> -
> -	intel_display_power_put(dev_priv,
> -				intel_aux_power_domain(dig_port),
> -				fetch_and_zero(&intel_dp->vdd_wakeref));
> -}
> -
> -static void edp_panel_vdd_work(struct work_struct *__work)
> -{
> -	struct intel_dp *intel_dp =
> -		container_of(to_delayed_work(__work),
> -			     struct intel_dp, panel_vdd_work);
> -	intel_wakeref_t wakeref;
> -
> -	with_pps_lock(intel_dp, wakeref) {
> -		if (!intel_dp->want_panel_vdd)
> -			edp_panel_vdd_off_sync(intel_dp);
> -	}
> -}
> -
> -static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
> -{
> -	unsigned long delay;
> -
> -	/*
> -	 * Queue the timer to fire a long time from now (relative to the power
> -	 * down delay) to keep the panel power up across a sequence of
> -	 * operations.
> -	 */
> -	delay = msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5);
> -	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
> -}
> -
> -/*
> - * Must be paired with edp_panel_vdd_on().
> - * Must hold pps_mutex around the whole on/off sequence.
> - * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> - */
> -static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	I915_STATE_WARN(!intel_dp->want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on",
> -			dp_to_dig_port(intel_dp)->base.base.base.id,
> -			dp_to_dig_port(intel_dp)->base.base.name);
> -
> -	intel_dp->want_panel_vdd = false;
> -
> -	if (sync)
> -		edp_panel_vdd_off_sync(intel_dp);
> -	else
> -		edp_panel_vdd_schedule_off(intel_dp);
> -}
> -
> -static void edp_panel_on(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	u32 pp;
> -	i915_reg_t pp_ctrl_reg;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power on\n",
> -		    dp_to_dig_port(intel_dp)->base.base.base.id,
> -		    dp_to_dig_port(intel_dp)->base.base.name);
> -
> -	if (drm_WARN(&dev_priv->drm, edp_have_panel_power(intel_dp),
> -		     "[ENCODER:%d:%s] panel power already on\n",
> -		     dp_to_dig_port(intel_dp)->base.base.base.id,
> -		     dp_to_dig_port(intel_dp)->base.base.name))
> -		return;
> -
> -	wait_panel_power_cycle(intel_dp);
> -
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -	pp = ilk_get_pp_control(intel_dp);
> -	if (IS_GEN(dev_priv, 5)) {
> -		/* ILK workaround: disable reset around power sequence */
> -		pp &= ~PANEL_POWER_RESET;
> -		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -	}
> -
> -	pp |= PANEL_POWER_ON;
> -	if (!IS_GEN(dev_priv, 5))
> -		pp |= PANEL_POWER_RESET;
> -
> -	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -
> -	wait_panel_on(intel_dp);
> -	intel_dp->last_power_on = jiffies;
> -
> -	if (IS_GEN(dev_priv, 5)) {
> -		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
> -		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -	}
> -}
> -
> -void intel_edp_panel_on(struct intel_dp *intel_dp)
> -{
> -	intel_wakeref_t wakeref;
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	with_pps_lock(intel_dp, wakeref)
> -		edp_panel_on(intel_dp);
> -}
> -
> -
> -static void edp_panel_off(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	u32 pp;
> -	i915_reg_t pp_ctrl_reg;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power off\n",
> -		    dig_port->base.base.base.id, dig_port->base.base.name);
> -
> -	drm_WARN(&dev_priv->drm, !intel_dp->want_panel_vdd,
> -		 "Need [ENCODER:%d:%s] VDD to turn off panel\n",
> -		 dig_port->base.base.base.id, dig_port->base.base.name);
> -
> -	pp = ilk_get_pp_control(intel_dp);
> -	/* We need to switch off panel power _and_ force vdd, for otherwise some
> -	 * panels get very unhappy and cease to work. */
> -	pp &= ~(PANEL_POWER_ON | PANEL_POWER_RESET | EDP_FORCE_VDD |
> -		EDP_BLC_ENABLE);
> -
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -
> -	intel_dp->want_panel_vdd = false;
> +	 *
> +	 * CPT PCH is quite different, having many bits moved
> +	 * to the TRANS_DP_CTL register instead. That
> +	 * configuration happens (oddly) in ilk_pch_enable
> +	 */
>  
> -	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	/* Preserve the BIOS-computed detected bit. This is
> +	 * supposed to be read-only.
> +	 */
> +	intel_dp->DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
>  
> -	wait_panel_off(intel_dp);
> -	intel_dp->panel_power_off_time = ktime_get_boottime();
> +	/* Handle DP bits in common between all three register formats */
> +	intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
> +	intel_dp->DP |= DP_PORT_WIDTH(pipe_config->lane_count);
>  
> -	/* We got a reference when we enabled the VDD. */
> -	intel_display_power_put(dev_priv,
> -				intel_aux_power_domain(dig_port),
> -				fetch_and_zero(&intel_dp->vdd_wakeref));
> -}
> +	/* Split out the IBX/CPU vs CPT settings */
>  
> -void intel_edp_panel_off(struct intel_dp *intel_dp)
> -{
> -	intel_wakeref_t wakeref;
> +	if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) {
> +		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
> +			intel_dp->DP |= DP_SYNC_HS_HIGH;
> +		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
> +			intel_dp->DP |= DP_SYNC_VS_HIGH;
> +		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
>  
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> +		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> +			intel_dp->DP |= DP_ENHANCED_FRAMING;
>  
> -	with_pps_lock(intel_dp, wakeref)
> -		edp_panel_off(intel_dp);
> -}
> +		intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe);
> +	} else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
> +		u32 trans_dp;
>  
> -/* Enable backlight in the panel power control. */
> -static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	intel_wakeref_t wakeref;
> +		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
>  
> -	/*
> -	 * If we enable the backlight right away following a panel power
> -	 * on, we may see slight flicker as the panel syncs with the eDP
> -	 * link.  So delay a bit to make sure the image is solid before
> -	 * allowing it to appear.
> -	 */
> -	wait_backlight_on(intel_dp);
> +		trans_dp = intel_de_read(dev_priv, TRANS_DP_CTL(crtc->pipe));
> +		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> +			trans_dp |= TRANS_DP_ENH_FRAMING;
> +		else
> +			trans_dp &= ~TRANS_DP_ENH_FRAMING;
> +		intel_de_write(dev_priv, TRANS_DP_CTL(crtc->pipe), trans_dp);
> +	} else {
> +		if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
> +			intel_dp->DP |= DP_COLOR_RANGE_16_235;
>  
> -	with_pps_lock(intel_dp, wakeref) {
> -		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -		u32 pp;
> +		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
> +			intel_dp->DP |= DP_SYNC_HS_HIGH;
> +		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
> +			intel_dp->DP |= DP_SYNC_VS_HIGH;
> +		intel_dp->DP |= DP_LINK_TRAIN_OFF;
>  
> -		pp = ilk_get_pp_control(intel_dp);
> -		pp |= EDP_BLC_ENABLE;
> +		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> +			intel_dp->DP |= DP_ENHANCED_FRAMING;
>  
> -		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +		if (IS_CHERRYVIEW(dev_priv))
> +			intel_dp->DP |= DP_PIPE_SEL_CHV(crtc->pipe);
> +		else
> +			intel_dp->DP |= DP_PIPE_SEL(crtc->pipe);
>  	}
>  }
>  
> +
>  /* Enable backlight PWM and backlight PP control. */
>  void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
>  			    const struct drm_connector_state *conn_state)
> @@ -3432,30 +2566,6 @@ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
>  	_intel_edp_backlight_on(intel_dp);
>  }
>  
> -/* Disable backlight in the panel power control. */
> -static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	intel_wakeref_t wakeref;
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	with_pps_lock(intel_dp, wakeref) {
> -		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -		u32 pp;
> -
> -		pp = ilk_get_pp_control(intel_dp);
> -		pp &= ~EDP_BLC_ENABLE;
> -
> -		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -	}
> -
> -	intel_dp->last_backlight_off = jiffies;
> -	edp_wait_backlight_off(intel_dp);
> -}
> -
>  /* Disable backlight PP control and backlight PWM. */
>  void intel_edp_backlight_off(const struct drm_connector_state *old_conn_state)
>  {
> @@ -3471,33 +2581,6 @@ void intel_edp_backlight_off(const struct drm_connector_state *old_conn_state)
>  	intel_panel_disable_backlight(old_conn_state);
>  }
>  
> -/*
> - * Hook for controlling the panel power control backlight through the bl_power
> - * sysfs attribute. Take care to handle multiple calls.
> - */
> -static void intel_edp_backlight_power(struct intel_connector *connector,
> -				      bool enable)
> -{
> -	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> -	struct intel_dp *intel_dp = intel_attached_dp(connector);
> -	intel_wakeref_t wakeref;
> -	bool is_enabled;
> -
> -	is_enabled = false;
> -	with_pps_lock(intel_dp, wakeref)
> -		is_enabled = ilk_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
> -	if (is_enabled == enable)
> -		return;
> -
> -	drm_dbg_kms(&i915->drm, "panel power control backlight %s\n",
> -		    enable ? "enable" : "disable");
> -
> -	if (enable)
> -		_intel_edp_backlight_on(intel_dp);
> -	else
> -		_intel_edp_backlight_off(intel_dp);
> -}
> -
>  static void assert_dp_port(struct intel_dp *intel_dp, bool state)
>  {
>  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> @@ -4498,112 +3581,6 @@ static void g4x_pre_enable_dp(struct intel_atomic_state *state,
>  		ilk_edp_pll_on(intel_dp, pipe_config);
>  }
>  
> -static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
> -{
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> -	enum pipe pipe = intel_dp->pps_pipe;
> -	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
> -
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
> -
> -	if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B))
> -		return;
> -
> -	edp_panel_vdd_off_sync(intel_dp);
> -
> -	/*
> -	 * VLV seems to get confused when multiple power sequencers
> -	 * have the same port selected (even if only one has power/vdd
> -	 * enabled). The failure manifests as vlv_wait_port_ready() failing
> -	 * CHV on the other hand doesn't seem to mind having the same port
> -	 * selected in multiple power sequencers, but let's clear the
> -	 * port select always when logically disconnecting a power sequencer
> -	 * from a port.
> -	 */
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "detaching pipe %c power sequencer from [ENCODER:%d:%s]\n",
> -		    pipe_name(pipe), dig_port->base.base.base.id,
> -		    dig_port->base.base.name);
> -	intel_de_write(dev_priv, pp_on_reg, 0);
> -	intel_de_posting_read(dev_priv, pp_on_reg);
> -
> -	intel_dp->pps_pipe = INVALID_PIPE;
> -}
> -
> -static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
> -				      enum pipe pipe)
> -{
> -	struct intel_encoder *encoder;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	for_each_intel_dp(&dev_priv->drm, encoder) {
> -		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -
> -		drm_WARN(&dev_priv->drm, intel_dp->active_pipe == pipe,
> -			 "stealing pipe %c power sequencer from active [ENCODER:%d:%s]\n",
> -			 pipe_name(pipe), encoder->base.base.id,
> -			 encoder->base.name);
> -
> -		if (intel_dp->pps_pipe != pipe)
> -			continue;
> -
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "stealing pipe %c power sequencer from [ENCODER:%d:%s]\n",
> -			    pipe_name(pipe), encoder->base.base.id,
> -			    encoder->base.name);
> -
> -		/* make sure vdd is off before we steal it */
> -		vlv_detach_power_sequencer(intel_dp);
> -	}
> -}
> -
> -static void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
> -					   const struct intel_crtc_state *crtc_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> -	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
> -
> -	if (intel_dp->pps_pipe != INVALID_PIPE &&
> -	    intel_dp->pps_pipe != crtc->pipe) {
> -		/*
> -		 * If another power sequencer was being used on this
> -		 * port previously make sure to turn off vdd there while
> -		 * we still have control of it.
> -		 */
> -		vlv_detach_power_sequencer(intel_dp);
> -	}
> -
> -	/*
> -	 * We may be stealing the power
> -	 * sequencer from another port.
> -	 */
> -	vlv_steal_power_sequencer(dev_priv, crtc->pipe);
> -
> -	intel_dp->active_pipe = crtc->pipe;
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	/* now it's all ours */
> -	intel_dp->pps_pipe = crtc->pipe;
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "initializing pipe %c power sequencer for [ENCODER:%d:%s]\n",
> -		    pipe_name(intel_dp->pps_pipe), encoder->base.base.id,
> -		    encoder->base.name);
> -
> -	/* init power sequencer on this pipe and port */
> -	intel_dp_init_panel_power_sequencer(intel_dp);
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
> -}
> -
>  static void vlv_pre_enable_dp(struct intel_atomic_state *state,
>  			      struct intel_encoder *encoder,
>  			      const struct intel_crtc_state *pipe_config,
> @@ -7324,31 +6301,6 @@ void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
>  		wait_panel_power_cycle(intel_dp);
>  }
>  
> -static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if (!edp_have_panel_vdd(intel_dp))
> -		return;
> -
> -	/*
> -	 * The VDD bit needs a power domain reference, so if the bit is
> -	 * already enabled when we boot or resume, grab this reference and
> -	 * schedule a vdd off, so we don't hold on to the reference
> -	 * indefinitely.
> -	 */
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "VDD left on by BIOS, adjusting state tracking\n");
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
> -	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
> -							intel_aux_power_domain(dig_port));
> -
> -	edp_panel_vdd_schedule_off(intel_dp);
> -}
> -
>  static enum pipe vlv_active_pipe(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> @@ -7554,19 +6506,6 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = {
>  	.destroy = intel_dp_encoder_destroy,
>  };
>  
> -static bool intel_edp_have_power(struct intel_dp *intel_dp)
> -{
> -	intel_wakeref_t wakeref;
> -	bool have_power = false;
> -
> -	with_pps_lock(intel_dp, wakeref) {
> -		have_power = edp_have_panel_power(intel_dp) &&
> -						  edp_have_panel_vdd(intel_dp);
> -	}
> -
> -	return have_power;
> -}
> -
>  enum irqreturn
>  intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd)
>  {
> @@ -7670,277 +6609,6 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
>  	}
>  }
>  
> -static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
> -{
> -	intel_dp->panel_power_off_time = ktime_get_boottime();
> -	intel_dp->last_power_on = jiffies;
> -	intel_dp->last_backlight_off = jiffies;
> -}
> -
> -static void
> -intel_pps_readout_hw_state(struct intel_dp *intel_dp, struct edp_power_seq *seq)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	u32 pp_on, pp_off, pp_ctl;
> -	struct pps_registers regs;
> -
> -	intel_pps_get_registers(intel_dp, &regs);
> -
> -	pp_ctl = ilk_get_pp_control(intel_dp);
> -
> -	/* Ensure PPS is unlocked */
> -	if (!HAS_DDI(dev_priv))
> -		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
> -
> -	pp_on = intel_de_read(dev_priv, regs.pp_on);
> -	pp_off = intel_de_read(dev_priv, regs.pp_off);
> -
> -	/* Pull timing values out of registers */
> -	seq->t1_t3 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, pp_on);
> -	seq->t8 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, pp_on);
> -	seq->t9 = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, pp_off);
> -	seq->t10 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, pp_off);
> -
> -	if (i915_mmio_reg_valid(regs.pp_div)) {
> -		u32 pp_div;
> -
> -		pp_div = intel_de_read(dev_priv, regs.pp_div);
> -
> -		seq->t11_t12 = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, pp_div) * 1000;
> -	} else {
> -		seq->t11_t12 = REG_FIELD_GET(BXT_POWER_CYCLE_DELAY_MASK, pp_ctl) * 1000;
> -	}
> -}
> -
> -static void
> -intel_pps_dump_state(const char *state_name, const struct edp_power_seq *seq)
> -{
> -	DRM_DEBUG_KMS("%s t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
> -		      state_name,
> -		      seq->t1_t3, seq->t8, seq->t9, seq->t10, seq->t11_t12);
> -}
> -
> -static void
> -intel_pps_verify_state(struct intel_dp *intel_dp)
> -{
> -	struct edp_power_seq hw;
> -	struct edp_power_seq *sw = &intel_dp->pps_delays;
> -
> -	intel_pps_readout_hw_state(intel_dp, &hw);
> -
> -	if (hw.t1_t3 != sw->t1_t3 || hw.t8 != sw->t8 || hw.t9 != sw->t9 ||
> -	    hw.t10 != sw->t10 || hw.t11_t12 != sw->t11_t12) {
> -		DRM_ERROR("PPS state mismatch\n");
> -		intel_pps_dump_state("sw", sw);
> -		intel_pps_dump_state("hw", &hw);
> -	}
> -}
> -
> -static void
> -intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct edp_power_seq cur, vbt, spec,
> -		*final = &intel_dp->pps_delays;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	/* already initialized? */
> -	if (final->t11_t12 != 0)
> -		return;
> -
> -	intel_pps_readout_hw_state(intel_dp, &cur);
> -
> -	intel_pps_dump_state("cur", &cur);
> -
> -	vbt = dev_priv->vbt.edp.pps;
> -	/* On Toshiba Satellite P50-C-18C system the VBT T12 delay
> -	 * of 500ms appears to be too short. Ocassionally the panel
> -	 * just fails to power back on. Increasing the delay to 800ms
> -	 * seems sufficient to avoid this problem.
> -	 */
> -	if (dev_priv->quirks & QUIRK_INCREASE_T12_DELAY) {
> -		vbt.t11_t12 = max_t(u16, vbt.t11_t12, 1300 * 10);
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "Increasing T12 panel delay as per the quirk to %d\n",
> -			    vbt.t11_t12);
> -	}
> -	/* T11_T12 delay is special and actually in units of 100ms, but zero
> -	 * based in the hw (so we need to add 100 ms). But the sw vbt
> -	 * table multiplies it with 1000 to make it in units of 100usec,
> -	 * too. */
> -	vbt.t11_t12 += 100 * 10;
> -
> -	/* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
> -	 * our hw here, which are all in 100usec. */
> -	spec.t1_t3 = 210 * 10;
> -	spec.t8 = 50 * 10; /* no limit for t8, use t7 instead */
> -	spec.t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */
> -	spec.t10 = 500 * 10;
> -	/* This one is special and actually in units of 100ms, but zero
> -	 * based in the hw (so we need to add 100 ms). But the sw vbt
> -	 * table multiplies it with 1000 to make it in units of 100usec,
> -	 * too. */
> -	spec.t11_t12 = (510 + 100) * 10;
> -
> -	intel_pps_dump_state("vbt", &vbt);
> -
> -	/* Use the max of the register settings and vbt. If both are
> -	 * unset, fall back to the spec limits. */
> -#define assign_final(field)	final->field = (max(cur.field, vbt.field) == 0 ? \
> -				       spec.field : \
> -				       max(cur.field, vbt.field))
> -	assign_final(t1_t3);
> -	assign_final(t8);
> -	assign_final(t9);
> -	assign_final(t10);
> -	assign_final(t11_t12);
> -#undef assign_final
> -
> -#define get_delay(field)	(DIV_ROUND_UP(final->field, 10))
> -	intel_dp->panel_power_up_delay = get_delay(t1_t3);
> -	intel_dp->backlight_on_delay = get_delay(t8);
> -	intel_dp->backlight_off_delay = get_delay(t9);
> -	intel_dp->panel_power_down_delay = get_delay(t10);
> -	intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
> -#undef get_delay
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "panel power up delay %d, power down delay %d, power cycle delay %d\n",
> -		    intel_dp->panel_power_up_delay,
> -		    intel_dp->panel_power_down_delay,
> -		    intel_dp->panel_power_cycle_delay);
> -
> -	drm_dbg_kms(&dev_priv->drm, "backlight on delay %d, off delay %d\n",
> -		    intel_dp->backlight_on_delay,
> -		    intel_dp->backlight_off_delay);
> -
> -	/*
> -	 * We override the HW backlight delays to 1 because we do manual waits
> -	 * on them. For T8, even BSpec recommends doing it. For T9, if we
> -	 * don't do this, we'll end up waiting for the backlight off delay
> -	 * twice: once when we do the manual sleep, and once when we disable
> -	 * the panel and wait for the PP_STATUS bit to become zero.
> -	 */
> -	final->t8 = 1;
> -	final->t9 = 1;
> -
> -	/*
> -	 * HW has only a 100msec granularity for t11_t12 so round it up
> -	 * accordingly.
> -	 */
> -	final->t11_t12 = roundup(final->t11_t12, 100 * 10);
> -}
> -
> -static void
> -intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
> -					      bool force_disable_vdd)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	u32 pp_on, pp_off, port_sel = 0;
> -	int div = RUNTIME_INFO(dev_priv)->rawclk_freq / 1000;
> -	struct pps_registers regs;
> -	enum port port = dp_to_dig_port(intel_dp)->base.port;
> -	const struct edp_power_seq *seq = &intel_dp->pps_delays;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	intel_pps_get_registers(intel_dp, &regs);
> -
> -	/*
> -	 * On some VLV machines the BIOS can leave the VDD
> -	 * enabled even on power sequencers which aren't
> -	 * hooked up to any port. This would mess up the
> -	 * power domain tracking the first time we pick
> -	 * one of these power sequencers for use since
> -	 * edp_panel_vdd_on() would notice that the VDD was
> -	 * already on and therefore wouldn't grab the power
> -	 * domain reference. Disable VDD first to avoid this.
> -	 * This also avoids spuriously turning the VDD on as
> -	 * soon as the new power sequencer gets initialized.
> -	 */
> -	if (force_disable_vdd) {
> -		u32 pp = ilk_get_pp_control(intel_dp);
> -
> -		drm_WARN(&dev_priv->drm, pp & PANEL_POWER_ON,
> -			 "Panel power already on\n");
> -
> -		if (pp & EDP_FORCE_VDD)
> -			drm_dbg_kms(&dev_priv->drm,
> -				    "VDD already on, disabling first\n");
> -
> -		pp &= ~EDP_FORCE_VDD;
> -
> -		intel_de_write(dev_priv, regs.pp_ctrl, pp);
> -	}
> -
> -	pp_on = REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, seq->t1_t3) |
> -		REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, seq->t8);
> -	pp_off = REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, seq->t9) |
> -		REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, seq->t10);
> -
> -	/* Haswell doesn't have any port selection bits for the panel
> -	 * power sequencer any more. */
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -		port_sel = PANEL_PORT_SELECT_VLV(port);
> -	} else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
> -		switch (port) {
> -		case PORT_A:
> -			port_sel = PANEL_PORT_SELECT_DPA;
> -			break;
> -		case PORT_C:
> -			port_sel = PANEL_PORT_SELECT_DPC;
> -			break;
> -		case PORT_D:
> -			port_sel = PANEL_PORT_SELECT_DPD;
> -			break;
> -		default:
> -			MISSING_CASE(port);
> -			break;
> -		}
> -	}
> -
> -	pp_on |= port_sel;
> -
> -	intel_de_write(dev_priv, regs.pp_on, pp_on);
> -	intel_de_write(dev_priv, regs.pp_off, pp_off);
> -
> -	/*
> -	 * Compute the divisor for the pp clock, simply match the Bspec formula.
> -	 */
> -	if (i915_mmio_reg_valid(regs.pp_div)) {
> -		intel_de_write(dev_priv, regs.pp_div,
> -			       REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, (100 * div) / 2 - 1) | REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000)));
> -	} else {
> -		u32 pp_ctl;
> -
> -		pp_ctl = intel_de_read(dev_priv, regs.pp_ctrl);
> -		pp_ctl &= ~BXT_POWER_CYCLE_DELAY_MASK;
> -		pp_ctl |= REG_FIELD_PREP(BXT_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000));
> -		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
> -	}
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
> -		    intel_de_read(dev_priv, regs.pp_on),
> -		    intel_de_read(dev_priv, regs.pp_off),
> -		    i915_mmio_reg_valid(regs.pp_div) ?
> -		    intel_de_read(dev_priv, regs.pp_div) :
> -		    (intel_de_read(dev_priv, regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK));
> -}
> -
> -static void intel_dp_pps_init(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -		vlv_initial_power_sequencer_setup(intel_dp);
> -	} else {
> -		intel_dp_init_panel_power_sequencer(intel_dp);
> -		intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> -	}
> -}
> -
>  /**
>   * intel_dp_set_drrs_state - program registers for RR switch to take effect
>   * @dev_priv: i915 device
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> index 4280a09fd8fd..d07bcdee9639 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> @@ -70,15 +70,11 @@ enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *dig_port,
>  void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
>  			    const struct drm_connector_state *conn_state);
>  void intel_edp_backlight_off(const struct drm_connector_state *conn_state);
> -void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
> -void intel_edp_panel_on(struct intel_dp *intel_dp);
> -void intel_edp_panel_off(struct intel_dp *intel_dp);
>  void intel_dp_mst_suspend(struct drm_i915_private *dev_priv);
>  void intel_dp_mst_resume(struct drm_i915_private *dev_priv);
>  int intel_dp_max_link_rate(struct intel_dp *intel_dp);
>  int intel_dp_max_lane_count(struct intel_dp *intel_dp);
>  int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
> -void intel_power_sequencer_reset(struct drm_i915_private *dev_priv);
>  u32 intel_dp_pack_aux(const u8 *src, int src_bytes);
>  
>  void intel_edp_drrs_enable(struct intel_dp *intel_dp,
> @@ -144,6 +140,7 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
>  				    struct intel_crtc_state *crtc_state);
>  void intel_dp_sync_state(struct intel_encoder *encoder,
>  			 const struct intel_crtc_state *crtc_state);
> +const struct dpll *vlv_get_dpll(struct drm_i915_private *i915);
>  
>  void intel_dp_check_frl_training(struct intel_dp *intel_dp);
>  void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp,
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
> new file mode 100644
> index 000000000000..83bd83b3e3c4
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -0,0 +1,1334 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#include "i915_drv.h"
> +#include "intel_display_types.h"
> +#include "intel_dp.h"
> +#include "intel_pps.h"
> +
> +static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
> +				      enum pipe pipe);
> +static void
> +intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp);
> +static void
> +intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
> +					      bool force_disable_vdd);
> +
> +intel_wakeref_t pps_lock(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	intel_wakeref_t wakeref;
> +
> +	/*
> +	 * See intel_power_sequencer_reset() why we need
> +	 * a power domain reference here.
> +	 */
> +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
> +	mutex_lock(&dev_priv->pps_mutex);
> +
> +	return wakeref;
> +}
> +
> +intel_wakeref_t pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	mutex_unlock(&dev_priv->pps_mutex);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
> +
> +	return 0;
> +}
> +
> +static void
> +vlv_power_sequencer_kick(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum pipe pipe = intel_dp->pps_pipe;
> +	bool pll_enabled, release_cl_override = false;
> +	enum dpio_phy phy = DPIO_PHY(pipe);
> +	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
> +	u32 DP;
> +
> +	if (drm_WARN(&dev_priv->drm,
> +		     intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN,
> +		     "skipping pipe %c power sequencer kick due to [ENCODER:%d:%s] being active\n",
> +		     pipe_name(pipe), dig_port->base.base.base.id,
> +		     dig_port->base.base.name))
> +		return;
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "kicking pipe %c power sequencer for [ENCODER:%d:%s]\n",
> +		    pipe_name(pipe), dig_port->base.base.base.id,
> +		    dig_port->base.base.name);
> +
> +	/* Preserve the BIOS-computed detected bit. This is
> +	 * supposed to be read-only.
> +	 */
> +	DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
> +	DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
> +	DP |= DP_PORT_WIDTH(1);
> +	DP |= DP_LINK_TRAIN_PAT_1;
> +
> +	if (IS_CHERRYVIEW(dev_priv))
> +		DP |= DP_PIPE_SEL_CHV(pipe);
> +	else
> +		DP |= DP_PIPE_SEL(pipe);
> +
> +	pll_enabled = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE;
> +
> +	/*
> +	 * The DPLL for the pipe must be enabled for this to work.
> +	 * So enable temporarily it if it's not already enabled.
> +	 */
> +	if (!pll_enabled) {
> +		release_cl_override = IS_CHERRYVIEW(dev_priv) &&
> +			!chv_phy_powergate_ch(dev_priv, phy, ch, true);
> +
> +		if (vlv_force_pll_on(dev_priv, pipe, vlv_get_dpll(dev_priv))) {
> +			drm_err(&dev_priv->drm,
> +				"Failed to force on pll for pipe %c!\n",
> +				pipe_name(pipe));
> +			return;
> +		}
> +	}
> +
> +	/*
> +	 * Similar magic as in intel_dp_enable_port().
> +	 * We _must_ do this port enable + disable trick
> +	 * to make this power sequencer lock onto the port.
> +	 * Otherwise even VDD force bit won't work.
> +	 */
> +	intel_de_write(dev_priv, intel_dp->output_reg, DP);
> +	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> +
> +	intel_de_write(dev_priv, intel_dp->output_reg, DP | DP_PORT_EN);
> +	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> +
> +	intel_de_write(dev_priv, intel_dp->output_reg, DP & ~DP_PORT_EN);
> +	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> +
> +	if (!pll_enabled) {
> +		vlv_force_pll_off(dev_priv, pipe);
> +
> +		if (release_cl_override)
> +			chv_phy_powergate_ch(dev_priv, phy, ch, false);
> +	}
> +}
> +
> +static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_encoder *encoder;
> +	unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
> +
> +	/*
> +	 * We don't have power sequencer currently.
> +	 * Pick one that's not used by other ports.
> +	 */
> +	for_each_intel_dp(&dev_priv->drm, encoder) {
> +		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +
> +		if (encoder->type == INTEL_OUTPUT_EDP) {
> +			drm_WARN_ON(&dev_priv->drm,
> +				    intel_dp->active_pipe != INVALID_PIPE &&
> +				    intel_dp->active_pipe !=
> +				    intel_dp->pps_pipe);
> +
> +			if (intel_dp->pps_pipe != INVALID_PIPE)
> +				pipes &= ~(1 << intel_dp->pps_pipe);
> +		} else {
> +			drm_WARN_ON(&dev_priv->drm,
> +				    intel_dp->pps_pipe != INVALID_PIPE);
> +
> +			if (intel_dp->active_pipe != INVALID_PIPE)
> +				pipes &= ~(1 << intel_dp->active_pipe);
> +		}
> +	}
> +
> +	if (pipes == 0)
> +		return INVALID_PIPE;
> +
> +	return ffs(pipes) - 1;
> +}
> +
> +static enum pipe
> +vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum pipe pipe;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	/* We should never land here with regular DP ports */
> +	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
> +
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE &&
> +		    intel_dp->active_pipe != intel_dp->pps_pipe);
> +
> +	if (intel_dp->pps_pipe != INVALID_PIPE)
> +		return intel_dp->pps_pipe;
> +
> +	pipe = vlv_find_free_pps(dev_priv);
> +
> +	/*
> +	 * Didn't find one. This should not happen since there
> +	 * are two power sequencers and up to two eDP ports.
> +	 */
> +	if (drm_WARN_ON(&dev_priv->drm, pipe == INVALID_PIPE))
> +		pipe = PIPE_A;
> +
> +	vlv_steal_power_sequencer(dev_priv, pipe);
> +	intel_dp->pps_pipe = pipe;
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "picked pipe %c power sequencer for [ENCODER:%d:%s]\n",
> +		    pipe_name(intel_dp->pps_pipe),
> +		    dig_port->base.base.base.id,
> +		    dig_port->base.base.name);
> +
> +	/* init power sequencer on this pipe and port */
> +	intel_dp_init_panel_power_sequencer(intel_dp);
> +	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
> +
> +	/*
> +	 * Even vdd force doesn't work until we've made
> +	 * the power sequencer lock in on the port.
> +	 */
> +	vlv_power_sequencer_kick(intel_dp);
> +
> +	return intel_dp->pps_pipe;
> +}
> +
> +static int
> +bxt_power_sequencer_idx(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	int backlight_controller = dev_priv->vbt.backlight.controller;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	/* We should never land here with regular DP ports */
> +	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
> +
> +	if (!intel_dp->pps_reset)
> +		return backlight_controller;
> +
> +	intel_dp->pps_reset = false;
> +
> +	/*
> +	 * Only the HW needs to be reprogrammed, the SW state is fixed and
> +	 * has been setup during connector init.
> +	 */
> +	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> +
> +	return backlight_controller;
> +}
> +
> +typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
> +			       enum pipe pipe);
> +
> +static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
> +			       enum pipe pipe)
> +{
> +	return intel_de_read(dev_priv, PP_STATUS(pipe)) & PP_ON;
> +}
> +
> +static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
> +				enum pipe pipe)
> +{
> +	return intel_de_read(dev_priv, PP_CONTROL(pipe)) & EDP_FORCE_VDD;
> +}
> +
> +static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
> +			 enum pipe pipe)
> +{
> +	return true;
> +}
> +
> +static enum pipe
> +vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
> +		     enum port port,
> +		     vlv_pipe_check pipe_check)
> +{
> +	enum pipe pipe;
> +
> +	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
> +		u32 port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(pipe)) &
> +			PANEL_PORT_SELECT_MASK;
> +
> +		if (port_sel != PANEL_PORT_SELECT_VLV(port))
> +			continue;
> +
> +		if (!pipe_check(dev_priv, pipe))
> +			continue;
> +
> +		return pipe;
> +	}
> +
> +	return INVALID_PIPE;
> +}
> +
> +static void
> +vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum port port = dig_port->base.port;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	/* try to find a pipe with this port selected */
> +	/* first pick one where the panel is on */
> +	intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> +						  vlv_pipe_has_pp_on);
> +	/* didn't find one? pick one where vdd is on */
> +	if (intel_dp->pps_pipe == INVALID_PIPE)
> +		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> +							  vlv_pipe_has_vdd_on);
> +	/* didn't find one? pick one with just the correct port */
> +	if (intel_dp->pps_pipe == INVALID_PIPE)
> +		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> +							  vlv_pipe_any);
> +
> +	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
> +	if (intel_dp->pps_pipe == INVALID_PIPE) {
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "no initial power sequencer for [ENCODER:%d:%s]\n",
> +			    dig_port->base.base.base.id,
> +			    dig_port->base.base.name);
> +		return;
> +	}
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "initial power sequencer for [ENCODER:%d:%s]: pipe %c\n",
> +		    dig_port->base.base.base.id,
> +		    dig_port->base.base.name,
> +		    pipe_name(intel_dp->pps_pipe));
> +
> +	intel_dp_init_panel_power_sequencer(intel_dp);
> +	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> +}
> +
> +void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_encoder *encoder;
> +
> +	if (drm_WARN_ON(&dev_priv->drm,
> +			!(IS_VALLEYVIEW(dev_priv) ||
> +			  IS_CHERRYVIEW(dev_priv) ||
> +			  IS_GEN9_LP(dev_priv))))
> +		return;
> +
> +	/*
> +	 * We can't grab pps_mutex here due to deadlock with power_domain
> +	 * mutex when power_domain functions are called while holding pps_mutex.
> +	 * That also means that in order to use pps_pipe the code needs to
> +	 * hold both a power domain reference and pps_mutex, and the power domain
> +	 * reference get/put must be done while _not_ holding pps_mutex.
> +	 * pps_{lock,unlock}() do these steps in the correct order, so one
> +	 * should use them always.
> +	 */
> +
> +	for_each_intel_dp(&dev_priv->drm, encoder) {
> +		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +
> +		drm_WARN_ON(&dev_priv->drm,
> +			    intel_dp->active_pipe != INVALID_PIPE);
> +
> +		if (encoder->type != INTEL_OUTPUT_EDP)
> +			continue;
> +
> +		if (IS_GEN9_LP(dev_priv))
> +			intel_dp->pps_reset = true;
> +		else
> +			intel_dp->pps_pipe = INVALID_PIPE;
> +	}
> +}
> +
> +struct pps_registers {
> +	i915_reg_t pp_ctrl;
> +	i915_reg_t pp_stat;
> +	i915_reg_t pp_on;
> +	i915_reg_t pp_off;
> +	i915_reg_t pp_div;
> +};
> +
> +static void intel_pps_get_registers(struct intel_dp *intel_dp,
> +				    struct pps_registers *regs)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	int pps_idx = 0;
> +
> +	memset(regs, 0, sizeof(*regs));
> +
> +	if (IS_GEN9_LP(dev_priv))
> +		pps_idx = bxt_power_sequencer_idx(intel_dp);
> +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		pps_idx = vlv_power_sequencer_pipe(intel_dp);
> +
> +	regs->pp_ctrl = PP_CONTROL(pps_idx);
> +	regs->pp_stat = PP_STATUS(pps_idx);
> +	regs->pp_on = PP_ON_DELAYS(pps_idx);
> +	regs->pp_off = PP_OFF_DELAYS(pps_idx);
> +
> +	/* Cycle delay moved from PP_DIVISOR to PP_CONTROL */
> +	if (IS_GEN9_LP(dev_priv) || INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
> +		regs->pp_div = INVALID_MMIO_REG;
> +	else
> +		regs->pp_div = PP_DIVISOR(pps_idx);
> +}
> +
> +static i915_reg_t
> +_pp_ctrl_reg(struct intel_dp *intel_dp)
> +{
> +	struct pps_registers regs;
> +
> +	intel_pps_get_registers(intel_dp, &regs);
> +
> +	return regs.pp_ctrl;
> +}
> +
> +static i915_reg_t
> +_pp_stat_reg(struct intel_dp *intel_dp)
> +{
> +	struct pps_registers regs;
> +
> +	intel_pps_get_registers(intel_dp, &regs);
> +
> +	return regs.pp_stat;
> +}
> +
> +static bool edp_have_panel_power(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> +	    intel_dp->pps_pipe == INVALID_PIPE)
> +		return false;
> +
> +	return (intel_de_read(dev_priv, _pp_stat_reg(intel_dp)) & PP_ON) != 0;
> +}
> +
> +static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> +	    intel_dp->pps_pipe == INVALID_PIPE)
> +		return false;
> +
> +	return intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
> +}
> +
> +void intel_dp_check_edp(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) {
> +		drm_WARN(&dev_priv->drm, 1,
> +			 "eDP powered off while attempting aux channel communication.\n");
> +		drm_dbg_kms(&dev_priv->drm, "Status 0x%08x Control 0x%08x\n",
> +			    intel_de_read(dev_priv, _pp_stat_reg(intel_dp)),
> +			    intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)));
> +	}
> +}
> +
> +#define IDLE_ON_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
> +#define IDLE_ON_VALUE   	(PP_ON | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
> +
> +#define IDLE_OFF_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | 0)
> +#define IDLE_OFF_VALUE		(0     | PP_SEQUENCE_NONE | 0                     | 0)
> +
> +#define IDLE_CYCLE_MASK		(PP_ON | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
> +#define IDLE_CYCLE_VALUE	(0     | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
> +
> +static void intel_pps_verify_state(struct intel_dp *intel_dp);
> +
> +static void wait_panel_status(struct intel_dp *intel_dp,
> +				       u32 mask,
> +				       u32 value)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	intel_pps_verify_state(intel_dp);
> +
> +	pp_stat_reg = _pp_stat_reg(intel_dp);
> +	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "mask %08x value %08x status %08x control %08x\n",
> +		    mask, value,
> +		    intel_de_read(dev_priv, pp_stat_reg),
> +		    intel_de_read(dev_priv, pp_ctrl_reg));
> +
> +	if (intel_de_wait_for_register(dev_priv, pp_stat_reg,
> +				       mask, value, 5000))
> +		drm_err(&dev_priv->drm,
> +			"Panel status timeout: status %08x control %08x\n",
> +			intel_de_read(dev_priv, pp_stat_reg),
> +			intel_de_read(dev_priv, pp_ctrl_reg));
> +
> +	drm_dbg_kms(&dev_priv->drm, "Wait complete\n");
> +}
> +
> +static void wait_panel_on(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +
> +	drm_dbg_kms(&i915->drm, "Wait for panel power on\n");
> +	wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
> +}
> +
> +static void wait_panel_off(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +
> +	drm_dbg_kms(&i915->drm, "Wait for panel power off time\n");
> +	wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
> +}
> +
> +void wait_panel_power_cycle(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +	ktime_t panel_power_on_time;
> +	s64 panel_power_off_duration;
> +
> +	drm_dbg_kms(&i915->drm, "Wait for panel power cycle\n");
> +
> +	/* take the difference of currrent time and panel power off time
> +	 * and then make panel wait for t11_t12 if needed. */
> +	panel_power_on_time = ktime_get_boottime();
> +	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->panel_power_off_time);
> +
> +	/* When we disable the VDD override bit last we have to do the manual
> +	 * wait. */
> +	if (panel_power_off_duration < (s64)intel_dp->panel_power_cycle_delay)
> +		wait_remaining_ms_from_jiffies(jiffies,
> +				       intel_dp->panel_power_cycle_delay - panel_power_off_duration);
> +
> +	wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
> +}
> +
> +static void wait_backlight_on(struct intel_dp *intel_dp)
> +{
> +	wait_remaining_ms_from_jiffies(intel_dp->last_power_on,
> +				       intel_dp->backlight_on_delay);
> +}
> +
> +static void edp_wait_backlight_off(struct intel_dp *intel_dp)
> +{
> +	wait_remaining_ms_from_jiffies(intel_dp->last_backlight_off,
> +				       intel_dp->backlight_off_delay);
> +}
> +
> +/* Read the current pp_control value, unlocking the register if it
> + * is locked
> + */
> +
> +static  u32 ilk_get_pp_control(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	u32 control;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	control = intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp));
> +	if (drm_WARN_ON(&dev_priv->drm, !HAS_DDI(dev_priv) &&
> +			(control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
> +		control &= ~PANEL_UNLOCK_MASK;
> +		control |= PANEL_UNLOCK_REGS;
> +	}
> +	return control;
> +}
> +
> +/*
> + * Must be paired with edp_panel_vdd_off().
> + * Must hold pps_mutex around the whole on/off sequence.
> + * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> + */
> +bool edp_panel_vdd_on(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	u32 pp;
> +	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> +	bool need_to_disable = !intel_dp->want_panel_vdd;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return false;
> +
> +	cancel_delayed_work(&intel_dp->panel_vdd_work);
> +	intel_dp->want_panel_vdd = true;
> +
> +	if (edp_have_panel_vdd(intel_dp))
> +		return need_to_disable;
> +
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
> +	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
> +							intel_aux_power_domain(dig_port));
> +
> +	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n",
> +		    dig_port->base.base.base.id,
> +		    dig_port->base.base.name);
> +
> +	if (!edp_have_panel_power(intel_dp))
> +		wait_panel_power_cycle(intel_dp);
> +
> +	pp = ilk_get_pp_control(intel_dp);
> +	pp |= EDP_FORCE_VDD;
> +
> +	pp_stat_reg = _pp_stat_reg(intel_dp);
> +	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +
> +	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
> +		    intel_de_read(dev_priv, pp_stat_reg),
> +		    intel_de_read(dev_priv, pp_ctrl_reg));
> +	/*
> +	 * If the panel wasn't on, delay before accessing aux channel
> +	 */
> +	if (!edp_have_panel_power(intel_dp)) {
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "[ENCODER:%d:%s] panel power wasn't enabled\n",
> +			    dig_port->base.base.base.id,
> +			    dig_port->base.base.name);
> +		msleep(intel_dp->panel_power_up_delay);
> +	}
> +
> +	return need_to_disable;
> +}
> +
> +/*
> + * Must be paired with intel_edp_panel_vdd_off() or
> + * intel_edp_panel_off().
> + * Nested calls to these functions are not allowed since
> + * we drop the lock. Caller must use some higher level
> + * locking to prevent nested calls from other threads.
> + */
> +void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
> +{
> +	intel_wakeref_t wakeref;
> +	bool vdd;
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	vdd = false;
> +	with_pps_lock(intel_dp, wakeref)
> +		vdd = edp_panel_vdd_on(intel_dp);
> +	I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n",
> +			dp_to_dig_port(intel_dp)->base.base.base.id,
> +			dp_to_dig_port(intel_dp)->base.base.name);
> +}
> +
> +void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port =
> +		dp_to_dig_port(intel_dp);
> +	u32 pp;
> +	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->want_panel_vdd);
> +
> +	if (!edp_have_panel_vdd(intel_dp))
> +		return;
> +
> +	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD off\n",
> +		    dig_port->base.base.base.id,
> +		    dig_port->base.base.name);
> +
> +	pp = ilk_get_pp_control(intel_dp);
> +	pp &= ~EDP_FORCE_VDD;
> +
> +	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +	pp_stat_reg = _pp_stat_reg(intel_dp);
> +
> +	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +
> +	/* Make sure sequencer is idle before allowing subsequent activity */
> +	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
> +		    intel_de_read(dev_priv, pp_stat_reg),
> +		    intel_de_read(dev_priv, pp_ctrl_reg));
> +
> +	if ((pp & PANEL_POWER_ON) == 0)
> +		intel_dp->panel_power_off_time = ktime_get_boottime();
> +
> +	intel_display_power_put(dev_priv,
> +				intel_aux_power_domain(dig_port),
> +				fetch_and_zero(&intel_dp->vdd_wakeref));
> +}
> +
> +void edp_panel_vdd_work(struct work_struct *__work)
> +{
> +	struct intel_dp *intel_dp =
> +		container_of(to_delayed_work(__work),
> +			     struct intel_dp, panel_vdd_work);
> +	intel_wakeref_t wakeref;
> +
> +	with_pps_lock(intel_dp, wakeref) {
> +		if (!intel_dp->want_panel_vdd)
> +			edp_panel_vdd_off_sync(intel_dp);
> +	}
> +}
> +
> +static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
> +{
> +	unsigned long delay;
> +
> +	/*
> +	 * Queue the timer to fire a long time from now (relative to the power
> +	 * down delay) to keep the panel power up across a sequence of
> +	 * operations.
> +	 */
> +	delay = msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5);
> +	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
> +}
> +
> +/*
> + * Must be paired with edp_panel_vdd_on().
> + * Must hold pps_mutex around the whole on/off sequence.
> + * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> + */
> +void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	I915_STATE_WARN(!intel_dp->want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on",
> +			dp_to_dig_port(intel_dp)->base.base.base.id,
> +			dp_to_dig_port(intel_dp)->base.base.name);
> +
> +	intel_dp->want_panel_vdd = false;
> +
> +	if (sync)
> +		edp_panel_vdd_off_sync(intel_dp);
> +	else
> +		edp_panel_vdd_schedule_off(intel_dp);
> +}
> +
> +void edp_panel_on(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	u32 pp;
> +	i915_reg_t pp_ctrl_reg;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power on\n",
> +		    dp_to_dig_port(intel_dp)->base.base.base.id,
> +		    dp_to_dig_port(intel_dp)->base.base.name);
> +
> +	if (drm_WARN(&dev_priv->drm, edp_have_panel_power(intel_dp),
> +		     "[ENCODER:%d:%s] panel power already on\n",
> +		     dp_to_dig_port(intel_dp)->base.base.base.id,
> +		     dp_to_dig_port(intel_dp)->base.base.name))
> +		return;
> +
> +	wait_panel_power_cycle(intel_dp);
> +
> +	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +	pp = ilk_get_pp_control(intel_dp);
> +	if (IS_GEN(dev_priv, 5)) {
> +		/* ILK workaround: disable reset around power sequence */
> +		pp &= ~PANEL_POWER_RESET;
> +		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	}
> +
> +	pp |= PANEL_POWER_ON;
> +	if (!IS_GEN(dev_priv, 5))
> +		pp |= PANEL_POWER_RESET;
> +
> +	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +
> +	wait_panel_on(intel_dp);
> +	intel_dp->last_power_on = jiffies;
> +
> +	if (IS_GEN(dev_priv, 5)) {
> +		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
> +		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	}
> +}
> +
> +void intel_edp_panel_on(struct intel_dp *intel_dp)
> +{
> +	intel_wakeref_t wakeref;
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	with_pps_lock(intel_dp, wakeref)
> +		edp_panel_on(intel_dp);
> +}
> +
> +void edp_panel_off(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	u32 pp;
> +	i915_reg_t pp_ctrl_reg;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power off\n",
> +		    dig_port->base.base.base.id, dig_port->base.base.name);
> +
> +	drm_WARN(&dev_priv->drm, !intel_dp->want_panel_vdd,
> +		 "Need [ENCODER:%d:%s] VDD to turn off panel\n",
> +		 dig_port->base.base.base.id, dig_port->base.base.name);
> +
> +	pp = ilk_get_pp_control(intel_dp);
> +	/* We need to switch off panel power _and_ force vdd, for otherwise some
> +	 * panels get very unhappy and cease to work. */
> +	pp &= ~(PANEL_POWER_ON | PANEL_POWER_RESET | EDP_FORCE_VDD |
> +		EDP_BLC_ENABLE);
> +
> +	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +
> +	intel_dp->want_panel_vdd = false;
> +
> +	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +
> +	wait_panel_off(intel_dp);
> +	intel_dp->panel_power_off_time = ktime_get_boottime();
> +
> +	/* We got a reference when we enabled the VDD. */
> +	intel_display_power_put(dev_priv,
> +				intel_aux_power_domain(dig_port),
> +				fetch_and_zero(&intel_dp->vdd_wakeref));
> +}
> +
> +void intel_edp_panel_off(struct intel_dp *intel_dp)
> +{
> +	intel_wakeref_t wakeref;
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	with_pps_lock(intel_dp, wakeref)
> +		edp_panel_off(intel_dp);
> +}
> +
> +/* Enable backlight in the panel power control. */
> +void _intel_edp_backlight_on(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	intel_wakeref_t wakeref;
> +
> +	/*
> +	 * If we enable the backlight right away following a panel power
> +	 * on, we may see slight flicker as the panel syncs with the eDP
> +	 * link.  So delay a bit to make sure the image is solid before
> +	 * allowing it to appear.
> +	 */
> +	wait_backlight_on(intel_dp);
> +
> +	with_pps_lock(intel_dp, wakeref) {
> +		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +		u32 pp;
> +
> +		pp = ilk_get_pp_control(intel_dp);
> +		pp |= EDP_BLC_ENABLE;
> +
> +		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	}
> +}
> +
> +/* Disable backlight in the panel power control. */
> +void _intel_edp_backlight_off(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	intel_wakeref_t wakeref;
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	with_pps_lock(intel_dp, wakeref) {
> +		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +		u32 pp;
> +
> +		pp = ilk_get_pp_control(intel_dp);
> +		pp &= ~EDP_BLC_ENABLE;
> +
> +		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	}
> +
> +	intel_dp->last_backlight_off = jiffies;
> +	edp_wait_backlight_off(intel_dp);
> +}
> +
> +/*
> + * Hook for controlling the panel power control backlight through the bl_power
> + * sysfs attribute. Take care to handle multiple calls.
> + */
> +void intel_edp_backlight_power(struct intel_connector *connector, bool enable)
> +{
> +	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> +	struct intel_dp *intel_dp = intel_attached_dp(connector);
> +	intel_wakeref_t wakeref;
> +	bool is_enabled;
> +
> +	is_enabled = false;
> +	with_pps_lock(intel_dp, wakeref)
> +		is_enabled = ilk_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
> +	if (is_enabled == enable)
> +		return;
> +
> +	drm_dbg_kms(&i915->drm, "panel power control backlight %s\n",
> +		    enable ? "enable" : "disable");
> +
> +	if (enable)
> +		_intel_edp_backlight_on(intel_dp);
> +	else
> +		_intel_edp_backlight_off(intel_dp);
> +}
> +
> +static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
> +{
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum pipe pipe = intel_dp->pps_pipe;
> +	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
> +
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
> +
> +	if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B))
> +		return;
> +
> +	edp_panel_vdd_off_sync(intel_dp);
> +
> +	/*
> +	 * VLV seems to get confused when multiple power sequencers
> +	 * have the same port selected (even if only one has power/vdd
> +	 * enabled). The failure manifests as vlv_wait_port_ready() failing
> +	 * CHV on the other hand doesn't seem to mind having the same port
> +	 * selected in multiple power sequencers, but let's clear the
> +	 * port select always when logically disconnecting a power sequencer
> +	 * from a port.
> +	 */
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "detaching pipe %c power sequencer from [ENCODER:%d:%s]\n",
> +		    pipe_name(pipe), dig_port->base.base.base.id,
> +		    dig_port->base.base.name);
> +	intel_de_write(dev_priv, pp_on_reg, 0);
> +	intel_de_posting_read(dev_priv, pp_on_reg);
> +
> +	intel_dp->pps_pipe = INVALID_PIPE;
> +}
> +
> +static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
> +				      enum pipe pipe)
> +{
> +	struct intel_encoder *encoder;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	for_each_intel_dp(&dev_priv->drm, encoder) {
> +		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +
> +		drm_WARN(&dev_priv->drm, intel_dp->active_pipe == pipe,
> +			 "stealing pipe %c power sequencer from active [ENCODER:%d:%s]\n",
> +			 pipe_name(pipe), encoder->base.base.id,
> +			 encoder->base.name);
> +
> +		if (intel_dp->pps_pipe != pipe)
> +			continue;
> +
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "stealing pipe %c power sequencer from [ENCODER:%d:%s]\n",
> +			    pipe_name(pipe), encoder->base.base.id,
> +			    encoder->base.name);
> +
> +		/* make sure vdd is off before we steal it */
> +		vlv_detach_power_sequencer(intel_dp);
> +	}
> +}
> +
> +void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
> +				    const struct intel_crtc_state *crtc_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
> +
> +	if (intel_dp->pps_pipe != INVALID_PIPE &&
> +	    intel_dp->pps_pipe != crtc->pipe) {
> +		/*
> +		 * If another power sequencer was being used on this
> +		 * port previously make sure to turn off vdd there while
> +		 * we still have control of it.
> +		 */
> +		vlv_detach_power_sequencer(intel_dp);
> +	}
> +
> +	/*
> +	 * We may be stealing the power
> +	 * sequencer from another port.
> +	 */
> +	vlv_steal_power_sequencer(dev_priv, crtc->pipe);
> +
> +	intel_dp->active_pipe = crtc->pipe;
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	/* now it's all ours */
> +	intel_dp->pps_pipe = crtc->pipe;
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "initializing pipe %c power sequencer for [ENCODER:%d:%s]\n",
> +		    pipe_name(intel_dp->pps_pipe), encoder->base.base.id,
> +		    encoder->base.name);
> +
> +	/* init power sequencer on this pipe and port */
> +	intel_dp_init_panel_power_sequencer(intel_dp);
> +	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
> +}
> +
> +void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if (!edp_have_panel_vdd(intel_dp))
> +		return;
> +
> +	/*
> +	 * The VDD bit needs a power domain reference, so if the bit is
> +	 * already enabled when we boot or resume, grab this reference and
> +	 * schedule a vdd off, so we don't hold on to the reference
> +	 * indefinitely.
> +	 */
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "VDD left on by BIOS, adjusting state tracking\n");
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
> +	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
> +							intel_aux_power_domain(dig_port));
> +
> +	edp_panel_vdd_schedule_off(intel_dp);
> +}
> +
> +bool intel_edp_have_power(struct intel_dp *intel_dp)
> +{
> +	intel_wakeref_t wakeref;
> +	bool have_power = false;
> +
> +	with_pps_lock(intel_dp, wakeref) {
> +		have_power = edp_have_panel_power(intel_dp) &&
> +						  edp_have_panel_vdd(intel_dp);
> +	}
> +
> +	return have_power;
> +}
> +
> +void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
> +{
> +	intel_dp->panel_power_off_time = ktime_get_boottime();
> +	intel_dp->last_power_on = jiffies;
> +	intel_dp->last_backlight_off = jiffies;
> +}
> +
> +static void
> +intel_pps_readout_hw_state(struct intel_dp *intel_dp, struct edp_power_seq *seq)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	u32 pp_on, pp_off, pp_ctl;
> +	struct pps_registers regs;
> +
> +	intel_pps_get_registers(intel_dp, &regs);
> +
> +	pp_ctl = ilk_get_pp_control(intel_dp);
> +
> +	/* Ensure PPS is unlocked */
> +	if (!HAS_DDI(dev_priv))
> +		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
> +
> +	pp_on = intel_de_read(dev_priv, regs.pp_on);
> +	pp_off = intel_de_read(dev_priv, regs.pp_off);
> +
> +	/* Pull timing values out of registers */
> +	seq->t1_t3 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, pp_on);
> +	seq->t8 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, pp_on);
> +	seq->t9 = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, pp_off);
> +	seq->t10 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, pp_off);
> +
> +	if (i915_mmio_reg_valid(regs.pp_div)) {
> +		u32 pp_div;
> +
> +		pp_div = intel_de_read(dev_priv, regs.pp_div);
> +
> +		seq->t11_t12 = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, pp_div) * 1000;
> +	} else {
> +		seq->t11_t12 = REG_FIELD_GET(BXT_POWER_CYCLE_DELAY_MASK, pp_ctl) * 1000;
> +	}
> +}
> +
> +static void
> +intel_pps_dump_state(const char *state_name, const struct edp_power_seq *seq)
> +{
> +	DRM_DEBUG_KMS("%s t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
> +		      state_name,
> +		      seq->t1_t3, seq->t8, seq->t9, seq->t10, seq->t11_t12);
> +}
> +
> +static void
> +intel_pps_verify_state(struct intel_dp *intel_dp)
> +{
> +	struct edp_power_seq hw;
> +	struct edp_power_seq *sw = &intel_dp->pps_delays;
> +
> +	intel_pps_readout_hw_state(intel_dp, &hw);
> +
> +	if (hw.t1_t3 != sw->t1_t3 || hw.t8 != sw->t8 || hw.t9 != sw->t9 ||
> +	    hw.t10 != sw->t10 || hw.t11_t12 != sw->t11_t12) {
> +		DRM_ERROR("PPS state mismatch\n");
> +		intel_pps_dump_state("sw", sw);
> +		intel_pps_dump_state("hw", &hw);
> +	}
> +}
> +
> +static void
> +intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct edp_power_seq cur, vbt, spec,
> +		*final = &intel_dp->pps_delays;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	/* already initialized? */
> +	if (final->t11_t12 != 0)
> +		return;
> +
> +	intel_pps_readout_hw_state(intel_dp, &cur);
> +
> +	intel_pps_dump_state("cur", &cur);
> +
> +	vbt = dev_priv->vbt.edp.pps;
> +	/* On Toshiba Satellite P50-C-18C system the VBT T12 delay
> +	 * of 500ms appears to be too short. Ocassionally the panel
> +	 * just fails to power back on. Increasing the delay to 800ms
> +	 * seems sufficient to avoid this problem.
> +	 */
> +	if (dev_priv->quirks & QUIRK_INCREASE_T12_DELAY) {
> +		vbt.t11_t12 = max_t(u16, vbt.t11_t12, 1300 * 10);
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "Increasing T12 panel delay as per the quirk to %d\n",
> +			    vbt.t11_t12);
> +	}
> +	/* T11_T12 delay is special and actually in units of 100ms, but zero
> +	 * based in the hw (so we need to add 100 ms). But the sw vbt
> +	 * table multiplies it with 1000 to make it in units of 100usec,
> +	 * too. */
> +	vbt.t11_t12 += 100 * 10;
> +
> +	/* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
> +	 * our hw here, which are all in 100usec. */
> +	spec.t1_t3 = 210 * 10;
> +	spec.t8 = 50 * 10; /* no limit for t8, use t7 instead */
> +	spec.t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */
> +	spec.t10 = 500 * 10;
> +	/* This one is special and actually in units of 100ms, but zero
> +	 * based in the hw (so we need to add 100 ms). But the sw vbt
> +	 * table multiplies it with 1000 to make it in units of 100usec,
> +	 * too. */
> +	spec.t11_t12 = (510 + 100) * 10;
> +
> +	intel_pps_dump_state("vbt", &vbt);
> +
> +	/* Use the max of the register settings and vbt. If both are
> +	 * unset, fall back to the spec limits. */
> +#define assign_final(field)	final->field = (max(cur.field, vbt.field) == 0 ? \
> +				       spec.field : \
> +				       max(cur.field, vbt.field))
> +	assign_final(t1_t3);
> +	assign_final(t8);
> +	assign_final(t9);
> +	assign_final(t10);
> +	assign_final(t11_t12);
> +#undef assign_final
> +
> +#define get_delay(field)	(DIV_ROUND_UP(final->field, 10))
> +	intel_dp->panel_power_up_delay = get_delay(t1_t3);
> +	intel_dp->backlight_on_delay = get_delay(t8);
> +	intel_dp->backlight_off_delay = get_delay(t9);
> +	intel_dp->panel_power_down_delay = get_delay(t10);
> +	intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
> +#undef get_delay
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "panel power up delay %d, power down delay %d, power cycle delay %d\n",
> +		    intel_dp->panel_power_up_delay,
> +		    intel_dp->panel_power_down_delay,
> +		    intel_dp->panel_power_cycle_delay);
> +
> +	drm_dbg_kms(&dev_priv->drm, "backlight on delay %d, off delay %d\n",
> +		    intel_dp->backlight_on_delay,
> +		    intel_dp->backlight_off_delay);
> +
> +	/*
> +	 * We override the HW backlight delays to 1 because we do manual waits
> +	 * on them. For T8, even BSpec recommends doing it. For T9, if we
> +	 * don't do this, we'll end up waiting for the backlight off delay
> +	 * twice: once when we do the manual sleep, and once when we disable
> +	 * the panel and wait for the PP_STATUS bit to become zero.
> +	 */
> +	final->t8 = 1;
> +	final->t9 = 1;
> +
> +	/*
> +	 * HW has only a 100msec granularity for t11_t12 so round it up
> +	 * accordingly.
> +	 */
> +	final->t11_t12 = roundup(final->t11_t12, 100 * 10);
> +}
> +
> +static void
> +intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
> +					      bool force_disable_vdd)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	u32 pp_on, pp_off, port_sel = 0;
> +	int div = RUNTIME_INFO(dev_priv)->rawclk_freq / 1000;
> +	struct pps_registers regs;
> +	enum port port = dp_to_dig_port(intel_dp)->base.port;
> +	const struct edp_power_seq *seq = &intel_dp->pps_delays;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	intel_pps_get_registers(intel_dp, &regs);
> +
> +	/*
> +	 * On some VLV machines the BIOS can leave the VDD
> +	 * enabled even on power sequencers which aren't
> +	 * hooked up to any port. This would mess up the
> +	 * power domain tracking the first time we pick
> +	 * one of these power sequencers for use since
> +	 * edp_panel_vdd_on() would notice that the VDD was
> +	 * already on and therefore wouldn't grab the power
> +	 * domain reference. Disable VDD first to avoid this.
> +	 * This also avoids spuriously turning the VDD on as
> +	 * soon as the new power sequencer gets initialized.
> +	 */
> +	if (force_disable_vdd) {
> +		u32 pp = ilk_get_pp_control(intel_dp);
> +
> +		drm_WARN(&dev_priv->drm, pp & PANEL_POWER_ON,
> +			 "Panel power already on\n");
> +
> +		if (pp & EDP_FORCE_VDD)
> +			drm_dbg_kms(&dev_priv->drm,
> +				    "VDD already on, disabling first\n");
> +
> +		pp &= ~EDP_FORCE_VDD;
> +
> +		intel_de_write(dev_priv, regs.pp_ctrl, pp);
> +	}
> +
> +	pp_on = REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, seq->t1_t3) |
> +		REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, seq->t8);
> +	pp_off = REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, seq->t9) |
> +		REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, seq->t10);
> +
> +	/* Haswell doesn't have any port selection bits for the panel
> +	 * power sequencer any more. */
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> +		port_sel = PANEL_PORT_SELECT_VLV(port);
> +	} else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
> +		switch (port) {
> +		case PORT_A:
> +			port_sel = PANEL_PORT_SELECT_DPA;
> +			break;
> +		case PORT_C:
> +			port_sel = PANEL_PORT_SELECT_DPC;
> +			break;
> +		case PORT_D:
> +			port_sel = PANEL_PORT_SELECT_DPD;
> +			break;
> +		default:
> +			MISSING_CASE(port);
> +			break;
> +		}
> +	}
> +
> +	pp_on |= port_sel;
> +
> +	intel_de_write(dev_priv, regs.pp_on, pp_on);
> +	intel_de_write(dev_priv, regs.pp_off, pp_off);
> +
> +	/*
> +	 * Compute the divisor for the pp clock, simply match the Bspec formula.
> +	 */
> +	if (i915_mmio_reg_valid(regs.pp_div)) {
> +		intel_de_write(dev_priv, regs.pp_div,
> +			       REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, (100 * div) / 2 - 1) | REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000)));
> +	} else {
> +		u32 pp_ctl;
> +
> +		pp_ctl = intel_de_read(dev_priv, regs.pp_ctrl);
> +		pp_ctl &= ~BXT_POWER_CYCLE_DELAY_MASK;
> +		pp_ctl |= REG_FIELD_PREP(BXT_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000));
> +		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
> +	}
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
> +		    intel_de_read(dev_priv, regs.pp_on),
> +		    intel_de_read(dev_priv, regs.pp_off),
> +		    i915_mmio_reg_valid(regs.pp_div) ?
> +		    intel_de_read(dev_priv, regs.pp_div) :
> +		    (intel_de_read(dev_priv, regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK));
> +}
> +
> +void intel_dp_pps_init(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> +		vlv_initial_power_sequencer_setup(intel_dp);
> +	} else {
> +		intel_dp_init_panel_power_sequencer(intel_dp);
> +		intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> +	}
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
> new file mode 100644
> index 000000000000..76d5cc565501
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_pps.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#ifndef __INTEL_PPS_H__
> +#define __INTEL_PPS_H__
> +
> +#include <linux/types.h>
> +
> +#include "intel_wakeref.h"
> +
> +struct drm_i915_private;
> +struct intel_connector;
> +struct intel_crtc_state;
> +struct intel_dp;
> +struct intel_encoder;
> +
> +intel_wakeref_t pps_lock(struct intel_dp *intel_dp);
> +intel_wakeref_t pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref);
> +
> +#define with_pps_lock(dp, wf)						\
> +	for ((wf) = pps_lock(dp); (wf); (wf) = pps_unlock((dp), (wf)))
> +
> +void intel_dp_check_edp(struct intel_dp *intel_dp);
> +void _intel_edp_backlight_on(struct intel_dp *intel_dp);
> +void _intel_edp_backlight_off(struct intel_dp *intel_dp);
> +void intel_edp_backlight_power(struct intel_connector *connector, bool enable);
> +
> +bool edp_panel_vdd_on(struct intel_dp *intel_dp);
> +void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
> +void edp_panel_vdd_off_sync(struct intel_dp *intel_dp);
> +void edp_panel_on(struct intel_dp *intel_dp);
> +void edp_panel_off(struct intel_dp *intel_dp);
> +void edp_panel_vdd_work(struct work_struct *__work);
> +
> +void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
> +void intel_edp_panel_on(struct intel_dp *intel_dp);
> +void intel_edp_panel_off(struct intel_dp *intel_dp);
> +bool intel_edp_have_power(struct intel_dp *intel_dp);
> +
> +void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp);
> +
> +void wait_panel_power_cycle(struct intel_dp *intel_dp);
> +
> +void intel_dp_pps_init(struct intel_dp *intel_dp);
> +void intel_power_sequencer_reset(struct drm_i915_private *i915);
> +void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp);
> +
> +void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
> +				    const struct intel_crtc_state *crtc_state);
> +
> +#endif /* __INTEL_PPS_H__ */

-- 
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 01/17] drm/i915/pps: abstract panel power sequencer from intel_dp.c
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 01/17] drm/i915/pps: abstract panel power sequencer from intel_dp.c Jani Nikula
  2021-01-13 15:34   ` Jani Nikula
@ 2021-01-13 16:47   ` Anshuman Gupta
  1 sibling, 0 replies; 37+ messages in thread
From: Anshuman Gupta @ 2021-01-13 16:47 UTC (permalink / raw)
  To: Jani Nikula; +Cc: intel-gfx

On 2021-01-08 at 19:44:09 +0200, Jani Nikula wrote:
> In a long overdue refactoring, split out all panel sequencer code from
> intel_dp.c to new intel_pps.[ch].
> 
> The first part is mostly just code movement as-is, without cleanups or
> functional changes.
> 
> We need to add a vlv_get_dpll() helper to get at the vlv/chv dpll from
> pps code.
> 
> v2: Rebase.
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Looks Good to me.
Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile                 |    1 +
>  drivers/gpu/drm/i915/display/intel_ddi.c      |    1 +
>  .../drm/i915/display/intel_display_power.c    |    2 +-
>  drivers/gpu/drm/i915/display/intel_dp.c       | 1436 +----------------
>  drivers/gpu/drm/i915/display/intel_dp.h       |    5 +-
>  drivers/gpu/drm/i915/display/intel_pps.c      | 1334 +++++++++++++++
>  drivers/gpu/drm/i915/display/intel_pps.h      |   53 +
>  7 files changed, 1443 insertions(+), 1389 deletions(-)
>  create mode 100644 drivers/gpu/drm/i915/display/intel_pps.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_pps.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile
> index 4074d8cb0d6e..8a04403a11bb 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -251,6 +251,7 @@ i915-y += \
>  	display/intel_lspcon.o \
>  	display/intel_lvds.o \
>  	display/intel_panel.o \
> +	display/intel_pps.o \
>  	display/intel_sdvo.o \
>  	display/intel_tv.o \
>  	display/intel_vdsc.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c
> index 3df6913369bc..f09a597bf730 100644
> --- a/drivers/gpu/drm/i915/display/intel_ddi.c
> +++ b/drivers/gpu/drm/i915/display/intel_ddi.c
> @@ -46,6 +46,7 @@
>  #include "intel_hotplug.h"
>  #include "intel_lspcon.h"
>  #include "intel_panel.h"
> +#include "intel_pps.h"
>  #include "intel_psr.h"
>  #include "intel_sprite.h"
>  #include "intel_tc.h"
> diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c
> index d52374f01316..a11bd8213df4 100644
> --- a/drivers/gpu/drm/i915/display/intel_display_power.c
> +++ b/drivers/gpu/drm/i915/display/intel_display_power.c
> @@ -4,7 +4,6 @@
>   */
>  
>  #include "display/intel_crt.h"
> -#include "display/intel_dp.h"
>  
>  #include "i915_drv.h"
>  #include "i915_irq.h"
> @@ -16,6 +15,7 @@
>  #include "intel_dpio_phy.h"
>  #include "intel_hotplug.h"
>  #include "intel_pm.h"
> +#include "intel_pps.h"
>  #include "intel_sideband.h"
>  #include "intel_tc.h"
>  #include "intel_vga.h"
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c
> index 4f190a82d4ad..07279b10812e 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -58,6 +58,7 @@
>  #include "intel_lspcon.h"
>  #include "intel_lvds.h"
>  #include "intel_panel.h"
> +#include "intel_pps.h"
>  #include "intel_psr.h"
>  #include "intel_sideband.h"
>  #include "intel_tc.h"
> @@ -121,6 +122,11 @@ static const struct dp_link_dpll chv_dpll[] = {
>  		{ .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } },
>  };
>  
> +const struct dpll *vlv_get_dpll(struct drm_i915_private *i915)
> +{
> +	return IS_CHERRYVIEW(i915) ? &chv_dpll[0].dpll : &vlv_dpll[0].dpll;
> +}
> +
>  /* Constants for DP DSC configurations */
>  static const u8 valid_dsc_bpp[] = {6, 8, 10, 12, 15};
>  
> @@ -145,12 +151,6 @@ bool intel_dp_is_edp(struct intel_dp *intel_dp)
>  
>  static void intel_dp_link_down(struct intel_encoder *encoder,
>  			       const struct intel_crtc_state *old_crtc_state);
> -static bool edp_panel_vdd_on(struct intel_dp *intel_dp);
> -static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
> -static void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
> -					   const struct intel_crtc_state *crtc_state);
> -static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
> -				      enum pipe pipe);
>  static void intel_dp_unset_edid(struct intel_dp *intel_dp);
>  
>  /* update sink rates from dpcd */
> @@ -877,447 +877,6 @@ static void intel_dp_unpack_aux(u32 src, u8 *dst, int dst_bytes)
>  		dst[i] = src >> ((3-i) * 8);
>  }
>  
> -static void
> -intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp);
> -static void
> -intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
> -					      bool force_disable_vdd);
> -static void
> -intel_dp_pps_init(struct intel_dp *intel_dp);
> -
> -static intel_wakeref_t
> -pps_lock(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	intel_wakeref_t wakeref;
> -
> -	/*
> -	 * See intel_power_sequencer_reset() why we need
> -	 * a power domain reference here.
> -	 */
> -	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
> -	mutex_lock(&dev_priv->pps_mutex);
> -
> -	return wakeref;
> -}
> -
> -static intel_wakeref_t
> -pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	mutex_unlock(&dev_priv->pps_mutex);
> -	intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
> -	return 0;
> -}
> -
> -#define with_pps_lock(dp, wf) \
> -	for ((wf) = pps_lock(dp); (wf); (wf) = pps_unlock((dp), (wf)))
> -
> -static void
> -vlv_power_sequencer_kick(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum pipe pipe = intel_dp->pps_pipe;
> -	bool pll_enabled, release_cl_override = false;
> -	enum dpio_phy phy = DPIO_PHY(pipe);
> -	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
> -	u32 DP;
> -
> -	if (drm_WARN(&dev_priv->drm,
> -		     intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN,
> -		     "skipping pipe %c power sequencer kick due to [ENCODER:%d:%s] being active\n",
> -		     pipe_name(pipe), dig_port->base.base.base.id,
> -		     dig_port->base.base.name))
> -		return;
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "kicking pipe %c power sequencer for [ENCODER:%d:%s]\n",
> -		    pipe_name(pipe), dig_port->base.base.base.id,
> -		    dig_port->base.base.name);
> -
> -	/* Preserve the BIOS-computed detected bit. This is
> -	 * supposed to be read-only.
> -	 */
> -	DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
> -	DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
> -	DP |= DP_PORT_WIDTH(1);
> -	DP |= DP_LINK_TRAIN_PAT_1;
> -
> -	if (IS_CHERRYVIEW(dev_priv))
> -		DP |= DP_PIPE_SEL_CHV(pipe);
> -	else
> -		DP |= DP_PIPE_SEL(pipe);
> -
> -	pll_enabled = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE;
> -
> -	/*
> -	 * The DPLL for the pipe must be enabled for this to work.
> -	 * So enable temporarily it if it's not already enabled.
> -	 */
> -	if (!pll_enabled) {
> -		release_cl_override = IS_CHERRYVIEW(dev_priv) &&
> -			!chv_phy_powergate_ch(dev_priv, phy, ch, true);
> -
> -		if (vlv_force_pll_on(dev_priv, pipe, IS_CHERRYVIEW(dev_priv) ?
> -				     &chv_dpll[0].dpll : &vlv_dpll[0].dpll)) {
> -			drm_err(&dev_priv->drm,
> -				"Failed to force on pll for pipe %c!\n",
> -				pipe_name(pipe));
> -			return;
> -		}
> -	}
> -
> -	/*
> -	 * Similar magic as in intel_dp_enable_port().
> -	 * We _must_ do this port enable + disable trick
> -	 * to make this power sequencer lock onto the port.
> -	 * Otherwise even VDD force bit won't work.
> -	 */
> -	intel_de_write(dev_priv, intel_dp->output_reg, DP);
> -	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> -
> -	intel_de_write(dev_priv, intel_dp->output_reg, DP | DP_PORT_EN);
> -	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> -
> -	intel_de_write(dev_priv, intel_dp->output_reg, DP & ~DP_PORT_EN);
> -	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> -
> -	if (!pll_enabled) {
> -		vlv_force_pll_off(dev_priv, pipe);
> -
> -		if (release_cl_override)
> -			chv_phy_powergate_ch(dev_priv, phy, ch, false);
> -	}
> -}
> -
> -static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv)
> -{
> -	struct intel_encoder *encoder;
> -	unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
> -
> -	/*
> -	 * We don't have power sequencer currently.
> -	 * Pick one that's not used by other ports.
> -	 */
> -	for_each_intel_dp(&dev_priv->drm, encoder) {
> -		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -
> -		if (encoder->type == INTEL_OUTPUT_EDP) {
> -			drm_WARN_ON(&dev_priv->drm,
> -				    intel_dp->active_pipe != INVALID_PIPE &&
> -				    intel_dp->active_pipe !=
> -				    intel_dp->pps_pipe);
> -
> -			if (intel_dp->pps_pipe != INVALID_PIPE)
> -				pipes &= ~(1 << intel_dp->pps_pipe);
> -		} else {
> -			drm_WARN_ON(&dev_priv->drm,
> -				    intel_dp->pps_pipe != INVALID_PIPE);
> -
> -			if (intel_dp->active_pipe != INVALID_PIPE)
> -				pipes &= ~(1 << intel_dp->active_pipe);
> -		}
> -	}
> -
> -	if (pipes == 0)
> -		return INVALID_PIPE;
> -
> -	return ffs(pipes) - 1;
> -}
> -
> -static enum pipe
> -vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum pipe pipe;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	/* We should never land here with regular DP ports */
> -	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
> -
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE &&
> -		    intel_dp->active_pipe != intel_dp->pps_pipe);
> -
> -	if (intel_dp->pps_pipe != INVALID_PIPE)
> -		return intel_dp->pps_pipe;
> -
> -	pipe = vlv_find_free_pps(dev_priv);
> -
> -	/*
> -	 * Didn't find one. This should not happen since there
> -	 * are two power sequencers and up to two eDP ports.
> -	 */
> -	if (drm_WARN_ON(&dev_priv->drm, pipe == INVALID_PIPE))
> -		pipe = PIPE_A;
> -
> -	vlv_steal_power_sequencer(dev_priv, pipe);
> -	intel_dp->pps_pipe = pipe;
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "picked pipe %c power sequencer for [ENCODER:%d:%s]\n",
> -		    pipe_name(intel_dp->pps_pipe),
> -		    dig_port->base.base.base.id,
> -		    dig_port->base.base.name);
> -
> -	/* init power sequencer on this pipe and port */
> -	intel_dp_init_panel_power_sequencer(intel_dp);
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
> -
> -	/*
> -	 * Even vdd force doesn't work until we've made
> -	 * the power sequencer lock in on the port.
> -	 */
> -	vlv_power_sequencer_kick(intel_dp);
> -
> -	return intel_dp->pps_pipe;
> -}
> -
> -static int
> -bxt_power_sequencer_idx(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	int backlight_controller = dev_priv->vbt.backlight.controller;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	/* We should never land here with regular DP ports */
> -	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
> -
> -	if (!intel_dp->pps_reset)
> -		return backlight_controller;
> -
> -	intel_dp->pps_reset = false;
> -
> -	/*
> -	 * Only the HW needs to be reprogrammed, the SW state is fixed and
> -	 * has been setup during connector init.
> -	 */
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> -
> -	return backlight_controller;
> -}
> -
> -typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
> -			       enum pipe pipe);
> -
> -static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
> -			       enum pipe pipe)
> -{
> -	return intel_de_read(dev_priv, PP_STATUS(pipe)) & PP_ON;
> -}
> -
> -static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
> -				enum pipe pipe)
> -{
> -	return intel_de_read(dev_priv, PP_CONTROL(pipe)) & EDP_FORCE_VDD;
> -}
> -
> -static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
> -			 enum pipe pipe)
> -{
> -	return true;
> -}
> -
> -static enum pipe
> -vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
> -		     enum port port,
> -		     vlv_pipe_check pipe_check)
> -{
> -	enum pipe pipe;
> -
> -	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
> -		u32 port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(pipe)) &
> -			PANEL_PORT_SELECT_MASK;
> -
> -		if (port_sel != PANEL_PORT_SELECT_VLV(port))
> -			continue;
> -
> -		if (!pipe_check(dev_priv, pipe))
> -			continue;
> -
> -		return pipe;
> -	}
> -
> -	return INVALID_PIPE;
> -}
> -
> -static void
> -vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum port port = dig_port->base.port;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	/* try to find a pipe with this port selected */
> -	/* first pick one where the panel is on */
> -	intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> -						  vlv_pipe_has_pp_on);
> -	/* didn't find one? pick one where vdd is on */
> -	if (intel_dp->pps_pipe == INVALID_PIPE)
> -		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> -							  vlv_pipe_has_vdd_on);
> -	/* didn't find one? pick one with just the correct port */
> -	if (intel_dp->pps_pipe == INVALID_PIPE)
> -		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> -							  vlv_pipe_any);
> -
> -	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
> -	if (intel_dp->pps_pipe == INVALID_PIPE) {
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "no initial power sequencer for [ENCODER:%d:%s]\n",
> -			    dig_port->base.base.base.id,
> -			    dig_port->base.base.name);
> -		return;
> -	}
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "initial power sequencer for [ENCODER:%d:%s]: pipe %c\n",
> -		    dig_port->base.base.base.id,
> -		    dig_port->base.base.name,
> -		    pipe_name(intel_dp->pps_pipe));
> -
> -	intel_dp_init_panel_power_sequencer(intel_dp);
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> -}
> -
> -void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
> -{
> -	struct intel_encoder *encoder;
> -
> -	if (drm_WARN_ON(&dev_priv->drm,
> -			!(IS_VALLEYVIEW(dev_priv) ||
> -			  IS_CHERRYVIEW(dev_priv) ||
> -			  IS_GEN9_LP(dev_priv))))
> -		return;
> -
> -	/*
> -	 * We can't grab pps_mutex here due to deadlock with power_domain
> -	 * mutex when power_domain functions are called while holding pps_mutex.
> -	 * That also means that in order to use pps_pipe the code needs to
> -	 * hold both a power domain reference and pps_mutex, and the power domain
> -	 * reference get/put must be done while _not_ holding pps_mutex.
> -	 * pps_{lock,unlock}() do these steps in the correct order, so one
> -	 * should use them always.
> -	 */
> -
> -	for_each_intel_dp(&dev_priv->drm, encoder) {
> -		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -
> -		drm_WARN_ON(&dev_priv->drm,
> -			    intel_dp->active_pipe != INVALID_PIPE);
> -
> -		if (encoder->type != INTEL_OUTPUT_EDP)
> -			continue;
> -
> -		if (IS_GEN9_LP(dev_priv))
> -			intel_dp->pps_reset = true;
> -		else
> -			intel_dp->pps_pipe = INVALID_PIPE;
> -	}
> -}
> -
> -struct pps_registers {
> -	i915_reg_t pp_ctrl;
> -	i915_reg_t pp_stat;
> -	i915_reg_t pp_on;
> -	i915_reg_t pp_off;
> -	i915_reg_t pp_div;
> -};
> -
> -static void intel_pps_get_registers(struct intel_dp *intel_dp,
> -				    struct pps_registers *regs)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	int pps_idx = 0;
> -
> -	memset(regs, 0, sizeof(*regs));
> -
> -	if (IS_GEN9_LP(dev_priv))
> -		pps_idx = bxt_power_sequencer_idx(intel_dp);
> -	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> -		pps_idx = vlv_power_sequencer_pipe(intel_dp);
> -
> -	regs->pp_ctrl = PP_CONTROL(pps_idx);
> -	regs->pp_stat = PP_STATUS(pps_idx);
> -	regs->pp_on = PP_ON_DELAYS(pps_idx);
> -	regs->pp_off = PP_OFF_DELAYS(pps_idx);
> -
> -	/* Cycle delay moved from PP_DIVISOR to PP_CONTROL */
> -	if (IS_GEN9_LP(dev_priv) || INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
> -		regs->pp_div = INVALID_MMIO_REG;
> -	else
> -		regs->pp_div = PP_DIVISOR(pps_idx);
> -}
> -
> -static i915_reg_t
> -_pp_ctrl_reg(struct intel_dp *intel_dp)
> -{
> -	struct pps_registers regs;
> -
> -	intel_pps_get_registers(intel_dp, &regs);
> -
> -	return regs.pp_ctrl;
> -}
> -
> -static i915_reg_t
> -_pp_stat_reg(struct intel_dp *intel_dp)
> -{
> -	struct pps_registers regs;
> -
> -	intel_pps_get_registers(intel_dp, &regs);
> -
> -	return regs.pp_stat;
> -}
> -
> -static bool edp_have_panel_power(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> -	    intel_dp->pps_pipe == INVALID_PIPE)
> -		return false;
> -
> -	return (intel_de_read(dev_priv, _pp_stat_reg(intel_dp)) & PP_ON) != 0;
> -}
> -
> -static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> -	    intel_dp->pps_pipe == INVALID_PIPE)
> -		return false;
> -
> -	return intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
> -}
> -
> -static void
> -intel_dp_check_edp(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) {
> -		drm_WARN(&dev_priv->drm, 1,
> -			 "eDP powered off while attempting aux channel communication.\n");
> -		drm_dbg_kms(&dev_priv->drm, "Status 0x%08x Control 0x%08x\n",
> -			    intel_de_read(dev_priv, _pp_stat_reg(intel_dp)),
> -			    intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)));
> -	}
> -}
> -
>  static u32
>  intel_dp_aux_wait_done(struct intel_dp *intel_dp)
>  {
> @@ -2931,491 +2490,66 @@ static void intel_dp_prepare(struct intel_encoder *encoder,
>  	 * IBX PCH and CPU are the same for almost everything,
>  	 * except that the CPU DP PLL is configured in this
>  	 * register
> -	 *
> -	 * CPT PCH is quite different, having many bits moved
> -	 * to the TRANS_DP_CTL register instead. That
> -	 * configuration happens (oddly) in ilk_pch_enable
> -	 */
> -
> -	/* Preserve the BIOS-computed detected bit. This is
> -	 * supposed to be read-only.
> -	 */
> -	intel_dp->DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
> -
> -	/* Handle DP bits in common between all three register formats */
> -	intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
> -	intel_dp->DP |= DP_PORT_WIDTH(pipe_config->lane_count);
> -
> -	/* Split out the IBX/CPU vs CPT settings */
> -
> -	if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) {
> -		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
> -			intel_dp->DP |= DP_SYNC_HS_HIGH;
> -		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
> -			intel_dp->DP |= DP_SYNC_VS_HIGH;
> -		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
> -
> -		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> -			intel_dp->DP |= DP_ENHANCED_FRAMING;
> -
> -		intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe);
> -	} else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
> -		u32 trans_dp;
> -
> -		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
> -
> -		trans_dp = intel_de_read(dev_priv, TRANS_DP_CTL(crtc->pipe));
> -		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> -			trans_dp |= TRANS_DP_ENH_FRAMING;
> -		else
> -			trans_dp &= ~TRANS_DP_ENH_FRAMING;
> -		intel_de_write(dev_priv, TRANS_DP_CTL(crtc->pipe), trans_dp);
> -	} else {
> -		if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
> -			intel_dp->DP |= DP_COLOR_RANGE_16_235;
> -
> -		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
> -			intel_dp->DP |= DP_SYNC_HS_HIGH;
> -		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
> -			intel_dp->DP |= DP_SYNC_VS_HIGH;
> -		intel_dp->DP |= DP_LINK_TRAIN_OFF;
> -
> -		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> -			intel_dp->DP |= DP_ENHANCED_FRAMING;
> -
> -		if (IS_CHERRYVIEW(dev_priv))
> -			intel_dp->DP |= DP_PIPE_SEL_CHV(crtc->pipe);
> -		else
> -			intel_dp->DP |= DP_PIPE_SEL(crtc->pipe);
> -	}
> -}
> -
> -#define IDLE_ON_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
> -#define IDLE_ON_VALUE   	(PP_ON | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
> -
> -#define IDLE_OFF_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | 0)
> -#define IDLE_OFF_VALUE		(0     | PP_SEQUENCE_NONE | 0                     | 0)
> -
> -#define IDLE_CYCLE_MASK		(PP_ON | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
> -#define IDLE_CYCLE_VALUE	(0     | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
> -
> -static void intel_pps_verify_state(struct intel_dp *intel_dp);
> -
> -static void wait_panel_status(struct intel_dp *intel_dp,
> -				       u32 mask,
> -				       u32 value)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	intel_pps_verify_state(intel_dp);
> -
> -	pp_stat_reg = _pp_stat_reg(intel_dp);
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "mask %08x value %08x status %08x control %08x\n",
> -		    mask, value,
> -		    intel_de_read(dev_priv, pp_stat_reg),
> -		    intel_de_read(dev_priv, pp_ctrl_reg));
> -
> -	if (intel_de_wait_for_register(dev_priv, pp_stat_reg,
> -				       mask, value, 5000))
> -		drm_err(&dev_priv->drm,
> -			"Panel status timeout: status %08x control %08x\n",
> -			intel_de_read(dev_priv, pp_stat_reg),
> -			intel_de_read(dev_priv, pp_ctrl_reg));
> -
> -	drm_dbg_kms(&dev_priv->drm, "Wait complete\n");
> -}
> -
> -static void wait_panel_on(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> -
> -	drm_dbg_kms(&i915->drm, "Wait for panel power on\n");
> -	wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
> -}
> -
> -static void wait_panel_off(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> -
> -	drm_dbg_kms(&i915->drm, "Wait for panel power off time\n");
> -	wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
> -}
> -
> -static void wait_panel_power_cycle(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> -	ktime_t panel_power_on_time;
> -	s64 panel_power_off_duration;
> -
> -	drm_dbg_kms(&i915->drm, "Wait for panel power cycle\n");
> -
> -	/* take the difference of currrent time and panel power off time
> -	 * and then make panel wait for t11_t12 if needed. */
> -	panel_power_on_time = ktime_get_boottime();
> -	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->panel_power_off_time);
> -
> -	/* When we disable the VDD override bit last we have to do the manual
> -	 * wait. */
> -	if (panel_power_off_duration < (s64)intel_dp->panel_power_cycle_delay)
> -		wait_remaining_ms_from_jiffies(jiffies,
> -				       intel_dp->panel_power_cycle_delay - panel_power_off_duration);
> -
> -	wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
> -}
> -
> -static void wait_backlight_on(struct intel_dp *intel_dp)
> -{
> -	wait_remaining_ms_from_jiffies(intel_dp->last_power_on,
> -				       intel_dp->backlight_on_delay);
> -}
> -
> -static void edp_wait_backlight_off(struct intel_dp *intel_dp)
> -{
> -	wait_remaining_ms_from_jiffies(intel_dp->last_backlight_off,
> -				       intel_dp->backlight_off_delay);
> -}
> -
> -/* Read the current pp_control value, unlocking the register if it
> - * is locked
> - */
> -
> -static  u32 ilk_get_pp_control(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	u32 control;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	control = intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp));
> -	if (drm_WARN_ON(&dev_priv->drm, !HAS_DDI(dev_priv) &&
> -			(control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
> -		control &= ~PANEL_UNLOCK_MASK;
> -		control |= PANEL_UNLOCK_REGS;
> -	}
> -	return control;
> -}
> -
> -/*
> - * Must be paired with edp_panel_vdd_off().
> - * Must hold pps_mutex around the whole on/off sequence.
> - * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> - */
> -static bool edp_panel_vdd_on(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	u32 pp;
> -	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> -	bool need_to_disable = !intel_dp->want_panel_vdd;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return false;
> -
> -	cancel_delayed_work(&intel_dp->panel_vdd_work);
> -	intel_dp->want_panel_vdd = true;
> -
> -	if (edp_have_panel_vdd(intel_dp))
> -		return need_to_disable;
> -
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
> -	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
> -							intel_aux_power_domain(dig_port));
> -
> -	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n",
> -		    dig_port->base.base.base.id,
> -		    dig_port->base.base.name);
> -
> -	if (!edp_have_panel_power(intel_dp))
> -		wait_panel_power_cycle(intel_dp);
> -
> -	pp = ilk_get_pp_control(intel_dp);
> -	pp |= EDP_FORCE_VDD;
> -
> -	pp_stat_reg = _pp_stat_reg(intel_dp);
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -
> -	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
> -		    intel_de_read(dev_priv, pp_stat_reg),
> -		    intel_de_read(dev_priv, pp_ctrl_reg));
> -	/*
> -	 * If the panel wasn't on, delay before accessing aux channel
> -	 */
> -	if (!edp_have_panel_power(intel_dp)) {
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "[ENCODER:%d:%s] panel power wasn't enabled\n",
> -			    dig_port->base.base.base.id,
> -			    dig_port->base.base.name);
> -		msleep(intel_dp->panel_power_up_delay);
> -	}
> -
> -	return need_to_disable;
> -}
> -
> -/*
> - * Must be paired with intel_edp_panel_vdd_off() or
> - * intel_edp_panel_off().
> - * Nested calls to these functions are not allowed since
> - * we drop the lock. Caller must use some higher level
> - * locking to prevent nested calls from other threads.
> - */
> -void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
> -{
> -	intel_wakeref_t wakeref;
> -	bool vdd;
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	vdd = false;
> -	with_pps_lock(intel_dp, wakeref)
> -		vdd = edp_panel_vdd_on(intel_dp);
> -	I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n",
> -			dp_to_dig_port(intel_dp)->base.base.base.id,
> -			dp_to_dig_port(intel_dp)->base.base.name);
> -}
> -
> -static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port =
> -		dp_to_dig_port(intel_dp);
> -	u32 pp;
> -	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->want_panel_vdd);
> -
> -	if (!edp_have_panel_vdd(intel_dp))
> -		return;
> -
> -	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD off\n",
> -		    dig_port->base.base.base.id,
> -		    dig_port->base.base.name);
> -
> -	pp = ilk_get_pp_control(intel_dp);
> -	pp &= ~EDP_FORCE_VDD;
> -
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -	pp_stat_reg = _pp_stat_reg(intel_dp);
> -
> -	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -
> -	/* Make sure sequencer is idle before allowing subsequent activity */
> -	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
> -		    intel_de_read(dev_priv, pp_stat_reg),
> -		    intel_de_read(dev_priv, pp_ctrl_reg));
> -
> -	if ((pp & PANEL_POWER_ON) == 0)
> -		intel_dp->panel_power_off_time = ktime_get_boottime();
> -
> -	intel_display_power_put(dev_priv,
> -				intel_aux_power_domain(dig_port),
> -				fetch_and_zero(&intel_dp->vdd_wakeref));
> -}
> -
> -static void edp_panel_vdd_work(struct work_struct *__work)
> -{
> -	struct intel_dp *intel_dp =
> -		container_of(to_delayed_work(__work),
> -			     struct intel_dp, panel_vdd_work);
> -	intel_wakeref_t wakeref;
> -
> -	with_pps_lock(intel_dp, wakeref) {
> -		if (!intel_dp->want_panel_vdd)
> -			edp_panel_vdd_off_sync(intel_dp);
> -	}
> -}
> -
> -static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
> -{
> -	unsigned long delay;
> -
> -	/*
> -	 * Queue the timer to fire a long time from now (relative to the power
> -	 * down delay) to keep the panel power up across a sequence of
> -	 * operations.
> -	 */
> -	delay = msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5);
> -	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
> -}
> -
> -/*
> - * Must be paired with edp_panel_vdd_on().
> - * Must hold pps_mutex around the whole on/off sequence.
> - * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> - */
> -static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	I915_STATE_WARN(!intel_dp->want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on",
> -			dp_to_dig_port(intel_dp)->base.base.base.id,
> -			dp_to_dig_port(intel_dp)->base.base.name);
> -
> -	intel_dp->want_panel_vdd = false;
> -
> -	if (sync)
> -		edp_panel_vdd_off_sync(intel_dp);
> -	else
> -		edp_panel_vdd_schedule_off(intel_dp);
> -}
> -
> -static void edp_panel_on(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	u32 pp;
> -	i915_reg_t pp_ctrl_reg;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power on\n",
> -		    dp_to_dig_port(intel_dp)->base.base.base.id,
> -		    dp_to_dig_port(intel_dp)->base.base.name);
> -
> -	if (drm_WARN(&dev_priv->drm, edp_have_panel_power(intel_dp),
> -		     "[ENCODER:%d:%s] panel power already on\n",
> -		     dp_to_dig_port(intel_dp)->base.base.base.id,
> -		     dp_to_dig_port(intel_dp)->base.base.name))
> -		return;
> -
> -	wait_panel_power_cycle(intel_dp);
> -
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -	pp = ilk_get_pp_control(intel_dp);
> -	if (IS_GEN(dev_priv, 5)) {
> -		/* ILK workaround: disable reset around power sequence */
> -		pp &= ~PANEL_POWER_RESET;
> -		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -	}
> -
> -	pp |= PANEL_POWER_ON;
> -	if (!IS_GEN(dev_priv, 5))
> -		pp |= PANEL_POWER_RESET;
> -
> -	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -
> -	wait_panel_on(intel_dp);
> -	intel_dp->last_power_on = jiffies;
> -
> -	if (IS_GEN(dev_priv, 5)) {
> -		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
> -		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -	}
> -}
> -
> -void intel_edp_panel_on(struct intel_dp *intel_dp)
> -{
> -	intel_wakeref_t wakeref;
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	with_pps_lock(intel_dp, wakeref)
> -		edp_panel_on(intel_dp);
> -}
> -
> -
> -static void edp_panel_off(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	u32 pp;
> -	i915_reg_t pp_ctrl_reg;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power off\n",
> -		    dig_port->base.base.base.id, dig_port->base.base.name);
> -
> -	drm_WARN(&dev_priv->drm, !intel_dp->want_panel_vdd,
> -		 "Need [ENCODER:%d:%s] VDD to turn off panel\n",
> -		 dig_port->base.base.base.id, dig_port->base.base.name);
> -
> -	pp = ilk_get_pp_control(intel_dp);
> -	/* We need to switch off panel power _and_ force vdd, for otherwise some
> -	 * panels get very unhappy and cease to work. */
> -	pp &= ~(PANEL_POWER_ON | PANEL_POWER_RESET | EDP_FORCE_VDD |
> -		EDP_BLC_ENABLE);
> -
> -	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -
> -	intel_dp->want_panel_vdd = false;
> +	 *
> +	 * CPT PCH is quite different, having many bits moved
> +	 * to the TRANS_DP_CTL register instead. That
> +	 * configuration happens (oddly) in ilk_pch_enable
> +	 */
>  
> -	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	/* Preserve the BIOS-computed detected bit. This is
> +	 * supposed to be read-only.
> +	 */
> +	intel_dp->DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
>  
> -	wait_panel_off(intel_dp);
> -	intel_dp->panel_power_off_time = ktime_get_boottime();
> +	/* Handle DP bits in common between all three register formats */
> +	intel_dp->DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
> +	intel_dp->DP |= DP_PORT_WIDTH(pipe_config->lane_count);
>  
> -	/* We got a reference when we enabled the VDD. */
> -	intel_display_power_put(dev_priv,
> -				intel_aux_power_domain(dig_port),
> -				fetch_and_zero(&intel_dp->vdd_wakeref));
> -}
> +	/* Split out the IBX/CPU vs CPT settings */
>  
> -void intel_edp_panel_off(struct intel_dp *intel_dp)
> -{
> -	intel_wakeref_t wakeref;
> +	if (IS_IVYBRIDGE(dev_priv) && port == PORT_A) {
> +		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
> +			intel_dp->DP |= DP_SYNC_HS_HIGH;
> +		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
> +			intel_dp->DP |= DP_SYNC_VS_HIGH;
> +		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
>  
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> +		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> +			intel_dp->DP |= DP_ENHANCED_FRAMING;
>  
> -	with_pps_lock(intel_dp, wakeref)
> -		edp_panel_off(intel_dp);
> -}
> +		intel_dp->DP |= DP_PIPE_SEL_IVB(crtc->pipe);
> +	} else if (HAS_PCH_CPT(dev_priv) && port != PORT_A) {
> +		u32 trans_dp;
>  
> -/* Enable backlight in the panel power control. */
> -static void _intel_edp_backlight_on(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	intel_wakeref_t wakeref;
> +		intel_dp->DP |= DP_LINK_TRAIN_OFF_CPT;
>  
> -	/*
> -	 * If we enable the backlight right away following a panel power
> -	 * on, we may see slight flicker as the panel syncs with the eDP
> -	 * link.  So delay a bit to make sure the image is solid before
> -	 * allowing it to appear.
> -	 */
> -	wait_backlight_on(intel_dp);
> +		trans_dp = intel_de_read(dev_priv, TRANS_DP_CTL(crtc->pipe));
> +		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> +			trans_dp |= TRANS_DP_ENH_FRAMING;
> +		else
> +			trans_dp &= ~TRANS_DP_ENH_FRAMING;
> +		intel_de_write(dev_priv, TRANS_DP_CTL(crtc->pipe), trans_dp);
> +	} else {
> +		if (IS_G4X(dev_priv) && pipe_config->limited_color_range)
> +			intel_dp->DP |= DP_COLOR_RANGE_16_235;
>  
> -	with_pps_lock(intel_dp, wakeref) {
> -		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -		u32 pp;
> +		if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
> +			intel_dp->DP |= DP_SYNC_HS_HIGH;
> +		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
> +			intel_dp->DP |= DP_SYNC_VS_HIGH;
> +		intel_dp->DP |= DP_LINK_TRAIN_OFF;
>  
> -		pp = ilk_get_pp_control(intel_dp);
> -		pp |= EDP_BLC_ENABLE;
> +		if (drm_dp_enhanced_frame_cap(intel_dp->dpcd))
> +			intel_dp->DP |= DP_ENHANCED_FRAMING;
>  
> -		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +		if (IS_CHERRYVIEW(dev_priv))
> +			intel_dp->DP |= DP_PIPE_SEL_CHV(crtc->pipe);
> +		else
> +			intel_dp->DP |= DP_PIPE_SEL(crtc->pipe);
>  	}
>  }
>  
> +
>  /* Enable backlight PWM and backlight PP control. */
>  void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
>  			    const struct drm_connector_state *conn_state)
> @@ -3432,30 +2566,6 @@ void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
>  	_intel_edp_backlight_on(intel_dp);
>  }
>  
> -/* Disable backlight in the panel power control. */
> -static void _intel_edp_backlight_off(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	intel_wakeref_t wakeref;
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	with_pps_lock(intel_dp, wakeref) {
> -		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> -		u32 pp;
> -
> -		pp = ilk_get_pp_control(intel_dp);
> -		pp &= ~EDP_BLC_ENABLE;
> -
> -		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> -		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> -	}
> -
> -	intel_dp->last_backlight_off = jiffies;
> -	edp_wait_backlight_off(intel_dp);
> -}
> -
>  /* Disable backlight PP control and backlight PWM. */
>  void intel_edp_backlight_off(const struct drm_connector_state *old_conn_state)
>  {
> @@ -3471,33 +2581,6 @@ void intel_edp_backlight_off(const struct drm_connector_state *old_conn_state)
>  	intel_panel_disable_backlight(old_conn_state);
>  }
>  
> -/*
> - * Hook for controlling the panel power control backlight through the bl_power
> - * sysfs attribute. Take care to handle multiple calls.
> - */
> -static void intel_edp_backlight_power(struct intel_connector *connector,
> -				      bool enable)
> -{
> -	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> -	struct intel_dp *intel_dp = intel_attached_dp(connector);
> -	intel_wakeref_t wakeref;
> -	bool is_enabled;
> -
> -	is_enabled = false;
> -	with_pps_lock(intel_dp, wakeref)
> -		is_enabled = ilk_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
> -	if (is_enabled == enable)
> -		return;
> -
> -	drm_dbg_kms(&i915->drm, "panel power control backlight %s\n",
> -		    enable ? "enable" : "disable");
> -
> -	if (enable)
> -		_intel_edp_backlight_on(intel_dp);
> -	else
> -		_intel_edp_backlight_off(intel_dp);
> -}
> -
>  static void assert_dp_port(struct intel_dp *intel_dp, bool state)
>  {
>  	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> @@ -4498,112 +3581,6 @@ static void g4x_pre_enable_dp(struct intel_atomic_state *state,
>  		ilk_edp_pll_on(intel_dp, pipe_config);
>  }
>  
> -static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
> -{
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> -	enum pipe pipe = intel_dp->pps_pipe;
> -	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
> -
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
> -
> -	if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B))
> -		return;
> -
> -	edp_panel_vdd_off_sync(intel_dp);
> -
> -	/*
> -	 * VLV seems to get confused when multiple power sequencers
> -	 * have the same port selected (even if only one has power/vdd
> -	 * enabled). The failure manifests as vlv_wait_port_ready() failing
> -	 * CHV on the other hand doesn't seem to mind having the same port
> -	 * selected in multiple power sequencers, but let's clear the
> -	 * port select always when logically disconnecting a power sequencer
> -	 * from a port.
> -	 */
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "detaching pipe %c power sequencer from [ENCODER:%d:%s]\n",
> -		    pipe_name(pipe), dig_port->base.base.base.id,
> -		    dig_port->base.base.name);
> -	intel_de_write(dev_priv, pp_on_reg, 0);
> -	intel_de_posting_read(dev_priv, pp_on_reg);
> -
> -	intel_dp->pps_pipe = INVALID_PIPE;
> -}
> -
> -static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
> -				      enum pipe pipe)
> -{
> -	struct intel_encoder *encoder;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	for_each_intel_dp(&dev_priv->drm, encoder) {
> -		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -
> -		drm_WARN(&dev_priv->drm, intel_dp->active_pipe == pipe,
> -			 "stealing pipe %c power sequencer from active [ENCODER:%d:%s]\n",
> -			 pipe_name(pipe), encoder->base.base.id,
> -			 encoder->base.name);
> -
> -		if (intel_dp->pps_pipe != pipe)
> -			continue;
> -
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "stealing pipe %c power sequencer from [ENCODER:%d:%s]\n",
> -			    pipe_name(pipe), encoder->base.base.id,
> -			    encoder->base.name);
> -
> -		/* make sure vdd is off before we steal it */
> -		vlv_detach_power_sequencer(intel_dp);
> -	}
> -}
> -
> -static void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
> -					   const struct intel_crtc_state *crtc_state)
> -{
> -	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> -	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> -	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
> -
> -	if (intel_dp->pps_pipe != INVALID_PIPE &&
> -	    intel_dp->pps_pipe != crtc->pipe) {
> -		/*
> -		 * If another power sequencer was being used on this
> -		 * port previously make sure to turn off vdd there while
> -		 * we still have control of it.
> -		 */
> -		vlv_detach_power_sequencer(intel_dp);
> -	}
> -
> -	/*
> -	 * We may be stealing the power
> -	 * sequencer from another port.
> -	 */
> -	vlv_steal_power_sequencer(dev_priv, crtc->pipe);
> -
> -	intel_dp->active_pipe = crtc->pipe;
> -
> -	if (!intel_dp_is_edp(intel_dp))
> -		return;
> -
> -	/* now it's all ours */
> -	intel_dp->pps_pipe = crtc->pipe;
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "initializing pipe %c power sequencer for [ENCODER:%d:%s]\n",
> -		    pipe_name(intel_dp->pps_pipe), encoder->base.base.id,
> -		    encoder->base.name);
> -
> -	/* init power sequencer on this pipe and port */
> -	intel_dp_init_panel_power_sequencer(intel_dp);
> -	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
> -}
> -
>  static void vlv_pre_enable_dp(struct intel_atomic_state *state,
>  			      struct intel_encoder *encoder,
>  			      const struct intel_crtc_state *pipe_config,
> @@ -7324,31 +6301,6 @@ void intel_dp_encoder_shutdown(struct intel_encoder *intel_encoder)
>  		wait_panel_power_cycle(intel_dp);
>  }
>  
> -static void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	if (!edp_have_panel_vdd(intel_dp))
> -		return;
> -
> -	/*
> -	 * The VDD bit needs a power domain reference, so if the bit is
> -	 * already enabled when we boot or resume, grab this reference and
> -	 * schedule a vdd off, so we don't hold on to the reference
> -	 * indefinitely.
> -	 */
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "VDD left on by BIOS, adjusting state tracking\n");
> -	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
> -	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
> -							intel_aux_power_domain(dig_port));
> -
> -	edp_panel_vdd_schedule_off(intel_dp);
> -}
> -
>  static enum pipe vlv_active_pipe(struct intel_dp *intel_dp)
>  {
>  	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> @@ -7554,19 +6506,6 @@ static const struct drm_encoder_funcs intel_dp_enc_funcs = {
>  	.destroy = intel_dp_encoder_destroy,
>  };
>  
> -static bool intel_edp_have_power(struct intel_dp *intel_dp)
> -{
> -	intel_wakeref_t wakeref;
> -	bool have_power = false;
> -
> -	with_pps_lock(intel_dp, wakeref) {
> -		have_power = edp_have_panel_power(intel_dp) &&
> -						  edp_have_panel_vdd(intel_dp);
> -	}
> -
> -	return have_power;
> -}
> -
>  enum irqreturn
>  intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd)
>  {
> @@ -7670,277 +6609,6 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
>  	}
>  }
>  
> -static void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
> -{
> -	intel_dp->panel_power_off_time = ktime_get_boottime();
> -	intel_dp->last_power_on = jiffies;
> -	intel_dp->last_backlight_off = jiffies;
> -}
> -
> -static void
> -intel_pps_readout_hw_state(struct intel_dp *intel_dp, struct edp_power_seq *seq)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	u32 pp_on, pp_off, pp_ctl;
> -	struct pps_registers regs;
> -
> -	intel_pps_get_registers(intel_dp, &regs);
> -
> -	pp_ctl = ilk_get_pp_control(intel_dp);
> -
> -	/* Ensure PPS is unlocked */
> -	if (!HAS_DDI(dev_priv))
> -		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
> -
> -	pp_on = intel_de_read(dev_priv, regs.pp_on);
> -	pp_off = intel_de_read(dev_priv, regs.pp_off);
> -
> -	/* Pull timing values out of registers */
> -	seq->t1_t3 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, pp_on);
> -	seq->t8 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, pp_on);
> -	seq->t9 = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, pp_off);
> -	seq->t10 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, pp_off);
> -
> -	if (i915_mmio_reg_valid(regs.pp_div)) {
> -		u32 pp_div;
> -
> -		pp_div = intel_de_read(dev_priv, regs.pp_div);
> -
> -		seq->t11_t12 = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, pp_div) * 1000;
> -	} else {
> -		seq->t11_t12 = REG_FIELD_GET(BXT_POWER_CYCLE_DELAY_MASK, pp_ctl) * 1000;
> -	}
> -}
> -
> -static void
> -intel_pps_dump_state(const char *state_name, const struct edp_power_seq *seq)
> -{
> -	DRM_DEBUG_KMS("%s t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
> -		      state_name,
> -		      seq->t1_t3, seq->t8, seq->t9, seq->t10, seq->t11_t12);
> -}
> -
> -static void
> -intel_pps_verify_state(struct intel_dp *intel_dp)
> -{
> -	struct edp_power_seq hw;
> -	struct edp_power_seq *sw = &intel_dp->pps_delays;
> -
> -	intel_pps_readout_hw_state(intel_dp, &hw);
> -
> -	if (hw.t1_t3 != sw->t1_t3 || hw.t8 != sw->t8 || hw.t9 != sw->t9 ||
> -	    hw.t10 != sw->t10 || hw.t11_t12 != sw->t11_t12) {
> -		DRM_ERROR("PPS state mismatch\n");
> -		intel_pps_dump_state("sw", sw);
> -		intel_pps_dump_state("hw", &hw);
> -	}
> -}
> -
> -static void
> -intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct edp_power_seq cur, vbt, spec,
> -		*final = &intel_dp->pps_delays;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	/* already initialized? */
> -	if (final->t11_t12 != 0)
> -		return;
> -
> -	intel_pps_readout_hw_state(intel_dp, &cur);
> -
> -	intel_pps_dump_state("cur", &cur);
> -
> -	vbt = dev_priv->vbt.edp.pps;
> -	/* On Toshiba Satellite P50-C-18C system the VBT T12 delay
> -	 * of 500ms appears to be too short. Ocassionally the panel
> -	 * just fails to power back on. Increasing the delay to 800ms
> -	 * seems sufficient to avoid this problem.
> -	 */
> -	if (dev_priv->quirks & QUIRK_INCREASE_T12_DELAY) {
> -		vbt.t11_t12 = max_t(u16, vbt.t11_t12, 1300 * 10);
> -		drm_dbg_kms(&dev_priv->drm,
> -			    "Increasing T12 panel delay as per the quirk to %d\n",
> -			    vbt.t11_t12);
> -	}
> -	/* T11_T12 delay is special and actually in units of 100ms, but zero
> -	 * based in the hw (so we need to add 100 ms). But the sw vbt
> -	 * table multiplies it with 1000 to make it in units of 100usec,
> -	 * too. */
> -	vbt.t11_t12 += 100 * 10;
> -
> -	/* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
> -	 * our hw here, which are all in 100usec. */
> -	spec.t1_t3 = 210 * 10;
> -	spec.t8 = 50 * 10; /* no limit for t8, use t7 instead */
> -	spec.t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */
> -	spec.t10 = 500 * 10;
> -	/* This one is special and actually in units of 100ms, but zero
> -	 * based in the hw (so we need to add 100 ms). But the sw vbt
> -	 * table multiplies it with 1000 to make it in units of 100usec,
> -	 * too. */
> -	spec.t11_t12 = (510 + 100) * 10;
> -
> -	intel_pps_dump_state("vbt", &vbt);
> -
> -	/* Use the max of the register settings and vbt. If both are
> -	 * unset, fall back to the spec limits. */
> -#define assign_final(field)	final->field = (max(cur.field, vbt.field) == 0 ? \
> -				       spec.field : \
> -				       max(cur.field, vbt.field))
> -	assign_final(t1_t3);
> -	assign_final(t8);
> -	assign_final(t9);
> -	assign_final(t10);
> -	assign_final(t11_t12);
> -#undef assign_final
> -
> -#define get_delay(field)	(DIV_ROUND_UP(final->field, 10))
> -	intel_dp->panel_power_up_delay = get_delay(t1_t3);
> -	intel_dp->backlight_on_delay = get_delay(t8);
> -	intel_dp->backlight_off_delay = get_delay(t9);
> -	intel_dp->panel_power_down_delay = get_delay(t10);
> -	intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
> -#undef get_delay
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "panel power up delay %d, power down delay %d, power cycle delay %d\n",
> -		    intel_dp->panel_power_up_delay,
> -		    intel_dp->panel_power_down_delay,
> -		    intel_dp->panel_power_cycle_delay);
> -
> -	drm_dbg_kms(&dev_priv->drm, "backlight on delay %d, off delay %d\n",
> -		    intel_dp->backlight_on_delay,
> -		    intel_dp->backlight_off_delay);
> -
> -	/*
> -	 * We override the HW backlight delays to 1 because we do manual waits
> -	 * on them. For T8, even BSpec recommends doing it. For T9, if we
> -	 * don't do this, we'll end up waiting for the backlight off delay
> -	 * twice: once when we do the manual sleep, and once when we disable
> -	 * the panel and wait for the PP_STATUS bit to become zero.
> -	 */
> -	final->t8 = 1;
> -	final->t9 = 1;
> -
> -	/*
> -	 * HW has only a 100msec granularity for t11_t12 so round it up
> -	 * accordingly.
> -	 */
> -	final->t11_t12 = roundup(final->t11_t12, 100 * 10);
> -}
> -
> -static void
> -intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
> -					      bool force_disable_vdd)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	u32 pp_on, pp_off, port_sel = 0;
> -	int div = RUNTIME_INFO(dev_priv)->rawclk_freq / 1000;
> -	struct pps_registers regs;
> -	enum port port = dp_to_dig_port(intel_dp)->base.port;
> -	const struct edp_power_seq *seq = &intel_dp->pps_delays;
> -
> -	lockdep_assert_held(&dev_priv->pps_mutex);
> -
> -	intel_pps_get_registers(intel_dp, &regs);
> -
> -	/*
> -	 * On some VLV machines the BIOS can leave the VDD
> -	 * enabled even on power sequencers which aren't
> -	 * hooked up to any port. This would mess up the
> -	 * power domain tracking the first time we pick
> -	 * one of these power sequencers for use since
> -	 * edp_panel_vdd_on() would notice that the VDD was
> -	 * already on and therefore wouldn't grab the power
> -	 * domain reference. Disable VDD first to avoid this.
> -	 * This also avoids spuriously turning the VDD on as
> -	 * soon as the new power sequencer gets initialized.
> -	 */
> -	if (force_disable_vdd) {
> -		u32 pp = ilk_get_pp_control(intel_dp);
> -
> -		drm_WARN(&dev_priv->drm, pp & PANEL_POWER_ON,
> -			 "Panel power already on\n");
> -
> -		if (pp & EDP_FORCE_VDD)
> -			drm_dbg_kms(&dev_priv->drm,
> -				    "VDD already on, disabling first\n");
> -
> -		pp &= ~EDP_FORCE_VDD;
> -
> -		intel_de_write(dev_priv, regs.pp_ctrl, pp);
> -	}
> -
> -	pp_on = REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, seq->t1_t3) |
> -		REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, seq->t8);
> -	pp_off = REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, seq->t9) |
> -		REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, seq->t10);
> -
> -	/* Haswell doesn't have any port selection bits for the panel
> -	 * power sequencer any more. */
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -		port_sel = PANEL_PORT_SELECT_VLV(port);
> -	} else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
> -		switch (port) {
> -		case PORT_A:
> -			port_sel = PANEL_PORT_SELECT_DPA;
> -			break;
> -		case PORT_C:
> -			port_sel = PANEL_PORT_SELECT_DPC;
> -			break;
> -		case PORT_D:
> -			port_sel = PANEL_PORT_SELECT_DPD;
> -			break;
> -		default:
> -			MISSING_CASE(port);
> -			break;
> -		}
> -	}
> -
> -	pp_on |= port_sel;
> -
> -	intel_de_write(dev_priv, regs.pp_on, pp_on);
> -	intel_de_write(dev_priv, regs.pp_off, pp_off);
> -
> -	/*
> -	 * Compute the divisor for the pp clock, simply match the Bspec formula.
> -	 */
> -	if (i915_mmio_reg_valid(regs.pp_div)) {
> -		intel_de_write(dev_priv, regs.pp_div,
> -			       REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, (100 * div) / 2 - 1) | REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000)));
> -	} else {
> -		u32 pp_ctl;
> -
> -		pp_ctl = intel_de_read(dev_priv, regs.pp_ctrl);
> -		pp_ctl &= ~BXT_POWER_CYCLE_DELAY_MASK;
> -		pp_ctl |= REG_FIELD_PREP(BXT_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000));
> -		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
> -	}
> -
> -	drm_dbg_kms(&dev_priv->drm,
> -		    "panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
> -		    intel_de_read(dev_priv, regs.pp_on),
> -		    intel_de_read(dev_priv, regs.pp_off),
> -		    i915_mmio_reg_valid(regs.pp_div) ?
> -		    intel_de_read(dev_priv, regs.pp_div) :
> -		    (intel_de_read(dev_priv, regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK));
> -}
> -
> -static void intel_dp_pps_init(struct intel_dp *intel_dp)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> -		vlv_initial_power_sequencer_setup(intel_dp);
> -	} else {
> -		intel_dp_init_panel_power_sequencer(intel_dp);
> -		intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> -	}
> -}
> -
>  /**
>   * intel_dp_set_drrs_state - program registers for RR switch to take effect
>   * @dev_priv: i915 device
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.h b/drivers/gpu/drm/i915/display/intel_dp.h
> index 4280a09fd8fd..d07bcdee9639 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.h
> +++ b/drivers/gpu/drm/i915/display/intel_dp.h
> @@ -70,15 +70,11 @@ enum irqreturn intel_dp_hpd_pulse(struct intel_digital_port *dig_port,
>  void intel_edp_backlight_on(const struct intel_crtc_state *crtc_state,
>  			    const struct drm_connector_state *conn_state);
>  void intel_edp_backlight_off(const struct drm_connector_state *conn_state);
> -void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
> -void intel_edp_panel_on(struct intel_dp *intel_dp);
> -void intel_edp_panel_off(struct intel_dp *intel_dp);
>  void intel_dp_mst_suspend(struct drm_i915_private *dev_priv);
>  void intel_dp_mst_resume(struct drm_i915_private *dev_priv);
>  int intel_dp_max_link_rate(struct intel_dp *intel_dp);
>  int intel_dp_max_lane_count(struct intel_dp *intel_dp);
>  int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
> -void intel_power_sequencer_reset(struct drm_i915_private *dev_priv);
>  u32 intel_dp_pack_aux(const u8 *src, int src_bytes);
>  
>  void intel_edp_drrs_enable(struct intel_dp *intel_dp,
> @@ -144,6 +140,7 @@ bool intel_dp_initial_fastset_check(struct intel_encoder *encoder,
>  				    struct intel_crtc_state *crtc_state);
>  void intel_dp_sync_state(struct intel_encoder *encoder,
>  			 const struct intel_crtc_state *crtc_state);
> +const struct dpll *vlv_get_dpll(struct drm_i915_private *i915);
>  
>  void intel_dp_check_frl_training(struct intel_dp *intel_dp);
>  void intel_dp_pcon_dsc_configure(struct intel_dp *intel_dp,
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
> new file mode 100644
> index 000000000000..83bd83b3e3c4
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> @@ -0,0 +1,1334 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#include "i915_drv.h"
> +#include "intel_display_types.h"
> +#include "intel_dp.h"
> +#include "intel_pps.h"
> +
> +static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
> +				      enum pipe pipe);
> +static void
> +intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp);
> +static void
> +intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
> +					      bool force_disable_vdd);
> +
> +intel_wakeref_t pps_lock(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	intel_wakeref_t wakeref;
> +
> +	/*
> +	 * See intel_power_sequencer_reset() why we need
> +	 * a power domain reference here.
> +	 */
> +	wakeref = intel_display_power_get(dev_priv, POWER_DOMAIN_DISPLAY_CORE);
> +	mutex_lock(&dev_priv->pps_mutex);
> +
> +	return wakeref;
> +}
> +
> +intel_wakeref_t pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	mutex_unlock(&dev_priv->pps_mutex);
> +	intel_display_power_put(dev_priv, POWER_DOMAIN_DISPLAY_CORE, wakeref);
> +
> +	return 0;
> +}
> +
> +static void
> +vlv_power_sequencer_kick(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum pipe pipe = intel_dp->pps_pipe;
> +	bool pll_enabled, release_cl_override = false;
> +	enum dpio_phy phy = DPIO_PHY(pipe);
> +	enum dpio_channel ch = vlv_pipe_to_channel(pipe);
> +	u32 DP;
> +
> +	if (drm_WARN(&dev_priv->drm,
> +		     intel_de_read(dev_priv, intel_dp->output_reg) & DP_PORT_EN,
> +		     "skipping pipe %c power sequencer kick due to [ENCODER:%d:%s] being active\n",
> +		     pipe_name(pipe), dig_port->base.base.base.id,
> +		     dig_port->base.base.name))
> +		return;
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "kicking pipe %c power sequencer for [ENCODER:%d:%s]\n",
> +		    pipe_name(pipe), dig_port->base.base.base.id,
> +		    dig_port->base.base.name);
> +
> +	/* Preserve the BIOS-computed detected bit. This is
> +	 * supposed to be read-only.
> +	 */
> +	DP = intel_de_read(dev_priv, intel_dp->output_reg) & DP_DETECTED;
> +	DP |= DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
> +	DP |= DP_PORT_WIDTH(1);
> +	DP |= DP_LINK_TRAIN_PAT_1;
> +
> +	if (IS_CHERRYVIEW(dev_priv))
> +		DP |= DP_PIPE_SEL_CHV(pipe);
> +	else
> +		DP |= DP_PIPE_SEL(pipe);
> +
> +	pll_enabled = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE;
> +
> +	/*
> +	 * The DPLL for the pipe must be enabled for this to work.
> +	 * So enable temporarily it if it's not already enabled.
> +	 */
> +	if (!pll_enabled) {
> +		release_cl_override = IS_CHERRYVIEW(dev_priv) &&
> +			!chv_phy_powergate_ch(dev_priv, phy, ch, true);
> +
> +		if (vlv_force_pll_on(dev_priv, pipe, vlv_get_dpll(dev_priv))) {
> +			drm_err(&dev_priv->drm,
> +				"Failed to force on pll for pipe %c!\n",
> +				pipe_name(pipe));
> +			return;
> +		}
> +	}
> +
> +	/*
> +	 * Similar magic as in intel_dp_enable_port().
> +	 * We _must_ do this port enable + disable trick
> +	 * to make this power sequencer lock onto the port.
> +	 * Otherwise even VDD force bit won't work.
> +	 */
> +	intel_de_write(dev_priv, intel_dp->output_reg, DP);
> +	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> +
> +	intel_de_write(dev_priv, intel_dp->output_reg, DP | DP_PORT_EN);
> +	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> +
> +	intel_de_write(dev_priv, intel_dp->output_reg, DP & ~DP_PORT_EN);
> +	intel_de_posting_read(dev_priv, intel_dp->output_reg);
> +
> +	if (!pll_enabled) {
> +		vlv_force_pll_off(dev_priv, pipe);
> +
> +		if (release_cl_override)
> +			chv_phy_powergate_ch(dev_priv, phy, ch, false);
> +	}
> +}
> +
> +static enum pipe vlv_find_free_pps(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_encoder *encoder;
> +	unsigned int pipes = (1 << PIPE_A) | (1 << PIPE_B);
> +
> +	/*
> +	 * We don't have power sequencer currently.
> +	 * Pick one that's not used by other ports.
> +	 */
> +	for_each_intel_dp(&dev_priv->drm, encoder) {
> +		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +
> +		if (encoder->type == INTEL_OUTPUT_EDP) {
> +			drm_WARN_ON(&dev_priv->drm,
> +				    intel_dp->active_pipe != INVALID_PIPE &&
> +				    intel_dp->active_pipe !=
> +				    intel_dp->pps_pipe);
> +
> +			if (intel_dp->pps_pipe != INVALID_PIPE)
> +				pipes &= ~(1 << intel_dp->pps_pipe);
> +		} else {
> +			drm_WARN_ON(&dev_priv->drm,
> +				    intel_dp->pps_pipe != INVALID_PIPE);
> +
> +			if (intel_dp->active_pipe != INVALID_PIPE)
> +				pipes &= ~(1 << intel_dp->active_pipe);
> +		}
> +	}
> +
> +	if (pipes == 0)
> +		return INVALID_PIPE;
> +
> +	return ffs(pipes) - 1;
> +}
> +
> +static enum pipe
> +vlv_power_sequencer_pipe(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum pipe pipe;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	/* We should never land here with regular DP ports */
> +	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
> +
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE &&
> +		    intel_dp->active_pipe != intel_dp->pps_pipe);
> +
> +	if (intel_dp->pps_pipe != INVALID_PIPE)
> +		return intel_dp->pps_pipe;
> +
> +	pipe = vlv_find_free_pps(dev_priv);
> +
> +	/*
> +	 * Didn't find one. This should not happen since there
> +	 * are two power sequencers and up to two eDP ports.
> +	 */
> +	if (drm_WARN_ON(&dev_priv->drm, pipe == INVALID_PIPE))
> +		pipe = PIPE_A;
> +
> +	vlv_steal_power_sequencer(dev_priv, pipe);
> +	intel_dp->pps_pipe = pipe;
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "picked pipe %c power sequencer for [ENCODER:%d:%s]\n",
> +		    pipe_name(intel_dp->pps_pipe),
> +		    dig_port->base.base.base.id,
> +		    dig_port->base.base.name);
> +
> +	/* init power sequencer on this pipe and port */
> +	intel_dp_init_panel_power_sequencer(intel_dp);
> +	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
> +
> +	/*
> +	 * Even vdd force doesn't work until we've made
> +	 * the power sequencer lock in on the port.
> +	 */
> +	vlv_power_sequencer_kick(intel_dp);
> +
> +	return intel_dp->pps_pipe;
> +}
> +
> +static int
> +bxt_power_sequencer_idx(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	int backlight_controller = dev_priv->vbt.backlight.controller;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	/* We should never land here with regular DP ports */
> +	drm_WARN_ON(&dev_priv->drm, !intel_dp_is_edp(intel_dp));
> +
> +	if (!intel_dp->pps_reset)
> +		return backlight_controller;
> +
> +	intel_dp->pps_reset = false;
> +
> +	/*
> +	 * Only the HW needs to be reprogrammed, the SW state is fixed and
> +	 * has been setup during connector init.
> +	 */
> +	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> +
> +	return backlight_controller;
> +}
> +
> +typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
> +			       enum pipe pipe);
> +
> +static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
> +			       enum pipe pipe)
> +{
> +	return intel_de_read(dev_priv, PP_STATUS(pipe)) & PP_ON;
> +}
> +
> +static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
> +				enum pipe pipe)
> +{
> +	return intel_de_read(dev_priv, PP_CONTROL(pipe)) & EDP_FORCE_VDD;
> +}
> +
> +static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
> +			 enum pipe pipe)
> +{
> +	return true;
> +}
> +
> +static enum pipe
> +vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
> +		     enum port port,
> +		     vlv_pipe_check pipe_check)
> +{
> +	enum pipe pipe;
> +
> +	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
> +		u32 port_sel = intel_de_read(dev_priv, PP_ON_DELAYS(pipe)) &
> +			PANEL_PORT_SELECT_MASK;
> +
> +		if (port_sel != PANEL_PORT_SELECT_VLV(port))
> +			continue;
> +
> +		if (!pipe_check(dev_priv, pipe))
> +			continue;
> +
> +		return pipe;
> +	}
> +
> +	return INVALID_PIPE;
> +}
> +
> +static void
> +vlv_initial_power_sequencer_setup(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum port port = dig_port->base.port;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	/* try to find a pipe with this port selected */
> +	/* first pick one where the panel is on */
> +	intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> +						  vlv_pipe_has_pp_on);
> +	/* didn't find one? pick one where vdd is on */
> +	if (intel_dp->pps_pipe == INVALID_PIPE)
> +		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> +							  vlv_pipe_has_vdd_on);
> +	/* didn't find one? pick one with just the correct port */
> +	if (intel_dp->pps_pipe == INVALID_PIPE)
> +		intel_dp->pps_pipe = vlv_initial_pps_pipe(dev_priv, port,
> +							  vlv_pipe_any);
> +
> +	/* didn't find one? just let vlv_power_sequencer_pipe() pick one when needed */
> +	if (intel_dp->pps_pipe == INVALID_PIPE) {
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "no initial power sequencer for [ENCODER:%d:%s]\n",
> +			    dig_port->base.base.base.id,
> +			    dig_port->base.base.name);
> +		return;
> +	}
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "initial power sequencer for [ENCODER:%d:%s]: pipe %c\n",
> +		    dig_port->base.base.base.id,
> +		    dig_port->base.base.name,
> +		    pipe_name(intel_dp->pps_pipe));
> +
> +	intel_dp_init_panel_power_sequencer(intel_dp);
> +	intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> +}
> +
> +void intel_power_sequencer_reset(struct drm_i915_private *dev_priv)
> +{
> +	struct intel_encoder *encoder;
> +
> +	if (drm_WARN_ON(&dev_priv->drm,
> +			!(IS_VALLEYVIEW(dev_priv) ||
> +			  IS_CHERRYVIEW(dev_priv) ||
> +			  IS_GEN9_LP(dev_priv))))
> +		return;
> +
> +	/*
> +	 * We can't grab pps_mutex here due to deadlock with power_domain
> +	 * mutex when power_domain functions are called while holding pps_mutex.
> +	 * That also means that in order to use pps_pipe the code needs to
> +	 * hold both a power domain reference and pps_mutex, and the power domain
> +	 * reference get/put must be done while _not_ holding pps_mutex.
> +	 * pps_{lock,unlock}() do these steps in the correct order, so one
> +	 * should use them always.
> +	 */
> +
> +	for_each_intel_dp(&dev_priv->drm, encoder) {
> +		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +
> +		drm_WARN_ON(&dev_priv->drm,
> +			    intel_dp->active_pipe != INVALID_PIPE);
> +
> +		if (encoder->type != INTEL_OUTPUT_EDP)
> +			continue;
> +
> +		if (IS_GEN9_LP(dev_priv))
> +			intel_dp->pps_reset = true;
> +		else
> +			intel_dp->pps_pipe = INVALID_PIPE;
> +	}
> +}
> +
> +struct pps_registers {
> +	i915_reg_t pp_ctrl;
> +	i915_reg_t pp_stat;
> +	i915_reg_t pp_on;
> +	i915_reg_t pp_off;
> +	i915_reg_t pp_div;
> +};
> +
> +static void intel_pps_get_registers(struct intel_dp *intel_dp,
> +				    struct pps_registers *regs)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	int pps_idx = 0;
> +
> +	memset(regs, 0, sizeof(*regs));
> +
> +	if (IS_GEN9_LP(dev_priv))
> +		pps_idx = bxt_power_sequencer_idx(intel_dp);
> +	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> +		pps_idx = vlv_power_sequencer_pipe(intel_dp);
> +
> +	regs->pp_ctrl = PP_CONTROL(pps_idx);
> +	regs->pp_stat = PP_STATUS(pps_idx);
> +	regs->pp_on = PP_ON_DELAYS(pps_idx);
> +	regs->pp_off = PP_OFF_DELAYS(pps_idx);
> +
> +	/* Cycle delay moved from PP_DIVISOR to PP_CONTROL */
> +	if (IS_GEN9_LP(dev_priv) || INTEL_PCH_TYPE(dev_priv) >= PCH_CNP)
> +		regs->pp_div = INVALID_MMIO_REG;
> +	else
> +		regs->pp_div = PP_DIVISOR(pps_idx);
> +}
> +
> +static i915_reg_t
> +_pp_ctrl_reg(struct intel_dp *intel_dp)
> +{
> +	struct pps_registers regs;
> +
> +	intel_pps_get_registers(intel_dp, &regs);
> +
> +	return regs.pp_ctrl;
> +}
> +
> +static i915_reg_t
> +_pp_stat_reg(struct intel_dp *intel_dp)
> +{
> +	struct pps_registers regs;
> +
> +	intel_pps_get_registers(intel_dp, &regs);
> +
> +	return regs.pp_stat;
> +}
> +
> +static bool edp_have_panel_power(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> +	    intel_dp->pps_pipe == INVALID_PIPE)
> +		return false;
> +
> +	return (intel_de_read(dev_priv, _pp_stat_reg(intel_dp)) & PP_ON) != 0;
> +}
> +
> +static bool edp_have_panel_vdd(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) &&
> +	    intel_dp->pps_pipe == INVALID_PIPE)
> +		return false;
> +
> +	return intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)) & EDP_FORCE_VDD;
> +}
> +
> +void intel_dp_check_edp(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	if (!edp_have_panel_power(intel_dp) && !edp_have_panel_vdd(intel_dp)) {
> +		drm_WARN(&dev_priv->drm, 1,
> +			 "eDP powered off while attempting aux channel communication.\n");
> +		drm_dbg_kms(&dev_priv->drm, "Status 0x%08x Control 0x%08x\n",
> +			    intel_de_read(dev_priv, _pp_stat_reg(intel_dp)),
> +			    intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp)));
> +	}
> +}
> +
> +#define IDLE_ON_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | PP_SEQUENCE_STATE_MASK)
> +#define IDLE_ON_VALUE   	(PP_ON | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_ON_IDLE)
> +
> +#define IDLE_OFF_MASK		(PP_ON | PP_SEQUENCE_MASK | 0                     | 0)
> +#define IDLE_OFF_VALUE		(0     | PP_SEQUENCE_NONE | 0                     | 0)
> +
> +#define IDLE_CYCLE_MASK		(PP_ON | PP_SEQUENCE_MASK | PP_CYCLE_DELAY_ACTIVE | PP_SEQUENCE_STATE_MASK)
> +#define IDLE_CYCLE_VALUE	(0     | PP_SEQUENCE_NONE | 0                     | PP_SEQUENCE_STATE_OFF_IDLE)
> +
> +static void intel_pps_verify_state(struct intel_dp *intel_dp);
> +
> +static void wait_panel_status(struct intel_dp *intel_dp,
> +				       u32 mask,
> +				       u32 value)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	intel_pps_verify_state(intel_dp);
> +
> +	pp_stat_reg = _pp_stat_reg(intel_dp);
> +	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "mask %08x value %08x status %08x control %08x\n",
> +		    mask, value,
> +		    intel_de_read(dev_priv, pp_stat_reg),
> +		    intel_de_read(dev_priv, pp_ctrl_reg));
> +
> +	if (intel_de_wait_for_register(dev_priv, pp_stat_reg,
> +				       mask, value, 5000))
> +		drm_err(&dev_priv->drm,
> +			"Panel status timeout: status %08x control %08x\n",
> +			intel_de_read(dev_priv, pp_stat_reg),
> +			intel_de_read(dev_priv, pp_ctrl_reg));
> +
> +	drm_dbg_kms(&dev_priv->drm, "Wait complete\n");
> +}
> +
> +static void wait_panel_on(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +
> +	drm_dbg_kms(&i915->drm, "Wait for panel power on\n");
> +	wait_panel_status(intel_dp, IDLE_ON_MASK, IDLE_ON_VALUE);
> +}
> +
> +static void wait_panel_off(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +
> +	drm_dbg_kms(&i915->drm, "Wait for panel power off time\n");
> +	wait_panel_status(intel_dp, IDLE_OFF_MASK, IDLE_OFF_VALUE);
> +}
> +
> +void wait_panel_power_cycle(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +	ktime_t panel_power_on_time;
> +	s64 panel_power_off_duration;
> +
> +	drm_dbg_kms(&i915->drm, "Wait for panel power cycle\n");
> +
> +	/* take the difference of currrent time and panel power off time
> +	 * and then make panel wait for t11_t12 if needed. */
> +	panel_power_on_time = ktime_get_boottime();
> +	panel_power_off_duration = ktime_ms_delta(panel_power_on_time, intel_dp->panel_power_off_time);
> +
> +	/* When we disable the VDD override bit last we have to do the manual
> +	 * wait. */
> +	if (panel_power_off_duration < (s64)intel_dp->panel_power_cycle_delay)
> +		wait_remaining_ms_from_jiffies(jiffies,
> +				       intel_dp->panel_power_cycle_delay - panel_power_off_duration);
> +
> +	wait_panel_status(intel_dp, IDLE_CYCLE_MASK, IDLE_CYCLE_VALUE);
> +}
> +
> +static void wait_backlight_on(struct intel_dp *intel_dp)
> +{
> +	wait_remaining_ms_from_jiffies(intel_dp->last_power_on,
> +				       intel_dp->backlight_on_delay);
> +}
> +
> +static void edp_wait_backlight_off(struct intel_dp *intel_dp)
> +{
> +	wait_remaining_ms_from_jiffies(intel_dp->last_backlight_off,
> +				       intel_dp->backlight_off_delay);
> +}
> +
> +/* Read the current pp_control value, unlocking the register if it
> + * is locked
> + */
> +
> +static  u32 ilk_get_pp_control(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	u32 control;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	control = intel_de_read(dev_priv, _pp_ctrl_reg(intel_dp));
> +	if (drm_WARN_ON(&dev_priv->drm, !HAS_DDI(dev_priv) &&
> +			(control & PANEL_UNLOCK_MASK) != PANEL_UNLOCK_REGS)) {
> +		control &= ~PANEL_UNLOCK_MASK;
> +		control |= PANEL_UNLOCK_REGS;
> +	}
> +	return control;
> +}
> +
> +/*
> + * Must be paired with edp_panel_vdd_off().
> + * Must hold pps_mutex around the whole on/off sequence.
> + * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> + */
> +bool edp_panel_vdd_on(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	u32 pp;
> +	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> +	bool need_to_disable = !intel_dp->want_panel_vdd;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return false;
> +
> +	cancel_delayed_work(&intel_dp->panel_vdd_work);
> +	intel_dp->want_panel_vdd = true;
> +
> +	if (edp_have_panel_vdd(intel_dp))
> +		return need_to_disable;
> +
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
> +	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
> +							intel_aux_power_domain(dig_port));
> +
> +	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD on\n",
> +		    dig_port->base.base.base.id,
> +		    dig_port->base.base.name);
> +
> +	if (!edp_have_panel_power(intel_dp))
> +		wait_panel_power_cycle(intel_dp);
> +
> +	pp = ilk_get_pp_control(intel_dp);
> +	pp |= EDP_FORCE_VDD;
> +
> +	pp_stat_reg = _pp_stat_reg(intel_dp);
> +	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +
> +	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
> +		    intel_de_read(dev_priv, pp_stat_reg),
> +		    intel_de_read(dev_priv, pp_ctrl_reg));
> +	/*
> +	 * If the panel wasn't on, delay before accessing aux channel
> +	 */
> +	if (!edp_have_panel_power(intel_dp)) {
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "[ENCODER:%d:%s] panel power wasn't enabled\n",
> +			    dig_port->base.base.base.id,
> +			    dig_port->base.base.name);
> +		msleep(intel_dp->panel_power_up_delay);
> +	}
> +
> +	return need_to_disable;
> +}
> +
> +/*
> + * Must be paired with intel_edp_panel_vdd_off() or
> + * intel_edp_panel_off().
> + * Nested calls to these functions are not allowed since
> + * we drop the lock. Caller must use some higher level
> + * locking to prevent nested calls from other threads.
> + */
> +void intel_edp_panel_vdd_on(struct intel_dp *intel_dp)
> +{
> +	intel_wakeref_t wakeref;
> +	bool vdd;
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	vdd = false;
> +	with_pps_lock(intel_dp, wakeref)
> +		vdd = edp_panel_vdd_on(intel_dp);
> +	I915_STATE_WARN(!vdd, "[ENCODER:%d:%s] VDD already requested on\n",
> +			dp_to_dig_port(intel_dp)->base.base.base.id,
> +			dp_to_dig_port(intel_dp)->base.base.name);
> +}
> +
> +void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port =
> +		dp_to_dig_port(intel_dp);
> +	u32 pp;
> +	i915_reg_t pp_stat_reg, pp_ctrl_reg;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->want_panel_vdd);
> +
> +	if (!edp_have_panel_vdd(intel_dp))
> +		return;
> +
> +	drm_dbg_kms(&dev_priv->drm, "Turning [ENCODER:%d:%s] VDD off\n",
> +		    dig_port->base.base.base.id,
> +		    dig_port->base.base.name);
> +
> +	pp = ilk_get_pp_control(intel_dp);
> +	pp &= ~EDP_FORCE_VDD;
> +
> +	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +	pp_stat_reg = _pp_stat_reg(intel_dp);
> +
> +	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +
> +	/* Make sure sequencer is idle before allowing subsequent activity */
> +	drm_dbg_kms(&dev_priv->drm, "PP_STATUS: 0x%08x PP_CONTROL: 0x%08x\n",
> +		    intel_de_read(dev_priv, pp_stat_reg),
> +		    intel_de_read(dev_priv, pp_ctrl_reg));
> +
> +	if ((pp & PANEL_POWER_ON) == 0)
> +		intel_dp->panel_power_off_time = ktime_get_boottime();
> +
> +	intel_display_power_put(dev_priv,
> +				intel_aux_power_domain(dig_port),
> +				fetch_and_zero(&intel_dp->vdd_wakeref));
> +}
> +
> +void edp_panel_vdd_work(struct work_struct *__work)
> +{
> +	struct intel_dp *intel_dp =
> +		container_of(to_delayed_work(__work),
> +			     struct intel_dp, panel_vdd_work);
> +	intel_wakeref_t wakeref;
> +
> +	with_pps_lock(intel_dp, wakeref) {
> +		if (!intel_dp->want_panel_vdd)
> +			edp_panel_vdd_off_sync(intel_dp);
> +	}
> +}
> +
> +static void edp_panel_vdd_schedule_off(struct intel_dp *intel_dp)
> +{
> +	unsigned long delay;
> +
> +	/*
> +	 * Queue the timer to fire a long time from now (relative to the power
> +	 * down delay) to keep the panel power up across a sequence of
> +	 * operations.
> +	 */
> +	delay = msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5);
> +	schedule_delayed_work(&intel_dp->panel_vdd_work, delay);
> +}
> +
> +/*
> + * Must be paired with edp_panel_vdd_on().
> + * Must hold pps_mutex around the whole on/off sequence.
> + * Can be nested with intel_edp_panel_vdd_{on,off}() calls.
> + */
> +void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	I915_STATE_WARN(!intel_dp->want_panel_vdd, "[ENCODER:%d:%s] VDD not forced on",
> +			dp_to_dig_port(intel_dp)->base.base.base.id,
> +			dp_to_dig_port(intel_dp)->base.base.name);
> +
> +	intel_dp->want_panel_vdd = false;
> +
> +	if (sync)
> +		edp_panel_vdd_off_sync(intel_dp);
> +	else
> +		edp_panel_vdd_schedule_off(intel_dp);
> +}
> +
> +void edp_panel_on(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	u32 pp;
> +	i915_reg_t pp_ctrl_reg;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power on\n",
> +		    dp_to_dig_port(intel_dp)->base.base.base.id,
> +		    dp_to_dig_port(intel_dp)->base.base.name);
> +
> +	if (drm_WARN(&dev_priv->drm, edp_have_panel_power(intel_dp),
> +		     "[ENCODER:%d:%s] panel power already on\n",
> +		     dp_to_dig_port(intel_dp)->base.base.base.id,
> +		     dp_to_dig_port(intel_dp)->base.base.name))
> +		return;
> +
> +	wait_panel_power_cycle(intel_dp);
> +
> +	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +	pp = ilk_get_pp_control(intel_dp);
> +	if (IS_GEN(dev_priv, 5)) {
> +		/* ILK workaround: disable reset around power sequence */
> +		pp &= ~PANEL_POWER_RESET;
> +		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	}
> +
> +	pp |= PANEL_POWER_ON;
> +	if (!IS_GEN(dev_priv, 5))
> +		pp |= PANEL_POWER_RESET;
> +
> +	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +
> +	wait_panel_on(intel_dp);
> +	intel_dp->last_power_on = jiffies;
> +
> +	if (IS_GEN(dev_priv, 5)) {
> +		pp |= PANEL_POWER_RESET; /* restore panel reset bit */
> +		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	}
> +}
> +
> +void intel_edp_panel_on(struct intel_dp *intel_dp)
> +{
> +	intel_wakeref_t wakeref;
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	with_pps_lock(intel_dp, wakeref)
> +		edp_panel_on(intel_dp);
> +}
> +
> +void edp_panel_off(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	u32 pp;
> +	i915_reg_t pp_ctrl_reg;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	drm_dbg_kms(&dev_priv->drm, "Turn [ENCODER:%d:%s] panel power off\n",
> +		    dig_port->base.base.base.id, dig_port->base.base.name);
> +
> +	drm_WARN(&dev_priv->drm, !intel_dp->want_panel_vdd,
> +		 "Need [ENCODER:%d:%s] VDD to turn off panel\n",
> +		 dig_port->base.base.base.id, dig_port->base.base.name);
> +
> +	pp = ilk_get_pp_control(intel_dp);
> +	/* We need to switch off panel power _and_ force vdd, for otherwise some
> +	 * panels get very unhappy and cease to work. */
> +	pp &= ~(PANEL_POWER_ON | PANEL_POWER_RESET | EDP_FORCE_VDD |
> +		EDP_BLC_ENABLE);
> +
> +	pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +
> +	intel_dp->want_panel_vdd = false;
> +
> +	intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +	intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +
> +	wait_panel_off(intel_dp);
> +	intel_dp->panel_power_off_time = ktime_get_boottime();
> +
> +	/* We got a reference when we enabled the VDD. */
> +	intel_display_power_put(dev_priv,
> +				intel_aux_power_domain(dig_port),
> +				fetch_and_zero(&intel_dp->vdd_wakeref));
> +}
> +
> +void intel_edp_panel_off(struct intel_dp *intel_dp)
> +{
> +	intel_wakeref_t wakeref;
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	with_pps_lock(intel_dp, wakeref)
> +		edp_panel_off(intel_dp);
> +}
> +
> +/* Enable backlight in the panel power control. */
> +void _intel_edp_backlight_on(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	intel_wakeref_t wakeref;
> +
> +	/*
> +	 * If we enable the backlight right away following a panel power
> +	 * on, we may see slight flicker as the panel syncs with the eDP
> +	 * link.  So delay a bit to make sure the image is solid before
> +	 * allowing it to appear.
> +	 */
> +	wait_backlight_on(intel_dp);
> +
> +	with_pps_lock(intel_dp, wakeref) {
> +		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +		u32 pp;
> +
> +		pp = ilk_get_pp_control(intel_dp);
> +		pp |= EDP_BLC_ENABLE;
> +
> +		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	}
> +}
> +
> +/* Disable backlight in the panel power control. */
> +void _intel_edp_backlight_off(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	intel_wakeref_t wakeref;
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	with_pps_lock(intel_dp, wakeref) {
> +		i915_reg_t pp_ctrl_reg = _pp_ctrl_reg(intel_dp);
> +		u32 pp;
> +
> +		pp = ilk_get_pp_control(intel_dp);
> +		pp &= ~EDP_BLC_ENABLE;
> +
> +		intel_de_write(dev_priv, pp_ctrl_reg, pp);
> +		intel_de_posting_read(dev_priv, pp_ctrl_reg);
> +	}
> +
> +	intel_dp->last_backlight_off = jiffies;
> +	edp_wait_backlight_off(intel_dp);
> +}
> +
> +/*
> + * Hook for controlling the panel power control backlight through the bl_power
> + * sysfs attribute. Take care to handle multiple calls.
> + */
> +void intel_edp_backlight_power(struct intel_connector *connector, bool enable)
> +{
> +	struct drm_i915_private *i915 = to_i915(connector->base.dev);
> +	struct intel_dp *intel_dp = intel_attached_dp(connector);
> +	intel_wakeref_t wakeref;
> +	bool is_enabled;
> +
> +	is_enabled = false;
> +	with_pps_lock(intel_dp, wakeref)
> +		is_enabled = ilk_get_pp_control(intel_dp) & EDP_BLC_ENABLE;
> +	if (is_enabled == enable)
> +		return;
> +
> +	drm_dbg_kms(&i915->drm, "panel power control backlight %s\n",
> +		    enable ? "enable" : "disable");
> +
> +	if (enable)
> +		_intel_edp_backlight_on(intel_dp);
> +	else
> +		_intel_edp_backlight_off(intel_dp);
> +}
> +
> +static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
> +{
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
> +	enum pipe pipe = intel_dp->pps_pipe;
> +	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);
> +
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
> +
> +	if (drm_WARN_ON(&dev_priv->drm, pipe != PIPE_A && pipe != PIPE_B))
> +		return;
> +
> +	edp_panel_vdd_off_sync(intel_dp);
> +
> +	/*
> +	 * VLV seems to get confused when multiple power sequencers
> +	 * have the same port selected (even if only one has power/vdd
> +	 * enabled). The failure manifests as vlv_wait_port_ready() failing
> +	 * CHV on the other hand doesn't seem to mind having the same port
> +	 * selected in multiple power sequencers, but let's clear the
> +	 * port select always when logically disconnecting a power sequencer
> +	 * from a port.
> +	 */
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "detaching pipe %c power sequencer from [ENCODER:%d:%s]\n",
> +		    pipe_name(pipe), dig_port->base.base.base.id,
> +		    dig_port->base.base.name);
> +	intel_de_write(dev_priv, pp_on_reg, 0);
> +	intel_de_posting_read(dev_priv, pp_on_reg);
> +
> +	intel_dp->pps_pipe = INVALID_PIPE;
> +}
> +
> +static void vlv_steal_power_sequencer(struct drm_i915_private *dev_priv,
> +				      enum pipe pipe)
> +{
> +	struct intel_encoder *encoder;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	for_each_intel_dp(&dev_priv->drm, encoder) {
> +		struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +
> +		drm_WARN(&dev_priv->drm, intel_dp->active_pipe == pipe,
> +			 "stealing pipe %c power sequencer from active [ENCODER:%d:%s]\n",
> +			 pipe_name(pipe), encoder->base.base.id,
> +			 encoder->base.name);
> +
> +		if (intel_dp->pps_pipe != pipe)
> +			continue;
> +
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "stealing pipe %c power sequencer from [ENCODER:%d:%s]\n",
> +			    pipe_name(pipe), encoder->base.base.id,
> +			    encoder->base.name);
> +
> +		/* make sure vdd is off before we steal it */
> +		vlv_detach_power_sequencer(intel_dp);
> +	}
> +}
> +
> +void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
> +				    const struct intel_crtc_state *crtc_state)
> +{
> +	struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
> +	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
> +	struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->active_pipe != INVALID_PIPE);
> +
> +	if (intel_dp->pps_pipe != INVALID_PIPE &&
> +	    intel_dp->pps_pipe != crtc->pipe) {
> +		/*
> +		 * If another power sequencer was being used on this
> +		 * port previously make sure to turn off vdd there while
> +		 * we still have control of it.
> +		 */
> +		vlv_detach_power_sequencer(intel_dp);
> +	}
> +
> +	/*
> +	 * We may be stealing the power
> +	 * sequencer from another port.
> +	 */
> +	vlv_steal_power_sequencer(dev_priv, crtc->pipe);
> +
> +	intel_dp->active_pipe = crtc->pipe;
> +
> +	if (!intel_dp_is_edp(intel_dp))
> +		return;
> +
> +	/* now it's all ours */
> +	intel_dp->pps_pipe = crtc->pipe;
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "initializing pipe %c power sequencer for [ENCODER:%d:%s]\n",
> +		    pipe_name(intel_dp->pps_pipe), encoder->base.base.id,
> +		    encoder->base.name);
> +
> +	/* init power sequencer on this pipe and port */
> +	intel_dp_init_panel_power_sequencer(intel_dp);
> +	intel_dp_init_panel_power_sequencer_registers(intel_dp, true);
> +}
> +
> +void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	if (!edp_have_panel_vdd(intel_dp))
> +		return;
> +
> +	/*
> +	 * The VDD bit needs a power domain reference, so if the bit is
> +	 * already enabled when we boot or resume, grab this reference and
> +	 * schedule a vdd off, so we don't hold on to the reference
> +	 * indefinitely.
> +	 */
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "VDD left on by BIOS, adjusting state tracking\n");
> +	drm_WARN_ON(&dev_priv->drm, intel_dp->vdd_wakeref);
> +	intel_dp->vdd_wakeref = intel_display_power_get(dev_priv,
> +							intel_aux_power_domain(dig_port));
> +
> +	edp_panel_vdd_schedule_off(intel_dp);
> +}
> +
> +bool intel_edp_have_power(struct intel_dp *intel_dp)
> +{
> +	intel_wakeref_t wakeref;
> +	bool have_power = false;
> +
> +	with_pps_lock(intel_dp, wakeref) {
> +		have_power = edp_have_panel_power(intel_dp) &&
> +						  edp_have_panel_vdd(intel_dp);
> +	}
> +
> +	return have_power;
> +}
> +
> +void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp)
> +{
> +	intel_dp->panel_power_off_time = ktime_get_boottime();
> +	intel_dp->last_power_on = jiffies;
> +	intel_dp->last_backlight_off = jiffies;
> +}
> +
> +static void
> +intel_pps_readout_hw_state(struct intel_dp *intel_dp, struct edp_power_seq *seq)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	u32 pp_on, pp_off, pp_ctl;
> +	struct pps_registers regs;
> +
> +	intel_pps_get_registers(intel_dp, &regs);
> +
> +	pp_ctl = ilk_get_pp_control(intel_dp);
> +
> +	/* Ensure PPS is unlocked */
> +	if (!HAS_DDI(dev_priv))
> +		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
> +
> +	pp_on = intel_de_read(dev_priv, regs.pp_on);
> +	pp_off = intel_de_read(dev_priv, regs.pp_off);
> +
> +	/* Pull timing values out of registers */
> +	seq->t1_t3 = REG_FIELD_GET(PANEL_POWER_UP_DELAY_MASK, pp_on);
> +	seq->t8 = REG_FIELD_GET(PANEL_LIGHT_ON_DELAY_MASK, pp_on);
> +	seq->t9 = REG_FIELD_GET(PANEL_LIGHT_OFF_DELAY_MASK, pp_off);
> +	seq->t10 = REG_FIELD_GET(PANEL_POWER_DOWN_DELAY_MASK, pp_off);
> +
> +	if (i915_mmio_reg_valid(regs.pp_div)) {
> +		u32 pp_div;
> +
> +		pp_div = intel_de_read(dev_priv, regs.pp_div);
> +
> +		seq->t11_t12 = REG_FIELD_GET(PANEL_POWER_CYCLE_DELAY_MASK, pp_div) * 1000;
> +	} else {
> +		seq->t11_t12 = REG_FIELD_GET(BXT_POWER_CYCLE_DELAY_MASK, pp_ctl) * 1000;
> +	}
> +}
> +
> +static void
> +intel_pps_dump_state(const char *state_name, const struct edp_power_seq *seq)
> +{
> +	DRM_DEBUG_KMS("%s t1_t3 %d t8 %d t9 %d t10 %d t11_t12 %d\n",
> +		      state_name,
> +		      seq->t1_t3, seq->t8, seq->t9, seq->t10, seq->t11_t12);
> +}
> +
> +static void
> +intel_pps_verify_state(struct intel_dp *intel_dp)
> +{
> +	struct edp_power_seq hw;
> +	struct edp_power_seq *sw = &intel_dp->pps_delays;
> +
> +	intel_pps_readout_hw_state(intel_dp, &hw);
> +
> +	if (hw.t1_t3 != sw->t1_t3 || hw.t8 != sw->t8 || hw.t9 != sw->t9 ||
> +	    hw.t10 != sw->t10 || hw.t11_t12 != sw->t11_t12) {
> +		DRM_ERROR("PPS state mismatch\n");
> +		intel_pps_dump_state("sw", sw);
> +		intel_pps_dump_state("hw", &hw);
> +	}
> +}
> +
> +static void
> +intel_dp_init_panel_power_sequencer(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct edp_power_seq cur, vbt, spec,
> +		*final = &intel_dp->pps_delays;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	/* already initialized? */
> +	if (final->t11_t12 != 0)
> +		return;
> +
> +	intel_pps_readout_hw_state(intel_dp, &cur);
> +
> +	intel_pps_dump_state("cur", &cur);
> +
> +	vbt = dev_priv->vbt.edp.pps;
> +	/* On Toshiba Satellite P50-C-18C system the VBT T12 delay
> +	 * of 500ms appears to be too short. Ocassionally the panel
> +	 * just fails to power back on. Increasing the delay to 800ms
> +	 * seems sufficient to avoid this problem.
> +	 */
> +	if (dev_priv->quirks & QUIRK_INCREASE_T12_DELAY) {
> +		vbt.t11_t12 = max_t(u16, vbt.t11_t12, 1300 * 10);
> +		drm_dbg_kms(&dev_priv->drm,
> +			    "Increasing T12 panel delay as per the quirk to %d\n",
> +			    vbt.t11_t12);
> +	}
> +	/* T11_T12 delay is special and actually in units of 100ms, but zero
> +	 * based in the hw (so we need to add 100 ms). But the sw vbt
> +	 * table multiplies it with 1000 to make it in units of 100usec,
> +	 * too. */
> +	vbt.t11_t12 += 100 * 10;
> +
> +	/* Upper limits from eDP 1.3 spec. Note that we use the clunky units of
> +	 * our hw here, which are all in 100usec. */
> +	spec.t1_t3 = 210 * 10;
> +	spec.t8 = 50 * 10; /* no limit for t8, use t7 instead */
> +	spec.t9 = 50 * 10; /* no limit for t9, make it symmetric with t8 */
> +	spec.t10 = 500 * 10;
> +	/* This one is special and actually in units of 100ms, but zero
> +	 * based in the hw (so we need to add 100 ms). But the sw vbt
> +	 * table multiplies it with 1000 to make it in units of 100usec,
> +	 * too. */
> +	spec.t11_t12 = (510 + 100) * 10;
> +
> +	intel_pps_dump_state("vbt", &vbt);
> +
> +	/* Use the max of the register settings and vbt. If both are
> +	 * unset, fall back to the spec limits. */
> +#define assign_final(field)	final->field = (max(cur.field, vbt.field) == 0 ? \
> +				       spec.field : \
> +				       max(cur.field, vbt.field))
> +	assign_final(t1_t3);
> +	assign_final(t8);
> +	assign_final(t9);
> +	assign_final(t10);
> +	assign_final(t11_t12);
> +#undef assign_final
> +
> +#define get_delay(field)	(DIV_ROUND_UP(final->field, 10))
> +	intel_dp->panel_power_up_delay = get_delay(t1_t3);
> +	intel_dp->backlight_on_delay = get_delay(t8);
> +	intel_dp->backlight_off_delay = get_delay(t9);
> +	intel_dp->panel_power_down_delay = get_delay(t10);
> +	intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
> +#undef get_delay
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "panel power up delay %d, power down delay %d, power cycle delay %d\n",
> +		    intel_dp->panel_power_up_delay,
> +		    intel_dp->panel_power_down_delay,
> +		    intel_dp->panel_power_cycle_delay);
> +
> +	drm_dbg_kms(&dev_priv->drm, "backlight on delay %d, off delay %d\n",
> +		    intel_dp->backlight_on_delay,
> +		    intel_dp->backlight_off_delay);
> +
> +	/*
> +	 * We override the HW backlight delays to 1 because we do manual waits
> +	 * on them. For T8, even BSpec recommends doing it. For T9, if we
> +	 * don't do this, we'll end up waiting for the backlight off delay
> +	 * twice: once when we do the manual sleep, and once when we disable
> +	 * the panel and wait for the PP_STATUS bit to become zero.
> +	 */
> +	final->t8 = 1;
> +	final->t9 = 1;
> +
> +	/*
> +	 * HW has only a 100msec granularity for t11_t12 so round it up
> +	 * accordingly.
> +	 */
> +	final->t11_t12 = roundup(final->t11_t12, 100 * 10);
> +}
> +
> +static void
> +intel_dp_init_panel_power_sequencer_registers(struct intel_dp *intel_dp,
> +					      bool force_disable_vdd)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	u32 pp_on, pp_off, port_sel = 0;
> +	int div = RUNTIME_INFO(dev_priv)->rawclk_freq / 1000;
> +	struct pps_registers regs;
> +	enum port port = dp_to_dig_port(intel_dp)->base.port;
> +	const struct edp_power_seq *seq = &intel_dp->pps_delays;
> +
> +	lockdep_assert_held(&dev_priv->pps_mutex);
> +
> +	intel_pps_get_registers(intel_dp, &regs);
> +
> +	/*
> +	 * On some VLV machines the BIOS can leave the VDD
> +	 * enabled even on power sequencers which aren't
> +	 * hooked up to any port. This would mess up the
> +	 * power domain tracking the first time we pick
> +	 * one of these power sequencers for use since
> +	 * edp_panel_vdd_on() would notice that the VDD was
> +	 * already on and therefore wouldn't grab the power
> +	 * domain reference. Disable VDD first to avoid this.
> +	 * This also avoids spuriously turning the VDD on as
> +	 * soon as the new power sequencer gets initialized.
> +	 */
> +	if (force_disable_vdd) {
> +		u32 pp = ilk_get_pp_control(intel_dp);
> +
> +		drm_WARN(&dev_priv->drm, pp & PANEL_POWER_ON,
> +			 "Panel power already on\n");
> +
> +		if (pp & EDP_FORCE_VDD)
> +			drm_dbg_kms(&dev_priv->drm,
> +				    "VDD already on, disabling first\n");
> +
> +		pp &= ~EDP_FORCE_VDD;
> +
> +		intel_de_write(dev_priv, regs.pp_ctrl, pp);
> +	}
> +
> +	pp_on = REG_FIELD_PREP(PANEL_POWER_UP_DELAY_MASK, seq->t1_t3) |
> +		REG_FIELD_PREP(PANEL_LIGHT_ON_DELAY_MASK, seq->t8);
> +	pp_off = REG_FIELD_PREP(PANEL_LIGHT_OFF_DELAY_MASK, seq->t9) |
> +		REG_FIELD_PREP(PANEL_POWER_DOWN_DELAY_MASK, seq->t10);
> +
> +	/* Haswell doesn't have any port selection bits for the panel
> +	 * power sequencer any more. */
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> +		port_sel = PANEL_PORT_SELECT_VLV(port);
> +	} else if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv)) {
> +		switch (port) {
> +		case PORT_A:
> +			port_sel = PANEL_PORT_SELECT_DPA;
> +			break;
> +		case PORT_C:
> +			port_sel = PANEL_PORT_SELECT_DPC;
> +			break;
> +		case PORT_D:
> +			port_sel = PANEL_PORT_SELECT_DPD;
> +			break;
> +		default:
> +			MISSING_CASE(port);
> +			break;
> +		}
> +	}
> +
> +	pp_on |= port_sel;
> +
> +	intel_de_write(dev_priv, regs.pp_on, pp_on);
> +	intel_de_write(dev_priv, regs.pp_off, pp_off);
> +
> +	/*
> +	 * Compute the divisor for the pp clock, simply match the Bspec formula.
> +	 */
> +	if (i915_mmio_reg_valid(regs.pp_div)) {
> +		intel_de_write(dev_priv, regs.pp_div,
> +			       REG_FIELD_PREP(PP_REFERENCE_DIVIDER_MASK, (100 * div) / 2 - 1) | REG_FIELD_PREP(PANEL_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000)));
> +	} else {
> +		u32 pp_ctl;
> +
> +		pp_ctl = intel_de_read(dev_priv, regs.pp_ctrl);
> +		pp_ctl &= ~BXT_POWER_CYCLE_DELAY_MASK;
> +		pp_ctl |= REG_FIELD_PREP(BXT_POWER_CYCLE_DELAY_MASK, DIV_ROUND_UP(seq->t11_t12, 1000));
> +		intel_de_write(dev_priv, regs.pp_ctrl, pp_ctl);
> +	}
> +
> +	drm_dbg_kms(&dev_priv->drm,
> +		    "panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
> +		    intel_de_read(dev_priv, regs.pp_on),
> +		    intel_de_read(dev_priv, regs.pp_off),
> +		    i915_mmio_reg_valid(regs.pp_div) ?
> +		    intel_de_read(dev_priv, regs.pp_div) :
> +		    (intel_de_read(dev_priv, regs.pp_ctrl) & BXT_POWER_CYCLE_DELAY_MASK));
> +}
> +
> +void intel_dp_pps_init(struct intel_dp *intel_dp)
> +{
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) {
> +		vlv_initial_power_sequencer_setup(intel_dp);
> +	} else {
> +		intel_dp_init_panel_power_sequencer(intel_dp);
> +		intel_dp_init_panel_power_sequencer_registers(intel_dp, false);
> +	}
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
> new file mode 100644
> index 000000000000..76d5cc565501
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_pps.h
> @@ -0,0 +1,53 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#ifndef __INTEL_PPS_H__
> +#define __INTEL_PPS_H__
> +
> +#include <linux/types.h>
> +
> +#include "intel_wakeref.h"
> +
> +struct drm_i915_private;
> +struct intel_connector;
> +struct intel_crtc_state;
> +struct intel_dp;
> +struct intel_encoder;
> +
> +intel_wakeref_t pps_lock(struct intel_dp *intel_dp);
> +intel_wakeref_t pps_unlock(struct intel_dp *intel_dp, intel_wakeref_t wakeref);
> +
> +#define with_pps_lock(dp, wf)						\
> +	for ((wf) = pps_lock(dp); (wf); (wf) = pps_unlock((dp), (wf)))
> +
> +void intel_dp_check_edp(struct intel_dp *intel_dp);
> +void _intel_edp_backlight_on(struct intel_dp *intel_dp);
> +void _intel_edp_backlight_off(struct intel_dp *intel_dp);
> +void intel_edp_backlight_power(struct intel_connector *connector, bool enable);
> +
> +bool edp_panel_vdd_on(struct intel_dp *intel_dp);
> +void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync);
> +void edp_panel_vdd_off_sync(struct intel_dp *intel_dp);
> +void edp_panel_on(struct intel_dp *intel_dp);
> +void edp_panel_off(struct intel_dp *intel_dp);
> +void edp_panel_vdd_work(struct work_struct *__work);
> +
> +void intel_edp_panel_vdd_on(struct intel_dp *intel_dp);
> +void intel_edp_panel_on(struct intel_dp *intel_dp);
> +void intel_edp_panel_off(struct intel_dp *intel_dp);
> +bool intel_edp_have_power(struct intel_dp *intel_dp);
> +
> +void intel_edp_panel_vdd_sanitize(struct intel_dp *intel_dp);
> +
> +void wait_panel_power_cycle(struct intel_dp *intel_dp);
> +
> +void intel_dp_pps_init(struct intel_dp *intel_dp);
> +void intel_power_sequencer_reset(struct drm_i915_private *i915);
> +void intel_dp_init_panel_power_timestamps(struct intel_dp *intel_dp);
> +
> +void vlv_init_panel_power_sequencer(struct intel_encoder *encoder,
> +				    const struct intel_crtc_state *crtc_state);
> +
> +#endif /* __INTEL_PPS_H__ */
> -- 
> 2.20.1
> 
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 13/17] drm/i915/pps: rename intel_dp_init_panel_power_sequencer* functions
  2021-01-13 11:02   ` Anshuman Gupta
@ 2021-01-14  8:31     ` Jani Nikula
  0 siblings, 0 replies; 37+ messages in thread
From: Jani Nikula @ 2021-01-14  8:31 UTC (permalink / raw)
  To: Anshuman Gupta; +Cc: intel-gfx

On Wed, 13 Jan 2021, Anshuman Gupta <anshuman.gupta@intel.com> wrote:
> On 2021-01-08 at 19:44:21 +0200, Jani Nikula wrote:
>> There are a number of functions that "init" pps in various ways. Try to
>> find some more consistency in the naming.
>> 
>> Rename:
>>  - intel_dp_init_panel_power_sequencer -> pps_init_delays
>>  - intel_dp_init_panel_power_sequencer_registers -> pps_init_registers
>>  - intel_dp_init_panel_power_timestamps -> pps_init_timestamps
>> 
>> as this is what the functions do. Skip the intel_ prefix here to
>> emphasize these are static and not exported.
>> 
>> No functional changes.
>> 
>> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> LGTM.
> Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>

Pushed the series up to and including this patch. Many thanks for the
reviews!

BR,
Jani.


-- 
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 14/17] drm/i915/pps: refactor init abstractions
  2021-01-13 11:44   ` Anshuman Gupta
@ 2021-01-14  8:46     ` Jani Nikula
  2021-01-20  4:20       ` Gupta, Anshuman
  0 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2021-01-14  8:46 UTC (permalink / raw)
  To: Anshuman Gupta; +Cc: intel-gfx

On Wed, 13 Jan 2021, Anshuman Gupta <anshuman.gupta@intel.com> wrote:
> On 2021-01-08 at 19:44:22 +0200, Jani Nikula wrote:
>> @@ -1366,20 +1352,21 @@ void intel_pps_encoder_reset(struct intel_dp *intel_dp)
>>  		 * Reinit the power sequencer, in case BIOS did something nasty
> 		IMHO above comment would need a improvement, or nuke it ?
> 		as intel_pps_encoder_reset() will also get called from intel_pps_init()	
> 		unlike only while resuming from suspend.

How about this?

-                * Reinit the power sequencer, in case BIOS did something nasty
-                * with it.
+                * Reinit the power sequencer also on the resume path, in case
+                * BIOS did something nasty with it.


BR,
Jani.


-- 
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 15/17] drm/i915/pps: move pps code over from intel_display.c and refactor
  2021-01-13 11:55   ` Anshuman Gupta
@ 2021-01-14  8:56     ` Jani Nikula
  2021-01-20  4:22       ` Gupta, Anshuman
  0 siblings, 1 reply; 37+ messages in thread
From: Jani Nikula @ 2021-01-14  8:56 UTC (permalink / raw)
  To: Anshuman Gupta; +Cc: intel-gfx

On Wed, 13 Jan 2021, Anshuman Gupta <anshuman.gupta@intel.com> wrote:
> On 2021-01-08 at 19:44:23 +0200, Jani Nikula wrote:
>> intel_display.c has some pps functions that belong to intel_pps.c. Move
>> them over.
>> 
>> While at it, refactor the duplicate intel_pps_init() in intel_display.c
>> into an orthogonal intel_pps_setup() in intel_pps.c, and call it earlier
>> in intel_modeset_init_nogem().
>> 
>> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
>> ---
>>  drivers/gpu/drm/i915/display/intel_display.c | 41 ++------------------
>>  drivers/gpu/drm/i915/display/intel_display.h |  1 -
>>  drivers/gpu/drm/i915/display/intel_pps.c     | 34 ++++++++++++++++
>>  drivers/gpu/drm/i915/display/intel_pps.h     |  3 ++
>>  drivers/gpu/drm/i915/i915_drv.c              |  1 +
>>  5 files changed, 42 insertions(+), 38 deletions(-)
>> 
>> diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c
>> index 0189d379a55e..f8806c4ecb21 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.c
>> +++ b/drivers/gpu/drm/i915/display/intel_display.c
>> @@ -81,6 +81,7 @@
>>  #include "intel_overlay.h"
>>  #include "intel_pipe_crc.h"
>>  #include "intel_pm.h"
>> +#include "intel_pps.h"
>>  #include "intel_psr.h"
>>  #include "intel_quirks.h"
>>  #include "intel_sideband.h"
>> @@ -16100,48 +16101,12 @@ static bool intel_ddi_crt_present(struct drm_i915_private *dev_priv)
>>  	return true;
>>  }
>>  
>> -void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
>> -{
>> -	int pps_num;
>> -	int pps_idx;
>> -
>> -	if (HAS_DDI(dev_priv))
>> -		return;
>> -	/*
>> -	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
>> -	 * everywhere where registers can be write protected.
>> -	 */
>> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>> -		pps_num = 2;
>> -	else
>> -		pps_num = 1;
>> -
>> -	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
>> -		u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx));
>> -
>> -		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
>> -		intel_de_write(dev_priv, PP_CONTROL(pps_idx), val);
>> -	}
>> -}
>> -
>> -static void intel_pps_init(struct drm_i915_private *dev_priv)
>> -{
>> -	if (HAS_PCH_SPLIT(dev_priv) || IS_GEN9_LP(dev_priv))
>> -		dev_priv->pps_mmio_base = PCH_PPS_BASE;
>> -	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>> -		dev_priv->pps_mmio_base = VLV_PPS_BASE;
>> -	else
>> -		dev_priv->pps_mmio_base = PPS_BASE;
>> -
>> -	intel_pps_unlock_regs_wa(dev_priv);
>> -}
>> -
>>  static void intel_setup_outputs(struct drm_i915_private *dev_priv)
>>  {
>>  	struct intel_encoder *encoder;
>>  	bool dpd_is_edp = false;
>>  
>> -	intel_pps_init(dev_priv);
>> +	intel_pps_unlock_regs_wa(dev_priv);
>>  
>>  	if (!HAS_DISPLAY(dev_priv))
>>  		return;
>> @@ -17199,6 +17164,8 @@ int intel_modeset_init_nogem(struct drm_i915_private *i915)
>>  
>>  	intel_panel_sanitize_ssc(i915);
>>  
>> +	intel_pps_setup(i915);
>> +
> This is mmio init, could you please guide me why i915_driver_mmio_probe()
> has not chosen to call intel_pps_setup() ?

Long term the goal is to divide gt and display probe more and more;
there's no clear place in i915_driver_mmio_probe() to stick this. I
certainly don't want to call intel_pps_setup() directly from there.

This is at least close to where gpio_mmio_base gets setup in
intel_gmbus_setup() right below.

BR,
Jani.

>>  	intel_gmbus_setup(i915);
>>  
>>  	drm_dbg_kms(&i915->drm, "%d display pipe%s available.\n",
>> diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h
>> index 7ddbc00a0f41..bbd5dbc61ce9 100644
>> --- a/drivers/gpu/drm/i915/display/intel_display.h
>> +++ b/drivers/gpu/drm/i915/display/intel_display.h
>> @@ -546,7 +546,6 @@ unsigned int intel_rotation_info_size(const struct intel_rotation_info *rot_info
>>  unsigned int intel_remapped_info_size(const struct intel_remapped_info *rem_info);
>>  bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv);
>>  int intel_display_suspend(struct drm_device *dev);
>> -void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);
>>  void intel_encoder_destroy(struct drm_encoder *encoder);
>>  struct drm_display_mode *
>>  intel_encoder_current_mode(struct intel_encoder *encoder);
>> diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c
>> index b4d026ca3313..c3a0fc933500 100644
>> --- a/drivers/gpu/drm/i915/display/intel_pps.c
>> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
>> @@ -1370,3 +1370,37 @@ void intel_pps_init(struct intel_dp *intel_dp)
>>  
>>  	intel_pps_encoder_reset(intel_dp);
>>  }
>> +
>> +void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv)
>> +{
>> +	int pps_num;
>> +	int pps_idx;
>> +
>> +	if (HAS_DDI(dev_priv))
>> +		return;
>> +	/*
>> +	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
>> +	 * everywhere where registers can be write protected.
>> +	 */
>> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
>> +		pps_num = 2;
>> +	else
>> +		pps_num = 1;
>> +
>> +	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
>> +		u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx));
>> +
>> +		val = (val & ~PANEL_UNLOCK_MASK) | PANEL_UNLOCK_REGS;
>> +		intel_de_write(dev_priv, PP_CONTROL(pps_idx), val);
>> +	}
>> +}
>> +
>> +void intel_pps_setup(struct drm_i915_private *i915)
>> +{
>> +	if (HAS_PCH_SPLIT(i915) || IS_GEN9_LP(i915))
>> +		i915->pps_mmio_base = PCH_PPS_BASE;
>> +	else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
>> +		i915->pps_mmio_base = VLV_PPS_BASE;
>> +	else
>> +		i915->pps_mmio_base = PPS_BASE;
>> +}
>> diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h
>> index 22045c5cdc86..fbbcca782e7b 100644
>> --- a/drivers/gpu/drm/i915/display/intel_pps.h
>> +++ b/drivers/gpu/drm/i915/display/intel_pps.h
>> @@ -46,4 +46,7 @@ void intel_pps_reset_all(struct drm_i915_private *i915);
>>  void vlv_pps_init(struct intel_encoder *encoder,
>>  		  const struct intel_crtc_state *crtc_state);
>>  
>> +void intel_pps_unlock_regs_wa(struct drm_i915_private *i915);
>> +void intel_pps_setup(struct drm_i915_private *i915);
>> +
>>  #endif /* __INTEL_PPS_H__ */
>> diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
>> index 3e504247f2da..7282c8f08318 100644
>> --- a/drivers/gpu/drm/i915/i915_drv.c
>> +++ b/drivers/gpu/drm/i915/i915_drv.c
>> @@ -58,6 +58,7 @@
>>  #include "display/intel_hotplug.h"
>>  #include "display/intel_overlay.h"
>>  #include "display/intel_pipe_crc.h"
>> +#include "display/intel_pps.h"
>>  #include "display/intel_sprite.h"
>>  #include "display/intel_vga.h"
>>  
>> -- 
>> 2.20.1
>> 

-- 
Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 14/17] drm/i915/pps: refactor init abstractions
  2021-01-14  8:46     ` Jani Nikula
@ 2021-01-20  4:20       ` Gupta, Anshuman
  0 siblings, 0 replies; 37+ messages in thread
From: Gupta, Anshuman @ 2021-01-20  4:20 UTC (permalink / raw)
  To: Nikula, Jani; +Cc: intel-gfx



> -----Original Message-----
> From: Jani Nikula <jani.nikula@intel.com>
> Sent: Thursday, January 14, 2021 2:16 PM
> To: Gupta, Anshuman <anshuman.gupta@intel.com>
> Cc: intel-gfx@lists.freedesktop.org; ville.syrjala@linux.intel.com
> Subject: Re: [PATCH v2 14/17] drm/i915/pps: refactor init abstractions
> 
> On Wed, 13 Jan 2021, Anshuman Gupta <anshuman.gupta@intel.com>
> wrote:
> > On 2021-01-08 at 19:44:22 +0200, Jani Nikula wrote:
> >> @@ -1366,20 +1352,21 @@ void intel_pps_encoder_reset(struct
> intel_dp *intel_dp)
> >>  		 * Reinit the power sequencer, in case BIOS did something
> nasty
> > 		IMHO above comment would need a improvement, or nuke
> it ?
> > 		as intel_pps_encoder_reset() will also get called from
> intel_pps_init()
> > 		unlike only while resuming from suspend.
> 
> How about this?
> 
> -                * Reinit the power sequencer, in case BIOS did something nasty
> -                * with it.
> +                * Reinit the power sequencer also on the resume path, in case
> +                * BIOS did something nasty with it.
> 
With that comment change.
Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com> 
> 
> BR,
> Jani.
> 
> 
> --
> Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 15/17] drm/i915/pps: move pps code over from intel_display.c and refactor
  2021-01-14  8:56     ` Jani Nikula
@ 2021-01-20  4:22       ` Gupta, Anshuman
  0 siblings, 0 replies; 37+ messages in thread
From: Gupta, Anshuman @ 2021-01-20  4:22 UTC (permalink / raw)
  To: Nikula, Jani; +Cc: intel-gfx



> -----Original Message-----
> From: Jani Nikula <jani.nikula@intel.com>
> Sent: Thursday, January 14, 2021 2:27 PM
> To: Gupta, Anshuman <anshuman.gupta@intel.com>
> Cc: intel-gfx@lists.freedesktop.org; ville.syrjala@linux.intel.com
> Subject: Re: [PATCH v2 15/17] drm/i915/pps: move pps code over from
> intel_display.c and refactor
> 
> On Wed, 13 Jan 2021, Anshuman Gupta <anshuman.gupta@intel.com>
> wrote:
> > On 2021-01-08 at 19:44:23 +0200, Jani Nikula wrote:
> >> intel_display.c has some pps functions that belong to intel_pps.c.
> >> Move them over.
> >>
> >> While at it, refactor the duplicate intel_pps_init() in
> >> intel_display.c into an orthogonal intel_pps_setup() in intel_pps.c,
> >> and call it earlier in intel_modeset_init_nogem().
> >>
> >> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> >> ---
> >>  drivers/gpu/drm/i915/display/intel_display.c | 41
> >> ++------------------  drivers/gpu/drm/i915/display/intel_display.h |  1 -
> >>  drivers/gpu/drm/i915/display/intel_pps.c     | 34 ++++++++++++++++
> >>  drivers/gpu/drm/i915/display/intel_pps.h     |  3 ++
> >>  drivers/gpu/drm/i915/i915_drv.c              |  1 +
> >>  5 files changed, 42 insertions(+), 38 deletions(-)
> >>
> >> diff --git a/drivers/gpu/drm/i915/display/intel_display.c
> >> b/drivers/gpu/drm/i915/display/intel_display.c
> >> index 0189d379a55e..f8806c4ecb21 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_display.c
> >> +++ b/drivers/gpu/drm/i915/display/intel_display.c
> >> @@ -81,6 +81,7 @@
> >>  #include "intel_overlay.h"
> >>  #include "intel_pipe_crc.h"
> >>  #include "intel_pm.h"
> >> +#include "intel_pps.h"
> >>  #include "intel_psr.h"
> >>  #include "intel_quirks.h"
> >>  #include "intel_sideband.h"
> >> @@ -16100,48 +16101,12 @@ static bool intel_ddi_crt_present(struct
> drm_i915_private *dev_priv)
> >>  	return true;
> >>  }
> >>
> >> -void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv) -{
> >> -	int pps_num;
> >> -	int pps_idx;
> >> -
> >> -	if (HAS_DDI(dev_priv))
> >> -		return;
> >> -	/*
> >> -	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
> >> -	 * everywhere where registers can be write protected.
> >> -	 */
> >> -	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> >> -		pps_num = 2;
> >> -	else
> >> -		pps_num = 1;
> >> -
> >> -	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
> >> -		u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx));
> >> -
> >> -		val = (val & ~PANEL_UNLOCK_MASK) |
> PANEL_UNLOCK_REGS;
> >> -		intel_de_write(dev_priv, PP_CONTROL(pps_idx), val);
> >> -	}
> >> -}
> >> -
> >> -static void intel_pps_init(struct drm_i915_private *dev_priv) -{
> >> -	if (HAS_PCH_SPLIT(dev_priv) || IS_GEN9_LP(dev_priv))
> >> -		dev_priv->pps_mmio_base = PCH_PPS_BASE;
> >> -	else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> >> -		dev_priv->pps_mmio_base = VLV_PPS_BASE;
> >> -	else
> >> -		dev_priv->pps_mmio_base = PPS_BASE;
> >> -
> >> -	intel_pps_unlock_regs_wa(dev_priv);
> >> -}
> >> -
> >>  static void intel_setup_outputs(struct drm_i915_private *dev_priv)
> >> {
> >>  	struct intel_encoder *encoder;
> >>  	bool dpd_is_edp = false;
> >>
> >> -	intel_pps_init(dev_priv);
> >> +	intel_pps_unlock_regs_wa(dev_priv);
> >>
> >>  	if (!HAS_DISPLAY(dev_priv))
> >>  		return;
> >> @@ -17199,6 +17164,8 @@ int intel_modeset_init_nogem(struct
> >> drm_i915_private *i915)
> >>
> >>  	intel_panel_sanitize_ssc(i915);
> >>
> >> +	intel_pps_setup(i915);
> >> +
> > This is mmio init, could you please guide me why
> > i915_driver_mmio_probe() has not chosen to call intel_pps_setup() ?
> 
> Long term the goal is to divide gt and display probe more and more; there's
> no clear place in i915_driver_mmio_probe() to stick this. I certainly don't
> want to call intel_pps_setup() directly from there.
> 
> This is at least close to where gpio_mmio_base gets setup in
> intel_gmbus_setup() right below.
Looks good to me.
Reviewed-by: Anshuman Gupta <anshuman.gupta@intel.com>
> 
> BR,
> Jani.
> 
> >>  	intel_gmbus_setup(i915);
> >>
> >>  	drm_dbg_kms(&i915->drm, "%d display pipe%s available.\n", diff
> >> --git a/drivers/gpu/drm/i915/display/intel_display.h
> >> b/drivers/gpu/drm/i915/display/intel_display.h
> >> index 7ddbc00a0f41..bbd5dbc61ce9 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_display.h
> >> +++ b/drivers/gpu/drm/i915/display/intel_display.h
> >> @@ -546,7 +546,6 @@ unsigned int intel_rotation_info_size(const
> >> struct intel_rotation_info *rot_info  unsigned int
> >> intel_remapped_info_size(const struct intel_remapped_info
> *rem_info);
> >> bool intel_has_pending_fb_unpin(struct drm_i915_private *dev_priv);
> >> int intel_display_suspend(struct drm_device *dev); -void
> >> intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv);  void
> >> intel_encoder_destroy(struct drm_encoder *encoder);  struct
> >> drm_display_mode *  intel_encoder_current_mode(struct
> intel_encoder
> >> *encoder); diff --git a/drivers/gpu/drm/i915/display/intel_pps.c
> >> b/drivers/gpu/drm/i915/display/intel_pps.c
> >> index b4d026ca3313..c3a0fc933500 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_pps.c
> >> +++ b/drivers/gpu/drm/i915/display/intel_pps.c
> >> @@ -1370,3 +1370,37 @@ void intel_pps_init(struct intel_dp
> *intel_dp)
> >>
> >>  	intel_pps_encoder_reset(intel_dp);
> >>  }
> >> +
> >> +void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv) {
> >> +	int pps_num;
> >> +	int pps_idx;
> >> +
> >> +	if (HAS_DDI(dev_priv))
> >> +		return;
> >> +	/*
> >> +	 * This w/a is needed at least on CPT/PPT, but to be sure apply it
> >> +	 * everywhere where registers can be write protected.
> >> +	 */
> >> +	if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
> >> +		pps_num = 2;
> >> +	else
> >> +		pps_num = 1;
> >> +
> >> +	for (pps_idx = 0; pps_idx < pps_num; pps_idx++) {
> >> +		u32 val = intel_de_read(dev_priv, PP_CONTROL(pps_idx));
> >> +
> >> +		val = (val & ~PANEL_UNLOCK_MASK) |
> PANEL_UNLOCK_REGS;
> >> +		intel_de_write(dev_priv, PP_CONTROL(pps_idx), val);
> >> +	}
> >> +}
> >> +
> >> +void intel_pps_setup(struct drm_i915_private *i915) {
> >> +	if (HAS_PCH_SPLIT(i915) || IS_GEN9_LP(i915))
> >> +		i915->pps_mmio_base = PCH_PPS_BASE;
> >> +	else if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
> >> +		i915->pps_mmio_base = VLV_PPS_BASE;
> >> +	else
> >> +		i915->pps_mmio_base = PPS_BASE;
> >> +}
> >> diff --git a/drivers/gpu/drm/i915/display/intel_pps.h
> >> b/drivers/gpu/drm/i915/display/intel_pps.h
> >> index 22045c5cdc86..fbbcca782e7b 100644
> >> --- a/drivers/gpu/drm/i915/display/intel_pps.h
> >> +++ b/drivers/gpu/drm/i915/display/intel_pps.h
> >> @@ -46,4 +46,7 @@ void intel_pps_reset_all(struct drm_i915_private
> >> *i915);  void vlv_pps_init(struct intel_encoder *encoder,
> >>  		  const struct intel_crtc_state *crtc_state);
> >>
> >> +void intel_pps_unlock_regs_wa(struct drm_i915_private *i915); void
> >> +intel_pps_setup(struct drm_i915_private *i915);
> >> +
> >>  #endif /* __INTEL_PPS_H__ */
> >> diff --git a/drivers/gpu/drm/i915/i915_drv.c
> >> b/drivers/gpu/drm/i915/i915_drv.c index
> 3e504247f2da..7282c8f08318
> >> 100644
> >> --- a/drivers/gpu/drm/i915/i915_drv.c
> >> +++ b/drivers/gpu/drm/i915/i915_drv.c
> >> @@ -58,6 +58,7 @@
> >>  #include "display/intel_hotplug.h"
> >>  #include "display/intel_overlay.h"
> >>  #include "display/intel_pipe_crc.h"
> >> +#include "display/intel_pps.h"
> >>  #include "display/intel_sprite.h"
> >>  #include "display/intel_vga.h"
> >>
> >> --
> >> 2.20.1
> >>
> 
> --
> Jani Nikula, Intel Open Source Graphics Center
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Intel-gfx] [PATCH v2 17/17] drm/i915/dp: split out aux functionality to intel_dp_aux.c
  2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 17/17] drm/i915/dp: split out aux functionality to intel_dp_aux.c Jani Nikula
@ 2021-01-20  4:44   ` Gupta, Anshuman
  0 siblings, 0 replies; 37+ messages in thread
From: Gupta, Anshuman @ 2021-01-20  4:44 UTC (permalink / raw)
  To: Nikula, Jani, intel-gfx; +Cc: Nikula, Jani



> -----Original Message-----
> From: Jani Nikula <jani.nikula@intel.com>
> Sent: Friday, January 8, 2021 11:14 PM
> To: intel-gfx@lists.freedesktop.org
> Cc: Nikula, Jani <jani.nikula@intel.com>; Gupta, Anshuman
> <anshuman.gupta@intel.com>; ville.syrjala@linux.intel.com
> Subject: [PATCH v2 17/17] drm/i915/dp: split out aux functionality to
> intel_dp_aux.c
> 
> Split out the DP aux functionality to a new intel_dp_aux.[ch]. This is a
> surprisingly clean cut.
> 
> Signed-off-by: Jani Nikula <jani.nikula@intel.com>
> ---
>  drivers/gpu/drm/i915/Makefile               |   1 +
>  drivers/gpu/drm/i915/display/intel_dp.c     | 680 +------------------
>  drivers/gpu/drm/i915/display/intel_dp_aux.c | 687
> ++++++++++++++++++++  drivers/gpu/drm/i915/display/intel_dp_aux.h |
> 18 +
>  4 files changed, 707 insertions(+), 679 deletions(-)  create mode 100644
> drivers/gpu/drm/i915/display/intel_dp_aux.c
>  create mode 100644 drivers/gpu/drm/i915/display/intel_dp_aux.h
> 
> diff --git a/drivers/gpu/drm/i915/Makefile
> b/drivers/gpu/drm/i915/Makefile index 8a04403a11bb..71df8cbd63bc
> 100644
> --- a/drivers/gpu/drm/i915/Makefile
> +++ b/drivers/gpu/drm/i915/Makefile
> @@ -238,6 +238,7 @@ i915-y += \
>  	display/intel_crt.o \
>  	display/intel_ddi.o \
>  	display/intel_dp.o \
> +	display/intel_dp_aux.o \
>  	display/intel_dp_aux_backlight.o \
>  	display/intel_dp_hdcp.o \
>  	display/intel_dp_link_training.o \
> diff --git a/drivers/gpu/drm/i915/display/intel_dp.c
> b/drivers/gpu/drm/i915/display/intel_dp.c
> index e6859b9925b9..1705d58bf64c 100644
> --- a/drivers/gpu/drm/i915/display/intel_dp.c
> +++ b/drivers/gpu/drm/i915/display/intel_dp.c
> @@ -41,13 +41,13 @@
> 
>  #include "i915_debugfs.h"
>  #include "i915_drv.h"
> -#include "i915_trace.h"
>  #include "intel_atomic.h"
>  #include "intel_audio.h"
>  #include "intel_connector.h"
>  #include "intel_ddi.h"
>  #include "intel_display_types.h"
>  #include "intel_dp.h"
> +#include "intel_dp_aux.h"
>  #include "intel_dp_link_training.h"
>  #include "intel_dp_mst.h"
>  #include "intel_dpio_phy.h"
> @@ -856,684 +856,6 @@ intel_dp_mode_valid(struct drm_connector
> *connector,
>  	return intel_mode_valid_max_plane_size(dev_priv, mode,
> bigjoiner);  }
> 
> -u32 intel_dp_pack_aux(const u8 *src, int src_bytes) -{
> -	int i;
> -	u32 v = 0;
> -
> -	if (src_bytes > 4)
> -		src_bytes = 4;
> -	for (i = 0; i < src_bytes; i++)
> -		v |= ((u32)src[i]) << ((3 - i) * 8);
> -	return v;
> -}
> -
> -static void intel_dp_unpack_aux(u32 src, u8 *dst, int dst_bytes) -{
> -	int i;
> -	if (dst_bytes > 4)
> -		dst_bytes = 4;
> -	for (i = 0; i < dst_bytes; i++)
> -		dst[i] = src >> ((3-i) * 8);
> -}
> -
> -static u32
> -intel_dp_aux_wait_done(struct intel_dp *intel_dp) -{
> -	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> -	i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
> -	const unsigned int timeout_ms = 10;
> -	u32 status;
> -	bool done;
> -
> -#define C (((status = intel_uncore_read_notrace(&i915->uncore, ch_ctl)) &
> DP_AUX_CH_CTL_SEND_BUSY) == 0)
> -	done = wait_event_timeout(i915->gmbus_wait_queue, C,
> -				  msecs_to_jiffies_timeout(timeout_ms));
> -
> -	/* just trace the final value */
> -	trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);
> -
> -	if (!done)
> -		drm_err(&i915->drm,
> -			"%s: did not complete or timeout within %ums
> (status 0x%08x)\n",
> -			intel_dp->aux.name, timeout_ms, status);
> -#undef C
> -
> -	return status;
> -}
> -
> -static u32 g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int index) -
> {
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -
> -	if (index)
> -		return 0;
> -
> -	/*
> -	 * The clock divider is based off the hrawclk, and would like to run at
> -	 * 2MHz.  So, take the hrawclk value and divide by 2000 and use
> that
> -	 */
> -	return DIV_ROUND_CLOSEST(RUNTIME_INFO(dev_priv)-
> >rawclk_freq, 2000);
> -}
> -
> -static u32 ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int index) -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	u32 freq;
> -
> -	if (index)
> -		return 0;
> -
> -	/*
> -	 * The clock divider is based off the cdclk or PCH rawclk, and would
> -	 * like to run at 2MHz.  So, take the cdclk or PCH rawclk value and
> -	 * divide by 2000 and use that
> -	 */
> -	if (dig_port->aux_ch == AUX_CH_A)
> -		freq = dev_priv->cdclk.hw.cdclk;
> -	else
> -		freq = RUNTIME_INFO(dev_priv)->rawclk_freq;
> -	return DIV_ROUND_CLOSEST(freq, 2000);
> -}
> -
> -static u32 hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int index)
> -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -
> -	if (dig_port->aux_ch != AUX_CH_A && HAS_PCH_LPT_H(dev_priv))
> {
> -		/* Workaround for non-ULT HSW */
> -		switch (index) {
> -		case 0: return 63;
> -		case 1: return 72;
> -		default: return 0;
> -		}
> -	}
> -
> -	return ilk_get_aux_clock_divider(intel_dp, index);
> -}
> -
> -static u32 skl_get_aux_clock_divider(struct intel_dp *intel_dp, int index) -{
> -	/*
> -	 * SKL doesn't need us to program the AUX clock divider (Hardware
> will
> -	 * derive the clock from CDCLK automatically). We still implement
> the
> -	 * get_aux_clock_divider vfunc to plug-in into the existing code.
> -	 */
> -	return index ? 0 : 1;
> -}
> -
> -static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
> -				int send_bytes,
> -				u32 aux_clock_divider)
> -{
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	struct drm_i915_private *dev_priv =
> -			to_i915(dig_port->base.base.dev);
> -	u32 precharge, timeout;
> -
> -	if (IS_GEN(dev_priv, 6))
> -		precharge = 3;
> -	else
> -		precharge = 5;
> -
> -	if (IS_BROADWELL(dev_priv))
> -		timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
> -	else
> -		timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
> -
> -	return DP_AUX_CH_CTL_SEND_BUSY |
> -	       DP_AUX_CH_CTL_DONE |
> -	       DP_AUX_CH_CTL_INTERRUPT |
> -	       DP_AUX_CH_CTL_TIME_OUT_ERROR |
> -	       timeout |
> -	       DP_AUX_CH_CTL_RECEIVE_ERROR |
> -	       (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
> -	       (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
> -	       (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT);
> -}
> -
> -static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
> -				int send_bytes,
> -				u32 unused)
> -{
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	struct drm_i915_private *i915 =
> -			to_i915(dig_port->base.base.dev);
> -	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
> -	u32 ret;
> -
> -	ret = DP_AUX_CH_CTL_SEND_BUSY |
> -	      DP_AUX_CH_CTL_DONE |
> -	      DP_AUX_CH_CTL_INTERRUPT |
> -	      DP_AUX_CH_CTL_TIME_OUT_ERROR |
> -	      DP_AUX_CH_CTL_TIME_OUT_MAX |
> -	      DP_AUX_CH_CTL_RECEIVE_ERROR |
> -	      (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
> -	      DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) |
> -	      DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
> -
> -	if (intel_phy_is_tc(i915, phy) &&
> -	    dig_port->tc_mode == TC_PORT_TBT_ALT)
> -		ret |= DP_AUX_CH_CTL_TBT_IO;
> -
> -	return ret;
> -}
> -
> -static int
> -intel_dp_aux_xfer(struct intel_dp *intel_dp,
> -		  const u8 *send, int send_bytes,
> -		  u8 *recv, int recv_size,
> -		  u32 aux_send_ctl_flags)
> -{
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	struct drm_i915_private *i915 =
> -			to_i915(dig_port->base.base.dev);
> -	struct intel_uncore *uncore = &i915->uncore;
> -	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
> -	bool is_tc_port = intel_phy_is_tc(i915, phy);
> -	i915_reg_t ch_ctl, ch_data[5];
> -	u32 aux_clock_divider;
> -	enum intel_display_power_domain aux_domain;
> -	intel_wakeref_t aux_wakeref;
> -	intel_wakeref_t pps_wakeref;
> -	int i, ret, recv_bytes;
> -	int try, clock = 0;
> -	u32 status;
> -	bool vdd;
> -
> -	ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
> -	for (i = 0; i < ARRAY_SIZE(ch_data); i++)
> -		ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
> -
> -	if (is_tc_port)
> -		intel_tc_port_lock(dig_port);
> -
> -	aux_domain = intel_aux_power_domain(dig_port);
> -
> -	aux_wakeref = intel_display_power_get(i915, aux_domain);
> -	pps_wakeref = intel_pps_lock(intel_dp);
> -
> -	/*
> -	 * We will be called with VDD already enabled for dpcd/edid/oui
> reads.
> -	 * In such cases we want to leave VDD enabled and it's up to upper
> layers
> -	 * to turn it off. But for eg. i2c-dev access we need to turn it on/off
> -	 * ourselves.
> -	 */
> -	vdd = intel_pps_vdd_on_unlocked(intel_dp);
> -
> -	/* dp aux is extremely sensitive to irq latency, hence request the
> -	 * lowest possible wakeup latency and so prevent the cpu from
> going into
> -	 * deep sleep states.
> -	 */
> -	cpu_latency_qos_update_request(&intel_dp->pm_qos, 0);
> -
> -	intel_pps_check_power_unlocked(intel_dp);
> -
> -	/* Try to wait for any previous AUX channel activity */
> -	for (try = 0; try < 3; try++) {
> -		status = intel_uncore_read_notrace(uncore, ch_ctl);
> -		if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
> -			break;
> -		msleep(1);
> -	}
> -	/* just trace the final value */
> -	trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);
> -
> -	if (try == 3) {
> -		const u32 status = intel_uncore_read(uncore, ch_ctl);
> -
> -		if (status != intel_dp->aux_busy_last_status) {
> -			drm_WARN(&i915->drm, 1,
> -				 "%s: not started (status 0x%08x)\n",
> -				 intel_dp->aux.name, status);
> -			intel_dp->aux_busy_last_status = status;
> -		}
> -
> -		ret = -EBUSY;
> -		goto out;
> -	}
> -
> -	/* Only 5 data registers! */
> -	if (drm_WARN_ON(&i915->drm, send_bytes > 20 || recv_size >
> 20)) {
> -		ret = -E2BIG;
> -		goto out;
> -	}
> -
> -	while ((aux_clock_divider = intel_dp-
> >get_aux_clock_divider(intel_dp, clock++))) {
> -		u32 send_ctl = intel_dp->get_aux_send_ctl(intel_dp,
> -							  send_bytes,
> -							  aux_clock_divider);
> -
> -		send_ctl |= aux_send_ctl_flags;
> -
> -		/* Must try at least 3 times according to DP spec */
> -		for (try = 0; try < 5; try++) {
> -			/* Load the send data into the aux channel data
> registers */
> -			for (i = 0; i < send_bytes; i += 4)
> -				intel_uncore_write(uncore,
> -						   ch_data[i >> 2],
> -						   intel_dp_pack_aux(send +
> i,
> -
> send_bytes - i));
> -
> -			/* Send the command and wait for it to complete */
> -			intel_uncore_write(uncore, ch_ctl, send_ctl);
> -
> -			status = intel_dp_aux_wait_done(intel_dp);
> -
> -			/* Clear done status and any errors */
> -			intel_uncore_write(uncore,
> -					   ch_ctl,
> -					   status |
> -					   DP_AUX_CH_CTL_DONE |
> -
> DP_AUX_CH_CTL_TIME_OUT_ERROR |
> -
> DP_AUX_CH_CTL_RECEIVE_ERROR);
> -
> -			/* DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2
> -			 *   400us delay required for errors and timeouts
> -			 *   Timeout errors from the HW already meet this
> -			 *   requirement so skip to next iteration
> -			 */
> -			if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR)
> -				continue;
> -
> -			if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
> -				usleep_range(400, 500);
> -				continue;
> -			}
> -			if (status & DP_AUX_CH_CTL_DONE)
> -				goto done;
> -		}
> -	}
> -
> -	if ((status & DP_AUX_CH_CTL_DONE) == 0) {
> -		drm_err(&i915->drm, "%s: not done (status 0x%08x)\n",
> -			intel_dp->aux.name, status);
> -		ret = -EBUSY;
> -		goto out;
> -	}
> -
> -done:
> -	/* Check for timeout or receive error.
> -	 * Timeouts occur when the sink is not connected
> -	 */
> -	if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
> -		drm_err(&i915->drm, "%s: receive error (status 0x%08x)\n",
> -			intel_dp->aux.name, status);
> -		ret = -EIO;
> -		goto out;
> -	}
> -
> -	/* Timeouts occur when the device isn't connected, so they're
> -	 * "normal" -- don't fill the kernel log with these */
> -	if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
> -		drm_dbg_kms(&i915->drm, "%s: timeout (status
> 0x%08x)\n",
> -			    intel_dp->aux.name, status);
> -		ret = -ETIMEDOUT;
> -		goto out;
> -	}
> -
> -	/* Unload any bytes sent back from the other side */
> -	recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK)
> >>
> -		      DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
> -
> -	/*
> -	 * By BSpec: "Message sizes of 0 or >20 are not allowed."
> -	 * We have no idea of what happened so we return -EBUSY so
> -	 * drm layer takes care for the necessary retries.
> -	 */
> -	if (recv_bytes == 0 || recv_bytes > 20) {
> -		drm_dbg_kms(&i915->drm,
> -			    "%s: Forbidden recv_bytes = %d on aux
> transaction\n",
> -			    intel_dp->aux.name, recv_bytes);
> -		ret = -EBUSY;
> -		goto out;
> -	}
> -
> -	if (recv_bytes > recv_size)
> -		recv_bytes = recv_size;
> -
> -	for (i = 0; i < recv_bytes; i += 4)
> -		intel_dp_unpack_aux(intel_uncore_read(uncore, ch_data[i
> >> 2]),
> -				    recv + i, recv_bytes - i);
> -
> -	ret = recv_bytes;
> -out:
> -	cpu_latency_qos_update_request(&intel_dp->pm_qos,
> PM_QOS_DEFAULT_VALUE);
> -
> -	if (vdd)
> -		intel_pps_vdd_off_unlocked(intel_dp, false);
> -
> -	intel_pps_unlock(intel_dp, pps_wakeref);
> -	intel_display_power_put_async(i915, aux_domain, aux_wakeref);
> -
> -	if (is_tc_port)
> -		intel_tc_port_unlock(dig_port);
> -
> -	return ret;
> -}
> -
> -#define BARE_ADDRESS_SIZE	3
> -#define HEADER_SIZE		(BARE_ADDRESS_SIZE + 1)
> -
> -static void
> -intel_dp_aux_header(u8 txbuf[HEADER_SIZE],
> -		    const struct drm_dp_aux_msg *msg)
> -{
> -	txbuf[0] = (msg->request << 4) | ((msg->address >> 16) & 0xf);
> -	txbuf[1] = (msg->address >> 8) & 0xff;
> -	txbuf[2] = msg->address & 0xff;
> -	txbuf[3] = msg->size - 1;
> -}
> -
> -static u32 intel_dp_aux_xfer_flags(const struct drm_dp_aux_msg *msg) -{
> -	/*
> -	 * If we're trying to send the HDCP Aksv, we need to set a the Aksv
> -	 * select bit to inform the hardware to send the Aksv after our
> header
> -	 * since we can't access that data from software.
> -	 */
> -	if ((msg->request & ~DP_AUX_I2C_MOT) ==
> DP_AUX_NATIVE_WRITE &&
> -	    msg->address == DP_AUX_HDCP_AKSV)
> -		return DP_AUX_CH_CTL_AUX_AKSV_SELECT;
> -
> -	return 0;
> -}
> -
> -static ssize_t
> -intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg
> *msg) -{
> -	struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux);
> -	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> -	u8 txbuf[20], rxbuf[20];
> -	size_t txsize, rxsize;
> -	u32 flags = intel_dp_aux_xfer_flags(msg);
> -	int ret;
> -
> -	intel_dp_aux_header(txbuf, msg);
> -
> -	switch (msg->request & ~DP_AUX_I2C_MOT) {
> -	case DP_AUX_NATIVE_WRITE:
> -	case DP_AUX_I2C_WRITE:
> -	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
> -		txsize = msg->size ? HEADER_SIZE + msg->size :
> BARE_ADDRESS_SIZE;
> -		rxsize = 2; /* 0 or 1 data bytes */
> -
> -		if (drm_WARN_ON(&i915->drm, txsize > 20))
> -			return -E2BIG;
> -
> -		drm_WARN_ON(&i915->drm, !msg->buffer != !msg->size);
> -
> -		if (msg->buffer)
> -			memcpy(txbuf + HEADER_SIZE, msg->buffer, msg-
> >size);
> -
> -		ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize,
> -					rxbuf, rxsize, flags);
> -		if (ret > 0) {
> -			msg->reply = rxbuf[0] >> 4;
> -
> -			if (ret > 1) {
> -				/* Number of bytes written in a short write.
> */
> -				ret = clamp_t(int, rxbuf[1], 0, msg->size);
> -			} else {
> -				/* Return payload size. */
> -				ret = msg->size;
> -			}
> -		}
> -		break;
> -
> -	case DP_AUX_NATIVE_READ:
> -	case DP_AUX_I2C_READ:
> -		txsize = msg->size ? HEADER_SIZE : BARE_ADDRESS_SIZE;
> -		rxsize = msg->size + 1;
> -
> -		if (drm_WARN_ON(&i915->drm, rxsize > 20))
> -			return -E2BIG;
> -
> -		ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize,
> -					rxbuf, rxsize, flags);
> -		if (ret > 0) {
> -			msg->reply = rxbuf[0] >> 4;
> -			/*
> -			 * Assume happy day, and copy the data. The caller
> is
> -			 * expected to check msg->reply before touching it.
> -			 *
> -			 * Return payload size.
> -			 */
> -			ret--;
> -			memcpy(msg->buffer, rxbuf + 1, ret);
> -		}
> -		break;
> -
> -	default:
> -		ret = -EINVAL;
> -		break;
> -	}
> -
> -	return ret;
> -}
> -
> -
> -static i915_reg_t g4x_aux_ctl_reg(struct intel_dp *intel_dp) -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum aux_ch aux_ch = dig_port->aux_ch;
> -
> -	switch (aux_ch) {
> -	case AUX_CH_B:
> -	case AUX_CH_C:
> -	case AUX_CH_D:
> -		return DP_AUX_CH_CTL(aux_ch);
> -	default:
> -		MISSING_CASE(aux_ch);
> -		return DP_AUX_CH_CTL(AUX_CH_B);
> -	}
> -}
> -
> -static i915_reg_t g4x_aux_data_reg(struct intel_dp *intel_dp, int index) -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum aux_ch aux_ch = dig_port->aux_ch;
> -
> -	switch (aux_ch) {
> -	case AUX_CH_B:
> -	case AUX_CH_C:
> -	case AUX_CH_D:
> -		return DP_AUX_CH_DATA(aux_ch, index);
> -	default:
> -		MISSING_CASE(aux_ch);
> -		return DP_AUX_CH_DATA(AUX_CH_B, index);
> -	}
> -}
> -
> -static i915_reg_t ilk_aux_ctl_reg(struct intel_dp *intel_dp) -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum aux_ch aux_ch = dig_port->aux_ch;
> -
> -	switch (aux_ch) {
> -	case AUX_CH_A:
> -		return DP_AUX_CH_CTL(aux_ch);
> -	case AUX_CH_B:
> -	case AUX_CH_C:
> -	case AUX_CH_D:
> -		return PCH_DP_AUX_CH_CTL(aux_ch);
> -	default:
> -		MISSING_CASE(aux_ch);
> -		return DP_AUX_CH_CTL(AUX_CH_A);
> -	}
> -}
> -
> -static i915_reg_t ilk_aux_data_reg(struct intel_dp *intel_dp, int index) -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum aux_ch aux_ch = dig_port->aux_ch;
> -
> -	switch (aux_ch) {
> -	case AUX_CH_A:
> -		return DP_AUX_CH_DATA(aux_ch, index);
> -	case AUX_CH_B:
> -	case AUX_CH_C:
> -	case AUX_CH_D:
> -		return PCH_DP_AUX_CH_DATA(aux_ch, index);
> -	default:
> -		MISSING_CASE(aux_ch);
> -		return DP_AUX_CH_DATA(AUX_CH_A, index);
> -	}
> -}
> -
> -static i915_reg_t skl_aux_ctl_reg(struct intel_dp *intel_dp) -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum aux_ch aux_ch = dig_port->aux_ch;
> -
> -	switch (aux_ch) {
> -	case AUX_CH_A:
> -	case AUX_CH_B:
> -	case AUX_CH_C:
> -	case AUX_CH_D:
> -	case AUX_CH_E:
> -	case AUX_CH_F:
> -		return DP_AUX_CH_CTL(aux_ch);
> -	default:
> -		MISSING_CASE(aux_ch);
> -		return DP_AUX_CH_CTL(AUX_CH_A);
> -	}
> -}
> -
> -static i915_reg_t skl_aux_data_reg(struct intel_dp *intel_dp, int index) -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum aux_ch aux_ch = dig_port->aux_ch;
> -
> -	switch (aux_ch) {
> -	case AUX_CH_A:
> -	case AUX_CH_B:
> -	case AUX_CH_C:
> -	case AUX_CH_D:
> -	case AUX_CH_E:
> -	case AUX_CH_F:
> -		return DP_AUX_CH_DATA(aux_ch, index);
> -	default:
> -		MISSING_CASE(aux_ch);
> -		return DP_AUX_CH_DATA(AUX_CH_A, index);
> -	}
> -}
> -
> -static i915_reg_t tgl_aux_ctl_reg(struct intel_dp *intel_dp) -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum aux_ch aux_ch = dig_port->aux_ch;
> -
> -	switch (aux_ch) {
> -	case AUX_CH_A:
> -	case AUX_CH_B:
> -	case AUX_CH_C:
> -	case AUX_CH_USBC1:
> -	case AUX_CH_USBC2:
> -	case AUX_CH_USBC3:
> -	case AUX_CH_USBC4:
> -	case AUX_CH_USBC5:
> -	case AUX_CH_USBC6:
> -		return DP_AUX_CH_CTL(aux_ch);
> -	default:
> -		MISSING_CASE(aux_ch);
> -		return DP_AUX_CH_CTL(AUX_CH_A);
> -	}
> -}
> -
> -static i915_reg_t tgl_aux_data_reg(struct intel_dp *intel_dp, int index) -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	enum aux_ch aux_ch = dig_port->aux_ch;
> -
> -	switch (aux_ch) {
> -	case AUX_CH_A:
> -	case AUX_CH_B:
> -	case AUX_CH_C:
> -	case AUX_CH_USBC1:
> -	case AUX_CH_USBC2:
> -	case AUX_CH_USBC3:
> -	case AUX_CH_USBC4:
> -	case AUX_CH_USBC5:
> -	case AUX_CH_USBC6:
> -		return DP_AUX_CH_DATA(aux_ch, index);
> -	default:
> -		MISSING_CASE(aux_ch);
> -		return DP_AUX_CH_DATA(AUX_CH_A, index);
> -	}
> -}
> -
> -static void
> -intel_dp_aux_fini(struct intel_dp *intel_dp) -{
> -	if (cpu_latency_qos_request_active(&intel_dp->pm_qos))
> -		cpu_latency_qos_remove_request(&intel_dp->pm_qos);
> -
> -	kfree(intel_dp->aux.name);
> -}
> -
> -static void
> -intel_dp_aux_init(struct intel_dp *intel_dp) -{
> -	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> -	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> -	struct intel_encoder *encoder = &dig_port->base;
> -	enum aux_ch aux_ch = dig_port->aux_ch;
> -
> -	if (INTEL_GEN(dev_priv) >= 12) {
> -		intel_dp->aux_ch_ctl_reg = tgl_aux_ctl_reg;
> -		intel_dp->aux_ch_data_reg = tgl_aux_data_reg;
> -	} else if (INTEL_GEN(dev_priv) >= 9) {
> -		intel_dp->aux_ch_ctl_reg = skl_aux_ctl_reg;
> -		intel_dp->aux_ch_data_reg = skl_aux_data_reg;
> -	} else if (HAS_PCH_SPLIT(dev_priv)) {
> -		intel_dp->aux_ch_ctl_reg = ilk_aux_ctl_reg;
> -		intel_dp->aux_ch_data_reg = ilk_aux_data_reg;
> -	} else {
> -		intel_dp->aux_ch_ctl_reg = g4x_aux_ctl_reg;
> -		intel_dp->aux_ch_data_reg = g4x_aux_data_reg;
> -	}
> -
> -	if (INTEL_GEN(dev_priv) >= 9)
> -		intel_dp->get_aux_clock_divider =
> skl_get_aux_clock_divider;
> -	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
> -		intel_dp->get_aux_clock_divider =
> hsw_get_aux_clock_divider;
> -	else if (HAS_PCH_SPLIT(dev_priv))
> -		intel_dp->get_aux_clock_divider =
> ilk_get_aux_clock_divider;
> -	else
> -		intel_dp->get_aux_clock_divider =
> g4x_get_aux_clock_divider;
> -
> -	if (INTEL_GEN(dev_priv) >= 9)
> -		intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
> -	else
> -		intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
> -
> -	drm_dp_aux_init(&intel_dp->aux);
> -
> -	/* Failure to allocate our preferred name is not critical */
> -	if (INTEL_GEN(dev_priv) >= 12 && aux_ch >= AUX_CH_USBC1)
> -		intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX
> USBC%c/%s",
> -					       aux_ch - AUX_CH_USBC1 + '1',
> -					       encoder->base.name);
> -	else
> -		intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %c/%s",
> -					       aux_ch_name(aux_ch),
> -					       encoder->base.name);
> -
> -	intel_dp->aux.transfer = intel_dp_aux_transfer;
> -	cpu_latency_qos_add_request(&intel_dp->pm_qos,
> PM_QOS_DEFAULT_VALUE);
> -}
> -
>  bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp)  {
>  	int max_rate = intel_dp->source_rates[intel_dp-
> >num_source_rates - 1]; diff --git
> a/drivers/gpu/drm/i915/display/intel_dp_aux.c
> b/drivers/gpu/drm/i915/display/intel_dp_aux.c
> new file mode 100644
> index 000000000000..3d96ab5851df
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.c
> @@ -0,0 +1,687 @@
> +// SPDX-License-Identifier: MIT
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#include "i915_drv.h"
> +#include "i915_trace.h"
> +#include "intel_display_types.h"
> +#include "intel_dp_aux.h"
> +#include "intel_pps.h"
> +#include "intel_tc.h"
> +
> +u32 intel_dp_pack_aux(const u8 *src, int src_bytes) {
> +	int i;
> +	u32 v = 0;
> +
> +	if (src_bytes > 4)
> +		src_bytes = 4;
> +	for (i = 0; i < src_bytes; i++)
> +		v |= ((u32)src[i]) << ((3 - i) * 8);
> +	return v;
> +}
> +
> +static void intel_dp_unpack_aux(u32 src, u8 *dst, int dst_bytes) {
> +	int i;
> +	if (dst_bytes > 4)
> +		dst_bytes = 4;
> +	for (i = 0; i < dst_bytes; i++)
> +		dst[i] = src >> ((3-i) * 8);
> +}
> +
> +static u32
> +intel_dp_aux_wait_done(struct intel_dp *intel_dp) {
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +	i915_reg_t ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
> +	const unsigned int timeout_ms = 10;
> +	u32 status;
> +	bool done;
> +
> +#define C (((status = intel_uncore_read_notrace(&i915->uncore, ch_ctl)) &
> DP_AUX_CH_CTL_SEND_BUSY) == 0)
> +	done = wait_event_timeout(i915->gmbus_wait_queue, C,
> +				  msecs_to_jiffies_timeout(timeout_ms));
> +
> +	/* just trace the final value */
> +	trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);
> +
> +	if (!done)
> +		drm_err(&i915->drm,
> +			"%s: did not complete or timeout within %ums
> (status 0x%08x)\n",
> +			intel_dp->aux.name, timeout_ms, status); #undef C
> +
> +	return status;
> +}
> +
> +static u32 g4x_get_aux_clock_divider(struct intel_dp *intel_dp, int
> +index) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +
> +	if (index)
> +		return 0;
> +
> +	/*
> +	 * The clock divider is based off the hrawclk, and would like to run at
> +	 * 2MHz.  So, take the hrawclk value and divide by 2000 and use
> that
> +	 */
> +	return DIV_ROUND_CLOSEST(RUNTIME_INFO(dev_priv)-
> >rawclk_freq, 2000); }
> +
> +static u32 ilk_get_aux_clock_divider(struct intel_dp *intel_dp, int
> +index) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	u32 freq;
> +
> +	if (index)
> +		return 0;
> +
> +	/*
> +	 * The clock divider is based off the cdclk or PCH rawclk, and would
> +	 * like to run at 2MHz.  So, take the cdclk or PCH rawclk value and
> +	 * divide by 2000 and use that
> +	 */
> +	if (dig_port->aux_ch == AUX_CH_A)
> +		freq = dev_priv->cdclk.hw.cdclk;
> +	else
> +		freq = RUNTIME_INFO(dev_priv)->rawclk_freq;
> +	return DIV_ROUND_CLOSEST(freq, 2000);
> +}
> +
> +static u32 hsw_get_aux_clock_divider(struct intel_dp *intel_dp, int
> +index) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +
> +	if (dig_port->aux_ch != AUX_CH_A && HAS_PCH_LPT_H(dev_priv))
> {
> +		/* Workaround for non-ULT HSW */
> +		switch (index) {
> +		case 0: return 63;
> +		case 1: return 72;
> +		default: return 0;
> +		}
> +	}
> +
> +	return ilk_get_aux_clock_divider(intel_dp, index); }
> +
> +static u32 skl_get_aux_clock_divider(struct intel_dp *intel_dp, int
> +index) {
> +	/*
> +	 * SKL doesn't need us to program the AUX clock divider (Hardware
> will
> +	 * derive the clock from CDCLK automatically). We still implement
> the
> +	 * get_aux_clock_divider vfunc to plug-in into the existing code.
> +	 */
> +	return index ? 0 : 1;
> +}
> +
> +static u32 g4x_get_aux_send_ctl(struct intel_dp *intel_dp,
> +				int send_bytes,
> +				u32 aux_clock_divider)
> +{
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	struct drm_i915_private *dev_priv =
> +			to_i915(dig_port->base.base.dev);
> +	u32 precharge, timeout;
> +
> +	if (IS_GEN(dev_priv, 6))
> +		precharge = 3;
> +	else
> +		precharge = 5;
> +
> +	if (IS_BROADWELL(dev_priv))
> +		timeout = DP_AUX_CH_CTL_TIME_OUT_600us;
> +	else
> +		timeout = DP_AUX_CH_CTL_TIME_OUT_400us;
> +
> +	return DP_AUX_CH_CTL_SEND_BUSY |
> +	       DP_AUX_CH_CTL_DONE |
> +	       DP_AUX_CH_CTL_INTERRUPT |
> +	       DP_AUX_CH_CTL_TIME_OUT_ERROR |
> +	       timeout |
> +	       DP_AUX_CH_CTL_RECEIVE_ERROR |
> +	       (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
> +	       (precharge << DP_AUX_CH_CTL_PRECHARGE_2US_SHIFT) |
> +	       (aux_clock_divider << DP_AUX_CH_CTL_BIT_CLOCK_2X_SHIFT);
> +}
> +
> +static u32 skl_get_aux_send_ctl(struct intel_dp *intel_dp,
> +				int send_bytes,
> +				u32 unused)
> +{
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	struct drm_i915_private *i915 =
> +			to_i915(dig_port->base.base.dev);
> +	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
> +	u32 ret;
> +
> +	ret = DP_AUX_CH_CTL_SEND_BUSY |
> +	      DP_AUX_CH_CTL_DONE |
> +	      DP_AUX_CH_CTL_INTERRUPT |
> +	      DP_AUX_CH_CTL_TIME_OUT_ERROR |
> +	      DP_AUX_CH_CTL_TIME_OUT_MAX |
> +	      DP_AUX_CH_CTL_RECEIVE_ERROR |
> +	      (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) |
> +	      DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) |
> +	      DP_AUX_CH_CTL_SYNC_PULSE_SKL(32);
> +
> +	if (intel_phy_is_tc(i915, phy) &&
> +	    dig_port->tc_mode == TC_PORT_TBT_ALT)
> +		ret |= DP_AUX_CH_CTL_TBT_IO;
> +
> +	return ret;
> +}
> +
> +static int
> +intel_dp_aux_xfer(struct intel_dp *intel_dp,
> +		  const u8 *send, int send_bytes,
> +		  u8 *recv, int recv_size,
> +		  u32 aux_send_ctl_flags)
> +{
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	struct drm_i915_private *i915 =
> +			to_i915(dig_port->base.base.dev);
> +	struct intel_uncore *uncore = &i915->uncore;
> +	enum phy phy = intel_port_to_phy(i915, dig_port->base.port);
> +	bool is_tc_port = intel_phy_is_tc(i915, phy);
> +	i915_reg_t ch_ctl, ch_data[5];
> +	u32 aux_clock_divider;
> +	enum intel_display_power_domain aux_domain;
> +	intel_wakeref_t aux_wakeref;
> +	intel_wakeref_t pps_wakeref;
> +	int i, ret, recv_bytes;
> +	int try, clock = 0;
> +	u32 status;
> +	bool vdd;
> +
> +	ch_ctl = intel_dp->aux_ch_ctl_reg(intel_dp);
> +	for (i = 0; i < ARRAY_SIZE(ch_data); i++)
> +		ch_data[i] = intel_dp->aux_ch_data_reg(intel_dp, i);
> +
> +	if (is_tc_port)
> +		intel_tc_port_lock(dig_port);
> +
> +	aux_domain = intel_aux_power_domain(dig_port);
> +
> +	aux_wakeref = intel_display_power_get(i915, aux_domain);
> +	pps_wakeref = intel_pps_lock(intel_dp);
> +
> +	/*
> +	 * We will be called with VDD already enabled for dpcd/edid/oui
> reads.
> +	 * In such cases we want to leave VDD enabled and it's up to upper
> layers
> +	 * to turn it off. But for eg. i2c-dev access we need to turn it on/off
> +	 * ourselves.
> +	 */
> +	vdd = intel_pps_vdd_on_unlocked(intel_dp);
> +
> +	/* dp aux is extremely sensitive to irq latency, hence request the
> +	 * lowest possible wakeup latency and so prevent the cpu from
> going into
> +	 * deep sleep states.
> +	 */
> +	cpu_latency_qos_update_request(&intel_dp->pm_qos, 0);
> +
> +	intel_pps_check_power_unlocked(intel_dp);
> +
> +	/* Try to wait for any previous AUX channel activity */
> +	for (try = 0; try < 3; try++) {
> +		status = intel_uncore_read_notrace(uncore, ch_ctl);
> +		if ((status & DP_AUX_CH_CTL_SEND_BUSY) == 0)
> +			break;
> +		msleep(1);
> +	}
> +	/* just trace the final value */
> +	trace_i915_reg_rw(false, ch_ctl, status, sizeof(status), true);
> +
> +	if (try == 3) {
> +		const u32 status = intel_uncore_read(uncore, ch_ctl);
> +
> +		if (status != intel_dp->aux_busy_last_status) {
> +			drm_WARN(&i915->drm, 1,
> +				 "%s: not started (status 0x%08x)\n",
> +				 intel_dp->aux.name, status);
> +			intel_dp->aux_busy_last_status = status;
> +		}
> +
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +
> +	/* Only 5 data registers! */
> +	if (drm_WARN_ON(&i915->drm, send_bytes > 20 || recv_size >
> 20)) {
> +		ret = -E2BIG;
> +		goto out;
> +	}
> +
> +	while ((aux_clock_divider = intel_dp-
> >get_aux_clock_divider(intel_dp, clock++))) {
> +		u32 send_ctl = intel_dp->get_aux_send_ctl(intel_dp,
> +							  send_bytes,
> +							  aux_clock_divider);
> +
> +		send_ctl |= aux_send_ctl_flags;
> +
> +		/* Must try at least 3 times according to DP spec */
> +		for (try = 0; try < 5; try++) {
> +			/* Load the send data into the aux channel data
> registers */
> +			for (i = 0; i < send_bytes; i += 4)
> +				intel_uncore_write(uncore,
> +						   ch_data[i >> 2],
> +						   intel_dp_pack_aux(send +
> i,
> +
> send_bytes - i));
> +
> +			/* Send the command and wait for it to complete */
> +			intel_uncore_write(uncore, ch_ctl, send_ctl);
> +
> +			status = intel_dp_aux_wait_done(intel_dp);
> +
> +			/* Clear done status and any errors */
> +			intel_uncore_write(uncore,
> +					   ch_ctl,
> +					   status |
> +					   DP_AUX_CH_CTL_DONE |
> +
> DP_AUX_CH_CTL_TIME_OUT_ERROR |
> +
> DP_AUX_CH_CTL_RECEIVE_ERROR);
> +
> +			/* DP CTS 1.2 Core Rev 1.1, 4.2.1.1 & 4.2.1.2
> +			 *   400us delay required for errors and timeouts
> +			 *   Timeout errors from the HW already meet this
> +			 *   requirement so skip to next iteration
> +			 */
> +			if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR)
> +				continue;
> +
> +			if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
> +				usleep_range(400, 500);
> +				continue;
> +			}
> +			if (status & DP_AUX_CH_CTL_DONE)
> +				goto done;
> +		}
> +	}
> +
> +	if ((status & DP_AUX_CH_CTL_DONE) == 0) {
> +		drm_err(&i915->drm, "%s: not done (status 0x%08x)\n",
> +			intel_dp->aux.name, status);
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +
> +done:
> +	/* Check for timeout or receive error.
> +	 * Timeouts occur when the sink is not connected
> +	 */
> +	if (status & DP_AUX_CH_CTL_RECEIVE_ERROR) {
> +		drm_err(&i915->drm, "%s: receive error (status 0x%08x)\n",
> +			intel_dp->aux.name, status);
> +		ret = -EIO;
> +		goto out;
> +	}
> +
> +	/* Timeouts occur when the device isn't connected, so they're
> +	 * "normal" -- don't fill the kernel log with these */
> +	if (status & DP_AUX_CH_CTL_TIME_OUT_ERROR) {
> +		drm_dbg_kms(&i915->drm, "%s: timeout (status
> 0x%08x)\n",
> +			    intel_dp->aux.name, status);
> +		ret = -ETIMEDOUT;
> +		goto out;
> +	}
> +
> +	/* Unload any bytes sent back from the other side */
> +	recv_bytes = ((status & DP_AUX_CH_CTL_MESSAGE_SIZE_MASK)
> >>
> +		      DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT);
> +
> +	/*
> +	 * By BSpec: "Message sizes of 0 or >20 are not allowed."
> +	 * We have no idea of what happened so we return -EBUSY so
> +	 * drm layer takes care for the necessary retries.
> +	 */
> +	if (recv_bytes == 0 || recv_bytes > 20) {
> +		drm_dbg_kms(&i915->drm,
> +			    "%s: Forbidden recv_bytes = %d on aux
> transaction\n",
> +			    intel_dp->aux.name, recv_bytes);
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +
> +	if (recv_bytes > recv_size)
> +		recv_bytes = recv_size;
> +
> +	for (i = 0; i < recv_bytes; i += 4)
> +		intel_dp_unpack_aux(intel_uncore_read(uncore, ch_data[i
> >> 2]),
> +				    recv + i, recv_bytes - i);
> +
> +	ret = recv_bytes;
> +out:
> +	cpu_latency_qos_update_request(&intel_dp->pm_qos,
> +PM_QOS_DEFAULT_VALUE);
> +
> +	if (vdd)
> +		intel_pps_vdd_off_unlocked(intel_dp, false);
> +
> +	intel_pps_unlock(intel_dp, pps_wakeref);
> +	intel_display_power_put_async(i915, aux_domain, aux_wakeref);
> +
> +	if (is_tc_port)
> +		intel_tc_port_unlock(dig_port);
> +
> +	return ret;
> +}
> +
> +#define BARE_ADDRESS_SIZE	3
> +#define HEADER_SIZE		(BARE_ADDRESS_SIZE + 1)
> +
> +static void
> +intel_dp_aux_header(u8 txbuf[HEADER_SIZE],
> +		    const struct drm_dp_aux_msg *msg) {
> +	txbuf[0] = (msg->request << 4) | ((msg->address >> 16) & 0xf);
> +	txbuf[1] = (msg->address >> 8) & 0xff;
> +	txbuf[2] = msg->address & 0xff;
> +	txbuf[3] = msg->size - 1;
> +}
> +
> +static u32 intel_dp_aux_xfer_flags(const struct drm_dp_aux_msg *msg) {
> +	/*
> +	 * If we're trying to send the HDCP Aksv, we need to set a the Aksv
> +	 * select bit to inform the hardware to send the Aksv after our
> header
> +	 * since we can't access that data from software.
> +	 */
> +	if ((msg->request & ~DP_AUX_I2C_MOT) ==
> DP_AUX_NATIVE_WRITE &&
> +	    msg->address == DP_AUX_HDCP_AKSV)
> +		return DP_AUX_CH_CTL_AUX_AKSV_SELECT;
> +
> +	return 0;
> +}
> +
> +static ssize_t
> +intel_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg
> +*msg) {
> +	struct intel_dp *intel_dp = container_of(aux, struct intel_dp, aux);
> +	struct drm_i915_private *i915 = dp_to_i915(intel_dp);
> +	u8 txbuf[20], rxbuf[20];
> +	size_t txsize, rxsize;
> +	u32 flags = intel_dp_aux_xfer_flags(msg);
> +	int ret;
> +
> +	intel_dp_aux_header(txbuf, msg);
> +
> +	switch (msg->request & ~DP_AUX_I2C_MOT) {
> +	case DP_AUX_NATIVE_WRITE:
> +	case DP_AUX_I2C_WRITE:
> +	case DP_AUX_I2C_WRITE_STATUS_UPDATE:
> +		txsize = msg->size ? HEADER_SIZE + msg->size :
> BARE_ADDRESS_SIZE;
> +		rxsize = 2; /* 0 or 1 data bytes */
> +
> +		if (drm_WARN_ON(&i915->drm, txsize > 20))
> +			return -E2BIG;
> +
> +		drm_WARN_ON(&i915->drm, !msg->buffer != !msg->size);
> +
> +		if (msg->buffer)
> +			memcpy(txbuf + HEADER_SIZE, msg->buffer, msg-
> >size);
> +
> +		ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize,
> +					rxbuf, rxsize, flags);
> +		if (ret > 0) {
> +			msg->reply = rxbuf[0] >> 4;
> +
> +			if (ret > 1) {
> +				/* Number of bytes written in a short write.
> */
> +				ret = clamp_t(int, rxbuf[1], 0, msg->size);
> +			} else {
> +				/* Return payload size. */
> +				ret = msg->size;
> +			}
> +		}
> +		break;
> +
> +	case DP_AUX_NATIVE_READ:
> +	case DP_AUX_I2C_READ:
> +		txsize = msg->size ? HEADER_SIZE : BARE_ADDRESS_SIZE;
> +		rxsize = msg->size + 1;
> +
> +		if (drm_WARN_ON(&i915->drm, rxsize > 20))
> +			return -E2BIG;
> +
> +		ret = intel_dp_aux_xfer(intel_dp, txbuf, txsize,
> +					rxbuf, rxsize, flags);
> +		if (ret > 0) {
> +			msg->reply = rxbuf[0] >> 4;
> +			/*
> +			 * Assume happy day, and copy the data. The caller
> is
> +			 * expected to check msg->reply before touching it.
> +			 *
> +			 * Return payload size.
> +			 */
> +			ret--;
> +			memcpy(msg->buffer, rxbuf + 1, ret);
> +		}
> +		break;
> +
> +	default:
> +		ret = -EINVAL;
> +		break;
> +	}
> +
> +	return ret;
> +}
> +
> +
> +static i915_reg_t g4x_aux_ctl_reg(struct intel_dp *intel_dp) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum aux_ch aux_ch = dig_port->aux_ch;
> +
> +	switch (aux_ch) {
> +	case AUX_CH_B:
> +	case AUX_CH_C:
> +	case AUX_CH_D:
> +		return DP_AUX_CH_CTL(aux_ch);
> +	default:
> +		MISSING_CASE(aux_ch);
> +		return DP_AUX_CH_CTL(AUX_CH_B);
> +	}
> +}
> +
> +static i915_reg_t g4x_aux_data_reg(struct intel_dp *intel_dp, int
> +index) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum aux_ch aux_ch = dig_port->aux_ch;
> +
> +	switch (aux_ch) {
> +	case AUX_CH_B:
> +	case AUX_CH_C:
> +	case AUX_CH_D:
> +		return DP_AUX_CH_DATA(aux_ch, index);
> +	default:
> +		MISSING_CASE(aux_ch);
> +		return DP_AUX_CH_DATA(AUX_CH_B, index);
> +	}
> +}
> +
> +static i915_reg_t ilk_aux_ctl_reg(struct intel_dp *intel_dp) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum aux_ch aux_ch = dig_port->aux_ch;
> +
> +	switch (aux_ch) {
> +	case AUX_CH_A:
> +		return DP_AUX_CH_CTL(aux_ch);
> +	case AUX_CH_B:
> +	case AUX_CH_C:
> +	case AUX_CH_D:
> +		return PCH_DP_AUX_CH_CTL(aux_ch);
> +	default:
> +		MISSING_CASE(aux_ch);
> +		return DP_AUX_CH_CTL(AUX_CH_A);
> +	}
> +}
> +
> +static i915_reg_t ilk_aux_data_reg(struct intel_dp *intel_dp, int
> +index) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum aux_ch aux_ch = dig_port->aux_ch;
> +
> +	switch (aux_ch) {
> +	case AUX_CH_A:
> +		return DP_AUX_CH_DATA(aux_ch, index);
> +	case AUX_CH_B:
> +	case AUX_CH_C:
> +	case AUX_CH_D:
> +		return PCH_DP_AUX_CH_DATA(aux_ch, index);
> +	default:
> +		MISSING_CASE(aux_ch);
> +		return DP_AUX_CH_DATA(AUX_CH_A, index);
> +	}
> +}
> +
> +static i915_reg_t skl_aux_ctl_reg(struct intel_dp *intel_dp) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum aux_ch aux_ch = dig_port->aux_ch;
> +
> +	switch (aux_ch) {
> +	case AUX_CH_A:
> +	case AUX_CH_B:
> +	case AUX_CH_C:
> +	case AUX_CH_D:
> +	case AUX_CH_E:
> +	case AUX_CH_F:
> +		return DP_AUX_CH_CTL(aux_ch);
> +	default:
> +		MISSING_CASE(aux_ch);
> +		return DP_AUX_CH_CTL(AUX_CH_A);
> +	}
> +}
> +
> +static i915_reg_t skl_aux_data_reg(struct intel_dp *intel_dp, int
> +index) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum aux_ch aux_ch = dig_port->aux_ch;
> +
> +	switch (aux_ch) {
> +	case AUX_CH_A:
> +	case AUX_CH_B:
> +	case AUX_CH_C:
> +	case AUX_CH_D:
> +	case AUX_CH_E:
> +	case AUX_CH_F:
> +		return DP_AUX_CH_DATA(aux_ch, index);
> +	default:
> +		MISSING_CASE(aux_ch);
> +		return DP_AUX_CH_DATA(AUX_CH_A, index);
> +	}
> +}
> +
> +static i915_reg_t tgl_aux_ctl_reg(struct intel_dp *intel_dp) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum aux_ch aux_ch = dig_port->aux_ch;
> +
> +	switch (aux_ch) {
> +	case AUX_CH_A:
> +	case AUX_CH_B:
> +	case AUX_CH_C:
> +	case AUX_CH_USBC1:
> +	case AUX_CH_USBC2:
> +	case AUX_CH_USBC3:
> +	case AUX_CH_USBC4:
> +	case AUX_CH_USBC5:
> +	case AUX_CH_USBC6:
> +		return DP_AUX_CH_CTL(aux_ch);
> +	default:
> +		MISSING_CASE(aux_ch);
> +		return DP_AUX_CH_CTL(AUX_CH_A);
> +	}
> +}
> +
> +static i915_reg_t tgl_aux_data_reg(struct intel_dp *intel_dp, int
> +index) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	enum aux_ch aux_ch = dig_port->aux_ch;
> +
> +	switch (aux_ch) {
> +	case AUX_CH_A:
> +	case AUX_CH_B:
> +	case AUX_CH_C:
> +	case AUX_CH_USBC1:
> +	case AUX_CH_USBC2:
> +	case AUX_CH_USBC3:
> +	case AUX_CH_USBC4:
> +	case AUX_CH_USBC5:
> +	case AUX_CH_USBC6:
> +		return DP_AUX_CH_DATA(aux_ch, index);
> +	default:
> +		MISSING_CASE(aux_ch);
> +		return DP_AUX_CH_DATA(AUX_CH_A, index);
> +	}
> +}
> +
> +void intel_dp_aux_fini(struct intel_dp *intel_dp) {
> +	if (cpu_latency_qos_request_active(&intel_dp->pm_qos))
> +		cpu_latency_qos_remove_request(&intel_dp->pm_qos);
> +
> +	kfree(intel_dp->aux.name);
> +}
> +
> +void intel_dp_aux_init(struct intel_dp *intel_dp) {
> +	struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
> +	struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
> +	struct intel_encoder *encoder = &dig_port->base;
> +	enum aux_ch aux_ch = dig_port->aux_ch;
> +
> +	if (INTEL_GEN(dev_priv) >= 12) {
> +		intel_dp->aux_ch_ctl_reg = tgl_aux_ctl_reg;
> +		intel_dp->aux_ch_data_reg = tgl_aux_data_reg;
> +	} else if (INTEL_GEN(dev_priv) >= 9) {
> +		intel_dp->aux_ch_ctl_reg = skl_aux_ctl_reg;
> +		intel_dp->aux_ch_data_reg = skl_aux_data_reg;
> +	} else if (HAS_PCH_SPLIT(dev_priv)) {
> +		intel_dp->aux_ch_ctl_reg = ilk_aux_ctl_reg;
> +		intel_dp->aux_ch_data_reg = ilk_aux_data_reg;
> +	} else {
> +		intel_dp->aux_ch_ctl_reg = g4x_aux_ctl_reg;
> +		intel_dp->aux_ch_data_reg = g4x_aux_data_reg;
> +	}
> +
> +	if (INTEL_GEN(dev_priv) >= 9)
> +		intel_dp->get_aux_clock_divider =
> skl_get_aux_clock_divider;
> +	else if (IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))
> +		intel_dp->get_aux_clock_divider =
> hsw_get_aux_clock_divider;
> +	else if (HAS_PCH_SPLIT(dev_priv))
> +		intel_dp->get_aux_clock_divider =
> ilk_get_aux_clock_divider;
> +	else
> +		intel_dp->get_aux_clock_divider =
> g4x_get_aux_clock_divider;
> +
> +	if (INTEL_GEN(dev_priv) >= 9)
> +		intel_dp->get_aux_send_ctl = skl_get_aux_send_ctl;
> +	else
> +		intel_dp->get_aux_send_ctl = g4x_get_aux_send_ctl;
> +
> +	drm_dp_aux_init(&intel_dp->aux);
> +
> +	/* Failure to allocate our preferred name is not critical */
> +	if (INTEL_GEN(dev_priv) >= 12 && aux_ch >= AUX_CH_USBC1)
> +		intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX
> USBC%c/%s",
> +					       aux_ch - AUX_CH_USBC1 + '1',
> +					       encoder->base.name);
> +	else
> +		intel_dp->aux.name = kasprintf(GFP_KERNEL, "AUX %c/%s",
> +					       aux_ch_name(aux_ch),
> +					       encoder->base.name);
> +
> +	intel_dp->aux.transfer = intel_dp_aux_transfer;
> +	cpu_latency_qos_add_request(&intel_dp->pm_qos,
> PM_QOS_DEFAULT_VALUE);
> +}
> diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux.h
> b/drivers/gpu/drm/i915/display/intel_dp_aux.h
> new file mode 100644
> index 000000000000..cea58dd86c49
> --- /dev/null
> +++ b/drivers/gpu/drm/i915/display/intel_dp_aux.h
> @@ -0,0 +1,18 @@
> +/* SPDX-License-Identifier: MIT */
> +/*
> + * Copyright © 2020 Intel Corporation
> + */
> +
> +#ifndef __INTEL_DP_AUX_H__
> +#define __INTEL_DP_AUX_H__
> +
> +#include <linux/types.h>
> +
> +struct intel_dp;
> +
> +u32 intel_dp_pack_aux(const u8 *src, int src_bytes);
This declaration has not removed from intel_dp.h in this patch.
Thanks,
Anshuman Gupta.
> +
> +void intel_dp_aux_fini(struct intel_dp *intel_dp); void
> +intel_dp_aux_init(struct intel_dp *intel_dp);
> +
> +#endif /* __INTEL_DP_AUX_H__ */
> --
> 2.20.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx

^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2021-01-20  4:44 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-08 17:44 [Intel-gfx] [PATCH v2 00/17] drm/i915/dp: split out pps and aux Jani Nikula
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 01/17] drm/i915/pps: abstract panel power sequencer from intel_dp.c Jani Nikula
2021-01-13 15:34   ` Jani Nikula
2021-01-13 16:47   ` Anshuman Gupta
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 02/17] drm/i915/pps: rename pps_{, un}lock -> intel_pps_{, un}lock Jani Nikula
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 03/17] drm/i915/pps: rename intel_edp_backlight_* to intel_pps_backlight_* Jani Nikula
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 04/17] drm/i915/pps: rename intel_edp_panel_* to intel_pps_* Jani Nikula
2021-01-13 10:39   ` Anshuman Gupta
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 05/17] drm/i915/pps: rename edp_panel_* to intel_pps_*_unlocked Jani Nikula
2021-01-13 10:41   ` Anshuman Gupta
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 06/17] drm/i915/pps: abstract intel_pps_vdd_off_sync Jani Nikula
2021-01-13 10:42   ` Anshuman Gupta
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 07/17] drm/i915/pps: add higher level intel_pps_init() call Jani Nikula
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 08/17] drm/i915/pps: abstract intel_pps_encoder_reset() Jani Nikula
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 09/17] drm/i915/pps: rename intel_dp_check_edp to intel_pps_check_power_unlocked Jani Nikula
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 10/17] drm/i915/pps: rename intel_power_sequencer_reset to intel_pps_reset_all Jani Nikula
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 11/17] drm/i915/pps: add locked intel_pps_wait_power_cycle Jani Nikula
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 12/17] drm/i915/pps: rename vlv_init_panel_power_sequencer to vlv_pps_init Jani Nikula
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 13/17] drm/i915/pps: rename intel_dp_init_panel_power_sequencer* functions Jani Nikula
2021-01-13 11:02   ` Anshuman Gupta
2021-01-14  8:31     ` Jani Nikula
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 14/17] drm/i915/pps: refactor init abstractions Jani Nikula
2021-01-13 11:44   ` Anshuman Gupta
2021-01-14  8:46     ` Jani Nikula
2021-01-20  4:20       ` Gupta, Anshuman
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 15/17] drm/i915/pps: move pps code over from intel_display.c and refactor Jani Nikula
2021-01-13 11:55   ` Anshuman Gupta
2021-01-14  8:56     ` Jani Nikula
2021-01-20  4:22       ` Gupta, Anshuman
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 16/17] drm/i915/dp: abstract struct intel_dp pps members to a sub-struct Jani Nikula
2021-01-13 11:58   ` Anshuman Gupta
2021-01-08 17:44 ` [Intel-gfx] [PATCH v2 17/17] drm/i915/dp: split out aux functionality to intel_dp_aux.c Jani Nikula
2021-01-20  4:44   ` Gupta, Anshuman
2021-01-08 19:23 ` [Intel-gfx] ✗ Fi.CI.CHECKPATCH: warning for drm/i915/dp: split out pps and aux (rev2) Patchwork
2021-01-08 19:24 ` [Intel-gfx] ✗ Fi.CI.SPARSE: " Patchwork
2021-01-08 19:52 ` [Intel-gfx] ✓ Fi.CI.BAT: success " Patchwork
2021-01-09  1:05 ` [Intel-gfx] ✗ Fi.CI.IGT: failure " Patchwork

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.