From 7cd015a0a37265e23bbdce7ce8f7e00507abe9ed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 5 Sep 2011 11:53:21 -0700 Subject: [PATCH 1/3] drm/i915: Enable dither whenever display bpc < frame buffer bpc We want to enable dithering on any pipe where the frame buffer has more color resolution than the output device. The previous code was incorrectly clamping the frame buffer bpc to the display bpc, effectively disabling dithering all of the time as the computed frame buffer bpc would never be larger than the display bpc. Signed-off-by: Keith Packard Reported-by: Oliver Hartkopp Tested-by: Oliver Hartkopp --- drivers/gpu/drm/i915/intel_display.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 56a8554d903961..9fb4a40bd9e506 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -4687,13 +4687,13 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, bpc = 6; /* min is 18bpp */ break; case 24: - bpc = min((unsigned int)8, display_bpc); + bpc = 8; break; case 30: - bpc = min((unsigned int)10, display_bpc); + bpc = 10; break; case 48: - bpc = min((unsigned int)12, display_bpc); + bpc = 12; break; default: DRM_DEBUG("unsupported depth, assuming 24 bits\n"); @@ -4701,10 +4701,12 @@ static bool intel_choose_pipe_bpp_dither(struct drm_crtc *crtc, break; } + display_bpc = min(display_bpc, bpc); + DRM_DEBUG_DRIVER("setting pipe bpc to %d (max display bpc %d)\n", bpc, display_bpc); - *pipe_bpp = bpc * 3; + *pipe_bpp = display_bpc * 3; return display_bpc != bpc; } From cc68c81aed7d892deaf12d720d5455208e94cd0a Mon Sep 17 00:00:00 2001 From: Simon Farnsworth Date: Wed, 21 Sep 2011 17:13:30 +0100 Subject: [PATCH 2/3] drm/i915: Enable SDVO hotplug interrupts for HDMI and DVI I was seeing a nasty 5 frame glitch every 10 seconds, caused by the poll for connection on DVI attached by SDVO. As my SDVO DVI supports hotplug detect interrupts, the fix is to enable them, and hook them in to the various bits of driver infrastructure so that they work reliably. Note that this is only tested on single-function DVI-D SDVOs, on two platforms (965GME and 945GSE), and has not been checked against a specification document. With lots of help from Adam Jackson on IRC. Signed-off-by: Simon Farnsworth Reviewed-by: Keith Packard Signed-off-by: Keith Packard --- drivers/gpu/drm/i915/intel_drv.h | 3 -- drivers/gpu/drm/i915/intel_sdvo.c | 88 ++++++++++--------------------- 2 files changed, 29 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 0b2ee9d39980c1..fe1099d8817e30 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -337,9 +337,6 @@ extern void intel_release_load_detect_pipe(struct intel_encoder *intel_encoder, struct drm_connector *connector, struct intel_load_detect_pipe *old); -extern struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB); -extern int intel_sdvo_supports_hotplug(struct drm_connector *connector); -extern void intel_sdvo_set_hotplug(struct drm_connector *connector, int enable); extern void intelfb_restore(void); extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, u16 blue, int regno); diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 30fe554d8936a8..6348c499616f08 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -92,6 +92,11 @@ struct intel_sdvo { */ uint16_t attached_output; + /* + * Hotplug activation bits for this device + */ + uint8_t hotplug_active[2]; + /** * This is used to select the color range of RBG outputs in HDMI mode. * It is only valid when using TMDS encoding and 8 bit per color mode. @@ -1208,74 +1213,20 @@ static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct in return true; } -/* No use! */ -#if 0 -struct drm_connector* intel_sdvo_find(struct drm_device *dev, int sdvoB) -{ - struct drm_connector *connector = NULL; - struct intel_sdvo *iout = NULL; - struct intel_sdvo *sdvo; - - /* find the sdvo connector */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - iout = to_intel_sdvo(connector); - - if (iout->type != INTEL_OUTPUT_SDVO) - continue; - - sdvo = iout->dev_priv; - - if (sdvo->sdvo_reg == SDVOB && sdvoB) - return connector; - - if (sdvo->sdvo_reg == SDVOC && !sdvoB) - return connector; - - } - - return NULL; -} - -int intel_sdvo_supports_hotplug(struct drm_connector *connector) +static int intel_sdvo_supports_hotplug(struct intel_sdvo *intel_sdvo) { u8 response[2]; - u8 status; - struct intel_sdvo *intel_sdvo; - DRM_DEBUG_KMS("\n"); - - if (!connector) - return 0; - - intel_sdvo = to_intel_sdvo(connector); return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, &response, 2) && response[0]; } -void intel_sdvo_set_hotplug(struct drm_connector *connector, int on) +static void intel_sdvo_enable_hotplug(struct intel_encoder *encoder) { - u8 response[2]; - u8 status; - struct intel_sdvo *intel_sdvo = to_intel_sdvo(connector); - - intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); - intel_sdvo_read_response(intel_sdvo, &response, 2); - - if (on) { - intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, 0); - status = intel_sdvo_read_response(intel_sdvo, &response, 2); - - intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); - } else { - response[0] = 0; - response[1] = 0; - intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &response, 2); - } + struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base); - intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, NULL, 0); - intel_sdvo_read_response(intel_sdvo, &response, 2); + intel_sdvo_write_cmd(intel_sdvo, SDVO_CMD_SET_ACTIVE_HOT_PLUG, &intel_sdvo->hotplug_active, 2); } -#endif static bool intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo) @@ -2045,6 +1996,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) { struct drm_encoder *encoder = &intel_sdvo->base.base; struct drm_connector *connector; + struct intel_encoder *intel_encoder = to_intel_encoder(encoder); struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; @@ -2062,7 +2014,17 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device) intel_connector = &intel_sdvo_connector->base; connector = &intel_connector->base; - connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; + if (intel_sdvo_supports_hotplug(intel_sdvo) & (1 << device)) { + connector->polled = DRM_CONNECTOR_POLL_HPD; + intel_sdvo->hotplug_active[0] |= 1 << device; + /* Some SDVO devices have one-shot hotplug interrupts. + * Ensure that they get re-enabled when an interrupt happens. + */ + intel_encoder->hot_plug = intel_sdvo_enable_hotplug; + intel_sdvo_enable_hotplug(intel_encoder); + } + else + connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; encoder->encoder_type = DRM_MODE_ENCODER_TMDS; connector->connector_type = DRM_MODE_CONNECTOR_DVID; @@ -2569,6 +2531,14 @@ bool intel_sdvo_init(struct drm_device *dev, int sdvo_reg) if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps)) goto err; + /* Set up hotplug command - note paranoia about contents of reply. + * We assume that the hardware is in a sane state, and only touch + * the bits we think we understand. + */ + intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG, + &intel_sdvo->hotplug_active, 2); + intel_sdvo->hotplug_active[0] &= ~0x3; + if (intel_sdvo_output_setup(intel_sdvo, intel_sdvo->caps.output_flags) != true) { DRM_DEBUG_KMS("SDVO output failed to setup on SDVO%c\n", From cd0de039bff32ee314046c0e4c047c38aa696f84 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 19 Sep 2011 21:34:19 -0700 Subject: [PATCH 3/3] drm/i915: FBC off for ironlake and older, otherwise on by default Make the default FBC behaviour chipset specific, allowing us to turn it on by default for Ironlake and older where it has been seen to cause trouble with screen updates. Signed-off-by: Keith Packard Tested-by: Francis Moreau --- drivers/gpu/drm/i915/i915_drv.c | 4 ++-- drivers/gpu/drm/i915/intel_display.c | 12 ++++++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ce045a8cf82c82..f07e4252b70834 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -67,11 +67,11 @@ module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600); MODULE_PARM_DESC(i915_enable_rc6, "Enable power-saving render C-state 6 (default: true)"); -unsigned int i915_enable_fbc __read_mostly = 1; +unsigned int i915_enable_fbc __read_mostly = -1; module_param_named(i915_enable_fbc, i915_enable_fbc, int, 0600); MODULE_PARM_DESC(i915_enable_fbc, "Enable frame buffer compression for power savings " - "(default: false)"); + "(default: -1 (use per-chip default))"); unsigned int i915_lvds_downclock __read_mostly = 0; module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9fb4a40bd9e506..04411ad2e779c2 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1799,6 +1799,7 @@ static void intel_update_fbc(struct drm_device *dev) struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; struct drm_i915_gem_object *obj; + int enable_fbc; DRM_DEBUG_KMS("\n"); @@ -1839,8 +1840,15 @@ static void intel_update_fbc(struct drm_device *dev) intel_fb = to_intel_framebuffer(fb); obj = intel_fb->obj; - if (!i915_enable_fbc) { - DRM_DEBUG_KMS("fbc disabled per module param (default off)\n"); + enable_fbc = i915_enable_fbc; + if (enable_fbc < 0) { + DRM_DEBUG_KMS("fbc set to per-chip default\n"); + enable_fbc = 1; + if (INTEL_INFO(dev)->gen <= 5) + enable_fbc = 0; + } + if (!enable_fbc) { + DRM_DEBUG_KMS("fbc disabled per module param\n"); dev_priv->no_fbc_reason = FBC_MODULE_PARAM; goto out_disable; }