summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2009-10-02 15:07:06 -0400
committerAdam Jackson <ajax@redhat.com>2009-10-02 15:07:06 -0400
commitee187bfbb73e2badaaab1a12857670f78585c971 (patch)
tree0df4c716411e1e527d082dd886dc9f1cfebacc52
parent532577ebc796596b52b54d89ff967e0ef3070381 (diff)
EDID detailed timing parse
-rw-r--r--edid.c70
1 files changed, 70 insertions, 0 deletions
diff --git a/edid.c b/edid.c
index 5f3adbb..1ac50a0 100644
--- a/edid.c
+++ b/edid.c
@@ -211,8 +211,78 @@ edid_standard_modes(struct mt_monitor *mon, struct mt_mode *list)
}
static struct mt_mode *
+edid_do_detailed_mode(uint8_t *x)
+{
+ uint32_t ha, hbl, hso, hspw, hborder, va, vbl, vso, vspw, vborder;
+ struct mt_mode *m = mt_mode_alloc();
+
+ ha = (x[2] + ((x[4] & 0xF0) << 4));
+ hbl = (x[3] + ((x[4] & 0x0F) << 8));
+ hso = (x[8] + ((x[11] & 0xC0) << 2));
+ hspw = (x[9] + ((x[11] & 0x30) << 4));
+ hborder = x[15];
+ va = (x[5] + ((x[7] & 0xF0) << 4));
+ vbl = (x[6] + ((x[7] & 0x0F) << 8));
+ vso = ((x[10] >> 4) + ((x[11] & 0x0C) << 2));
+ vspw = ((x[10] & 0x0F) + ((x[11] & 0x03) << 4));
+ vborder = x[16];
+
+ m->clock = (x[0] + (x[1] << 8)) * 10;
+ m->hdisplay = ha;
+ m->hsyncstart = ha + hso;
+ m->hsyncend = ha + hso + hspw;
+ m->htotal = ha + hbl;
+ /* hborder */
+ m->vdisplay = va;
+ m->vsyncstart = va + vso;
+ m->vsyncend = va + vso + vspw;
+ m->vtotal = va + vbl;
+ /* vborder */
+
+ if (x[17] & 0x04)
+ m->flags |= MT_FLAG_PVSYNC;
+ else
+ m->flags |= MT_FLAG_NVSYNC;
+
+ if (x[17] & 0x02)
+ m->flags |= MT_FLAG_PHSYNC;
+ else
+ m->flags |= MT_FLAG_NHSYNC;
+
+ if (x[17] & 0x80)
+ m->flags |= MT_FLAG_INTERLACED;
+
+ /* XXX timings are reduced? */
+
+ return m;
+}
+
+static struct mt_mode *
+edid_do_detailed_block(uint8_t *x)
+{
+ if (x[0] == 0 && x[1] == 0) {
+ switch (x[3]) {
+ case 0xF7: /* EST III */
+ case 0xF8: /* CVT */
+ case 0xFA: /* standard */
+ default:
+ return NULL;
+ }
+ }
+
+ return edid_do_detailed_mode(x);
+}
+
+static struct mt_mode *
edid_detailed_block_modes(struct mt_monitor *mon, struct mt_mode *list)
{
+ uint8_t *block = mon->block;
+ int i;
+
+ for (i = 0; i < 4; i++)
+ list = mt_modes_add(list,
+ edid_do_detailed_block(block + 0x36 + (i*18)));
+
return list;
}