Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 44cb734c authored by Imre Deak's avatar Imre Deak
Browse files

drm/i915: Merge the PPS register definitions



The PPS registers are pretty much the same everywhere, the differences
being:
- Register fields appearing, disappearing from one platform to the
  next: panel-reset-on-powerdown, backlight-on, panel-port,
  register-unlock
- Different register base addresses
- Different number of PPS instances: 2 on VLV/CHV/BXT, 1 everywhere
  else.

We can merge the separate set of PPS definitions by extending the PPS
instance argument to all platforms and using instance 0 on platforms
with a single instance. This means we'll need to calculate the register
addresses dynamically based on the given platform and PPS instance.

v2:
- Simplify if ladder in intel_pps_get_registers(). (Ville)

Signed-off-by: default avatarImre Deak <imre.deak@intel.com>
Reviewed-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1470827254-21954-1-git-send-email-imre.deak@intel.com
parent 774439e1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1749,6 +1749,8 @@ struct drm_i915_private {

	uint32_t psr_mmio_base;

	uint32_t pps_mmio_base;

	wait_queue_head_t gmbus_wait_queue;

	struct pci_dev *bridge_dev;
+59 −86
Original line number Diff line number Diff line
@@ -3660,7 +3660,16 @@ enum {
#define   VIDEO_DIP_ENABLE_SPD_HSW	(1 << 0)

/* Panel power sequencing */
#define PP_STATUS	_MMIO(0x61200)
#define PPS_BASE			0x61200
#define VLV_PPS_BASE			(VLV_DISPLAY_BASE + PPS_BASE)
#define PCH_PPS_BASE			0xC7200

#define _MMIO_PPS(pps_idx, reg)		_MMIO(dev_priv->pps_mmio_base -	\
					      PPS_BASE + (reg) +	\
					      (pps_idx) * 0x100)

#define _PP_STATUS			0x61200
#define PP_STATUS(pps_idx)		_MMIO_PPS(pps_idx, _PP_STATUS)
#define   PP_ON				(1 << 31)
/*
 * Indicates that all dependencies of the panel are on:
@@ -3686,11 +3695,46 @@ enum {
#define   PP_SEQUENCE_STATE_ON_S1_2	(0xa << 0)
#define   PP_SEQUENCE_STATE_ON_S1_3	(0xb << 0)
#define   PP_SEQUENCE_STATE_RESET	(0xf << 0)
#define PP_CONTROL	_MMIO(0x61204)

#define _PP_CONTROL			0x61204
#define PP_CONTROL(pps_idx)		_MMIO_PPS(pps_idx, _PP_CONTROL)
#define  PANEL_UNLOCK_REGS		(0xabcd << 16)
#define  PANEL_UNLOCK_MASK		(0xffff << 16)
#define  BXT_POWER_CYCLE_DELAY_MASK	0x1f0
#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
#define  EDP_FORCE_VDD			(1 << 3)
#define  EDP_BLC_ENABLE			(1 << 2)
#define  PANEL_POWER_RESET		(1 << 1)
#define  PANEL_POWER_OFF		(0 << 0)
#define  PANEL_POWER_ON			(1 << 0)
#define  POWER_TARGET_ON		(1 << 0)
#define PP_ON_DELAYS	_MMIO(0x61208)
#define PP_OFF_DELAYS	_MMIO(0x6120c)
#define PP_DIVISOR	_MMIO(0x61210)

#define _PP_ON_DELAYS			0x61208
#define PP_ON_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_ON_DELAYS)
#define  PANEL_PORT_SELECT_MASK		(3 << 30)
#define  PANEL_PORT_SELECT_LVDS		(0 << 30)
#define  PANEL_PORT_SELECT_DPA		(1 << 30)
#define  PANEL_PORT_SELECT_DPC		(2 << 30)
#define  PANEL_PORT_SELECT_DPD		(3 << 30)
#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
#define  PANEL_POWER_UP_DELAY_MASK	0x1fff0000
#define  PANEL_POWER_UP_DELAY_SHIFT	16
#define  PANEL_LIGHT_ON_DELAY_MASK	0x1fff
#define  PANEL_LIGHT_ON_DELAY_SHIFT	0

#define _PP_OFF_DELAYS			0x6120C
#define PP_OFF_DELAYS(pps_idx)		_MMIO_PPS(pps_idx, _PP_OFF_DELAYS)
#define  PANEL_POWER_DOWN_DELAY_MASK	0x1fff0000
#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
#define  PANEL_LIGHT_OFF_DELAY_MASK	0x1fff
#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0

#define _PP_DIVISOR			0x61210
#define PP_DIVISOR(pps_idx)		_MMIO_PPS(pps_idx, _PP_DIVISOR)
#define  PP_REFERENCE_DIVIDER_MASK	0xffffff00
#define  PP_REFERENCE_DIVIDER_SHIFT	8
#define  PANEL_POWER_CYCLE_DELAY_MASK	0x1f
#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0

/* Panel fitting */
#define PFIT_CONTROL	_MMIO(dev_priv->info.display_mmio_offset + 0x61230)
@@ -6750,77 +6794,6 @@ enum {
#define PCH_LVDS	_MMIO(0xe1180)
#define  LVDS_DETECTED	(1 << 1)

/* vlv has 2 sets of panel control regs. */
#define _PIPEA_PP_STATUS         (VLV_DISPLAY_BASE + 0x61200)
#define _PIPEA_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61204)
#define _PIPEA_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61208)
#define  PANEL_PORT_SELECT_VLV(port)	((port) << 30)
#define _PIPEA_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6120c)
#define _PIPEA_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61210)

#define _PIPEB_PP_STATUS         (VLV_DISPLAY_BASE + 0x61300)
#define _PIPEB_PP_CONTROL        (VLV_DISPLAY_BASE + 0x61304)
#define _PIPEB_PP_ON_DELAYS      (VLV_DISPLAY_BASE + 0x61308)
#define _PIPEB_PP_OFF_DELAYS     (VLV_DISPLAY_BASE + 0x6130c)
#define _PIPEB_PP_DIVISOR        (VLV_DISPLAY_BASE + 0x61310)

#define VLV_PIPE_PP_STATUS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_STATUS, _PIPEB_PP_STATUS)
#define VLV_PIPE_PP_CONTROL(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_CONTROL, _PIPEB_PP_CONTROL)
#define VLV_PIPE_PP_ON_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_ON_DELAYS, _PIPEB_PP_ON_DELAYS)
#define VLV_PIPE_PP_OFF_DELAYS(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_OFF_DELAYS, _PIPEB_PP_OFF_DELAYS)
#define VLV_PIPE_PP_DIVISOR(pipe)	_MMIO_PIPE(pipe, _PIPEA_PP_DIVISOR, _PIPEB_PP_DIVISOR)

#define _PCH_PP_STATUS		0xc7200
#define _PCH_PP_CONTROL		0xc7204
#define  PANEL_UNLOCK_REGS	(0xabcd << 16)
#define  PANEL_UNLOCK_MASK	(0xffff << 16)
#define  BXT_POWER_CYCLE_DELAY_MASK	(0x1f0)
#define  BXT_POWER_CYCLE_DELAY_SHIFT	4
#define  EDP_FORCE_VDD		(1 << 3)
#define  EDP_BLC_ENABLE		(1 << 2)
#define  PANEL_POWER_RESET	(1 << 1)
#define  PANEL_POWER_OFF	(0 << 0)
#define  PANEL_POWER_ON		(1 << 0)
#define _PCH_PP_ON_DELAYS	0xc7208
#define  PANEL_PORT_SELECT_MASK	(3 << 30)
#define  PANEL_PORT_SELECT_LVDS	(0 << 30)
#define  PANEL_PORT_SELECT_DPA	(1 << 30)
#define  PANEL_PORT_SELECT_DPC	(2 << 30)
#define  PANEL_PORT_SELECT_DPD	(3 << 30)
#define  PANEL_POWER_UP_DELAY_MASK	(0x1fff0000)
#define  PANEL_POWER_UP_DELAY_SHIFT	16
#define  PANEL_LIGHT_ON_DELAY_MASK	(0x1fff)
#define  PANEL_LIGHT_ON_DELAY_SHIFT	0

#define _PCH_PP_OFF_DELAYS		0xc720c
#define  PANEL_POWER_DOWN_DELAY_MASK	(0x1fff0000)
#define  PANEL_POWER_DOWN_DELAY_SHIFT	16
#define  PANEL_LIGHT_OFF_DELAY_MASK	(0x1fff)
#define  PANEL_LIGHT_OFF_DELAY_SHIFT	0

#define _PCH_PP_DIVISOR			0xc7210
#define  PP_REFERENCE_DIVIDER_MASK	(0xffffff00)
#define  PP_REFERENCE_DIVIDER_SHIFT	8
#define  PANEL_POWER_CYCLE_DELAY_MASK	(0x1f)
#define  PANEL_POWER_CYCLE_DELAY_SHIFT	0

#define PCH_PP_STATUS			_MMIO(_PCH_PP_STATUS)
#define PCH_PP_CONTROL			_MMIO(_PCH_PP_CONTROL)
#define PCH_PP_ON_DELAYS		_MMIO(_PCH_PP_ON_DELAYS)
#define PCH_PP_OFF_DELAYS		_MMIO(_PCH_PP_OFF_DELAYS)
#define PCH_PP_DIVISOR			_MMIO(_PCH_PP_DIVISOR)

/* BXT PPS changes - 2nd set of PPS registers */
#define _BXT_PP_STATUS2 	0xc7300
#define _BXT_PP_CONTROL2 	0xc7304
#define _BXT_PP_ON_DELAYS2	0xc7308
#define _BXT_PP_OFF_DELAYS2	0xc730c

#define BXT_PP_STATUS(n)	_MMIO_PIPE(n, _PCH_PP_STATUS, _BXT_PP_STATUS2)
#define BXT_PP_CONTROL(n)	_MMIO_PIPE(n, _PCH_PP_CONTROL, _BXT_PP_CONTROL2)
#define BXT_PP_ON_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_ON_DELAYS, _BXT_PP_ON_DELAYS2)
#define BXT_PP_OFF_DELAYS(n)	_MMIO_PIPE(n, _PCH_PP_OFF_DELAYS, _BXT_PP_OFF_DELAYS2)

#define _PCH_DP_B		0xe4100
#define PCH_DP_B		_MMIO(_PCH_DP_B)
#define _PCH_DPB_AUX_CH_CTL	0xe4110
+10 −20
Original line number Diff line number Diff line
@@ -44,16 +44,11 @@ static void i915_save_display(struct drm_device *dev)
		dev_priv->regfile.saveLVDS = I915_READ(LVDS);

	/* Panel power sequencer */
	if (HAS_PCH_SPLIT(dev)) {
		dev_priv->regfile.savePP_CONTROL = I915_READ(PCH_PP_CONTROL);
		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PCH_PP_ON_DELAYS);
		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PCH_PP_OFF_DELAYS);
		dev_priv->regfile.savePP_DIVISOR = I915_READ(PCH_PP_DIVISOR);
	} else if (INTEL_INFO(dev)->gen <= 4) {
		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL);
		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS);
		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS);
		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR);
	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
		dev_priv->regfile.savePP_CONTROL = I915_READ(PP_CONTROL(0));
		dev_priv->regfile.savePP_ON_DELAYS = I915_READ(PP_ON_DELAYS(0));
		dev_priv->regfile.savePP_OFF_DELAYS = I915_READ(PP_OFF_DELAYS(0));
		dev_priv->regfile.savePP_DIVISOR = I915_READ(PP_DIVISOR(0));
	}

	/* save FBC interval */
@@ -79,16 +74,11 @@ static void i915_restore_display(struct drm_device *dev)
		I915_WRITE(LVDS, dev_priv->regfile.saveLVDS & mask);

	/* Panel power sequencer */
	if (HAS_PCH_SPLIT(dev)) {
		I915_WRITE(PCH_PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
		I915_WRITE(PCH_PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
		I915_WRITE(PCH_PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
		I915_WRITE(PCH_PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
	} else if (INTEL_INFO(dev)->gen <= 4) {
		I915_WRITE(PP_ON_DELAYS, dev_priv->regfile.savePP_ON_DELAYS);
		I915_WRITE(PP_OFF_DELAYS, dev_priv->regfile.savePP_OFF_DELAYS);
		I915_WRITE(PP_DIVISOR, dev_priv->regfile.savePP_DIVISOR);
		I915_WRITE(PP_CONTROL, dev_priv->regfile.savePP_CONTROL);
	if (HAS_PCH_SPLIT(dev_priv) || INTEL_GEN(dev_priv) <= 4) {
		I915_WRITE(PP_ON_DELAYS(0), dev_priv->regfile.savePP_ON_DELAYS);
		I915_WRITE(PP_OFF_DELAYS(0), dev_priv->regfile.savePP_OFF_DELAYS);
		I915_WRITE(PP_DIVISOR(0), dev_priv->regfile.savePP_DIVISOR);
		I915_WRITE(PP_CONTROL(0), dev_priv->regfile.savePP_CONTROL);
	}

	/* only restore FBC info on the platform that supports FBC*/
+17 −5
Original line number Diff line number Diff line
@@ -1202,8 +1202,8 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
	if (HAS_PCH_SPLIT(dev)) {
		u32 port_sel;

		pp_reg = PCH_PP_CONTROL;
		port_sel = I915_READ(PCH_PP_ON_DELAYS) & PANEL_PORT_SELECT_MASK;
		pp_reg = PP_CONTROL(0);
		port_sel = I915_READ(PP_ON_DELAYS(0)) & PANEL_PORT_SELECT_MASK;

		if (port_sel == PANEL_PORT_SELECT_LVDS &&
		    I915_READ(PCH_LVDS) & LVDS_PIPEB_SELECT)
@@ -1211,10 +1211,10 @@ void assert_panel_unlocked(struct drm_i915_private *dev_priv,
		/* XXX: else fix for eDP */
	} else if (IS_VALLEYVIEW(dev) || IS_CHERRYVIEW(dev)) {
		/* presumably write lock depends on pipe, not port select */
		pp_reg = VLV_PIPE_PP_CONTROL(pipe);
		pp_reg = PP_CONTROL(pipe);
		panel_pipe = pipe;
	} else {
		pp_reg = PP_CONTROL;
		pp_reg = PP_CONTROL(0);
		if (I915_READ(LVDS) & LVDS_PIPEB_SELECT)
			panel_pipe = PIPE_B;
	}
@@ -9491,7 +9491,7 @@ static void assert_can_disable_lcpll(struct drm_i915_private *dev_priv)
	I915_STATE_WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL enabled\n");
	I915_STATE_WARN(I915_READ(WRPLL_CTL(0)) & WRPLL_PLL_ENABLE, "WRPLL1 enabled\n");
	I915_STATE_WARN(I915_READ(WRPLL_CTL(1)) & WRPLL_PLL_ENABLE, "WRPLL2 enabled\n");
	I915_STATE_WARN(I915_READ(PCH_PP_STATUS) & PP_ON, "Panel power on\n");
	I915_STATE_WARN(I915_READ(PP_STATUS(0)) & PP_ON, "Panel power on\n");
	I915_STATE_WARN(I915_READ(BLC_PWM_CPU_CTL2) & BLM_PWM_ENABLE,
	     "CPU PWM1 enabled\n");
	if (IS_HASWELL(dev))
@@ -14729,12 +14729,24 @@ static bool intel_crt_present(struct drm_device *dev)
	return true;
}

static void intel_pps_init(struct drm_i915_private *dev_priv)
{
	if (HAS_PCH_SPLIT(dev_priv) || IS_BROXTON(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;
}

static void intel_setup_outputs(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = to_i915(dev);
	struct intel_encoder *encoder;
	bool dpd_is_edp = false;

	intel_pps_init(dev_priv);

	/*
	 * intel_edp_init_connector() depends on this completing first, to
	 * prevent the registeration of both eDP and LVDS and the incorrect
+18 −27
Original line number Diff line number Diff line
@@ -463,13 +463,13 @@ typedef bool (*vlv_pipe_check)(struct drm_i915_private *dev_priv,
static bool vlv_pipe_has_pp_on(struct drm_i915_private *dev_priv,
			       enum pipe pipe)
{
	return I915_READ(VLV_PIPE_PP_STATUS(pipe)) & PP_ON;
	return I915_READ(PP_STATUS(pipe)) & PP_ON;
}

static bool vlv_pipe_has_vdd_on(struct drm_i915_private *dev_priv,
				enum pipe pipe)
{
	return I915_READ(VLV_PIPE_PP_CONTROL(pipe)) & EDP_FORCE_VDD;
	return I915_READ(PP_CONTROL(pipe)) & EDP_FORCE_VDD;
}

static bool vlv_pipe_any(struct drm_i915_private *dev_priv,
@@ -486,7 +486,7 @@ vlv_initial_pps_pipe(struct drm_i915_private *dev_priv,
	enum pipe pipe;

	for (pipe = PIPE_A; pipe <= PIPE_B; pipe++) {
		u32 port_sel = I915_READ(VLV_PIPE_PP_ON_DELAYS(pipe)) &
		u32 port_sel = I915_READ(PP_ON_DELAYS(pipe)) &
			PANEL_PORT_SELECT_MASK;

		if (port_sel != PANEL_PORT_SELECT_VLV(port))
@@ -583,30 +583,21 @@ static void intel_pps_get_registers(struct drm_i915_private *dev_priv,
				    struct intel_dp *intel_dp,
				    struct pps_registers *regs)
{
	int pps_idx = 0;

	memset(regs, 0, sizeof(*regs));

	if (IS_BROXTON(dev_priv)) {
		int idx = bxt_power_sequencer_idx(intel_dp);

		regs->pp_ctrl = BXT_PP_CONTROL(idx);
		regs->pp_stat = BXT_PP_STATUS(idx);
		regs->pp_on = BXT_PP_ON_DELAYS(idx);
		regs->pp_off = BXT_PP_OFF_DELAYS(idx);
	} else if (HAS_PCH_SPLIT(dev_priv)) {
		regs->pp_ctrl = PCH_PP_CONTROL;
		regs->pp_stat = PCH_PP_STATUS;
		regs->pp_on = PCH_PP_ON_DELAYS;
		regs->pp_off = PCH_PP_OFF_DELAYS;
		regs->pp_div = PCH_PP_DIVISOR;
	} else {
		enum pipe pipe = vlv_power_sequencer_pipe(intel_dp);
	if (IS_BROXTON(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 = VLV_PIPE_PP_CONTROL(pipe);
		regs->pp_stat = VLV_PIPE_PP_STATUS(pipe);
		regs->pp_on = VLV_PIPE_PP_ON_DELAYS(pipe);
		regs->pp_off = VLV_PIPE_PP_OFF_DELAYS(pipe);
		regs->pp_div = VLV_PIPE_PP_DIVISOR(pipe);
	}
	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);
	if (!IS_BROXTON(dev_priv))
		regs->pp_div = PP_DIVISOR(pps_idx);
}

static i915_reg_t
@@ -651,8 +642,8 @@ static int edp_notify_handler(struct notifier_block *this, unsigned long code,
		i915_reg_t pp_ctrl_reg, pp_div_reg;
		u32 pp_div;

		pp_ctrl_reg = VLV_PIPE_PP_CONTROL(pipe);
		pp_div_reg  = VLV_PIPE_PP_DIVISOR(pipe);
		pp_ctrl_reg = PP_CONTROL(pipe);
		pp_div_reg  = PP_DIVISOR(pipe);
		pp_div = I915_READ(pp_div_reg);
		pp_div &= PP_REFERENCE_DIVIDER_MASK;

@@ -2729,7 +2720,7 @@ static void vlv_detach_power_sequencer(struct intel_dp *intel_dp)
	struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp);
	struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev);
	enum pipe pipe = intel_dp->pps_pipe;
	i915_reg_t pp_on_reg = VLV_PIPE_PP_ON_DELAYS(pipe);
	i915_reg_t pp_on_reg = PP_ON_DELAYS(pipe);

	edp_panel_vdd_off_sync(intel_dp);

Loading