From 9aaa722329d31d31b6ea64881db3e27531b17968 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 21 Feb 2011 22:23:52 +0000 Subject: [PATCH] drm/i915: Add support for limited color range of broadcast outputs In order to prevent "crushed blacks" on TVs, the range of the RGB output may be limited to 16-235. This used to be available through Xorg under the "Broadcast RGB" option, so reintroduce support for KMS. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=34543 Signed-off-by: Chris Wilson --- drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_dp.c | 22 ++++++++++++++++++++-- drivers/gpu/drm/i915/intel_hdmi.c | 19 +++++++++++++++++++ drivers/gpu/drm/i915/intel_sdvo.c | 26 ++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 139d152..63ed072 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1387,6 +1387,7 @@ #define SDVO_ENCODING_HDMI (0x2 << 10) /** Requird for HDMI operation */ #define SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9) +#define SDVO_COLOR_RANGE_16_235 (1 << 8) #define SDVO_BORDER_ENABLE (1 << 7) #define SDVO_AUDIO_ENABLE (1 << 6) /** New with 965, default is to be set */ diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 7ffb324..2d6c00a 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -49,6 +49,7 @@ struct intel_dp { uint8_t link_configuration[DP_LINK_CONFIGURATION_SIZE]; bool has_audio; int force_audio; + uint32_t color_range; int dpms_mode; uint8_t link_bw; uint8_t lane_count; @@ -60,6 +61,7 @@ struct intel_dp { uint8_t link_status[DP_LINK_STATUS_SIZE]; struct drm_property *force_audio_property; + struct drm_property *broadcast_rgb_property; }; /** @@ -741,8 +743,8 @@ intel_dp_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_crtc *crtc = intel_dp->base.base.crtc; struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - intel_dp->DP = (DP_VOLTAGE_0_4 | - DP_PRE_EMPHASIS_0); + intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0; + intel_dp->DP |= intel_dp->color_range; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) intel_dp->DP |= DP_SYNC_HS_HIGH; @@ -1708,6 +1710,14 @@ intel_dp_set_property(struct drm_connector *connector, goto done; } + if (property == intel_dp->broadcast_rgb_property) { + if (val == !!intel_dp->color_range) + return 0; + + intel_dp->color_range = val ? DP_COLOR_RANGE_16_235 : 0; + goto done; + } + return -EINVAL; done: @@ -1827,6 +1837,14 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect intel_dp->force_audio_property->values[1] = 1; drm_connector_attach_property(connector, intel_dp->force_audio_property, 0); } + + intel_dp->broadcast_rgb_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE, "broadcast rgb", 2); + if (intel_dp->broadcast_rgb_property) { + intel_dp->broadcast_rgb_property->values[0] = 0; + intel_dp->broadcast_rgb_property->values[1] = 1; + drm_connector_attach_property(connector, intel_dp->broadcast_rgb_property, 0); + } } void diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index c635c9e..3db78aa 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -41,10 +41,12 @@ struct intel_hdmi { struct intel_encoder base; u32 sdvox_reg; int ddc_bus; + uint32_t color_range; bool has_hdmi_sink; bool has_audio; int force_audio; struct drm_property *force_audio_property; + struct drm_property *broadcast_rgb_property; }; static struct intel_hdmi *enc_to_intel_hdmi(struct drm_encoder *encoder) @@ -124,6 +126,7 @@ static void intel_hdmi_mode_set(struct drm_encoder *encoder, u32 sdvox; sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE; + sdvox |= intel_hdmi->color_range; if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) sdvox |= SDVO_VSYNC_ACTIVE_HIGH; if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) @@ -305,6 +308,14 @@ intel_hdmi_set_property(struct drm_connector *connector, goto done; } + if (property == intel_hdmi->broadcast_rgb_property) { + if (val == !!intel_hdmi->color_range) + return 0; + + intel_hdmi->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0; + goto done; + } + return -EINVAL; done: @@ -363,6 +374,14 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c intel_hdmi->force_audio_property->values[1] = 1; drm_connector_attach_property(connector, intel_hdmi->force_audio_property, 0); } + + intel_hdmi->broadcast_rgb_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE, "broadcast rgb", 2); + if (intel_hdmi->broadcast_rgb_property) { + intel_hdmi->broadcast_rgb_property->values[0] = 0; + intel_hdmi->broadcast_rgb_property->values[1] = 1; + drm_connector_attach_property(connector, intel_hdmi->broadcast_rgb_property, 0); + } } void intel_hdmi_init(struct drm_device *dev, int sdvox_reg) diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index 19c817a..c40fc06 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c @@ -93,6 +93,12 @@ struct intel_sdvo { uint16_t attached_output; /** + * 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. + */ + uint32_t color_range; + + /** * This is set if we're going to treat the device as TV-out. * * While we have these nice friendly flags for output types that ought @@ -143,6 +149,7 @@ struct intel_sdvo_connector { struct drm_property *tv_format; struct drm_property *force_audio_property; + struct drm_property *broadcast_rgb_property; /* add the property for the SDVO-TV */ struct drm_property *left; @@ -1056,6 +1063,8 @@ static void intel_sdvo_mode_set(struct drm_encoder *encoder, /* Set the SDVO control regs. */ if (INTEL_INFO(dev)->gen >= 4) { sdvox = 0; + if (intel_sdvo->is_hdmi) /* XXX DevCL/DevCTG and 8bpp only */ + sdvox |= intel_sdvo->color_range; if (INTEL_INFO(dev)->gen < 5) sdvox |= SDVO_BORDER_ENABLE; if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) @@ -1724,6 +1733,14 @@ intel_sdvo_set_property(struct drm_connector *connector, goto done; } + if (property == intel_sdvo_connector->broadcast_rgb_property) { + if (val == !!intel_sdvo->color_range) + return 0; + + intel_sdvo->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0; + goto done; + } + #define CHECK_PROPERTY(name, NAME) \ if (intel_sdvo_connector->name == property) { \ if (intel_sdvo_connector->cur_##name == temp_value) return 0; \ @@ -2028,6 +2045,15 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo_connector *connector) drm_connector_attach_property(&connector->base.base, connector->force_audio_property, 0); } + + connector->broadcast_rgb_property = + drm_property_create(dev, DRM_MODE_PROP_RANGE, "broadcast rgb", 2); + if (connector->broadcast_rgb_property) { + connector->broadcast_rgb_property->values[0] = 0; + connector->broadcast_rgb_property->values[1] = 1; + drm_connector_attach_property(&connector->base.base, + connector->broadcast_rgb_property, 0); + } } static bool -- 1.7.2.3