drm/i915: disable PCH ports if needed when disabling a CRTC
Disable any PCH ports associated with a pipe when disabling it. This should prevent transcoder disable failures due to ports still being on. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> [ickle: introduce *_PIPE_ENABLED() macro] Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Родитель
bed636abea
Коммит
47a05eca72
|
@ -1440,6 +1440,7 @@
|
|||
#define LVDS_PORT_EN (1 << 31)
|
||||
/* Selects pipe B for LVDS data. Must be set on pre-965. */
|
||||
#define LVDS_PIPEB_SELECT (1 << 30)
|
||||
#define LVDS_PIPE_MASK (1 << 30)
|
||||
/* LVDS dithering flag on 965/g4x platform */
|
||||
#define LVDS_ENABLE_DITHER (1 << 25)
|
||||
/* LVDS sync polarity flags. Set to invert (i.e. negative) */
|
||||
|
@ -1479,6 +1480,9 @@
|
|||
#define LVDS_B0B3_POWER_DOWN (0 << 2)
|
||||
#define LVDS_B0B3_POWER_UP (3 << 2)
|
||||
|
||||
#define LVDS_PIPE_ENABLED(V, P) \
|
||||
(((V) & (LVDS_PIPE_MASK | LVDS_PORT_EN)) == ((P) << 30 | LVDS_PORT_EN))
|
||||
|
||||
/* Video Data Island Packet control */
|
||||
#define VIDEO_DIP_DATA 0x61178
|
||||
#define VIDEO_DIP_CTL 0x61170
|
||||
|
@ -2067,6 +2071,10 @@
|
|||
|
||||
#define DP_PORT_EN (1 << 31)
|
||||
#define DP_PIPEB_SELECT (1 << 30)
|
||||
#define DP_PIPE_MASK (1 << 30)
|
||||
|
||||
#define DP_PIPE_ENABLED(V, P) \
|
||||
(((V) & (DP_PIPE_MASK | DP_PORT_EN)) == ((P) << 30 | DP_PORT_EN))
|
||||
|
||||
/* Link training mode - select a suitable mode for each stage */
|
||||
#define DP_LINK_TRAIN_PAT_1 (0 << 28)
|
||||
|
@ -3180,11 +3188,15 @@
|
|||
#define ADPA_CRT_HOTPLUG_VOLREF_475MV (1<<17)
|
||||
#define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
|
||||
|
||||
#define ADPA_PIPE_ENABLED(V, P) \
|
||||
(((V) & (ADPA_TRANS_SELECT_MASK | ADPA_DAC_ENABLE)) == ((P) << 30 | ADPA_DAC_ENABLE))
|
||||
|
||||
/* or SDVOB */
|
||||
#define HDMIB 0xe1140
|
||||
#define PORT_ENABLE (1 << 31)
|
||||
#define TRANSCODER_A (0)
|
||||
#define TRANSCODER_B (1 << 30)
|
||||
#define TRANSCODER_MASK (1 << 30)
|
||||
#define COLOR_FORMAT_8bpc (0)
|
||||
#define COLOR_FORMAT_12bpc (3 << 26)
|
||||
#define SDVOB_HOTPLUG_ENABLE (1 << 23)
|
||||
|
@ -3200,6 +3212,9 @@
|
|||
#define HSYNC_ACTIVE_HIGH (1 << 3)
|
||||
#define PORT_DETECTED (1 << 2)
|
||||
|
||||
#define HDMI_PIPE_ENABLED(V, P) \
|
||||
(((V) & (TRANSCODER_MASK | PORT_ENABLE)) == ((P) << 30 | PORT_ENABLE))
|
||||
|
||||
/* PCH SDVOB multiplex with HDMIB */
|
||||
#define PCH_SDVOB HDMIB
|
||||
|
||||
|
|
|
@ -1270,12 +1270,8 @@ static void assert_transcoder_disabled(struct drm_i915_private *dev_priv,
|
|||
static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe, int reg)
|
||||
{
|
||||
u32 val;
|
||||
u32 sel_pipe;
|
||||
|
||||
val = I915_READ(reg);
|
||||
sel_pipe = (val & DP_PIPEB_SELECT) >> 30;
|
||||
WARN((val & DP_PORT_EN) && sel_pipe == pipe,
|
||||
u32 val = I915_READ(reg);
|
||||
WARN(DP_PIPE_ENABLED(val, pipe),
|
||||
"PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
|
||||
reg, pipe_name(pipe));
|
||||
}
|
||||
|
@ -1283,12 +1279,8 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
|
|||
static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe, int reg)
|
||||
{
|
||||
u32 val;
|
||||
u32 sel_pipe;
|
||||
|
||||
val = I915_READ(reg);
|
||||
sel_pipe = (val & TRANSCODER_B) >> 30;
|
||||
WARN((val & PORT_ENABLE) && sel_pipe == pipe,
|
||||
u32 val = I915_READ(reg);
|
||||
WARN(HDMI_PIPE_ENABLED(val, pipe),
|
||||
"PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
|
||||
reg, pipe_name(pipe));
|
||||
}
|
||||
|
@ -1298,7 +1290,6 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
|
|||
{
|
||||
int reg;
|
||||
u32 val;
|
||||
u32 sel_pipe;
|
||||
|
||||
assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B);
|
||||
assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C);
|
||||
|
@ -1306,15 +1297,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
|
|||
|
||||
reg = PCH_ADPA;
|
||||
val = I915_READ(reg);
|
||||
sel_pipe = (val & ADPA_TRANS_B_SELECT) >> 30;
|
||||
WARN(sel_pipe == pipe && (val & ADPA_DAC_ENABLE),
|
||||
WARN(ADPA_PIPE_ENABLED(val, pipe),
|
||||
"PCH VGA enabled on transcoder %c, should be disabled\n",
|
||||
pipe_name(pipe));
|
||||
|
||||
reg = PCH_LVDS;
|
||||
val = I915_READ(reg);
|
||||
sel_pipe = (val & LVDS_PIPEB_SELECT) >> 30;
|
||||
WARN(sel_pipe == pipe && (val & LVDS_PORT_EN),
|
||||
WARN(LVDS_PIPE_ENABLED(val, pipe),
|
||||
"PCH LVDS enabled on transcoder %c, should be disabled\n",
|
||||
pipe_name(pipe));
|
||||
|
||||
|
@ -1628,6 +1617,53 @@ static void intel_disable_plane(struct drm_i915_private *dev_priv,
|
|||
intel_wait_for_vblank(dev_priv->dev, pipe);
|
||||
}
|
||||
|
||||
static void disable_pch_dp(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe, int reg)
|
||||
{
|
||||
u32 val = I915_READ(reg);
|
||||
if (DP_PIPE_ENABLED(val, pipe))
|
||||
I915_WRITE(reg, val & ~DP_PORT_EN);
|
||||
}
|
||||
|
||||
static void disable_pch_hdmi(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe, int reg)
|
||||
{
|
||||
u32 val = I915_READ(reg);
|
||||
if (HDMI_PIPE_ENABLED(val, pipe))
|
||||
I915_WRITE(reg, val & ~PORT_ENABLE);
|
||||
}
|
||||
|
||||
/* Disable any ports connected to this transcoder */
|
||||
static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
|
||||
enum pipe pipe)
|
||||
{
|
||||
u32 reg, val;
|
||||
|
||||
val = I915_READ(PCH_PP_CONTROL);
|
||||
I915_WRITE(PCH_PP_CONTROL, val | PANEL_UNLOCK_REGS);
|
||||
|
||||
disable_pch_dp(dev_priv, pipe, PCH_DP_B);
|
||||
disable_pch_dp(dev_priv, pipe, PCH_DP_C);
|
||||
disable_pch_dp(dev_priv, pipe, PCH_DP_D);
|
||||
|
||||
reg = PCH_ADPA;
|
||||
val = I915_READ(reg);
|
||||
if (ADPA_PIPE_ENABLED(val, pipe))
|
||||
I915_WRITE(reg, val & ~ADPA_DAC_ENABLE);
|
||||
|
||||
reg = PCH_LVDS;
|
||||
val = I915_READ(reg);
|
||||
if (LVDS_PIPE_ENABLED(val, pipe)) {
|
||||
I915_WRITE(reg, val & ~LVDS_PORT_EN);
|
||||
POSTING_READ(reg);
|
||||
udelay(100);
|
||||
}
|
||||
|
||||
disable_pch_hdmi(dev_priv, pipe, HDMIB);
|
||||
disable_pch_hdmi(dev_priv, pipe, HDMIC);
|
||||
disable_pch_hdmi(dev_priv, pipe, HDMID);
|
||||
}
|
||||
|
||||
static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
|
@ -2864,14 +2900,12 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
|
|||
|
||||
ironlake_fdi_disable(crtc);
|
||||
|
||||
if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
|
||||
temp = I915_READ(PCH_LVDS);
|
||||
if (temp & LVDS_PORT_EN) {
|
||||
I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN);
|
||||
POSTING_READ(PCH_LVDS);
|
||||
udelay(100);
|
||||
}
|
||||
}
|
||||
/* This is a horrible layering violation; we should be doing this in
|
||||
* the connector/encoder ->prepare instead, but we don't always have
|
||||
* enough information there about the config to know whether it will
|
||||
* actually be necessary or just cause undesired flicker.
|
||||
*/
|
||||
intel_disable_pch_ports(dev_priv, pipe);
|
||||
|
||||
intel_disable_transcoder(dev_priv, pipe);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче