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 <chris@chris-wilson.co.uk>
This commit is contained in:
parent
ce453d81cb
commit
e953fd7bb3
|
@ -707,6 +707,8 @@ typedef struct drm_i915_private {
|
|||
|
||||
/* list of fbdev register on this device */
|
||||
struct intel_fbdev *fbdev;
|
||||
|
||||
struct drm_property *broadcast_rgb_property;
|
||||
} drm_i915_private_t;
|
||||
|
||||
struct drm_i915_gem_object {
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
@ -741,8 +742,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;
|
||||
|
@ -1680,6 +1681,7 @@ intel_dp_set_property(struct drm_connector *connector,
|
|||
struct drm_property *property,
|
||||
uint64_t val)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
struct intel_dp *intel_dp = intel_attached_dp(connector);
|
||||
int ret;
|
||||
|
||||
|
@ -1708,6 +1710,14 @@ intel_dp_set_property(struct drm_connector *connector,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (property == dev_priv->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,8 @@ 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_attach_broadcast_rgb_property(connector);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -237,6 +237,8 @@ struct intel_unpin_work {
|
|||
int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
|
||||
extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
|
||||
|
||||
extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
|
||||
|
||||
extern void intel_crt_init(struct drm_device *dev);
|
||||
extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
|
||||
void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
|
||||
|
|
|
@ -41,6 +41,7 @@ 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;
|
||||
|
@ -124,6 +125,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)
|
||||
|
@ -278,6 +280,7 @@ intel_hdmi_set_property(struct drm_connector *connector,
|
|||
uint64_t val)
|
||||
{
|
||||
struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = drm_connector_property_set_value(connector, property, val);
|
||||
|
@ -305,6 +308,14 @@ intel_hdmi_set_property(struct drm_connector *connector,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (property == dev_priv->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,8 @@ 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_attach_broadcast_rgb_property(connector);
|
||||
}
|
||||
|
||||
void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
|
||||
|
|
|
@ -80,3 +80,33 @@ int intel_ddc_get_modes(struct drm_connector *connector,
|
|||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const char *broadcast_rgb_names[] = {
|
||||
"Full",
|
||||
"Limited 16:235",
|
||||
};
|
||||
|
||||
void
|
||||
intel_attach_broadcast_rgb_property(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_i915_private *dev_priv = dev->dev_private;
|
||||
struct drm_property *prop;
|
||||
int i;
|
||||
|
||||
prop = dev_priv->broadcast_rgb_property;
|
||||
if (prop == NULL) {
|
||||
prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
|
||||
"Broadcast RGB",
|
||||
ARRAY_SIZE(broadcast_rgb_names));
|
||||
if (prop == NULL)
|
||||
return;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(broadcast_rgb_names); i++)
|
||||
drm_property_add_enum(prop, i, i, broadcast_rgb_names[i]);
|
||||
|
||||
dev_priv->broadcast_rgb_property = prop;
|
||||
}
|
||||
|
||||
drm_connector_attach_property(connector, prop, 0);
|
||||
}
|
||||
|
|
|
@ -92,6 +92,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.
|
||||
*
|
||||
|
@ -1056,6 +1062,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)
|
||||
sdvox |= intel_sdvo->color_range;
|
||||
if (INTEL_INFO(dev)->gen < 5)
|
||||
sdvox |= SDVO_BORDER_ENABLE;
|
||||
if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
|
||||
|
@ -1695,6 +1703,7 @@ intel_sdvo_set_property(struct drm_connector *connector,
|
|||
{
|
||||
struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
|
||||
struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
|
||||
struct drm_i915_private *dev_priv = connector->dev->dev_private;
|
||||
uint16_t temp_value;
|
||||
uint8_t cmd;
|
||||
int ret;
|
||||
|
@ -1724,6 +1733,14 @@ intel_sdvo_set_property(struct drm_connector *connector,
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (property == dev_priv->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,9 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo_connector *connector)
|
|||
drm_connector_attach_property(&connector->base.base,
|
||||
connector->force_audio_property, 0);
|
||||
}
|
||||
|
||||
if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev))
|
||||
intel_attach_broadcast_rgb_property(&connector->base.base);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
Loading…
Reference in New Issue