include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / gpu / drm / drm_edid.c
index defcaf1..d196d7e 100644 (file)
@@ -27,6 +27,7 @@
  * DEALINGS IN THE SOFTWARE.
  */
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/i2c.h>
 #include <linux/i2c-algo-bit.h>
 #include "drmP.h"
@@ -60,8 +61,7 @@
 #define EDID_QUIRK_FIRST_DETAILED_PREFERRED    (1 << 5)
 /* use +hsync +vsync for detailed mode */
 #define EDID_QUIRK_DETAILED_SYNC_PP            (1 << 6)
-/* define the number of Extension EDID block */
-#define MAX_EDID_EXT_NUM 4
+
 
 #define LEVEL_DMT      0
 #define LEVEL_GTF      1
@@ -114,14 +114,14 @@ static const u8 edid_header[] = {
 };
 
 /**
- * edid_is_valid - sanity check EDID data
+ * drm_edid_is_valid - sanity check EDID data
  * @edid: EDID data
  *
  * Sanity check the EDID block by looking at the header, the version number
  * and the checksum.  Return 0 if the EDID doesn't check out, or 1 if it's
  * valid.
  */
-static bool edid_is_valid(struct edid *edid)
+bool drm_edid_is_valid(struct edid *edid)
 {
        int i, score = 0;
        u8 csum = 0;
@@ -163,6 +163,7 @@ bad:
        }
        return 0;
 }
+EXPORT_SYMBOL(drm_edid_is_valid);
 
 /**
  * edid_vendor - match a string against EDID's obfuscated vendor field
@@ -598,6 +599,50 @@ struct drm_display_mode *drm_mode_std(struct drm_device *dev,
        return mode;
 }
 
+/*
+ * EDID is delightfully ambiguous about how interlaced modes are to be
+ * encoded.  Our internal representation is of frame height, but some
+ * HDTV detailed timings are encoded as field height.
+ *
+ * The format list here is from CEA, in frame size.  Technically we
+ * should be checking refresh rate too.  Whatever.
+ */
+static void
+drm_mode_do_interlace_quirk(struct drm_display_mode *mode,
+                           struct detailed_pixel_timing *pt)
+{
+       int i;
+       static const struct {
+               int w, h;
+       } cea_interlaced[] = {
+               { 1920, 1080 },
+               {  720,  480 },
+               { 1440,  480 },
+               { 2880,  480 },
+               {  720,  576 },
+               { 1440,  576 },
+               { 2880,  576 },
+       };
+       static const int n_sizes =
+               sizeof(cea_interlaced)/sizeof(cea_interlaced[0]);
+
+       if (!(pt->misc & DRM_EDID_PT_INTERLACED))
+               return;
+
+       for (i = 0; i < n_sizes; i++) {
+               if ((mode->hdisplay == cea_interlaced[i].w) &&
+                   (mode->vdisplay == cea_interlaced[i].h / 2)) {
+                       mode->vdisplay *= 2;
+                       mode->vsync_start *= 2;
+                       mode->vsync_end *= 2;
+                       mode->vtotal *= 2;
+                       mode->vtotal |= 1;
+               }
+       }
+
+       mode->flags |= DRM_MODE_FLAG_INTERLACE;
+}
+
 /**
  * drm_mode_detailed - create a new mode from an EDID detailed timing section
  * @dev: DRM device (needed to create new mode)
@@ -633,8 +678,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
                return NULL;
        }
        if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) {
-               printk(KERN_WARNING "integrated sync not supported\n");
-               return NULL;
+               printk(KERN_WARNING "composite sync not supported\n");
        }
 
        /* it is incorrect if hsync/vsync width is zero */
@@ -681,8 +725,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
 
        drm_mode_set_name(mode);
 
-       if (pt->misc & DRM_EDID_PT_INTERLACED)
-               mode->flags |= DRM_MODE_FLAG_INTERLACE;
+       drm_mode_do_interlace_quirk(mode, pt);
 
        if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) {
                pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE;
@@ -1070,8 +1113,8 @@ static int add_detailed_info_eedid(struct drm_connector *connector,
        }
 
        /* Chose real EDID extension number */
-       edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ?
-                      MAX_EDID_EXT_NUM : edid->extensions;
+       edid_ext_num = edid->extensions > DRM_MAX_EDID_EXT_NUM ?
+               DRM_MAX_EDID_EXT_NUM : edid->extensions;
 
        /* Find CEA extension */
        for (i = 0; i < edid_ext_num; i++) {
@@ -1153,7 +1196,7 @@ static int drm_ddc_read_edid(struct drm_connector *connector,
        for (i = 0; i < 4; i++) {
                if (drm_do_probe_ddc_edid(adapter, buf, len))
                        return -1;
-               if (edid_is_valid((struct edid *)buf))
+               if (drm_edid_is_valid((struct edid *)buf))
                        return 0;
        }
 
@@ -1178,7 +1221,7 @@ struct edid *drm_get_edid(struct drm_connector *connector,
        int ret;
        struct edid *edid;
 
-       edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1),
+       edid = kmalloc(EDID_LENGTH * (DRM_MAX_EDID_EXT_NUM + 1),
                       GFP_KERNEL);
        if (edid == NULL) {
                dev_warn(&connector->dev->pdev->dev,
@@ -1196,14 +1239,14 @@ struct edid *drm_get_edid(struct drm_connector *connector,
        if (edid->extensions != 0) {
                int edid_ext_num = edid->extensions;
 
-               if (edid_ext_num > MAX_EDID_EXT_NUM) {
+               if (edid_ext_num > DRM_MAX_EDID_EXT_NUM) {
                        dev_warn(&connector->dev->pdev->dev,
                                 "The number of extension(%d) is "
                                 "over max (%d), actually read number (%d)\n",
-                                edid_ext_num, MAX_EDID_EXT_NUM,
-                                MAX_EDID_EXT_NUM);
+                                edid_ext_num, DRM_MAX_EDID_EXT_NUM,
+                                DRM_MAX_EDID_EXT_NUM);
                        /* Reset EDID extension number to be read */
-                       edid_ext_num = MAX_EDID_EXT_NUM;
+                       edid_ext_num = DRM_MAX_EDID_EXT_NUM;
                }
                /* Read EDID including extensions too */
                ret = drm_ddc_read_edid(connector, adapter, (char *)edid,
@@ -1246,8 +1289,8 @@ bool drm_detect_hdmi_monitor(struct edid *edid)
                goto end;
 
        /* Chose real EDID extension number */
-       edid_ext_num = edid->extensions > MAX_EDID_EXT_NUM ?
-                      MAX_EDID_EXT_NUM : edid->extensions;
+       edid_ext_num = edid->extensions > DRM_MAX_EDID_EXT_NUM ?
+                      DRM_MAX_EDID_EXT_NUM : edid->extensions;
 
        /* Find CEA extension */
        for (i = 0; i < edid_ext_num; i++) {
@@ -1304,7 +1347,7 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
        if (edid == NULL) {
                return 0;
        }
-       if (!edid_is_valid(edid)) {
+       if (!drm_edid_is_valid(edid)) {
                dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
                         drm_get_connector_name(connector));
                return 0;