summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Jackson <ajax@redhat.com>2009-10-02 15:27:30 -0400
committerAdam Jackson <ajax@redhat.com>2009-10-02 15:27:30 -0400
commitb82197fdc81a988e48e82bc7d2e8032412223ca1 (patch)
tree06a1b30e83a0dc40e4cd17614f0156a733e2b649
parenta14b5eeecedd1a33ab2c5753c813345d1b3251e6 (diff)
EDID CVT decode
-rw-r--r--cvt.c10
-rw-r--r--edid.c79
-rw-r--r--minitru.h2
3 files changed, 85 insertions, 6 deletions
diff --git a/cvt.c b/cvt.c
index edff0a4..d7cd570 100644
--- a/cvt.c
+++ b/cvt.c
@@ -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);
diff --git a/edid.c b/edid.c
index 3913c3a..f8ba728 100644
--- a/edid.c
+++ b/edid.c
@@ -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;
diff --git a/minitru.h b/minitru.h
index 4256321..db9dae3 100644
--- a/minitru.h
+++ b/minitru.h
@@ -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);