These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / gpu / drm / i915 / intel_sdvo.c
index 987b81f..c42b636 100644 (file)
@@ -53,7 +53,7 @@
 #define IS_DIGITAL(c) (c->output_flag & (SDVO_TMDS_MASK | SDVO_LVDS_MASK))
 
 
-static const char *tv_format_names[] = {
+static const char * const tv_format_names[] = {
        "NTSC_M"   , "NTSC_J"  , "NTSC_443",
        "PAL_B"    , "PAL_D"   , "PAL_G"   ,
        "PAL_H"    , "PAL_I"   , "PAL_M"   ,
@@ -63,7 +63,7 @@ static const char *tv_format_names[] = {
        "SECAM_60"
 };
 
-#define TV_FORMAT_NUM  (sizeof(tv_format_names) / sizeof(*tv_format_names))
+#define TV_FORMAT_NUM  ARRAY_SIZE(tv_format_names)
 
 struct intel_sdvo {
        struct intel_encoder base;
@@ -106,6 +106,11 @@ struct intel_sdvo {
        uint32_t color_range;
        bool color_range_auto;
 
+       /**
+        * HDMI user specified aspect ratio
+        */
+       enum hdmi_picture_aspect aspect_ratio;
+
        /**
         * This is set if we're going to treat the device as TV-out.
         *
@@ -242,7 +247,15 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val)
 
        if (intel_sdvo->sdvo_reg == PCH_SDVOB) {
                I915_WRITE(intel_sdvo->sdvo_reg, val);
-               I915_READ(intel_sdvo->sdvo_reg);
+               POSTING_READ(intel_sdvo->sdvo_reg);
+               /*
+                * HW workaround, need to write this twice for issue
+                * that may result in first write getting masked.
+                */
+               if (HAS_PCH_IBX(dev)) {
+                       I915_WRITE(intel_sdvo->sdvo_reg, val);
+                       POSTING_READ(intel_sdvo->sdvo_reg);
+               }
                return;
        }
 
@@ -259,9 +272,9 @@ static void intel_sdvo_write_sdvox(struct intel_sdvo *intel_sdvo, u32 val)
        for (i = 0; i < 2; i++)
        {
                I915_WRITE(GEN3_SDVOB, bval);
-               I915_READ(GEN3_SDVOB);
+               POSTING_READ(GEN3_SDVOB);
                I915_WRITE(GEN3_SDVOC, cval);
-               I915_READ(GEN3_SDVOC);
+               POSTING_READ(GEN3_SDVOC);
        }
 }
 
@@ -444,7 +457,7 @@ static void intel_sdvo_debug_write(struct intel_sdvo *intel_sdvo, u8 cmd,
        DRM_DEBUG_KMS("%s: W: %02X %s\n", SDVO_NAME(intel_sdvo), cmd, buffer);
 }
 
-static const char *cmd_status_names[] = {
+static const char * const cmd_status_names[] = {
        "Power on",
        "Success",
        "Not supported",
@@ -595,11 +608,11 @@ log_fail:
        return false;
 }
 
-static int intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode)
+static int intel_sdvo_get_pixel_multiplier(const struct drm_display_mode *adjusted_mode)
 {
-       if (mode->clock >= 100000)
+       if (adjusted_mode->crtc_clock >= 100000)
                return 1;
-       else if (mode->clock >= 50000)
+       else if (adjusted_mode->crtc_clock >= 50000)
                return 2;
        else
                return 4;
@@ -1173,6 +1186,10 @@ static bool intel_sdvo_compute_config(struct intel_encoder *encoder,
        if (intel_sdvo->is_tv)
                i9xx_adjust_sdvo_tv_clock(pipe_config);
 
+       /* Set user selected PAR to incoming mode's member */
+       if (intel_sdvo->is_hdmi)
+               adjusted_mode->picture_aspect_ratio = intel_sdvo->aspect_ratio;
+
        return true;
 }
 
@@ -1181,8 +1198,7 @@ static void intel_sdvo_pre_enable(struct intel_encoder *intel_encoder)
        struct drm_device *dev = intel_encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_crtc *crtc = to_intel_crtc(intel_encoder->base.crtc);
-       struct drm_display_mode *adjusted_mode =
-               &crtc->config->base.adjusted_mode;
+       const struct drm_display_mode *adjusted_mode = &crtc->config->base.adjusted_mode;
        struct drm_display_mode *mode = &crtc->config->base.mode;
        struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder);
        u32 sdvox;
@@ -1429,6 +1445,7 @@ static void intel_disable_sdvo(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
        struct intel_sdvo *intel_sdvo = to_sdvo(encoder);
+       struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
        u32 temp;
 
        intel_sdvo_set_active_outputs(intel_sdvo, 0);
@@ -1437,35 +1454,34 @@ static void intel_disable_sdvo(struct intel_encoder *encoder)
                                                   DRM_MODE_DPMS_OFF);
 
        temp = I915_READ(intel_sdvo->sdvo_reg);
-       if ((temp & SDVO_ENABLE) != 0) {
-               /* HW workaround for IBX, we need to move the port to
-                * transcoder A before disabling it. */
-               if (HAS_PCH_IBX(encoder->base.dev)) {
-                       struct drm_crtc *crtc = encoder->base.crtc;
-                       int pipe = crtc ? to_intel_crtc(crtc)->pipe : -1;
-
-                       if (temp & SDVO_PIPE_B_SELECT) {
-                               temp &= ~SDVO_PIPE_B_SELECT;
-                               I915_WRITE(intel_sdvo->sdvo_reg, temp);
-                               POSTING_READ(intel_sdvo->sdvo_reg);
-
-                               /* Again we need to write this twice. */
-                               I915_WRITE(intel_sdvo->sdvo_reg, temp);
-                               POSTING_READ(intel_sdvo->sdvo_reg);
-
-                               /* Transcoder selection bits only update
-                                * effectively on vblank. */
-                               if (crtc)
-                                       intel_wait_for_vblank(encoder->base.dev, pipe);
-                               else
-                                       msleep(50);
-                       }
-               }
 
-               intel_sdvo_write_sdvox(intel_sdvo, temp & ~SDVO_ENABLE);
+       temp &= ~SDVO_ENABLE;
+       intel_sdvo_write_sdvox(intel_sdvo, temp);
+
+       /*
+        * HW workaround for IBX, we need to move the port
+        * to transcoder A after disabling it to allow the
+        * matching DP port to be enabled on transcoder A.
+        */
+       if (HAS_PCH_IBX(dev_priv) && crtc->pipe == PIPE_B) {
+               temp &= ~SDVO_PIPE_B_SELECT;
+               temp |= SDVO_ENABLE;
+               intel_sdvo_write_sdvox(intel_sdvo, temp);
+
+               temp &= ~SDVO_ENABLE;
+               intel_sdvo_write_sdvox(intel_sdvo, temp);
        }
 }
 
+static void pch_disable_sdvo(struct intel_encoder *encoder)
+{
+}
+
+static void pch_post_disable_sdvo(struct intel_encoder *encoder)
+{
+       intel_disable_sdvo(encoder);
+}
+
 static void intel_enable_sdvo(struct intel_encoder *encoder)
 {
        struct drm_device *dev = encoder->base.dev;
@@ -1478,14 +1494,9 @@ static void intel_enable_sdvo(struct intel_encoder *encoder)
        bool success;
 
        temp = I915_READ(intel_sdvo->sdvo_reg);
-       if ((temp & SDVO_ENABLE) == 0) {
-               /* HW workaround for IBX, we need to move the port
-                * to transcoder A before disabling it, so restore it here. */
-               if (HAS_PCH_IBX(dev))
-                       temp |= SDVO_PIPE_SEL(intel_crtc->pipe);
+       temp |= SDVO_ENABLE;
+       intel_sdvo_write_sdvox(intel_sdvo, temp);
 
-               intel_sdvo_write_sdvox(intel_sdvo, temp | SDVO_ENABLE);
-       }
        for (i = 0; i < 2; i++)
                intel_wait_for_vblank(dev, intel_crtc->pipe);
 
@@ -1505,51 +1516,6 @@ static void intel_enable_sdvo(struct intel_encoder *encoder)
        intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
 }
 
-/* Special dpms function to support cloning between dvo/sdvo/crt. */
-static void intel_sdvo_dpms(struct drm_connector *connector, int mode)
-{
-       struct drm_crtc *crtc;
-       struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
-
-       /* dvo supports only 2 dpms states. */
-       if (mode != DRM_MODE_DPMS_ON)
-               mode = DRM_MODE_DPMS_OFF;
-
-       if (mode == connector->dpms)
-               return;
-
-       connector->dpms = mode;
-
-       /* Only need to change hw state when actually enabled */
-       crtc = intel_sdvo->base.base.crtc;
-       if (!crtc) {
-               intel_sdvo->base.connectors_active = false;
-               return;
-       }
-
-       /* We set active outputs manually below in case pipe dpms doesn't change
-        * due to cloning. */
-       if (mode != DRM_MODE_DPMS_ON) {
-               intel_sdvo_set_active_outputs(intel_sdvo, 0);
-               if (0)
-                       intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
-
-               intel_sdvo->base.connectors_active = false;
-
-               intel_crtc_update_dpms(crtc);
-       } else {
-               intel_sdvo->base.connectors_active = true;
-
-               intel_crtc_update_dpms(crtc);
-
-               if (0)
-                       intel_sdvo_set_encoder_power_state(intel_sdvo, mode);
-               intel_sdvo_set_active_outputs(intel_sdvo, intel_sdvo->attached_output);
-       }
-
-       intel_modeset_check_state(connector->dev);
-}
-
 static enum drm_mode_status
 intel_sdvo_mode_valid(struct drm_connector *connector,
                      struct drm_display_mode *mode)
@@ -2086,6 +2052,23 @@ intel_sdvo_set_property(struct drm_connector *connector,
                goto done;
        }
 
+       if (property == connector->dev->mode_config.aspect_ratio_property) {
+               switch (val) {
+               case DRM_MODE_PICTURE_ASPECT_NONE:
+                       intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
+                       break;
+               case DRM_MODE_PICTURE_ASPECT_4_3:
+                       intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_4_3;
+                       break;
+               case DRM_MODE_PICTURE_ASPECT_16_9:
+                       intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_16_9;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               goto done;
+       }
+
 #define CHECK_PROPERTY(name, NAME) \
        if (intel_sdvo_connector->name == property) { \
                if (intel_sdvo_connector->cur_##name == temp_value) return 0; \
@@ -2187,7 +2170,7 @@ done:
 }
 
 static const struct drm_connector_funcs intel_sdvo_connector_funcs = {
-       .dpms = intel_sdvo_dpms,
+       .dpms = drm_atomic_helper_connector_dpms,
        .detect = intel_sdvo_detect,
        .fill_modes = drm_helper_probe_single_connector_modes,
        .set_property = intel_sdvo_set_property,
@@ -2264,7 +2247,7 @@ intel_sdvo_guess_ddc_bus(struct intel_sdvo *sdvo)
  */
 static void
 intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
-                         struct intel_sdvo *sdvo, u32 reg)
+                         struct intel_sdvo *sdvo)
 {
        struct sdvo_device_mapping *mapping;
 
@@ -2281,7 +2264,7 @@ intel_sdvo_select_ddc_bus(struct drm_i915_private *dev_priv,
 
 static void
 intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
-                         struct intel_sdvo *sdvo, u32 reg)
+                         struct intel_sdvo *sdvo)
 {
        struct sdvo_device_mapping *mapping;
        u8 pin;
@@ -2291,10 +2274,11 @@ intel_sdvo_select_i2c_bus(struct drm_i915_private *dev_priv,
        else
                mapping = &dev_priv->sdvo_mappings[1];
 
-       if (mapping->initialized && intel_gmbus_is_port_valid(mapping->i2c_pin))
+       if (mapping->initialized &&
+           intel_gmbus_is_valid_pin(dev_priv, mapping->i2c_pin))
                pin = mapping->i2c_pin;
        else
-               pin = GMBUS_PORT_DPB;
+               pin = GMBUS_PIN_DPB;
 
        sdvo->i2c = intel_gmbus_get_adapter(dev_priv, pin);
 
@@ -2424,6 +2408,8 @@ intel_sdvo_add_hdmi_properties(struct intel_sdvo *intel_sdvo,
                intel_attach_broadcast_rgb_property(&connector->base.base);
                intel_sdvo->color_range_auto = true;
        }
+       intel_attach_aspect_ratio_property(&connector->base.base);
+       intel_sdvo->aspect_ratio = HDMI_PICTURE_ASPECT_NONE;
 }
 
 static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void)
@@ -2966,7 +2952,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
        intel_sdvo->sdvo_reg = sdvo_reg;
        intel_sdvo->is_sdvob = is_sdvob;
        intel_sdvo->slave_addr = intel_sdvo_get_slave_addr(dev, intel_sdvo) >> 1;
-       intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo, sdvo_reg);
+       intel_sdvo_select_i2c_bus(dev_priv, intel_sdvo);
        if (!intel_sdvo_init_ddc_proxy(intel_sdvo, dev))
                goto err_i2c_bus;
 
@@ -2987,7 +2973,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
        }
 
        intel_encoder->compute_config = intel_sdvo_compute_config;
-       intel_encoder->disable = intel_disable_sdvo;
+       if (HAS_PCH_SPLIT(dev)) {
+               intel_encoder->disable = pch_disable_sdvo;
+               intel_encoder->post_disable = pch_post_disable_sdvo;
+       } else {
+               intel_encoder->disable = intel_disable_sdvo;
+       }
        intel_encoder->pre_enable = intel_sdvo_pre_enable;
        intel_encoder->enable = intel_enable_sdvo;
        intel_encoder->get_hw_state = intel_sdvo_get_hw_state;
@@ -3023,7 +3014,7 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
         */
        intel_sdvo->base.cloneable = 0;
 
-       intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);
+       intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo);
 
        /* Set the input timing to the screen. Assume always input 0. */
        if (!intel_sdvo_set_target_input(intel_sdvo))