[PATCH 2/6] implement unified interface and detailed timing operation in interpret_edid.c
Ma Ling
ling.ma at intel.com
Thu Nov 27 00:08:53 PST 2008
implement unified interface and detailed timing operation
---
hw/xfree86/ddc/interpret_edid.c | 312 ++++++++++++++++++++++++++-------------
1 files changed, 208 insertions(+), 104 deletions(-)
diff --git a/hw/xfree86/ddc/interpret_edid.c b/hw/xfree86/ddc/interpret_edid.c
index c4d8963..0e4e152 100644
--- a/hw/xfree86/ddc/interpret_edid.c
+++ b/hw/xfree86/ddc/interpret_edid.c
@@ -41,8 +41,11 @@ 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);
+ struct detailed_monitor_section *det_mon);
static void copy_string(Uchar *, Uchar *);
static void get_dst_timing_section(Uchar *, struct std_timings *,
struct edid_version *);
@@ -52,11 +55,27 @@ static void get_detailed_timing_section(Uchar*, struct detailed_timings *);
static Bool validate_version(int scrnIndex, struct edid_version *);
static void
+find_ranges_section(struct detailed_monitor_section *det, void *ranges)
+{
+ if (det->type == DS_RANGES)
+ *(struct monitor_ranges **)ranges = &det->section.ranges;
+}
+
+static void
+find_max_detailed_clock(struct detailed_monitor_section *det, void *ret)
+{
+ int *clock = ret;
+
+ if (det->type == DT) {
+ struct detailed_timings *t = &det->section.d_timings;
+ *clock = max(*clock, t->clock);
+ }
+}
+
+static void
handle_edid_quirks(xf86MonPtr m)
{
- int i, j;
- struct detailed_timings *preferred_timing;
- struct monitor_ranges *ranges;
+ struct monitor_ranges *ranges = NULL;
/*
* max_clock is only encoded in EDID in tens of MHz, so occasionally we
@@ -64,28 +83,116 @@ handle_edid_quirks(xf86MonPtr m)
* similar. Strictly we should refuse to round up too far, but let's
* see how well this works.
*/
- for (i = 0; i < 4; i++) {
- if (m->det_mon[i].type == DS_RANGES) {
- ranges = &m->det_mon[i].section.ranges;
- for (j = 0; j < 4; j++) {
- if (m->det_mon[j].type == DT) {
- preferred_timing = &m->det_mon[j].section.d_timings;
- if (!ranges->max_clock) continue; /* zero is legal */
- if (ranges->max_clock * 1000000 < preferred_timing->clock) {
- xf86Msg(X_WARNING,
- "EDID preferred timing clock %.2fMHz exceeds "
- "claimed max %dMHz, fixing\n",
- preferred_timing->clock / 1.0e6,
- ranges->max_clock);
- ranges->max_clock =
- (preferred_timing->clock+999999)/1000000;
- return;
- }
- }
- }
- }
+ xf86ForEachDetailedBlock(m, find_ranges_section, &ranges);
+ if (ranges && ranges->max_clock) {
+ int clock = 0;
+ xf86ForEachDetailedBlock(m, find_max_detailed_clock, &clock);
+ if (clock && (ranges->max_clock * 1e6 < clock)) {
+ xf86Msg(X_WARNING, "EDID timing clock %.2f exceeds claimed max "
+ "%dMHz, fixing\n", clock / 1.0e6, ranges->max_clock);
+ ranges->max_clock = (clock+999999)/1e6;
+ }
+ }
+
+}
+
+static int GetCEADetailTiming(Uchar *blk, xf86MonPtr mon,
+ struct detailed_monitor_section *det_mon)
+
+{
+ int num;
+ int dt_offset = ((struct cea_ext_body *)blk)->dt_offset;
+
+ num = 0;
+
+ if (dt_offset < CEA_EXT_MIN_DATA_OFFSET)
+ return num;
+
+ while (dt_offset < (CEA_EXT_MAX_DATA_OFFSET - DET_TIMING_INFO_LEN) &&
+ num < CEA_EXT_DET_TIMING_NUM) {
+
+ fetch_detailed_block(blk + dt_offset, &mon->ver, det_mon + num);
+
+ num = num + 1 ;
+
+ _NEXT_DT_MD_SECTION(dt_offset);
+ }
+
+ return num;
+}
+
+
+static void HandleCEADetailedBlock(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 = GetCEADetailTiming(ext, mon, det_mon);
+
+ for (i = 0; i < det_mon_num; i = i + 1)
+ 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 = i + 1) {
+ ext = &mon->rawData[EDID1_LEN + i * EDID1_LEN];
+ switch (ext[EXT_TAG]){
+ case CEA_EXT:
+ HandleCEADetailedBlock(ext, mon, fn, data);
+ break;
+ case VTB_EXT:
+ case DI_EXT:
+ case LS_EXT:
+ case MI_EXT:
+ break;
+ }
}
+}
+
+struct det_hv_perameter {
+ int real_hsize;
+ int real_vsize;
+ float target_aspect;
+};
+
+static void handle_detailed_hvsize(struct detailed_monitor_section *det_mon,
+ void *data)
+{
+ struct det_hv_perameter *p = (struct det_hv_perameter *)data;
+ float timing_aspect;
+ if (det_mon->type == DT) {
+ struct detailed_timings *timing;
+ timing = &det_mon->section.d_timings;
+
+ if (!timing->v_size)
+ return;
+
+ timing_aspect = (float)timing->h_size / (float)timing->v_size;
+ if (fabs(1 - (timing_aspect / p->target_aspect)) < 0.05) {
+ p->real_hsize = max(p->real_hsize, timing->h_size);
+ p->real_vsize = max(p->real_vsize, timing->v_size);
+ }
+ }
+}
+
+static void encode_aspect_ratio(xf86MonPtr m)
+{
/*
* some monitors encode the aspect ratio instead of the physical size.
* try to find the largest detailed timing that matches that aspect
@@ -95,36 +202,24 @@ handle_edid_quirks(xf86MonPtr m)
(m->features.hsize == 16 && m->features.vsize == 10) ||
(m->features.hsize == 4 && m->features.vsize == 3) ||
(m->features.hsize == 5 && m->features.vsize == 4)) {
- int real_hsize = 0, real_vsize = 0;
- float target_aspect, timing_aspect;
-
- target_aspect = (float)m->features.hsize / (float)m->features.vsize;
- for (i = 0; i < 4; i++) {
- if (m->det_mon[i].type == DT) {
- struct detailed_timings *timing;
- timing = &m->det_mon[i].section.d_timings;
-
- if (!timing->v_size)
- continue;
-
- timing_aspect = (float)timing->h_size / (float)timing->v_size;
- if (fabs(1 - (timing_aspect / target_aspect)) < 0.05) {
- real_hsize = max(real_hsize, timing->h_size);
- real_vsize = max(real_vsize, timing->v_size);
- }
- }
- }
-
- if (!real_hsize || !real_vsize) {
+
+ struct det_hv_perameter p;
+ p.real_hsize = 0;
+ p.real_vsize = 0;
+ p.target_aspect = (float)m->features.hsize /(float)m->features.vsize;
+
+ xf86ForEachDetailedBlock(m, handle_detailed_hvsize, &p);
+
+ if (!p.real_hsize || !p.real_vsize) {
m->features.hsize = m->features.vsize = 0;
- } else if ((m->features.hsize * 10 == real_hsize) &&
- (m->features.vsize * 10 == real_vsize)) {
+ } else if ((m->features.hsize * 10 == p.real_hsize) &&
+ (m->features.vsize * 10 == p.real_vsize)) {
/* exact match is just unlikely, should do a better check though */
m->features.hsize = m->features.vsize = 0;
} else {
/* convert mm to cm */
- m->features.hsize = (real_hsize + 5) / 10;
- m->features.vsize = (real_vsize + 5) / 10;
+ m->features.hsize = (p.real_hsize + 5) / 10;
+ m->features.vsize = (p.real_vsize + 5) / 10;
}
xf86Msg(X_INFO, "Quirked EDID physical size to %dx%d cm\n",
@@ -151,10 +246,13 @@ xf86InterpretEDID(int scrnIndex, Uchar *block)
&m->timings1);
get_std_timing_section(SECTION(STD_TIMING_SECTION,block),m->timings2,
&m->ver);
- get_dt_md_section(SECTION(DET_TIMING_SECTION,block),&m->ver, m->det_mon);
+ get_dt_md_section(SECTION(DET_TIMING_SECTION,block), &m->ver,
+ m->det_mon);
+
m->no_sections = (int)*(char *)SECTION(NO_EDID,block);
handle_edid_quirks(m);
+ encode_aspect_ratio(m);
return (m);
@@ -285,65 +383,71 @@ get_std_timing_section(Uchar *c, struct std_timings *r,
}
static void
+fetch_detailed_block(Uchar *c, struct edid_version *ver,
+ struct detailed_monitor_section *det_mon)
+{
+ 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;
+ 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[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
--
1.5.4.4
More information about the xorg
mailing list