diff options
author | Adam Jackson | 2010-08-03 20:38:17 +0200 |
---|---|---|
committer | Dave Airlie | 2010-08-10 02:46:57 +0200 |
commit | 4d76a22134d5a5ad259fd667f3d2b215b7e71d10 (patch) | |
tree | 683d8df7efc2a652cc78146022a31bbab1877950 | |
parent | drm: Remove unused fields from drm_display_info (diff) | |
download | kernel-qcow2-linux-4d76a22134d5a5ad259fd667f3d2b215b7e71d10.tar.gz kernel-qcow2-linux-4d76a22134d5a5ad259fd667f3d2b215b7e71d10.tar.xz kernel-qcow2-linux-4d76a22134d5a5ad259fd667f3d2b215b7e71d10.zip |
drm/edid: Add detailed block walk for CEA extensions
Signed-off-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | drivers/gpu/drm/drm_edid.c | 38 | ||||
-rw-r--r-- | include/drm/drm_edid.h | 6 |
2 files changed, 43 insertions, 1 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 3d6abde8e785..30b286ba16c4 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -685,6 +685,33 @@ EXPORT_SYMBOL(drm_mode_find_dmt); typedef void detailed_cb(struct detailed_timing *timing, void *closure); static void +cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) +{ + int i, n = 0; + u8 rev = ext[0x01], d = ext[0x02]; + u8 *det_base = ext + d; + + switch (rev) { + case 0: + /* can't happen */ + return; + case 1: + /* have to infer how many blocks we have, check pixel clock */ + for (i = 0; i < 6; i++) + if (det_base[18*i] || det_base[18*i+1]) + n++; + break; + default: + /* explicit count */ + n = min(ext[0x03] & 0x0f, 6); + break; + } + + for (i = 0; i < n; i++) + cb((struct detailed_timing *)(det_base + 18 * i), closure); +} + +static void drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) { int i; @@ -696,7 +723,16 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) for (i = 0; i < EDID_DETAILED_TIMINGS; i++) cb(&(edid->detailed_timings[i]), closure); - /* XXX extension block walk */ + for (i = 1; i <= raw_edid[0x7e]; i++) { + u8 *ext = raw_edid + (i * EDID_LENGTH); + switch (*ext) { + case CEA_EXT: + cea_for_each_detailed_block(ext, cb, closure); + break; + default: + break; + } + } } static void diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 39e2cc5c7e66..5881fad91faa 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -28,6 +28,12 @@ #define EDID_LENGTH 128 #define DDC_ADDR 0x50 +#define CEA_EXT 0x02 +#define VTB_EXT 0x10 +#define DI_EXT 0x40 +#define LS_EXT 0x50 +#define MI_EXT 0x60 + struct est_timings { u8 t1; u8 t2; |