[SeaBIOS] [PATCH 3/3] bochsvga: dynamic generation of EDID

Hiroshi Miura miurahr at linux.com
Sun Sep 9 16:00:24 CEST 2012


Generate EDID according to preferred resolution
from VBE_DISPI interface.

Signed-off-by: Hiroshi Miura <miurahr at linux.com>
---
 vgasrc/bochsedid.c |   54 ++++++++++++++++++++++++++++++++++++++++++----------
 vgasrc/bochsedid.h |    1 +
 vgasrc/bochsvga.c  |    2 ++
 3 files changed, 47 insertions(+), 10 deletions(-)

diff --git a/vgasrc/bochsedid.c b/vgasrc/bochsedid.c
index 5a40593..6bea389 100644
--- a/vgasrc/bochsedid.c
+++ b/vgasrc/bochsedid.c
@@ -47,6 +47,23 @@ struct edid_monitor_range_limit edid_range_limit VAR16 = {
     0x20,0x20 /* padding */
     };
 
+u16 prefered_xres VAR16, prefered_yres VAR16;
+
+void bochs_init_preferred_resolution(u16 max_xres, u16 max_yres) {
+
+    if (max_xres >= 1920 && max_yres >= 1200){
+        max_xres = 1920; max_yres = 1200;
+    } else if (max_xres >= 1600 && max_yres >= 1200){
+        max_xres = 1600; max_yres = 1200;
+    } else if (max_xres >= 1280 && max_yres >= 1024){
+        max_xres = 1280; max_yres = 1024;
+    } else {
+        max_xres = 1152; max_yres = 864;
+    }
+    SET_VGA(prefered_xres,max_xres);
+    SET_VGA(prefered_yres,max_yres);
+}
+
 int bochs_read_edid_block0(u16 unit, u16 block, u16 seg, void *data, u8 next)
 {
     struct edid_info  *info = data;
@@ -90,18 +107,34 @@ int bochs_read_edid_block0(u16 unit, u16 block, u16 seg, void *data, u8 next)
     /* 720x400 at 70Hz, 720x400 at 88Hz, 640x480 at 60Hz, 640x480 at 67Hz, 640x480 at 72Hz, 640x480 at 75Hz,
        800x600 at 56Hz, 800x600 at 60Hz, 800x600 at 72Hz, 800x600 at 75Hz, 832x624 at 75Hz, 1152x870 at 75Hz,
        not 1024x768 at 87Hz(I), 1024x768 at 60Hz, 1024x768 at 70Hz, 1024x768 at 75Hz, 1280x1024 at 75Hz */
-    /* standard timings */
+  /* standard timings & detailed timing block */
     SET_FARVAR(seg, info->standard_timing[0], EDID_STD_640x480_85Hz);
     SET_FARVAR(seg, info->standard_timing[1], EDID_STD_800x600_85Hz);
-    SET_FARVAR(seg, info->standard_timing[2], EDID_STD_1024x768_85Hz);
-    SET_FARVAR(seg, info->standard_timing[3], EDID_STD_1280x720_70Hz);
-    SET_FARVAR(seg, info->standard_timing[4], EDID_STD_1280x960_60Hz);
-    SET_FARVAR(seg, info->standard_timing[5], EDID_STD_1440x900_60Hz);
-    SET_FARVAR(seg, info->standard_timing[6], EDID_STD_1600x1200_60Hz);
-    SET_FARVAR(seg, info->standard_timing[7], EDID_STD_NOP);
-    /* detailed timing blocks */
-    memcpy_far(seg, &(info->desc[0].dtd), get_global_seg(), &edid_dtd_1600x1200,
-               sizeof (edid_dtd_1600x1200));
+    if (GET_GLOBAL(prefered_xres) < 1280) {
+        SET_FARVAR(seg, info->standard_timing[2], EDID_STD_1024x768_85Hz);
+        SET_FARVAR(seg, info->standard_timing[3], EDID_STD_1152x864_70Hz);
+        memcpy_far(seg, &(info->desc[0].dtd), get_global_seg(), &edid_dtd_1152x864,
+               sizeof (struct edid_detailed_timing));
+    } else if (GET_GLOBAL(prefered_xres) < 1600) {
+        SET_FARVAR(seg, info->standard_timing[2], EDID_STD_1024x768_85Hz);
+        SET_FARVAR(seg, info->standard_timing[3], EDID_STD_1280x1024_60Hz);
+        memcpy_far(seg, &(info->desc[0].dtd), get_global_seg(), &edid_dtd_1280x1024,
+               sizeof (struct edid_detailed_timing));
+    } else if (GET_GLOBAL(prefered_xres) >= 1600 && GET_GLOBAL(prefered_xres) < 1920) {
+        SET_FARVAR(seg, info->standard_timing[2], EDID_STD_1440x900_60Hz);
+        SET_FARVAR(seg, info->standard_timing[3], EDID_STD_1600x1200_60Hz);
+        memcpy_far(seg, &(info->desc[0].dtd), get_global_seg(), &edid_dtd_1600x1200,
+               sizeof (struct edid_detailed_timing));
+    } else {
+        SET_FARVAR(seg, info->standard_timing[2], EDID_STD_1440x900_60Hz);
+        SET_FARVAR(seg, info->standard_timing[3], EDID_STD_1920x1200_60Hz);
+        memcpy_far(seg, &(info->desc[0].dtd), get_global_seg(), &edid_dtd_1920x1200,
+               sizeof (struct edid_detailed_timing));
+    }
+    for (i = 4; i < 8; i++) { /* FILL with NOP */
+        SET_FARVAR(seg, info->standard_timing[i], EDID_STD_NOP);
+    }
+    /* detailed timing block here has already set with standard timings */
     /* monitor range */
     memcpy_far(seg, &(info->desc[1].mrld), get_global_seg(), &edid_range_limit,
                sizeof(edid_range_limit));
@@ -145,3 +178,4 @@ int bochs_read_edid(u16 unit, u16 block, u16 seg, void *data)
         return -1;
     }
 }
+
diff --git a/vgasrc/bochsedid.h b/vgasrc/bochsedid.h
index 0f925df..be60f9f 100644
--- a/vgasrc/bochsedid.h
+++ b/vgasrc/bochsedid.h
@@ -131,6 +131,7 @@ struct edid_info {
 #define EDID_STD_1920x1200_60Hz                      0x00D1
 #define EDID_STD_NOP                                 0x0101
 
+void bochs_init_preferred_resolution(u16 max_xres, u16 max_yres);
 int bochs_get_ddc_capabilities(u16 unit);
 int bochs_read_edid(u16 unit, u16 block, u16 seg, void *data);
 #endif /* bochedid.h */
diff --git a/vgasrc/bochsvga.c b/vgasrc/bochsvga.c
index 2a8aeb1..72240c3 100644
--- a/vgasrc/bochsvga.c
+++ b/vgasrc/bochsvga.c
@@ -373,6 +373,7 @@ bochsvga_init(void)
     u16 en = dispi_read(VBE_DISPI_INDEX_ENABLE);
     dispi_write(VBE_DISPI_INDEX_ENABLE, en | VBE_DISPI_GETCAPS);
     u16 max_xres = dispi_read(VBE_DISPI_INDEX_XRES);
+    u16 max_yres = dispi_read(VBE_DISPI_INDEX_YRES);
     u16 max_bpp = dispi_read(VBE_DISPI_INDEX_BPP);
     dispi_write(VBE_DISPI_INDEX_ENABLE, en);
     struct bochsvga_mode *m = bochsvga_modes;
@@ -388,6 +389,7 @@ bochsvga_init(void)
             SET_VGA(m->mode, 0xffff);
         }
     }
+    bochs_init_preferred_resolution(max_xres, max_yres);
 
     return 0;
 }
-- 
1.7.9.5




More information about the SeaBIOS mailing list