Add interface to EDID part.
Now bios initialize code can register preferred mode
from information of host OS.
Signed-off-by: Hiroshi Miura <[email protected]>
---
vgasrc/vbe_edid.c | 104
+++++++++++++++++++++++++++++++++++++++++++++--------
vgasrc/vbe_edid.h | 4 +++
2 files changed, 94 insertions(+), 14 deletions(-)
diff --git a/vgasrc/vbe_edid.c b/vgasrc/vbe_edid.c
index 41570fc..ede5474 100644
--- a/vgasrc/vbe_edid.c
+++ b/vgasrc/vbe_edid.c
@@ -5,6 +5,7 @@
// This file may be distributed under the terms of the GNU LGPLv3 license.
#include "vbe.h" // VBE_CAPABILITY_8BIT_DAC
+#include "biosvar.h" // GET_GLOBAL
#include "util.h" // dprintf
#include "config.h" // CONFIG_*
#include "vbe_edid.h"
@@ -36,10 +37,65 @@ struct edid_detailed_timing vbe_edid_dtd_1600x1200 VAR16 = {
0x40, 0x40, 0xC0, 0x13, 0x00, 0x2C, 0xE1, 0x10,
0x00, 0x00, 0x1E};
+struct edid_monitor_range_limit vbe_edid_range VAR16 = {
+ {0x00,0x00,0x00,0xfD,0x00},
+ 50,150, /* Vertical 50Hz - 150Hz */
+ 31,135, /* Horiz 31kHz - 135kHz */
+ 20, /* clock 200MHz */
+ 0, /* no ext */
+ 0x0A,0x20,0x20,
+ 0x2020,
+ 0x20,0x20 /* padding */
+ };
+
+static struct prefered_mode_info prefered_mode VAR16 = {0, 0};
+
+int vesa_set_prefered_mode(u16 x, u16 y) {
+
+ SET_VGA(prefered_mode.x, x);
+ SET_VGA(prefered_mode.y, y);
+ return 0;
+}
+
+int vesa_get_prefered_mode(u16 seg, void *data) {
+ struct prefered_mode_info *info = data;
+ int a, b;
+
+ a = GET_GLOBAL(prefered_mode.x);
+ b = GET_GLOBAL(prefered_mode.y);
+ SET_FARVAR(seg, info->x, a);
+ SET_FARVAR(seg, info->y, b);
+ return 0;
+}
+
+static void get_prefered_resolution(struct edid_detailed_timing *dtd, u16 *x, u16 *y) {
+ u16 maxx, maxy;
+
+ maxx = GET_GLOBAL(prefered_mode.x);
+ maxy = GET_GLOBAL(prefered_mode.y);
+ if (maxx == 0 && maxy == 0) {/* unknown, no-preference */
+ dtd = &vbe_edid_dtd_1920x1080;
+ maxx = 1920; maxy = 1080;
+ } else if (maxx >= 1920 && (maxy >= 1080 || maxy == 0)){
+ dtd = &vbe_edid_dtd_1920x1080;
+ maxx = 1920; maxy = 1080;
+ } else if (maxx >= 1600 && (maxy >= 1200 || maxy == 0)){
+ dtd = &vbe_edid_dtd_1600x1200;
+ maxx = 1600; maxy = 1200;
+ } else {
+ dtd = &vbe_edid_dtd_1280x1024;
+ maxx = 1280; maxy = 1024;
+ }
+ *x = maxx; *y = maxy;
+}
+
int vesa_read_edid_block0(u16 unit, u16 block, u16 seg, void *data, u8 next)
{
- struct vbe_edid_info *info = data;
- int i;
+ struct vbe_edid_info *info = data;
+ struct edid_detailed_timing *dtd = &vbe_edid_dtd_1920x1080;
+ u16 max_x=1920;
+ u16 max_y=1080;
+ int i,j;
memset_far(seg, info, 0, sizeof(*info));
/* header */
@@ -67,7 +123,7 @@ int vesa_read_edid_block0(u16 unit, u16 block, u16 seg, void *data, u8 next)
SET_FARVAR(seg, info->screen_width,0x21);
SET_FARVAR(seg, info->screen_height,0x19); /* 330 mm * 250 mm */
SET_FARVAR(seg, info->gamma,0x78); /* 2.2 */
- SET_FARVAR(seg, info->feature_flag,0x0D); /* no DMPS states, RGB, display is continuous frequency */
+ SET_FARVAR(seg, info->feature_flag,0x0F); /* no DMPS states, RGB, display is continuous frequency, prefered mode */
SET_FARVAR(seg, info->least_chromaticity[0],0x78);
SET_FARVAR(seg, info->least_chromaticity[1],0xF5);
memcpy_far(seg, info->most_chromaticity, get_global_seg(), most_chromaticity,
@@ -80,19 +136,39 @@ int vesa_read_edid_block0(u16 unit, u16 block, u16 seg, void *data, u8 next)
800x600@56Hz, 800x600@60Hz, 800x600@72Hz, 800x600@75Hz, 832x624@75Hz, 1152x870@75Hz,
not 1024x768@87Hz(I), 1024x768@60Hz, 1024x768@70Hz, 1024x768@75Hz, 1280x1024@75Hz */
/* standard timings */
+ get_prefered_resolution(dtd, &max_x, &max_y);
SET_FARVAR(seg, info->standard_timing[0], VBE_EDID_STD_640x480_85Hz);
SET_FARVAR(seg, info->standard_timing[1], VBE_EDID_STD_800x600_85Hz);
- SET_FARVAR(seg, info->standard_timing[2], VBE_EDID_STD_1024x768_85Hz);
- SET_FARVAR(seg, info->standard_timing[3], VBE_EDID_STD_1280x720_70Hz);
- SET_FARVAR(seg, info->standard_timing[4], VBE_EDID_STD_1280x960_60Hz);
- SET_FARVAR(seg, info->standard_timing[5], VBE_EDID_STD_1440x900_60Hz);
- SET_FARVAR(seg, info->standard_timing[6], VBE_EDID_STD_1600x1200_60Hz);
- SET_FARVAR(seg, info->standard_timing[7], VBE_EDID_STD_1680x1050_60Hz);
- /* detailed timing blocks */
- memcpy_far(seg, &(info->desc[0].dtd), get_global_seg(), &vbe_edid_dtd_1152x864,
- sizeof (vbe_edid_dtd_1152x864));
- memcpy_far(seg, &(info->desc[1].dtd), get_global_seg(), &vbe_edid_dtd_1280x1024,
- sizeof (vbe_edid_dtd_1280x1024));
+ j=2;
+ if (max_x >= 1152 && max_x < 1024) {
+ SET_FARVAR(seg, info->standard_timing[2], VBE_EDID_STD_1152x864_70Hz);
+ j=3;
+ } else if (max_x >= 1024 && max_x < 1280) {
+ SET_FARVAR(seg, info->standard_timing[2], VBE_EDID_STD_1152x864_70Hz);
+ SET_FARVAR(seg, info->standard_timing[3], VBE_EDID_STD_1024x768_85Hz);
+ j=4;
+ } else if (max_x >= 1280 && max_x < 1600) {
+ SET_FARVAR(seg, info->standard_timing[2], VBE_EDID_STD_1024x768_85Hz);
+ SET_FARVAR(seg, info->standard_timing[3], VBE_EDID_STD_1280x1024_60Hz);
+ j=4;
+ } else if (max_x >= 1600 && max_x < 1920) {
+ SET_FARVAR(seg, info->standard_timing[3], VBE_EDID_STD_1440x900_60Hz);
+ SET_FARVAR(seg, info->standard_timing[4], VBE_EDID_STD_1600x900_60Hz);
+ j=5;
+ } else {
+ SET_FARVAR(seg, info->standard_timing[2], VBE_EDID_STD_1600x900_60Hz);
+ SET_FARVAR(seg, info->standard_timing[3], VBE_EDID_STD_1920x1080_60Hz);
+ j=4;
+ }
+ for (i = j; i < 8; i++) { /* FILL with NOP */
+ SET_FARVAR(seg, info->standard_timing[i], VBE_EDID_STD_NOP);
+ }
+ /* detailed timing block */
+ memcpy_far(seg, &(info->desc[0].dtd), get_global_seg(), dtd,
+ sizeof (struct edid_detailed_timing));
+ /* monitor range */
+ memcpy_far(seg, &(info->desc[1].mrld), get_global_seg(), &vbe_edid_range,
+ sizeof(vbe_edid_range));
/* serial */
for (i = 0; i < 5; i++) {
SET_FARVAR(seg, info->desc[2].mtxtd.header[i], 0);
diff --git a/vgasrc/vbe_edid.h b/vgasrc/vbe_edid.h
index b5222aa..389cd20 100644
--- a/vgasrc/vbe_edid.h
+++ b/vgasrc/vbe_edid.h
@@ -113,6 +113,8 @@ struct vbe_edid_info {
u8 checksum;
} PACKED;
+struct prefered_mode_info {u16 x; u16 y;} PACKED;
+
/* EDID Standard Timing Description */
/* First byte: X resolution, divided by 8, less 31 (256â2288 pixels) */
@@ -133,6 +135,8 @@ struct vbe_edid_info {
#define VBE_EDID_STD_1920x1080_60Hz 0xC0D1
#define VBE_EDID_STD_NOP 0x0101
+int vesa_set_prefered_mode(u16 x, u16 y);
+int vesa_get_prefered_mode(u16 seg, void *data);
int vesa_get_ddc_capabilities(u16 unit);
int vesa_read_edid(u16 unit, u16 block, u16 seg, void *data);
#endif /* vbe_edid.h */
_______________________________________________
SeaBIOS mailing list
[email protected]
http://www.seabios.org/mailman/listinfo/seabios