]> Pileus Git - ~andy/linux/blobdiff - drivers/gpu/drm/i915/intel_hdmi.c
Merge tag 'for-3.9-rc1' of git://gitorious.org/linux-pwm/linux-pwm
[~andy/linux] / drivers / gpu / drm / i915 / intel_hdmi.c
index 6387f9b0df994fa9ea8306f1dd3f906ad3b75018..fa8ec4a26041c65ccf48ebba4bc8bd9ec9b30946 100644 (file)
@@ -331,6 +331,7 @@ static void intel_set_infoframe(struct drm_encoder *encoder,
 static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
                                         struct drm_display_mode *adjusted_mode)
 {
+       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
        struct dip_infoframe avi_if = {
                .type = DIP_TYPE_AVI,
                .ver = DIP_VERSION_AVI,
@@ -340,7 +341,14 @@ static void intel_hdmi_set_avi_infoframe(struct drm_encoder *encoder,
        if (adjusted_mode->flags & DRM_MODE_FLAG_DBLCLK)
                avi_if.body.avi.YQ_CN_PR |= DIP_AVI_PR_2;
 
-       avi_if.body.avi.VIC = drm_mode_cea_vic(adjusted_mode);
+       if (intel_hdmi->rgb_quant_range_selectable) {
+               if (adjusted_mode->private_flags & INTEL_MODE_LIMITED_COLOR_RANGE)
+                       avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_LIMITED;
+               else
+                       avi_if.body.avi.ITC_EC_Q_SC |= DIP_AVI_RGB_QUANT_RANGE_FULL;
+       }
+
+       avi_if.body.avi.VIC = drm_match_cea_mode(adjusted_mode);
 
        intel_set_infoframe(encoder, &avi_if);
 }
@@ -364,7 +372,8 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
                               struct drm_display_mode *adjusted_mode)
 {
        struct drm_i915_private *dev_priv = encoder->dev->dev_private;
-       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+       struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+       struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
        u32 reg = VIDEO_DIP_CTL;
        u32 val = I915_READ(reg);
        u32 port;
@@ -391,11 +400,11 @@ static void g4x_set_infoframes(struct drm_encoder *encoder,
                return;
        }
 
-       switch (intel_hdmi->sdvox_reg) {
-       case SDVOB:
+       switch (intel_dig_port->port) {
+       case PORT_B:
                port = VIDEO_DIP_PORT_B;
                break;
-       case SDVOC:
+       case PORT_C:
                port = VIDEO_DIP_PORT_C;
                break;
        default:
@@ -428,7 +437,8 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
 {
        struct drm_i915_private *dev_priv = encoder->dev->dev_private;
        struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc);
-       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
+       struct intel_digital_port *intel_dig_port = enc_to_dig_port(encoder);
+       struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi;
        u32 reg = TVIDEO_DIP_CTL(intel_crtc->pipe);
        u32 val = I915_READ(reg);
        u32 port;
@@ -447,14 +457,14 @@ static void ibx_set_infoframes(struct drm_encoder *encoder,
                return;
        }
 
-       switch (intel_hdmi->sdvox_reg) {
-       case HDMIB:
+       switch (intel_dig_port->port) {
+       case PORT_B:
                port = VIDEO_DIP_PORT_B;
                break;
-       case HDMIC:
+       case PORT_C:
                port = VIDEO_DIP_PORT_C;
                break;
-       case HDMID:
+       case PORT_D:
                port = VIDEO_DIP_PORT_D;
                break;
        default:
@@ -766,28 +776,21 @@ bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
                           const struct drm_display_mode *mode,
                           struct drm_display_mode *adjusted_mode)
 {
-       return true;
-}
-
-static bool g4x_hdmi_connected(struct intel_hdmi *intel_hdmi)
-{
-       struct drm_device *dev = intel_hdmi_to_dev(intel_hdmi);
-       struct drm_i915_private *dev_priv = dev->dev_private;
-       uint32_t bit;
+       struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
 
-       switch (intel_hdmi->sdvox_reg) {
-       case SDVOB:
-               bit = HDMIB_HOTPLUG_LIVE_STATUS;
-               break;
-       case SDVOC:
-               bit = HDMIC_HOTPLUG_LIVE_STATUS;
-               break;
-       default:
-               bit = 0;
-               break;
+       if (intel_hdmi->color_range_auto) {
+               /* See CEA-861-E - 5.1 Default Encoding Parameters */
+               if (intel_hdmi->has_hdmi_sink &&
+                   drm_match_cea_mode(adjusted_mode) > 1)
+                       intel_hdmi->color_range = SDVO_COLOR_RANGE_16_235;
+               else
+                       intel_hdmi->color_range = 0;
        }
 
-       return I915_READ(PORT_HOTPLUG_STAT) & bit;
+       if (intel_hdmi->color_range)
+               adjusted_mode->private_flags |= INTEL_MODE_LIMITED_COLOR_RANGE;
+
+       return true;
 }
 
 static enum drm_connector_status
@@ -802,15 +805,9 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
        struct edid *edid;
        enum drm_connector_status status = connector_status_disconnected;
 
-
-       if (IS_G4X(dev) && !g4x_hdmi_connected(intel_hdmi))
-               return status;
-       else if (HAS_PCH_SPLIT(dev) &&
-                !ibx_digital_port_connected(dev_priv, intel_dig_port))
-                return status;
-
        intel_hdmi->has_hdmi_sink = false;
        intel_hdmi->has_audio = false;
+       intel_hdmi->rgb_quant_range_selectable = false;
        edid = drm_get_edid(connector,
                            intel_gmbus_get_adapter(dev_priv,
                                                    intel_hdmi->ddc_bus));
@@ -822,6 +819,8 @@ intel_hdmi_detect(struct drm_connector *connector, bool force)
                                intel_hdmi->has_hdmi_sink =
                                                drm_detect_hdmi_monitor(edid);
                        intel_hdmi->has_audio = drm_detect_monitor_audio(edid);
+                       intel_hdmi->rgb_quant_range_selectable =
+                               drm_rgb_quant_range_selectable(edid);
                }
                kfree(edid);
        }
@@ -907,10 +906,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;
        }
 
@@ -933,7 +943,6 @@ static void intel_hdmi_destroy(struct drm_connector *connector)
 static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = {
        .mode_fixup = intel_hdmi_mode_fixup,
        .mode_set = intel_hdmi_mode_set,
-       .disable = intel_encoder_noop,
 };
 
 static const struct drm_connector_funcs intel_hdmi_connector_funcs = {
@@ -959,6 +968,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,
@@ -982,15 +992,15 @@ void intel_hdmi_init_connector(struct intel_digital_port *intel_dig_port,
        switch (port) {
        case PORT_B:
                intel_hdmi->ddc_bus = GMBUS_PORT_DPB;
-               dev_priv->hotplug_supported_mask |= HDMIB_HOTPLUG_INT_STATUS;
+               dev_priv->hotplug_supported_mask |= PORTB_HOTPLUG_INT_STATUS;
                break;
        case PORT_C:
                intel_hdmi->ddc_bus = GMBUS_PORT_DPC;
-               dev_priv->hotplug_supported_mask |= HDMIC_HOTPLUG_INT_STATUS;
+               dev_priv->hotplug_supported_mask |= PORTC_HOTPLUG_INT_STATUS;
                break;
        case PORT_D:
                intel_hdmi->ddc_bus = GMBUS_PORT_DPD;
-               dev_priv->hotplug_supported_mask |= HDMID_HOTPLUG_INT_STATUS;
+               dev_priv->hotplug_supported_mask |= PORTD_HOTPLUG_INT_STATUS;
                break;
        case PORT_A:
                /* Internal port only for eDP. */