diff options
author | Ville Syrjälä <ville.syrjala@linux.intel.com> | 2014-08-14 18:22:07 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-09-03 05:05:24 -0400 |
commit | b6b5d049780c29fe6073b6ecbb712dd8dcb27ebc (patch) | |
tree | 430498f78d9abd507fece663c195094003a0ace3 /drivers/gpu | |
parent | 5f080c0f4bd526b36361dd15c4d22f6bbad95af9 (diff) |
drm/i915: Add pipe B force quirk for 830M
830M has problems when some of the pipes are disabled. Namely if a
plane, DVO port etc. is currently assigned to a disabled pipe, it
can't moved to the other pipe until the current pipe is also enabled.
To keep things simple just leave both pipes running all the time.
Ideally I think should turn the pipes off if neither is active, and
when either becomes active we enable both. But that would reuquire
proper atomic modeset support, and probably a bit of extra care in
the order things get enabled.
v2: Reorder wrt. double wide handling changes
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Tested-by: Thomas Richter <richter@rus.uni-stuttgart.de>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 39 |
2 files changed, 28 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 13db41833f3d..dbf9a26d1a89 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -709,6 +709,7 @@ enum intel_sbi_destination { | |||
709 | #define QUIRK_LVDS_SSC_DISABLE (1<<1) | 709 | #define QUIRK_LVDS_SSC_DISABLE (1<<1) |
710 | #define QUIRK_INVERT_BRIGHTNESS (1<<2) | 710 | #define QUIRK_INVERT_BRIGHTNESS (1<<2) |
711 | #define QUIRK_BACKLIGHT_PRESENT (1<<3) | 711 | #define QUIRK_BACKLIGHT_PRESENT (1<<3) |
712 | #define QUIRK_PIPEB_FORCE (1<<4) | ||
712 | 713 | ||
713 | struct intel_fbdev; | 714 | struct intel_fbdev; |
714 | struct intel_fbc_work; | 715 | struct intel_fbc_work; |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index c06b516c1359..7e20b00d56a3 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -1261,8 +1261,9 @@ void assert_pipe(struct drm_i915_private *dev_priv, | |||
1261 | enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, | 1261 | enum transcoder cpu_transcoder = intel_pipe_to_cpu_transcoder(dev_priv, |
1262 | pipe); | 1262 | pipe); |
1263 | 1263 | ||
1264 | /* if we need the pipe A quirk it must be always on */ | 1264 | /* if we need the pipe quirk it must be always on */ |
1265 | if (pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) | 1265 | if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) || |
1266 | (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE)) | ||
1266 | state = true; | 1267 | state = true; |
1267 | 1268 | ||
1268 | if (!intel_display_power_enabled(dev_priv, | 1269 | if (!intel_display_power_enabled(dev_priv, |
@@ -1662,8 +1663,9 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) | |||
1662 | */ | 1663 | */ |
1663 | static void i9xx_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) | 1664 | static void i9xx_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe) |
1664 | { | 1665 | { |
1665 | /* Don't disable pipe A or pipe A PLLs if needed */ | 1666 | /* Don't disable pipe or pipe PLLs if needed */ |
1666 | if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE)) | 1667 | if ((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) || |
1668 | (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE)) | ||
1667 | return; | 1669 | return; |
1668 | 1670 | ||
1669 | /* Make sure the pipe isn't still relying on us */ | 1671 | /* Make sure the pipe isn't still relying on us */ |
@@ -2031,8 +2033,8 @@ static void intel_enable_pipe(struct intel_crtc *crtc) | |||
2031 | reg = PIPECONF(cpu_transcoder); | 2033 | reg = PIPECONF(cpu_transcoder); |
2032 | val = I915_READ(reg); | 2034 | val = I915_READ(reg); |
2033 | if (val & PIPECONF_ENABLE) { | 2035 | if (val & PIPECONF_ENABLE) { |
2034 | WARN_ON(!(pipe == PIPE_A && | 2036 | WARN_ON(!((pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) || |
2035 | dev_priv->quirks & QUIRK_PIPEA_FORCE)); | 2037 | (pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE))); |
2036 | return; | 2038 | return; |
2037 | } | 2039 | } |
2038 | 2040 | ||
@@ -2079,7 +2081,8 @@ static void intel_disable_pipe(struct intel_crtc *crtc) | |||
2079 | val &= ~PIPECONF_DOUBLE_WIDE; | 2081 | val &= ~PIPECONF_DOUBLE_WIDE; |
2080 | 2082 | ||
2081 | /* Don't disable pipe or pipe PLLs if needed */ | 2083 | /* Don't disable pipe or pipe PLLs if needed */ |
2082 | if (!(pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE)) | 2084 | if (!(pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) && |
2085 | !(pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE)) | ||
2083 | val &= ~PIPECONF_ENABLE; | 2086 | val &= ~PIPECONF_ENABLE; |
2084 | 2087 | ||
2085 | I915_WRITE(reg, val); | 2088 | I915_WRITE(reg, val); |
@@ -6039,9 +6042,9 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) | |||
6039 | 6042 | ||
6040 | pipeconf = 0; | 6043 | pipeconf = 0; |
6041 | 6044 | ||
6042 | if (dev_priv->quirks & QUIRK_PIPEA_FORCE && | 6045 | if ((intel_crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) || |
6043 | I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE) | 6046 | (intel_crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE)) |
6044 | pipeconf |= PIPECONF_ENABLE; | 6047 | pipeconf |= I915_READ(PIPECONF(intel_crtc->pipe)) & PIPECONF_ENABLE; |
6045 | 6048 | ||
6046 | if (intel_crtc->config.double_wide) | 6049 | if (intel_crtc->config.double_wide) |
6047 | pipeconf |= PIPECONF_DOUBLE_WIDE; | 6050 | pipeconf |= PIPECONF_DOUBLE_WIDE; |
@@ -10754,8 +10757,9 @@ check_crtc_state(struct drm_device *dev) | |||
10754 | active = dev_priv->display.get_pipe_config(crtc, | 10757 | active = dev_priv->display.get_pipe_config(crtc, |
10755 | &pipe_config); | 10758 | &pipe_config); |
10756 | 10759 | ||
10757 | /* hw state is inconsistent with the pipe A quirk */ | 10760 | /* hw state is inconsistent with the pipe quirk */ |
10758 | if (crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) | 10761 | if ((crtc->pipe == PIPE_A && dev_priv->quirks & QUIRK_PIPEA_FORCE) || |
10762 | (crtc->pipe == PIPE_B && dev_priv->quirks & QUIRK_PIPEB_FORCE)) | ||
10759 | active = crtc->active; | 10763 | active = crtc->active; |
10760 | 10764 | ||
10761 | for_each_intel_encoder(dev, encoder) { | 10765 | for_each_intel_encoder(dev, encoder) { |
@@ -12565,6 +12569,14 @@ static void quirk_pipea_force(struct drm_device *dev) | |||
12565 | DRM_INFO("applying pipe a force quirk\n"); | 12569 | DRM_INFO("applying pipe a force quirk\n"); |
12566 | } | 12570 | } |
12567 | 12571 | ||
12572 | static void quirk_pipeb_force(struct drm_device *dev) | ||
12573 | { | ||
12574 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
12575 | |||
12576 | dev_priv->quirks |= QUIRK_PIPEB_FORCE; | ||
12577 | DRM_INFO("applying pipe b force quirk\n"); | ||
12578 | } | ||
12579 | |||
12568 | /* | 12580 | /* |
12569 | * Some machines (Lenovo U160) do not work with SSC on LVDS for some reason | 12581 | * Some machines (Lenovo U160) do not work with SSC on LVDS for some reason |
12570 | */ | 12582 | */ |
@@ -12642,6 +12654,9 @@ static struct intel_quirk intel_quirks[] = { | |||
12642 | /* 830 needs to leave pipe A & dpll A up */ | 12654 | /* 830 needs to leave pipe A & dpll A up */ |
12643 | { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, | 12655 | { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, |
12644 | 12656 | ||
12657 | /* 830 needs to leave pipe B & dpll B up */ | ||
12658 | { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipeb_force }, | ||
12659 | |||
12645 | /* Lenovo U160 cannot use SSC on LVDS */ | 12660 | /* Lenovo U160 cannot use SSC on LVDS */ |
12646 | { 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable }, | 12661 | { 0x0046, 0x17aa, 0x3920, quirk_ssc_force_disable }, |
12647 | 12662 | ||