]> Pileus Git - ~andy/linux/blobdiff - drivers/gpu/drm/i915/intel_sdvo.c
Merge tag 'drm-intel-next-2013-06-18' of git://people.freedesktop.org/~danvet/drm...
[~andy/linux] / drivers / gpu / drm / i915 / intel_sdvo.c
index c5584193770522b2d9e0ec9bc4daceea46f3a954..2628d56224499307cffa4e409a646122a9578db0 100644 (file)
@@ -80,7 +80,7 @@ struct intel_sdvo {
 
        /*
         * Capabilities of the SDVO device returned by
-        * i830_sdvo_get_capabilities()
+        * intel_sdvo_get_capabilities()
         */
        struct intel_sdvo_caps caps;
 
@@ -1219,6 +1219,7 @@ static void intel_sdvo_mode_set(struct intel_encoder *intel_encoder)
 
        switch (intel_crtc->config.pixel_multiplier) {
        default:
+               WARN(1, "unknown pixel mutlipler specified\n");
        case 1: rate = SDVO_CLOCK_RATE_MULT_1X; break;
        case 2: rate = SDVO_CLOCK_RATE_MULT_2X; break;
        case 4: rate = SDVO_CLOCK_RATE_MULT_4X; break;
@@ -1276,7 +1277,7 @@ static bool intel_sdvo_connector_get_hw_state(struct intel_connector *connector)
        struct intel_sdvo_connector *intel_sdvo_connector =
                to_intel_sdvo_connector(&connector->base);
        struct intel_sdvo *intel_sdvo = intel_attached_sdvo(&connector->base);
-       u16 active_outputs;
+       u16 active_outputs = 0;
 
        intel_sdvo_get_active_outputs(intel_sdvo, &active_outputs);
 
@@ -1292,7 +1293,7 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
        struct drm_device *dev = encoder->base.dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
-       u16 active_outputs;
+       u16 active_outputs = 0;
        u32 tmp;
 
        tmp = I915_READ(intel_sdvo->sdvo_reg);
@@ -1312,28 +1313,69 @@ static bool intel_sdvo_get_hw_state(struct intel_encoder *encoder,
 static void intel_sdvo_get_config(struct intel_encoder *encoder,
                                  struct intel_crtc_config *pipe_config)
 {
+       struct drm_device *dev = encoder->base.dev;
+       struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_sdvo *intel_sdvo = to_intel_sdvo(&encoder->base);
        struct intel_sdvo_dtd dtd;
-       u32 flags = 0;
+       int encoder_pixel_multiplier = 0;
+       u32 flags = 0, sdvox;
+       u8 val;
        bool ret;
 
        ret = intel_sdvo_get_input_timing(intel_sdvo, &dtd);
        if (!ret) {
+               /* Some sdvo encoders are not spec compliant and don't
+                * implement the mandatory get_timings function. */
                DRM_DEBUG_DRIVER("failed to retrieve SDVO DTD\n");
-               return;
+               pipe_config->quirks |= PIPE_CONFIG_QUIRK_MODE_SYNC_FLAGS;
+       } else {
+               if (dtd.part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE)
+                       flags |= DRM_MODE_FLAG_PHSYNC;
+               else
+                       flags |= DRM_MODE_FLAG_NHSYNC;
+
+               if (dtd.part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE)
+                       flags |= DRM_MODE_FLAG_PVSYNC;
+               else
+                       flags |= DRM_MODE_FLAG_NVSYNC;
        }
 
-       if (dtd.part2.dtd_flags & DTD_FLAG_HSYNC_POSITIVE)
-               flags |= DRM_MODE_FLAG_PHSYNC;
-       else
-               flags |= DRM_MODE_FLAG_NHSYNC;
+       pipe_config->adjusted_mode.flags |= flags;
 
-       if (dtd.part2.dtd_flags & DTD_FLAG_VSYNC_POSITIVE)
-               flags |= DRM_MODE_FLAG_PVSYNC;
-       else
-               flags |= DRM_MODE_FLAG_NVSYNC;
+       /*
+        * pixel multiplier readout is tricky: Only on i915g/gm it is stored in
+        * the sdvo port register, on all other platforms it is part of the dpll
+        * state. Since the general pipe state readout happens before the
+        * encoder->get_config we so already have a valid pixel multplier on all
+        * other platfroms.
+        */
+       if (IS_I915G(dev) || IS_I915GM(dev)) {
+               sdvox = I915_READ(intel_sdvo->sdvo_reg);
+               pipe_config->pixel_multiplier =
+                       ((sdvox & SDVO_PORT_MULTIPLY_MASK)
+                        >> SDVO_PORT_MULTIPLY_SHIFT) + 1;
+       }
 
-       pipe_config->adjusted_mode.flags |= flags;
+       /* Cross check the port pixel multiplier with the sdvo encoder state. */
+       intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_CLOCK_RATE_MULT, &val, 1);
+       switch (val) {
+       case SDVO_CLOCK_RATE_MULT_1X:
+               encoder_pixel_multiplier = 1;
+               break;
+       case SDVO_CLOCK_RATE_MULT_2X:
+               encoder_pixel_multiplier = 2;
+               break;
+       case SDVO_CLOCK_RATE_MULT_4X:
+               encoder_pixel_multiplier = 4;
+               break;
+       }
+
+       if(HAS_PCH_SPLIT(dev))
+               return; /* no pixel multiplier readout support yet */
+
+       WARN(encoder_pixel_multiplier != pipe_config->pixel_multiplier,
+            "SDVO pixel multiplier mismatch, port: %i, encoder: %i\n",
+            pipe_config->pixel_multiplier, encoder_pixel_multiplier);
 }
 
 static void intel_disable_sdvo(struct intel_encoder *encoder)
@@ -2819,7 +2861,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
        struct drm_i915_private *dev_priv = dev->dev_private;
        struct intel_encoder *intel_encoder;
        struct intel_sdvo *intel_sdvo;
-       u32 hotplug_mask;
        int i;
        intel_sdvo = kzalloc(sizeof(struct intel_sdvo), GFP_KERNEL);
        if (!intel_sdvo)
@@ -2848,18 +2889,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                }
        }
 
-       hotplug_mask = 0;
-       if (IS_G4X(dev)) {
-               hotplug_mask = intel_sdvo->is_sdvob ?
-                       SDVOB_HOTPLUG_INT_STATUS_G4X : SDVOC_HOTPLUG_INT_STATUS_G4X;
-       } else if (IS_GEN4(dev)) {
-               hotplug_mask = intel_sdvo->is_sdvob ?
-                       SDVOB_HOTPLUG_INT_STATUS_I965 : SDVOC_HOTPLUG_INT_STATUS_I965;
-       } else {
-               hotplug_mask = intel_sdvo->is_sdvob ?
-                       SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;
-       }
-
        intel_encoder->compute_config = intel_sdvo_compute_config;
        intel_encoder->disable = intel_disable_sdvo;
        intel_encoder->mode_set = intel_sdvo_mode_set;