drm/i915: use the default context
[deliverable/linux.git] / drivers / gpu / drm / drm_edid.c
index c6366e90041e8240c6b88ffd3b9932eea972ef67..c3b5139eba7f8eec492ab8d5c818638d897cb272 100644 (file)
@@ -66,6 +66,8 @@
 #define EDID_QUIRK_FIRST_DETAILED_PREFERRED    (1 << 5)
 /* use +hsync +vsync for detailed mode */
 #define EDID_QUIRK_DETAILED_SYNC_PP            (1 << 6)
+/* Force reduced-blanking timings for detailed modes */
+#define EDID_QUIRK_FORCE_REDUCED_BLANKING      (1 << 7)
 
 struct detailed_mode_closure {
        struct drm_connector *connector;
@@ -81,7 +83,7 @@ struct detailed_mode_closure {
 #define LEVEL_CVT      3
 
 static struct edid_quirk {
-       char *vendor;
+       char vendor[4];
        int product_id;
        u32 quirks;
 } edid_quirk_list[] = {
@@ -120,6 +122,9 @@ static struct edid_quirk {
        /* Samsung SyncMaster 22[5-6]BW */
        { "SAM", 596, EDID_QUIRK_PREFER_LARGE_60 },
        { "SAM", 638, EDID_QUIRK_PREFER_LARGE_60 },
+
+       /* ViewSonic VA2026w */
+       { "VSC", 5020, EDID_QUIRK_FORCE_REDUCED_BLANKING },
 };
 
 /*** DDC fetch and block validation ***/
@@ -149,13 +154,13 @@ EXPORT_SYMBOL(drm_edid_header_is_valid);
  * Sanity check the EDID block (base or extension).  Return 0 if the block
  * doesn't check out, or 1 if it's valid.
  */
-bool drm_edid_block_valid(u8 *raw_edid)
+bool drm_edid_block_valid(u8 *raw_edid, int block)
 {
        int i;
        u8 csum = 0;
        struct edid *edid = (struct edid *)raw_edid;
 
-       if (raw_edid[0] == 0x00) {
+       if (block == 0) {
                int score = drm_edid_header_is_valid(raw_edid);
                if (score == 8) ;
                else if (score >= 6) {
@@ -219,7 +224,7 @@ bool drm_edid_is_valid(struct edid *edid)
                return false;
 
        for (i = 0; i <= edid->extensions; i++)
-               if (!drm_edid_block_valid(raw + i * EDID_LENGTH))
+               if (!drm_edid_block_valid(raw + i * EDID_LENGTH, i))
                        return false;
 
        return true;
@@ -299,7 +304,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
        for (i = 0; i < 4; i++) {
                if (drm_do_probe_ddc_edid(adapter, block, 0, EDID_LENGTH))
                        goto out;
-               if (drm_edid_block_valid(block))
+               if (drm_edid_block_valid(block, 0))
                        break;
                if (i == 0 && drm_edid_is_zero(block, EDID_LENGTH)) {
                        connector->null_edid_counter++;
@@ -324,7 +329,7 @@ drm_do_get_edid(struct drm_connector *connector, struct i2c_adapter *adapter)
                                  block + (valid_extensions + 1) * EDID_LENGTH,
                                  j, EDID_LENGTH))
                                goto out;
-                       if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH)) {
+                       if (drm_edid_block_valid(block + (valid_extensions + 1) * EDID_LENGTH, j)) {
                                valid_extensions++;
                                break;
                        }
@@ -885,12 +890,19 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
                                "Wrong Hsync/Vsync pulse width\n");
                return NULL;
        }
+
+       if (quirks & EDID_QUIRK_FORCE_REDUCED_BLANKING) {
+               mode = drm_cvt_mode(dev, hactive, vactive, 60, true, false, false);
+               if (!mode)
+                       return NULL;
+
+               goto set_size;
+       }
+
        mode = drm_mode_create(dev);
        if (!mode)
                return NULL;
 
-       mode->type = DRM_MODE_TYPE_DRIVER;
-
        if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH)
                timing->pixel_clock = cpu_to_le16(1088);
 
@@ -914,8 +926,6 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
 
        drm_mode_do_interlace_quirk(mode, pt);
 
-       drm_mode_set_name(mode);
-
        if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
                pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
        }
@@ -925,6 +935,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
        mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ?
                DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC;
 
+set_size:
        mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4;
        mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8;
 
@@ -938,6 +949,9 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
                mode->height_mm = edid->height_cm * 10;
        }
 
+       mode->type = DRM_MODE_TYPE_DRIVER;
+       drm_mode_set_name(mode);
+
        return mode;
 }
 
This page took 0.02684 seconds and 5 git commands to generate.