}
 
 #define DDC_ADDR 0x50
-
-unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter)
+/**
+ * Get EDID information via I2C.
+ *
+ * \param adapter : i2c device adaptor
+ * \param buf     : EDID data buffer to be filled
+ * \param len     : EDID data buffer length
+ * \return 0 on success or -1 on failure.
+ *
+ * Try to fetch EDID information by calling i2c driver function.
+ */
+int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
+                         unsigned char *buf, int len)
 {
        unsigned char start = 0x0;
-       unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
        struct i2c_msg msgs[] = {
                {
                        .addr   = DDC_ADDR,
                }, {
                        .addr   = DDC_ADDR,
                        .flags  = I2C_M_RD,
-                       .len    = EDID_LENGTH,
+                       .len    = len,
                        .buf    = buf,
                }
        };
 
-       if (!buf) {
-               dev_warn(&adapter->dev, "unable to allocate memory for EDID "
-                        "block.\n");
-               return NULL;
-       }
-
        if (i2c_transfer(adapter, msgs, 2) == 2)
-               return buf;
+               return 0;
 
        dev_info(&adapter->dev, "unable to read EDID block.\n");
-       kfree(buf);
-       return NULL;
+       return -1;
 }
 EXPORT_SYMBOL(drm_do_probe_ddc_edid);
 
-static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
+/**
+ * Get EDID information.
+ *
+ * \param adapter : i2c device adaptor.
+ * \param buf     : EDID data buffer to be filled
+ * \param len     : EDID data buffer length
+ * \return 0 on success or -1 on failure.
+ *
+ * Initialize DDC, then fetch EDID information
+ * by calling drm_do_probe_ddc_edid function.
+ */
+static int drm_ddc_read(struct i2c_adapter *adapter,
+                       unsigned char *buf, int len)
 {
        struct i2c_algo_bit_data *algo_data = adapter->algo_data;
-       unsigned char *edid = NULL;
        int i, j;
+       int ret = -1;
 
        algo_data->setscl(algo_data->data, 1);
 
                msleep(15);
 
                /* Do the real work */
-               edid = drm_do_probe_ddc_edid(adapter);
+               ret = drm_do_probe_ddc_edid(adapter, buf, len);
                algo_data->setsda(algo_data->data, 0);
                algo_data->setscl(algo_data->data, 0);
                msleep(15);
                msleep(15);
                algo_data->setscl(algo_data->data, 0);
                algo_data->setsda(algo_data->data, 0);
-               if (edid)
+               if (ret == 0)
                        break;
        }
        /* Release the DDC lines when done or the Apple Cinema HD display
        algo_data->setsda(algo_data->data, 1);
        algo_data->setscl(algo_data->data, 1);
 
-       return edid;
+       return ret;
+}
+
+static int drm_ddc_read_edid(struct drm_connector *connector,
+                            struct i2c_adapter *adapter,
+                            char *buf, int len)
+{
+       int ret;
+
+       ret = drm_ddc_read(adapter, buf, len);
+       if (ret != 0) {
+               dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
+                        drm_get_connector_name(connector));
+               goto end;
+       }
+       if (!edid_is_valid((struct edid *)buf)) {
+               dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
+                        drm_get_connector_name(connector));
+               ret = -1;
+       }
+end:
+       return ret;
 }
 
+#define MAX_EDID_EXT_NUM 4
 /**
  * drm_get_edid - get EDID data, if available
  * @connector: connector we're probing
 struct edid *drm_get_edid(struct drm_connector *connector,
                          struct i2c_adapter *adapter)
 {
+       int ret;
        struct edid *edid;
 
-       edid = (struct edid *)drm_ddc_read(adapter);
-       if (!edid) {
-               dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
-                        drm_get_connector_name(connector));
-               return NULL;
+       edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1),
+                      GFP_KERNEL);
+       if (edid == NULL) {
+               dev_warn(&connector->dev->pdev->dev,
+                        "Failed to allocate EDID\n");
+               goto end;
        }
-       if (!edid_is_valid(edid)) {
-               dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
-                        drm_get_connector_name(connector));
-               kfree(edid);
-               return NULL;
+
+       /* Read first EDID block */
+       ret = drm_ddc_read_edid(connector, adapter,
+                               (unsigned char *)edid, EDID_LENGTH);
+       if (ret != 0)
+               goto clean_up;
+
+       /* There are EDID extensions to be read */
+       if (edid->extensions != 0) {
+               int edid_ext_num = edid->extensions;
+
+               if (edid_ext_num > 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);
+                       /* Reset EDID extension number to be read */
+                       edid_ext_num = MAX_EDID_EXT_NUM;
+               }
+               /* Read EDID including extensions too */
+               ret = drm_ddc_read_edid(connector, adapter, (char *)edid,
+                                       EDID_LENGTH * (edid_ext_num + 1));
+               if (ret != 0)
+                       goto clean_up;
+
        }
 
        connector->display_info.raw_edid = (char *)edid;
+       goto end;
 
+clean_up:
+       kfree(edid);
+       edid = NULL;
+end:
        return edid;
+
 }
 EXPORT_SYMBOL(drm_get_edid);