diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_display.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 79 |
1 files changed, 66 insertions, 13 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 2b6ce9b2674a..461a637f1ef7 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -3253,6 +3253,16 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc) | |||
3253 | 3253 | ||
3254 | if (HAS_PCH_CPT(dev)) | 3254 | if (HAS_PCH_CPT(dev)) |
3255 | intel_cpt_verify_modeset(dev, intel_crtc->pipe); | 3255 | intel_cpt_verify_modeset(dev, intel_crtc->pipe); |
3256 | |||
3257 | /* | ||
3258 | * There seems to be a race in PCH platform hw (at least on some | ||
3259 | * outputs) where an enabled pipe still completes any pageflip right | ||
3260 | * away (as if the pipe is off) instead of waiting for vblank. As soon | ||
3261 | * as the first vblank happend, everything works as expected. Hence just | ||
3262 | * wait for one vblank before returning to avoid strange things | ||
3263 | * happening. | ||
3264 | */ | ||
3265 | intel_wait_for_vblank(dev, intel_crtc->pipe); | ||
3256 | } | 3266 | } |
3257 | 3267 | ||
3258 | static void ironlake_crtc_disable(struct drm_crtc *crtc) | 3268 | static void ironlake_crtc_disable(struct drm_crtc *crtc) |
@@ -7882,6 +7892,34 @@ struct intel_quirk { | |||
7882 | void (*hook)(struct drm_device *dev); | 7892 | void (*hook)(struct drm_device *dev); |
7883 | }; | 7893 | }; |
7884 | 7894 | ||
7895 | /* For systems that don't have a meaningful PCI subdevice/subvendor ID */ | ||
7896 | struct intel_dmi_quirk { | ||
7897 | void (*hook)(struct drm_device *dev); | ||
7898 | const struct dmi_system_id (*dmi_id_list)[]; | ||
7899 | }; | ||
7900 | |||
7901 | static int intel_dmi_reverse_brightness(const struct dmi_system_id *id) | ||
7902 | { | ||
7903 | DRM_INFO("Backlight polarity reversed on %s\n", id->ident); | ||
7904 | return 1; | ||
7905 | } | ||
7906 | |||
7907 | static const struct intel_dmi_quirk intel_dmi_quirks[] = { | ||
7908 | { | ||
7909 | .dmi_id_list = &(const struct dmi_system_id[]) { | ||
7910 | { | ||
7911 | .callback = intel_dmi_reverse_brightness, | ||
7912 | .ident = "NCR Corporation", | ||
7913 | .matches = {DMI_MATCH(DMI_SYS_VENDOR, "NCR Corporation"), | ||
7914 | DMI_MATCH(DMI_PRODUCT_NAME, ""), | ||
7915 | }, | ||
7916 | }, | ||
7917 | { } /* terminating entry */ | ||
7918 | }, | ||
7919 | .hook = quirk_invert_brightness, | ||
7920 | }, | ||
7921 | }; | ||
7922 | |||
7885 | static struct intel_quirk intel_quirks[] = { | 7923 | static struct intel_quirk intel_quirks[] = { |
7886 | /* HP Mini needs pipe A force quirk (LP: #322104) */ | 7924 | /* HP Mini needs pipe A force quirk (LP: #322104) */ |
7887 | { 0x27ae, 0x103c, 0x361a, quirk_pipea_force }, | 7925 | { 0x27ae, 0x103c, 0x361a, quirk_pipea_force }, |
@@ -7892,8 +7930,7 @@ static struct intel_quirk intel_quirks[] = { | |||
7892 | /* ThinkPad T60 needs pipe A force quirk (bug #16494) */ | 7930 | /* ThinkPad T60 needs pipe A force quirk (bug #16494) */ |
7893 | { 0x2782, 0x17aa, 0x201a, quirk_pipea_force }, | 7931 | { 0x2782, 0x17aa, 0x201a, quirk_pipea_force }, |
7894 | 7932 | ||
7895 | /* 855 & before need to leave pipe A & dpll A up */ | 7933 | /* 830/845 need to leave pipe A & dpll A up */ |
7896 | { 0x3582, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, | ||
7897 | { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, | 7934 | { 0x2562, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, |
7898 | { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, | 7935 | { 0x3577, PCI_ANY_ID, PCI_ANY_ID, quirk_pipea_force }, |
7899 | 7936 | ||
@@ -7922,6 +7959,10 @@ static void intel_init_quirks(struct drm_device *dev) | |||
7922 | q->subsystem_device == PCI_ANY_ID)) | 7959 | q->subsystem_device == PCI_ANY_ID)) |
7923 | q->hook(dev); | 7960 | q->hook(dev); |
7924 | } | 7961 | } |
7962 | for (i = 0; i < ARRAY_SIZE(intel_dmi_quirks); i++) { | ||
7963 | if (dmi_check_system(*intel_dmi_quirks[i].dmi_id_list) != 0) | ||
7964 | intel_dmi_quirks[i].hook(dev); | ||
7965 | } | ||
7925 | } | 7966 | } |
7926 | 7967 | ||
7927 | /* Disable the VGA plane that we never use */ | 7968 | /* Disable the VGA plane that we never use */ |
@@ -8049,29 +8090,42 @@ static void intel_enable_pipe_a(struct drm_device *dev) | |||
8049 | 8090 | ||
8050 | } | 8091 | } |
8051 | 8092 | ||
8093 | static bool | ||
8094 | intel_check_plane_mapping(struct intel_crtc *crtc) | ||
8095 | { | ||
8096 | struct drm_i915_private *dev_priv = crtc->base.dev->dev_private; | ||
8097 | u32 reg, val; | ||
8098 | |||
8099 | if (dev_priv->num_pipe == 1) | ||
8100 | return true; | ||
8101 | |||
8102 | reg = DSPCNTR(!crtc->plane); | ||
8103 | val = I915_READ(reg); | ||
8104 | |||
8105 | if ((val & DISPLAY_PLANE_ENABLE) && | ||
8106 | (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) | ||
8107 | return false; | ||
8108 | |||
8109 | return true; | ||
8110 | } | ||
8111 | |||
8052 | static void intel_sanitize_crtc(struct intel_crtc *crtc) | 8112 | static void intel_sanitize_crtc(struct intel_crtc *crtc) |
8053 | { | 8113 | { |
8054 | struct drm_device *dev = crtc->base.dev; | 8114 | struct drm_device *dev = crtc->base.dev; |
8055 | struct drm_i915_private *dev_priv = dev->dev_private; | 8115 | struct drm_i915_private *dev_priv = dev->dev_private; |
8056 | u32 reg, val; | 8116 | u32 reg; |
8057 | 8117 | ||
8058 | /* Clear any frame start delays used for debugging left by the BIOS */ | 8118 | /* Clear any frame start delays used for debugging left by the BIOS */ |
8059 | reg = PIPECONF(crtc->pipe); | 8119 | reg = PIPECONF(crtc->pipe); |
8060 | I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); | 8120 | I915_WRITE(reg, I915_READ(reg) & ~PIPECONF_FRAME_START_DELAY_MASK); |
8061 | 8121 | ||
8062 | /* We need to sanitize the plane -> pipe mapping first because this will | 8122 | /* We need to sanitize the plane -> pipe mapping first because this will |
8063 | * disable the crtc (and hence change the state) if it is wrong. */ | 8123 | * disable the crtc (and hence change the state) if it is wrong. Note |
8064 | if (!HAS_PCH_SPLIT(dev)) { | 8124 | * that gen4+ has a fixed plane -> pipe mapping. */ |
8125 | if (INTEL_INFO(dev)->gen < 4 && !intel_check_plane_mapping(crtc)) { | ||
8065 | struct intel_connector *connector; | 8126 | struct intel_connector *connector; |
8066 | bool plane; | 8127 | bool plane; |
8067 | 8128 | ||
8068 | reg = DSPCNTR(crtc->plane); | ||
8069 | val = I915_READ(reg); | ||
8070 | |||
8071 | if ((val & DISPLAY_PLANE_ENABLE) == 0 && | ||
8072 | (!!(val & DISPPLANE_SEL_PIPE_MASK) == crtc->pipe)) | ||
8073 | goto ok; | ||
8074 | |||
8075 | DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n", | 8129 | DRM_DEBUG_KMS("[CRTC:%d] wrong plane connection detected!\n", |
8076 | crtc->base.base.id); | 8130 | crtc->base.base.id); |
8077 | 8131 | ||
@@ -8095,7 +8149,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc) | |||
8095 | WARN_ON(crtc->active); | 8149 | WARN_ON(crtc->active); |
8096 | crtc->base.enabled = false; | 8150 | crtc->base.enabled = false; |
8097 | } | 8151 | } |
8098 | ok: | ||
8099 | 8152 | ||
8100 | if (dev_priv->quirks & QUIRK_PIPEA_FORCE && | 8153 | if (dev_priv->quirks & QUIRK_PIPEA_FORCE && |
8101 | crtc->pipe == PIPE_A && !crtc->active) { | 8154 | crtc->pipe == PIPE_A && !crtc->active) { |