Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e953fd7b authored by Chris Wilson's avatar Chris Wilson
Browse files

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: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent ce453d81
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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 {
+1 −0
Original line number Diff line number Diff line
@@ -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 */
+14 −2
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -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);
+13 −0
Original line number Diff line number Diff line
@@ -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)
Loading