]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/commitdiff
drm/i915: Add "Automatic" mode for the "Broadcast RGB" property
authorVille Syrjälä <ville.syrjala@linux.intel.com>
Thu, 17 Jan 2013 14:31:29 +0000 (16:31 +0200)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Sun, 20 Jan 2013 12:09:44 +0000 (13:09 +0100)
Add a new "Automatic" mode to the "Broadcast RGB" range property.
When selected the driver automagically selects between full range and
limited range output.

Based on CEA-861 [1] guidelines, limited range output is selected if the
mode is a CEA mode, except 640x480. Otherwise full range output is used.
Additionally DVI monitors should most likely default to full range
always.

As per DP1.2a [2] DisplayPort should always use full range for 18bpp, and
otherwise will follow CEA-861 rules.

NOTE: The default value for the property will now be "Automatic"
so some people may be affected in case they're relying on the
current full range default.

[1] CEA-861-E - 5.1 Default Encoding Parameters
[2] VESA DisplayPort Ver.1.2a - 5.1.1.1 Video Colorimetry

v2: Use has_hdmi_sink to check if a HDMI monitor is present
v3: Add information about relevant spec chapters

Reviewed-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_drv.h
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_modes.c
drivers/gpu/drm/i915/intel_sdvo.c

index f3f2e5e1393fbac1219bb8f9321428f6ddb1e0a8..0a2a18b8a0750ba73c18311f4b636d9e72a7f399 100644 (file)
@@ -1811,5 +1811,9 @@ __i915_write(64, q)
 #define POSTING_READ(reg)      (void)I915_READ_NOTRACE(reg)
 #define POSTING_READ16(reg)    (void)I915_READ16_NOTRACE(reg)
 
+/* "Broadcast RGB" property */
+#define INTEL_BROADCAST_RGB_AUTO 0
+#define INTEL_BROADCAST_RGB_FULL 1
+#define INTEL_BROADCAST_RGB_LIMITED 2
 
 #endif
index d9956278a56eabe0127c5f918e10eedd0e6a7982..1492706ed08711c83c77d4410375a639297fd9b5 100644 (file)
@@ -764,6 +764,18 @@ intel_dp_mode_fixup(struct drm_encoder *encoder,
 
        bpp = adjusted_mode->private_flags & INTEL_MODE_DP_FORCE_6BPC ? 18 : 24;
 
+       if (intel_dp->color_range_auto) {
+               /*
+                * See:
+                * CEA-861-E - 5.1 Default Encoding Parameters
+                * VESA DisplayPort Ver.1.2a - 5.1.1.1 Video Colorimetry
+                */
+               if (bpp != 18 && drm_mode_cea_vic(adjusted_mode) > 1)
+                       intel_dp->color_range = DP_COLOR_RANGE_16_235;
+               else
+                       intel_dp->color_range = 0;
+       }
+
        if (intel_dp->color_range)
                adjusted_mode->private_flags |= INTEL_MODE_LIMITED_COLOR_RANGE;
 
@@ -2462,10 +2474,21 @@ intel_dp_set_property(struct drm_connector *connector,
        }
 
        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;
+               switch (val) {
+               case INTEL_BROADCAST_RGB_AUTO:
+                       intel_dp->color_range_auto = true;
+                       break;
+               case INTEL_BROADCAST_RGB_FULL:
+                       intel_dp->color_range_auto = false;
+                       intel_dp->color_range = 0;
+                       break;
+               case INTEL_BROADCAST_RGB_LIMITED:
+                       intel_dp->color_range_auto = false;
+                       intel_dp->color_range = DP_COLOR_RANGE_16_235;
+                       break;
+               default:
+                       return -EINVAL;
+               }
                goto done;
        }
 
@@ -2606,6 +2629,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
 
        intel_attach_force_audio_property(connector);
        intel_attach_broadcast_rgb_property(connector);
+       intel_dp->color_range_auto = true;
 
        if (is_edp(intel_dp)) {
                drm_mode_create_scaling_mode_property(connector->dev);
index 4df47be84abd1439b78f7831abdbf4cd33cf2bd8..1a698c6f16e79e0595d1ea45b57298500d49942a 100644 (file)
@@ -343,6 +343,7 @@ struct intel_hdmi {
        u32 sdvox_reg;
        int ddc_bus;
        uint32_t color_range;
+       bool color_range_auto;
        bool has_hdmi_sink;
        bool has_audio;
        enum hdmi_force_audio force_audio;
@@ -362,6 +363,7 @@ struct intel_dp {
        bool has_audio;
        enum hdmi_force_audio force_audio;
        uint32_t color_range;
+       bool color_range_auto;
        uint8_t link_bw;
        uint8_t lane_count;
        uint8_t dpcd[DP_RECEIVER_CAP_SIZE];
index f194d756a58c14ae33225662590a2ed5775e9a6a..db67be66639ba1ab2a8e5641a3457ae2cf164546 100644 (file)
@@ -768,6 +768,15 @@ bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
 {
        struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 
+       if (intel_hdmi->color_range_auto) {
+               /* See CEA-861-E - 5.1 Default Encoding Parameters */
+               if (intel_hdmi->has_hdmi_sink &&
+                   drm_mode_cea_vic(adjusted_mode) > 1)
+                       intel_hdmi->color_range = SDVO_COLOR_RANGE_16_235;
+               else
+                       intel_hdmi->color_range = 0;
+       }
+
        if (intel_hdmi->color_range)
                adjusted_mode->private_flags |= INTEL_MODE_LIMITED_COLOR_RANGE;
 
@@ -912,10 +921,21 @@ intel_hdmi_set_property(struct drm_connector *connector,
        }
 
        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;
+               switch (val) {
+               case INTEL_BROADCAST_RGB_AUTO:
+                       intel_hdmi->color_range_auto = true;
+                       break;
+               case INTEL_BROADCAST_RGB_FULL:
+                       intel_hdmi->color_range_auto = false;
+                       intel_hdmi->color_range = 0;
+                       break;
+               case INTEL_BROADCAST_RGB_LIMITED:
+                       intel_hdmi->color_range_auto = false;
+                       intel_hdmi->color_range = SDVO_COLOR_RANGE_16_235;
+                       break;
+               default:
+                       return -EINVAL;
+               }
                goto done;
        }
 
@@ -964,6 +984,7 @@ intel_hdmi_add_properties(struct intel_hdmi *intel_hdmi, struct drm_connector *c
 {
        intel_attach_force_audio_property(connector);
        intel_attach_broadcast_rgb_property(connector);
+       intel_hdmi->color_range_auto = true;
 }
 
 void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
index 49249bb974859a931bdcaaeb85f292ad1b6eab0c..0e860f39933d8581cce867d8a3eaa8d955edc4a9 100644 (file)
@@ -100,8 +100,9 @@ intel_attach_force_audio_property(struct drm_connector *connector)
 }
 
 static const struct drm_prop_enum_list broadcast_rgb_names[] = {
-       { 0, "Full" },
-       { 1, "Limited 16:235" },
+       { INTEL_BROADCAST_RGB_AUTO, "Automatic" },
+       { INTEL_BROADCAST_RGB_FULL, "Full" },
+       { INTEL_BROADCAST_RGB_LIMITED, "Limited 16:235" },
 };
 
 void
index 3b8491af1f236ac2f5df969768b5b644e5808950..3e34a3592e324ed24ee24ab5c4af2bd229fd3a3b 100644 (file)
@@ -103,6 +103,7 @@ struct intel_sdvo {
         * It is only valid when using TMDS encoding and 8 bit per color mode.
         */
        uint32_t color_range;
+       bool color_range_auto;
 
        /**
         * This is set if we're going to treat the device as TV-out.
@@ -1064,6 +1065,15 @@ static bool intel_sdvo_mode_fixup(struct drm_encoder *encoder,
        multiplier = intel_sdvo_get_pixel_multiplier(adjusted_mode);
        intel_mode_set_pixel_multiplier(adjusted_mode, multiplier);
 
+       if (intel_sdvo->color_range_auto) {
+               /* See CEA-861-E - 5.1 Default Encoding Parameters */
+               if (intel_sdvo->has_hdmi_monitor &&
+                   drm_mode_cea_vic(adjusted_mode) > 1)
+                       intel_sdvo->color_range = SDVO_COLOR_RANGE_16_235;
+               else
+                       intel_sdvo->color_range = 0;
+       }
+
        if (intel_sdvo->color_range)
                adjusted_mode->private_flags |= INTEL_MODE_LIMITED_COLOR_RANGE;
 
@@ -1900,10 +1910,21 @@ intel_sdvo_set_property(struct drm_connector *connector,
        }
 
        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;
+               switch (val) {
+               case INTEL_BROADCAST_RGB_AUTO:
+                       intel_sdvo->color_range_auto = true;
+                       break;
+               case INTEL_BROADCAST_RGB_FULL:
+                       intel_sdvo->color_range_auto = false;
+                       intel_sdvo->color_range = 0;
+                       break;
+               case INTEL_BROADCAST_RGB_LIMITED:
+                       intel_sdvo->color_range_auto = false;
+                       intel_sdvo->color_range = SDVO_COLOR_RANGE_16_235;
+                       break;
+               default:
+                       return -EINVAL;
+               }
                goto done;
        }
 
@@ -2200,13 +2221,16 @@ intel_sdvo_connector_init(struct intel_sdvo_connector *connector,
 }
 
 static void
-intel_sdvo_add_hdmi_properties(struct intel_sdvo_connector *connector)
+intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo,
+                              struct intel_sdvo_connector *connector)
 {
        struct drm_device *dev = connector->base.base.dev;
 
        intel_attach_force_audio_property(&connector->base.base);
-       if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev))
+       if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev)) {
                intel_attach_broadcast_rgb_property(&connector->base.base);
+               intel_sdvo->color_range_auto = true;
+       }
 }
 
 static bool
@@ -2254,7 +2278,7 @@ intel_sdvo_dvi_init(struct intel_sdvo *intel_sdvo, int device)
 
        intel_sdvo_connector_init(intel_sdvo_connector, intel_sdvo);
        if (intel_sdvo->is_hdmi)
-               intel_sdvo_add_hdmi_properties(intel_sdvo_connector);
+               intel_sdvo_add_hdmi_properties(intel_sdvo, intel_sdvo_connector);
 
        return true;
 }