construct unified interface, anytime when program need detailed timing block, it always dynamically parse and handle it through the interface.
--- hw/xfree86/ddc/interpret_edid.c | 182 +++++++++++++++++++++++++++------------ hw/xfree86/ddc/xf86DDC.h | 5 + 2 files changed, 132 insertions(+), 55 deletions(-) diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c index c0e3df9..f04c6bc 100644 --- a/hw/xfree86/ddc/interpret_edid.c +++ b/hw/xfree86/ddc/interpret_edid.c @@ -41,6 +41,8 @@ static void get_display_section(Uchar*, struct disp_features *, static void get_established_timing_section(Uchar*, struct established_timings *); static void get_std_timing_section(Uchar*, struct std_timings *, struct edid_version *); +static void fetch_detailed_block(Uchar *c, struct edid_version *ver, + struct detailed_monitor_section *det_mon); static void get_dt_md_section(Uchar *, struct edid_version *, struct detailed_monitor_section *det_mon); static void copy_string(Uchar *, Uchar *); @@ -163,6 +165,70 @@ xf86InterpretEDID(int scrnIndex, Uchar *block) return NULL; } +static int get_cea_detail_timing(Uchar *blk, xf86MonPtr mon, + struct detailed_monitor_section *det_mon) +{ + int dt_num; + int dt_offset = ((struct cea_ext_body *)blk)->dt_offset; + + dt_num = 0; + + if (dt_offset < CEA_EXT_MIN_DATA_OFFSET) + return dt_num; + + for (; dt_offset < (CEA_EXT_MAX_DATA_OFFSET - DET_TIMING_INFO_LEN) && + dt_num < CEA_EXT_DET_TIMING_NUM; + _NEXT_DT_MD_SECTION(dt_offset)) { + + fetch_detailed_block(blk + dt_offset, &mon->ver, det_mon + dt_num); + dt_num = dt_num + 1 ; + } + + return dt_num; +} + +static void handle_cea_detail_block(Uchar *ext, xf86MonPtr mon, + handle_detailed_fn fn, + void *data) +{ + int i; + struct detailed_monitor_section det_mon[CEA_EXT_DET_TIMING_NUM]; + int det_mon_num; + + det_mon_num = get_cea_detail_timing(ext, mon, det_mon); + + for (i = 0; i < det_mon_num; i++) + fn(det_mon + i, data); +} + +void xf86ForEachDetailedBlock(xf86MonPtr mon, + handle_detailed_fn fn, + void *data) +{ + int i; + Uchar *ext; + + if (mon == NULL) + return; + + for (i = 0; i < DET_TIMINGS; i++) + fn(mon->det_mon + i, data); + + for (i = 0; i < mon->no_sections; i++) { + ext = mon->rawData + EDID1_LEN * (i + 1); + switch (ext[EXT_TAG]){ + case CEA_EXT: + handle_cea_detail_block(ext, mon, fn, data); + break; + case VTB_EXT: + case DI_EXT: + case LS_EXT: + case MI_EXT: + break; + } + } +} + xf86MonPtr xf86InterpretEEDID(int scrnIndex, Uchar *block) { @@ -285,65 +351,71 @@ get_std_timing_section(Uchar *c, struct std_timings *r, } static void -get_dt_md_section(Uchar *c, struct edid_version *ver, - struct detailed_monitor_section *det_mon) +fetch_detailed_block(Uchar *c, struct edid_version *ver, + struct detailed_monitor_section *det_mon) { - int i; - - for (i=0;i<DET_TIMINGS;i++) { if (ver->version == 1 && ver->revision >= 1 && IS_MONITOR_DESC) { + switch (MONITOR_DESC_TYPE) { + case SERIAL_NUMBER: + det_mon->type = DS_SERIAL; + copy_string(c,det_mon->section.serial); + break; + case ASCII_STR: + det_mon->type = DS_ASCII_STR; + copy_string(c,det_mon->section.ascii_data); + break; + case MONITOR_RANGES: + det_mon->type = DS_RANGES; + get_monitor_ranges(c,&det_mon->section.ranges); + break; + case MONITOR_NAME: + det_mon->type = DS_NAME; + copy_string(c,det_mon->section.name); + break; + case ADD_COLOR_POINT: + det_mon->type = DS_WHITE_P; + get_whitepoint_section(c,det_mon->section.wp); + break; + case ADD_STD_TIMINGS: + det_mon->type = DS_STD_TIMINGS; + get_dst_timing_section(c,det_mon->section.std_t, ver); + break; + case COLOR_MANAGEMENT_DATA: + det_mon->type = DS_CMD; + break; + case CVT_3BYTE_DATA: + det_mon->type = DS_CVT; + get_cvt_timing_section(c, det_mon->section.cvt); + break; + case ADD_EST_TIMINGS: + det_mon->type = DS_EST_III; + break; + case ADD_DUMMY: + det_mon->type = DS_DUMMY; + break; + default: + det_mon->type = DS_UNKOWN; + break; + } + if (c[3] <= 0x0F) { + det_mon->type = DS_VENDOR + c[3]; + } + } else { + det_mon->type = DT; + get_detailed_timing_section(c, &det_mon->section.d_timings); + } +} + +static void +get_dt_md_section(Uchar *c, struct edid_version *ver, + struct detailed_monitor_section *det_mon) +{ + int i; - switch (MONITOR_DESC_TYPE) { - case SERIAL_NUMBER: - det_mon[i].type = DS_SERIAL; - copy_string(c,det_mon[i].section.serial); - break; - case ASCII_STR: - det_mon[i].type = DS_ASCII_STR; - copy_string(c,det_mon[i].section.ascii_data); - break; - case MONITOR_RANGES: - det_mon[i].type = DS_RANGES; - get_monitor_ranges(c,&det_mon[i].section.ranges); - break; - case MONITOR_NAME: - det_mon[i].type = DS_NAME; - copy_string(c,det_mon[i].section.name); - break; - case ADD_COLOR_POINT: - det_mon[i].type = DS_WHITE_P; - get_whitepoint_section(c,det_mon[i].section.wp); - break; - case ADD_STD_TIMINGS: - det_mon[i].type = DS_STD_TIMINGS; - get_dst_timing_section(c,det_mon[i].section.std_t, ver); - break; - case COLOR_MANAGEMENT_DATA: - det_mon[i].type = DS_CMD; - break; - case CVT_3BYTE_DATA: - det_mon[i].type = DS_CVT; - get_cvt_timing_section(c, det_mon[i].section.cvt); - break; - case ADD_EST_TIMINGS: - det_mon[i].type = DS_EST_III; - break; - case ADD_DUMMY: - det_mon[i].type = DS_DUMMY; - break; - default: - det_mon[i].type = DS_UNKOWN; - break; - } - if (c[3] <= 0x0F) { - det_mon[i].type = DS_VENDOR + c[3]; - } - } else { - det_mon[i].type = DT; - get_detailed_timing_section(c,&det_mon[i].section.d_timings); + for (i=0; i < DET_TIMINGS; i++) { + fetch_detailed_block(c, ver, det_mon + i); + NEXT_DT_MD_SECTION; } - NEXT_DT_MD_SECTION; - } } static void diff --git a/hw/xfree86/ddc/xf86DDC.h b/hw/xfree86/ddc/xf86DDC.h index 07411b8..b865e1a 100644 --- a/hw/xfree86/ddc/xf86DDC.h +++ b/hw/xfree86/ddc/xf86DDC.h @@ -62,4 +62,9 @@ extern _X_EXPORT DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC); extern _X_EXPORT Bool xf86MonitorIsHDMI(xf86MonPtr mon); +typedef void (* handle_detailed_fn)(struct detailed_monitor_section *,void *); + +void xf86ForEachDetailedBlock(xf86MonPtr mon, + handle_detailed_fn, + void *data); #endif -- 1.5.4.4 _______________________________________________ xorg mailing list xorg@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/xorg