diff options
author | Adam Jackson <ajax@redhat.com> | 2009-10-02 15:27:30 -0400 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2009-10-02 15:27:30 -0400 |
commit | b82197fdc81a988e48e82bc7d2e8032412223ca1 (patch) | |
tree | 06a1b30e83a0dc40e4cd17614f0156a733e2b649 | |
parent | a14b5eeecedd1a33ab2c5753c813345d1b3251e6 (diff) |
EDID CVT decode
-rw-r--r-- | cvt.c | 10 | ||||
-rw-r--r-- | edid.c | 79 | ||||
-rw-r--r-- | minitru.h | 2 |
3 files changed, 85 insertions, 6 deletions
@@ -47,7 +47,7 @@ * */ struct mt_mode * -mt_ct_mode(int hdisplay, int vdisplay, float vrefresh, uint32_t flags) +mt_cvt_mode(uint32_t hdisplay, uint32_t vdisplay, float refresh, uint32_t flags) { struct mt_mode *mode = mt_mode_alloc(); int interlaced = !!(flags & MT_FLAG_INTERLACED); @@ -75,14 +75,14 @@ mt_ct_mode(int hdisplay, int vdisplay, float vrefresh, uint32_t flags) float interlace; /* please rename this */ /* CVT default is 60.0Hz */ - if (!vrefresh) - vrefresh = 60.0; + if (!refresh) + refresh = 60.0; /* 1. Required field rate */ if (interlaced) - vfieldrate = vrefresh * 2; + vfieldrate = refresh * 2; else - vfieldrate = vrefresh; + vfieldrate = refresh; /* 2. Horizontal pixels */ hdisplayrnd = hdisplay - (hdisplay % CVT_H_GRANULARITY); @@ -290,6 +290,84 @@ edid_estiii_modes(uint8_t *x) return ret; } +static uint32_t +edid_cvt_next_refresh(uint32_t *refreshes, uint32_t *flag) +{ + if (*refreshes & 0x10) { + *refreshes &= 0x10; + return 50; + } + if (*refreshes & 0x08) { + *refreshes &= 0x08; + return 60; + } + if (*refreshes & 0x04) { + *refreshes &= 0x04; + return 75; + } + if (*refreshes & 0x02) { + *refreshes &= 0x02; + return 85; + } + if (*refreshes &= 0x01) { + *refreshes &= 0x01; + *flag = MT_FLAG_REDUCED; + return 60; + } + + *refreshes = 0; + return 0; +} + +static struct mt_mode * +edid_cvt_mode(uint8_t *x) +{ + struct mt_mode *ret = NULL; + const uint8_t empty[3] = { 0, 0, 0 }; + uint32_t width, height, refreshes; + + if (!memcmp(x, empty, 3)) + return NULL; + + height = x[0]; + height |= (x[1] & 0xf0) << 4; + height++; + height *= 2; + + switch (x[1] & 0x0c) { + case 0x00: + width = (height * 4) / 3; break; + case 0x04: + width = (height * 16) / 9; break; + case 0x08: + width = (height * 16) / 10; break; + case 0x0c: + width = (height * 15) / 9; break; + } + + refreshes = x[2] & 0x1f; + + while (refreshes) { + uint32_t flag = 0; + uint32_t refresh = edid_cvt_next_refresh(&refreshes, &flag); + ret = mt_modes_add(ret, mt_cvt_mode(width, height, refresh, flag)); + } + + return ret; +} + +static struct mt_mode * +edid_cvt_modes(uint8_t *x) +{ + struct mt_mode *ret = NULL; + int i; + + for (i = 0; i < 4; i++) + ret = mt_modes_add(ret, edid_cvt_mode(x + 6 + (i * 3))); + + return ret; +} + static struct mt_mode * edid_do_detailed_mode(uint8_t *x) { @@ -345,6 +423,7 @@ edid_do_detailed_block(uint8_t *x) case 0xF7: /* EST III */ return edid_estiii_modes(x); case 0xF8: /* CVT */ + return edid_cvt_modes(x); case 0xFA: /* standard */ default: return NULL; @@ -73,7 +73,7 @@ struct mt_mode { extern struct mt_mode *mt_monitor_mode_list(struct mt_monitor *monitor); extern struct mt_mode *mt_dmt_mode_list(void); -extern struct mt_mode *mt_cvt_mode(uint32_t width, uint32_t height, +extern struct mt_mode *mt_cvt_mode(uint32_t hdisplay, uint32_t vdisplay, float refresh, uint32_t flags); extern struct mt_mode *mt_gtf_mode(uint32_t width, uint32_t height, float refresh, uint32_t flags); |