@@ -4160,9 +4160,8 @@ static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
}
static int
-add_cea_modes(struct drm_connector *connector, struct edid *edid)
+handle_cea_modes(struct drm_connector *connector, const u8 *cea)
{
- const u8 *cea = drm_find_cea_extension(edid);
const u8 *db, *hdmi = NULL, *video = NULL;
u8 dbl, hdmi_len, video_len = 0;
int modes = 0;
@@ -4206,6 +4205,55 @@ add_cea_modes(struct drm_connector *connector, struct edid *edid)
return modes;
}
+static int
+add_cea_modes(struct drm_connector *connector, struct edid *edid)
+{
+ const u8 *cea = NULL;
+ u8 *edid_ext = NULL;
+ int modes = 0;
+ int block_index = 0;
+
+ /*
+ * Based on HDMI(2.x) CTS: HF1-66 (Iter 06), two blocks with same
+ * tag (Tag = 0x02: CTA 861) are included in EDID. Ori. solution
+ * checks for all additional blocks, BUT it always checks from
+ * HEAD. Result is only 1st CTA 861 can be found and checked.
+ * Therefore, any following CTA 861 block is never found
+ * to handle. The modified method is to check each additional
+ * block by pointing to the start address of that block, instead
+ * of finding from HEAD of EDID.
+ *
+ * TODO: EDID parser may need re-designed, since ori. parser can't
+ * correctly parse multiple same ext. blocks (Tag = 0x02 in this
+ * case), since it finds and parse the 1st target ext. block only.
+ * 1. Ori. method is not flexible to work with EDID like HF1-66.
+ * 2. Ori. method is not efficient: a block may be checked many times.
+ * 3. Ori. method does not support new features, e.g. Ext. BLK MAP.
+ * etc...
+ */
+ for (block_index = 0; block_index < edid->extensions; block_index++) {
+ edid_ext = (((u8 *)edid) + (EDID_LENGTH * (block_index + 1)));
+
+ if (edid_ext[0] == CEA_EXT) {
+ cea = ((const u8 *)edid_ext);
+ modes += handle_cea_modes(connector, cea);
+ }
+ }
+
+ /*
+ * If no Video Data extension block, go check DisplayID block,
+ * because CEA block may be embedded in DisplayID block.
+ */
+ if (!cea) {
+ cea = drm_find_cea_extension(edid);
+
+ if (cea)
+ modes += handle_cea_modes(connector, cea);
+ }
+
+ return modes;
+}
+
static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
{
const struct drm_display_mode *cea_mode;