]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/gpu/drm/i915/intel_crt.c
rcu: rcu_barrier VS cpu_hotplug: Ensure callbacks in dead cpu are migrated to online cpu
[linux-2.6-omap-h63xx.git] / drivers / gpu / drm / i915 / intel_crt.c
index dcaed3466e835efb1be64b6ece3189e9c38f508c..2b6d44381c310874926eb9f2e8d55b5b6e91fad8 100644 (file)
@@ -64,11 +64,21 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode)
 static int intel_crt_mode_valid(struct drm_connector *connector,
                                struct drm_display_mode *mode)
 {
+       struct drm_device *dev = connector->dev;
+
+       int max_clock = 0;
        if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
                return MODE_NO_DBLESCAN;
 
-       if (mode->clock > 400000 || mode->clock < 25000)
-               return MODE_CLOCK_RANGE;
+       if (mode->clock < 25000)
+               return MODE_CLOCK_LOW;
+
+       if (!IS_I9XX(dev))
+               max_clock = 350000;
+       else
+               max_clock = 400000;
+       if (mode->clock > max_clock)
+               return MODE_CLOCK_HIGH;
 
        return MODE_OK;
 }
@@ -113,10 +123,13 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
        if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
                adpa |= ADPA_VSYNC_ACTIVE_HIGH;
 
-       if (intel_crtc->pipe == 0)
+       if (intel_crtc->pipe == 0) {
                adpa |= ADPA_PIPE_A_SELECT;
-       else
+               I915_WRITE(BCLRPAT_A, 0);
+       } else {
                adpa |= ADPA_PIPE_B_SELECT;
+               I915_WRITE(BCLRPAT_B, 0);
+       }
 
        I915_WRITE(ADPA, adpa);
 }
@@ -133,20 +146,39 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector)
 {
        struct drm_device *dev = connector->dev;
        struct drm_i915_private *dev_priv = dev->dev_private;
-       u32 temp;
-
-       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
-
-       temp = I915_READ(PORT_HOTPLUG_EN);
-
-       I915_WRITE(PORT_HOTPLUG_EN,
-                  temp | CRT_HOTPLUG_FORCE_DETECT | (1 << 5));
+       u32 hotplug_en;
+       int i, tries = 0;
+       /*
+        * On 4 series desktop, CRT detect sequence need to be done twice
+        * to get a reliable result.
+        */
 
-       do {
-               if (!(I915_READ(PORT_HOTPLUG_EN) & CRT_HOTPLUG_FORCE_DETECT))
-                       break;
-               msleep(1);
-       } while (time_after(timeout, jiffies));
+       if (IS_G4X(dev) && !IS_GM45(dev))
+               tries = 2;
+       else
+               tries = 1;
+       hotplug_en = I915_READ(PORT_HOTPLUG_EN);
+       hotplug_en &= ~(CRT_HOTPLUG_MASK);
+       hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
+
+       if (IS_GM45(dev))
+               hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
+
+       hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
+
+       for (i = 0; i < tries ; i++) {
+               unsigned long timeout;
+               /* turn on the FORCE_DETECT */
+               I915_WRITE(PORT_HOTPLUG_EN, hotplug_en);
+               timeout = jiffies + msecs_to_jiffies(1000);
+               /* wait for FORCE_DETECT to go off */
+               do {
+                       if (!(I915_READ(PORT_HOTPLUG_EN) &
+                                       CRT_HOTPLUG_FORCE_DETECT))
+                               break;
+                       msleep(1);
+               } while (time_after(timeout, jiffies));
+       }
 
        if ((I915_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) ==
            CRT_HOTPLUG_MONITOR_COLOR)