diff --git a/patches.drivers/0001-drm-i915-Use-ACPI-OpRegion-to-determine-lid-status.patch b/patches.drivers/0001-drm-i915-Use-ACPI-OpRegion-to-determine-lid-status.patch new file mode 100644 index 0000000..2089369 --- /dev/null +++ b/patches.drivers/0001-drm-i915-Use-ACPI-OpRegion-to-determine-lid-status.patch @@ -0,0 +1,64 @@ +From 38c1a19fb78da8c2a617b1d8a3fcafb691c1409f Mon Sep 17 00:00:00 2001 +From: Chris Wilson +Date: Sun, 16 Jan 2011 19:37:30 +0000 +Subject: [PATCH 1/3] drm/i915: Use ACPI OpRegion to determine lid status + +Admittedly, trusting ACPI or the BIOS at all to be correct is littered +with numerous examples where it is wrong. Maybe, just maybe, we will +have better luck using the ACPI OpRegion lid status... + +Signed-off-by: Chris Wilson +--- + drivers/gpu/drm/i915/i915_drv.h | 1 + + drivers/gpu/drm/i915/intel_lvds.c | 7 +++++++ + drivers/gpu/drm/i915/intel_opregion.c | 2 ++ + 3 files changed, 10 insertions(+), 0 deletions(-) + +diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h +index 456f404..a299cc6 100644 +--- a/drivers/gpu/drm/i915/i915_drv.h ++++ b/drivers/gpu/drm/i915/i915_drv.h +@@ -111,6 +111,7 @@ struct intel_opregion { + struct opregion_swsci *swsci; + struct opregion_asle *asle; + void *vbt; ++ u32 __iomem *lid_state; + }; + #define OPREGION_SIZE (8*1024) + +diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c +index bcdba7b..aa29228 100644 +--- a/drivers/gpu/drm/i915/intel_lvds.c ++++ b/drivers/gpu/drm/i915/intel_lvds.c +@@ -472,8 +472,15 @@ static enum drm_connector_status + intel_lvds_detect(struct drm_connector *connector, bool force) + { + struct drm_device *dev = connector->dev; ++ struct drm_i915_private *dev_priv = dev->dev_private; + enum drm_connector_status status = connector_status_connected; + ++ /* Assume that the BIOS does not lie through the OpRegion... */ ++ if (dev_priv->opregion.lid_state) ++ return ioread32(dev_priv->opregion.lid_state) & 0x1 ? ++ connector_status_connected : ++ connector_status_disconnected; ++ + /* ACPI lid methods were generally unreliable in this generation, so + * don't even bother. + */ +diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c +index 64fd644..9efccb9 100644 +--- a/drivers/gpu/drm/i915/intel_opregion.c ++++ b/drivers/gpu/drm/i915/intel_opregion.c +@@ -489,6 +489,8 @@ int intel_opregion_setup(struct drm_device *dev) + opregion->header = base; + opregion->vbt = base + OPREGION_VBT_OFFSET; + ++ opregion->lid_state = base + 0x01ac; ++ + mboxes = opregion->header->mboxes; + if (mboxes & MBOX_ACPI) { + DRM_DEBUG_DRIVER("Public ACPI methods supported\n"); +-- +1.7.6.5 + diff --git a/patches.drivers/0002-drm-i915-don-t-enable-plane-pipe-and-PLL-prematurely.patch b/patches.drivers/0002-drm-i915-don-t-enable-plane-pipe-and-PLL-prematurely.patch new file mode 100644 index 0000000..1f09f95 --- /dev/null +++ b/patches.drivers/0002-drm-i915-don-t-enable-plane-pipe-and-PLL-prematurely.patch @@ -0,0 +1,35 @@ +From 9e4eb0947431c5a6b55f442aee3eb505e5a334d5 Mon Sep 17 00:00:00 2001 +From: Jesse Barnes +Date: Tue, 4 Jan 2011 15:09:29 -0800 +Subject: [PATCH 2/3] drm/i915: don't enable plane, pipe and PLL prematurely + +On Ironlake+ we need to enable these in a specific order. + +Signed-off-by: Jesse Barnes +Signed-off-by: Chris Wilson +--- + drivers/gpu/drm/i915/intel_display.c | 8 +++++--- + 1 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c +index 49fb54f..711beca 100644 +--- a/drivers/gpu/drm/i915/intel_display.c ++++ b/drivers/gpu/drm/i915/intel_display.c +@@ -4322,9 +4322,11 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, + pipeconf &= ~PIPECONF_DOUBLE_WIDE; + } + +- dspcntr |= DISPLAY_PLANE_ENABLE; +- pipeconf |= PIPECONF_ENABLE; +- dpll |= DPLL_VCO_ENABLE; ++ if (!HAS_PCH_SPLIT(dev)) { ++ dspcntr |= DISPLAY_PLANE_ENABLE; ++ pipeconf |= PIPECONF_ENABLE; ++ dpll |= DPLL_VCO_ENABLE; ++ } + + DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); + drm_mode_debug_printmodeline(mode); +-- +1.7.6.5 + diff --git a/patches.drivers/0003-drm-i915-add-pipe-plane-enable-disable-functions.patch b/patches.drivers/0003-drm-i915-add-pipe-plane-enable-disable-functions.patch new file mode 100644 index 0000000..9cc0428 --- /dev/null +++ b/patches.drivers/0003-drm-i915-add-pipe-plane-enable-disable-functions.patch @@ -0,0 +1,429 @@ +From 152d92c3e618d1c17c6a84c66aec00af227c3f0e Mon Sep 17 00:00:00 2001 +From: Jesse Barnes +Date: Tue, 4 Jan 2011 15:09:30 -0800 +Subject: [PATCH 3/3] drm/i915: add pipe/plane enable/disable functions + +Add plane enable/disable functions to prevent duplicated code and allow +us to easily check for plane enable/disable requirements (such as pipe +enable, plane status, pll status etc). + +Signed-off-by: Jesse Barnes +Signed-off-by: Chris Wilson +--- + drivers/gpu/drm/i915/i915_reg.h | 5 +- + drivers/gpu/drm/i915/intel_display.c | 308 +++++++++++++++++++++++----------- + 2 files changed, 216 insertions(+), 97 deletions(-) + +diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h +index 12c547a..b0f1290 100644 +--- a/drivers/gpu/drm/i915/i915_reg.h ++++ b/drivers/gpu/drm/i915/i915_reg.h +@@ -2537,9 +2537,10 @@ + #define DISPPLANE_32BPP_30BIT_NO_ALPHA (0xa<<26) + #define DISPPLANE_STEREO_ENABLE (1<<25) + #define DISPPLANE_STEREO_DISABLE 0 +-#define DISPPLANE_SEL_PIPE_MASK (1<<24) ++#define DISPPLANE_SEL_PIPE_SHIFT 24 ++#define DISPPLANE_SEL_PIPE_MASK (3<> ++ DISPPLANE_SEL_PIPE_SHIFT; ++ WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe, ++ "plane %d assertion failure, should be off on pipe %c but is still active\n", ++ i, pipe ? 'B' : 'A'); ++ } ++} ++ ++/** ++ * intel_enable_pipe - enable a pipe, assertiing requirements ++ * @dev_priv: i915 private structure ++ * @pipe: pipe to enable ++ * ++ * Enable @pipe, making sure that various hardware specific requirements ++ * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc. ++ * ++ * @pipe should be %PIPE_A or %PIPE_B. ++ * ++ * Will wait until the pipe is actually running (i.e. first vblank) before ++ * returning. ++ */ ++static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe) ++{ ++ int reg; ++ u32 val; ++ ++ /* ++ * A pipe without a PLL won't actually be able to drive bits from ++ * a plane. On ILK+ the pipe PLLs are integrated, so we don't ++ * need the check. ++ */ ++ if (!HAS_PCH_SPLIT(dev_priv->dev)) ++ assert_pll_enabled(dev_priv, pipe); ++ ++ reg = PIPECONF(pipe); ++ val = I915_READ(reg); ++ val |= PIPECONF_ENABLE; ++ I915_WRITE(reg, val); ++ POSTING_READ(reg); ++ intel_wait_for_vblank(dev_priv->dev, pipe); ++} ++ ++/** ++ * intel_disable_pipe - disable a pipe, assertiing requirements ++ * @dev_priv: i915 private structure ++ * @pipe: pipe to disable ++ * ++ * Disable @pipe, making sure that various hardware specific requirements ++ * are met, if applicable, e.g. plane disabled, panel fitter off, etc. ++ * ++ * @pipe should be %PIPE_A or %PIPE_B. ++ * ++ * Will wait until the pipe has shut down before returning. ++ */ ++static void intel_disable_pipe(struct drm_i915_private *dev_priv, ++ enum pipe pipe) ++{ ++ int reg; ++ u32 val; ++ ++ /* ++ * Make sure planes won't keep trying to pump pixels to us, ++ * or we might hang the display. ++ */ ++ assert_planes_disabled(dev_priv, pipe); ++ ++ /* Don't disable pipe A or pipe A PLLs if needed */ ++ if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) ++ return; ++ ++ reg = PIPECONF(pipe); ++ val = I915_READ(reg); ++ val &= ~PIPECONF_ENABLE; ++ I915_WRITE(reg, val); ++ POSTING_READ(reg); ++ intel_wait_for_pipe_off(dev_priv->dev, pipe); ++} ++ ++/** ++ * intel_enable_plane - enable a display plane on a given pipe ++ * @dev_priv: i915 private structure ++ * @plane: plane to enable ++ * @pipe: pipe being fed ++ * ++ * Enable @plane on @pipe, making sure that @pipe is running first. ++ */ ++static void intel_enable_plane(struct drm_i915_private *dev_priv, ++ enum plane plane, enum pipe pipe) ++{ ++ int reg; ++ u32 val; ++ ++ /* If the pipe isn't enabled, we can't pump pixels and may hang */ ++ assert_pipe_enabled(dev_priv, pipe); ++ ++ reg = DSPCNTR(plane); ++ val = I915_READ(reg); ++ val |= DISPLAY_PLANE_ENABLE; ++ I915_WRITE(reg, val); ++ POSTING_READ(reg); ++ intel_wait_for_vblank(dev_priv->dev, pipe); ++} ++ ++/* ++ * Plane regs are double buffered, going from enabled->disabled needs a ++ * trigger in order to latch. The display address reg provides this. ++ */ ++static void intel_flush_display_plane(struct drm_i915_private *dev_priv, ++ enum plane plane) ++{ ++ u32 reg = DSPADDR(plane); ++ I915_WRITE(reg, I915_READ(reg)); ++} ++ ++/** ++ * intel_disable_plane - disable a display plane ++ * @dev_priv: i915 private structure ++ * @plane: plane to disable ++ * @pipe: pipe consuming the data ++ * ++ * Disable @plane; should be an independent operation. ++ */ ++static void intel_disable_plane(struct drm_i915_private *dev_priv, ++ enum plane plane, enum pipe pipe) ++{ ++ int reg; ++ u32 val; ++ ++ reg = DSPCNTR(plane); ++ val = I915_READ(reg); ++ val &= ~DISPLAY_PLANE_ENABLE; ++ I915_WRITE(reg, val); ++ POSTING_READ(reg); ++ intel_flush_display_plane(dev_priv, plane); ++ intel_wait_for_vblank(dev_priv->dev, pipe); ++} ++ + static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval) + { + struct drm_device *dev = crtc->dev; +@@ -2003,14 +2200,6 @@ static void ironlake_fdi_enable(struct drm_crtc *crtc) + } + } + +-static void intel_flush_display_plane(struct drm_device *dev, +- int plane) +-{ +- struct drm_i915_private *dev_priv = dev->dev_private; +- u32 reg = DSPADDR(plane); +- I915_WRITE(reg, I915_READ(reg)); +-} +- + /* + * When we disable a pipe, we need to clear any pending scanline wait events + * to avoid hanging the ring, which we assume we are waiting on. +@@ -2158,22 +2347,8 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) + dev_priv->pch_pf_size); + } + +- /* Enable CPU pipe */ +- reg = PIPECONF(pipe); +- temp = I915_READ(reg); +- if ((temp & PIPECONF_ENABLE) == 0) { +- I915_WRITE(reg, temp | PIPECONF_ENABLE); +- POSTING_READ(reg); +- intel_wait_for_vblank(dev, intel_crtc->pipe); +- } +- +- /* configure and enable CPU plane */ +- reg = DSPCNTR(plane); +- temp = I915_READ(reg); +- if ((temp & DISPLAY_PLANE_ENABLE) == 0) { +- I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE); +- intel_flush_display_plane(dev, plane); +- } ++ intel_enable_pipe(dev_priv, pipe); ++ intel_enable_plane(dev_priv, plane, pipe); + + /* Skip the PCH stuff if possible */ + if (!is_pch_port) +@@ -2285,27 +2460,13 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc) + drm_vblank_off(dev, pipe); + intel_crtc_update_cursor(crtc, false); + +- /* Disable display plane */ +- reg = DSPCNTR(plane); +- temp = I915_READ(reg); +- if (temp & DISPLAY_PLANE_ENABLE) { +- I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE); +- intel_flush_display_plane(dev, plane); +- } ++ intel_disable_plane(dev_priv, plane, pipe); + + if (dev_priv->cfb_plane == plane && + dev_priv->display.disable_fbc) + dev_priv->display.disable_fbc(dev); + +- /* disable cpu pipe, disable after all planes disabled */ +- reg = PIPECONF(pipe); +- temp = I915_READ(reg); +- if (temp & PIPECONF_ENABLE) { +- I915_WRITE(reg, temp & ~PIPECONF_ENABLE); +- POSTING_READ(reg); +- /* wait for cpu pipe off, pipe state */ +- intel_wait_for_pipe_off(dev, intel_crtc->pipe); +- } ++ intel_disable_pipe(dev_priv, pipe); + + /* Disable PF */ + I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0); +@@ -2500,19 +2661,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) + udelay(150); + } + +- /* Enable the pipe */ +- reg = PIPECONF(pipe); +- temp = I915_READ(reg); +- if ((temp & PIPECONF_ENABLE) == 0) +- I915_WRITE(reg, temp | PIPECONF_ENABLE); +- +- /* Enable the plane */ +- reg = DSPCNTR(plane); +- temp = I915_READ(reg); +- if ((temp & DISPLAY_PLANE_ENABLE) == 0) { +- I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE); +- intel_flush_display_plane(dev, plane); +- } ++ intel_enable_pipe(dev_priv, pipe); ++ intel_enable_plane(dev_priv, plane, pipe); + + intel_crtc_load_lut(crtc); + intel_update_fbc(dev); +@@ -2544,33 +2694,13 @@ static void i9xx_crtc_disable(struct drm_crtc *crtc) + dev_priv->display.disable_fbc) + dev_priv->display.disable_fbc(dev); + +- /* Disable display plane */ +- reg = DSPCNTR(plane); +- temp = I915_READ(reg); +- if (temp & DISPLAY_PLANE_ENABLE) { +- I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE); +- /* Flush the plane changes */ +- intel_flush_display_plane(dev, plane); +- +- /* Wait for vblank for the disable to take effect */ +- if (IS_GEN2(dev)) +- intel_wait_for_vblank(dev, pipe); +- } ++ intel_disable_plane(dev_priv, plane, pipe); + + /* Don't disable pipe A or pipe A PLLs if needed */ + if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) + goto done; + +- /* Next, disable display pipes */ +- reg = PIPECONF(pipe); +- temp = I915_READ(reg); +- if (temp & PIPECONF_ENABLE) { +- I915_WRITE(reg, temp & ~PIPECONF_ENABLE); +- +- /* Wait for the pipe to turn off */ +- POSTING_READ(reg); +- intel_wait_for_pipe_off(dev, pipe); +- } ++ intel_disable_pipe(dev_priv, pipe); + + reg = DPLL(pipe); + temp = I915_READ(reg); +@@ -4322,11 +4452,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, + pipeconf &= ~PIPECONF_DOUBLE_WIDE; + } + +- if (!HAS_PCH_SPLIT(dev)) { +- dspcntr |= DISPLAY_PLANE_ENABLE; +- pipeconf |= PIPECONF_ENABLE; ++ if (!HAS_PCH_SPLIT(dev)) + dpll |= DPLL_VCO_ENABLE; +- } + + DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B'); + drm_mode_debug_printmodeline(mode); +@@ -4535,6 +4662,8 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, + + I915_WRITE(PIPECONF(pipe), pipeconf); + POSTING_READ(PIPECONF(pipe)); ++ if (!HAS_PCH_SPLIT(dev)) ++ intel_enable_pipe(dev_priv, pipe); + + intel_wait_for_vblank(dev, pipe); + +@@ -4545,6 +4674,9 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, + } + + I915_WRITE(DSPCNTR(plane), dspcntr); ++ POSTING_READ(DSPCNTR(plane)); ++ if (!HAS_PCH_SPLIT(dev)) ++ intel_enable_plane(dev_priv, plane, pipe); + + ret = intel_pipe_set_base(crtc, x, y, old_fb); + +@@ -5694,22 +5826,8 @@ static void intel_sanitize_modesetting(struct drm_device *dev, + pipe = !pipe; + + /* Disable the plane and wait for it to stop reading from the pipe. */ +- I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE); +- intel_flush_display_plane(dev, plane); +- +- if (IS_GEN2(dev)) +- intel_wait_for_vblank(dev, pipe); +- +- if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) +- return; +- +- /* Switch off the pipe. */ +- reg = PIPECONF(pipe); +- val = I915_READ(reg); +- if (val & PIPECONF_ENABLE) { +- I915_WRITE(reg, val & ~PIPECONF_ENABLE); +- intel_wait_for_pipe_off(dev, pipe); +- } ++ intel_disable_plane(dev_priv, plane, pipe); ++ intel_disable_pipe(dev_priv, pipe); + } + + static void intel_crtc_init(struct drm_device *dev, int pipe) +-- +1.7.6.5 + diff --git a/series-xenlinux.conf b/series-xenlinux.conf index 68801f5..56de175 100644 --- a/series-xenlinux.conf +++ b/series-xenlinux.conf @@ -497,6 +497,10 @@ # DRM/Video ######################################################## + patches.drivers/0001-drm-i915-Use-ACPI-OpRegion-to-determine-lid-status.patch + patches.drivers/0002-drm-i915-don-t-enable-plane-pipe-and-PLL-prematurely.patch + patches.drivers/0003-drm-i915-add-pipe-plane-enable-disable-functions.patch + ######################################################## # video4linux ########################################################