From 25d884a52a1819792bc97cac9890d44a72446b7c Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Tue, 14 Dec 2010 17:06:32 +0000 Subject: [PATCH] move generic parts of EDID handling (structure, checksumming) to generic location --- ChangeLog.vbe-autodetect | 7 ++-- grub-core/video/i386/pc/vbe.c | 27 +++------------ grub-core/video/video.c | 19 +++++++++++ include/grub/i386/pc/vbe.h | 64 ++--------------------------------- include/grub/video.h | 62 +++++++++++++++++++++++++++++++++ 5 files changed, 92 insertions(+), 87 deletions(-) diff --git a/ChangeLog.vbe-autodetect b/ChangeLog.vbe-autodetect index 7d16ebee2..0d96fc0a2 100644 --- a/ChangeLog.vbe-autodetect +++ b/ChangeLog.vbe-autodetect @@ -2,11 +2,11 @@ Preferred resolution detection for VBE. + * grub-core/video/video.c (grub_video_edid_checksum): New function. * grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info): - New function. + Likewise. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. - (grub_vbe_edid_checksum): Likewise. (grub_vbe_get_preferred_mode): Likewise. Try EDID followed by the Flat Panel extension, in line with the X.org VESA driver. (grub_video_vbe_setup): When the mode is "auto", try to get the @@ -14,9 +14,10 @@ than the preferred mode (some BIOSes expose a preferred mode that is not in their mode list!). If this fails, fall back to 640x480 as a safe conservative choice. + * include/grub/video.h (struct grub_vbe_edid_info): New structure. + (grub_video_edid_checksum): Add prototype. * include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New structure. - (struct grub_vbe_edid_info): Likewise. (grub_vbe_bios_get_flat_panel_info): Add prototype. (grub_vbe_bios_get_ddc_capabilities): Likewise. (grub_vbe_bios_read_edid): Likewise. diff --git a/grub-core/video/i386/pc/vbe.c b/grub-core/video/i386/pc/vbe.c index 1794addae..e2dcc151e 100644 --- a/grub-core/video/i386/pc/vbe.c +++ b/grub-core/video/i386/pc/vbe.c @@ -308,7 +308,7 @@ grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level) /* Call VESA BIOS 0x4f15 to read EDID information, return status. */ grub_vbe_status_t -grub_vbe_bios_read_edid (struct grub_vbe_edid_info *edid_info) +grub_vbe_bios_read_edid (struct grub_video_edid_info *edid_info) { struct grub_bios_int_registers regs; @@ -377,31 +377,12 @@ grub_vbe_probe (struct grub_vbe_info_block *info_block) return GRUB_ERR_NONE; } -static grub_err_t -grub_vbe_edid_checksum (struct grub_vbe_edid_info *edid_info) -{ - const char *edid_bytes = (const char *) edid_info; - int i; - char checksum = 0; - - /* Check EDID checksum. */ - for (i = 0; i < 128; ++i) - checksum += edid_bytes[i]; - - if (checksum != 0) - return grub_error (GRUB_ERR_BAD_DEVICE, - "invalid EDID checksum %d", checksum); - - grub_errno = GRUB_ERR_NONE; - return grub_errno; -} - static grub_err_t grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) { grub_vbe_status_t status; grub_uint8_t ddc_level; - struct grub_vbe_edid_info edid_info; + struct grub_video_edid_info edid_info; struct grub_vbe_flat_panel_info flat_panel_info; if (controller_info.version >= 0x200 @@ -412,10 +393,10 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height) /* Bit 1 in the Feature Support field indicates that the first Detailed Timing Description is the preferred timing mode. */ if (status == GRUB_VBE_STATUS_OK - && grub_vbe_edid_checksum (&edid_info) == GRUB_ERR_NONE + && grub_video_edid_checksum (&edid_info) == GRUB_ERR_NONE && edid_info.version == 1 /* we don't understand later versions */ && (edid_info.feature_support - & GRUB_VBE_EDID_FEATURE_PREFERRED_TIMING_MODE) + & GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE) && edid_info.detailed_timings[0].pixel_clock) { *width = edid_info.detailed_timings[0].horizontal_active_lo diff --git a/grub-core/video/video.c b/grub-core/video/video.c index 7a1a446e4..f3ecab94d 100644 --- a/grub-core/video/video.c +++ b/grub-core/video/video.c @@ -374,6 +374,25 @@ grub_video_get_active_render_target (struct grub_video_render_target **target) return grub_video_adapter_active->get_active_render_target (target); } +grub_err_t +grub_video_edid_checksum (struct grub_video_edid_info *edid_info) +{ + const char *edid_bytes = (const char *) edid_info; + int i; + char checksum = 0; + + /* Check EDID checksum. */ + for (i = 0; i < 128; ++i) + checksum += edid_bytes[i]; + + if (checksum != 0) + return grub_error (GRUB_ERR_BAD_DEVICE, + "invalid EDID checksum %d", checksum); + + grub_errno = GRUB_ERR_NONE; + return grub_errno; +} + /* Parse x[x]*/ static grub_err_t parse_modespec (const char *current_mode, int *width, int *height, int *depth) diff --git a/include/grub/i386/pc/vbe.h b/include/grub/i386/pc/vbe.h index 5be34fdec..0422558db 100644 --- a/include/grub/i386/pc/vbe.h +++ b/include/grub/i386/pc/vbe.h @@ -19,6 +19,8 @@ #ifndef GRUB_VBE_MACHINE_HEADER #define GRUB_VBE_MACHINE_HEADER 1 +#include + /* Default video mode to be used. */ #define GRUB_VBE_DEFAULT_VIDEO_MODE 0x101 @@ -184,66 +186,6 @@ struct grub_vbe_flat_panel_info grub_uint8_t reserved[14]; } __attribute__ ((packed)); -struct grub_vbe_edid_info -{ - grub_uint8_t header[8]; - grub_uint16_t manufacturer_id; - grub_uint16_t product_id; - grub_uint32_t serial_number; - grub_uint8_t week_of_manufacture; - grub_uint8_t year_of_manufacture; - grub_uint8_t version; - grub_uint8_t revision; - - grub_uint8_t video_input_definition; - grub_uint8_t max_horizontal_image_size; - grub_uint8_t max_vertical_image_size; - grub_uint8_t display_gamma; - grub_uint8_t feature_support; -#define GRUB_VBE_EDID_FEATURE_PREFERRED_TIMING_MODE (1 << 1) - - grub_uint8_t red_green_lo; - grub_uint8_t blue_white_lo; - grub_uint8_t red_x_hi; - grub_uint8_t red_y_hi; - grub_uint8_t green_x_hi; - grub_uint8_t green_y_hi; - grub_uint8_t blue_x_hi; - grub_uint8_t blue_y_hi; - grub_uint8_t white_x_hi; - grub_uint8_t white_y_hi; - - grub_uint8_t established_timings_1; - grub_uint8_t established_timings_2; - grub_uint8_t manufacturer_reserved_timings; - - grub_uint16_t standard_timings[8]; - - struct { - grub_uint16_t pixel_clock; - /* Only valid if the pixel clock is non-null. */ - grub_uint8_t horizontal_active_lo; - grub_uint8_t horizontal_blanking_lo; - grub_uint8_t horizontal_hi; - grub_uint8_t vertical_active_lo; - grub_uint8_t vertical_blanking_lo; - grub_uint8_t vertical_hi; - grub_uint8_t horizontal_sync_offset_lo; - grub_uint8_t horizontal_sync_pulse_width_lo; - grub_uint8_t vertical_sync_lo; - grub_uint8_t sync_hi; - grub_uint8_t horizontal_image_size_lo; - grub_uint8_t vertical_image_size_lo; - grub_uint8_t image_size_hi; - grub_uint8_t horizontal_border; - grub_uint8_t vertical_border; - grub_uint8_t flags; - } detailed_timings[4]; - - grub_uint8_t extension_flag; - grub_uint8_t checksum; -} __attribute__ ((packed)); - /* Prototypes for helper functions. */ /* Call VESA BIOS 0x4f00 to get VBE Controller Information, return status. */ grub_vbe_status_t @@ -280,7 +222,7 @@ grub_vbe_status_t grub_vbe_bios_get_ddc_capabilities (grub_uint8_t *level); /* Call VESA BIOS 0x4f15 to read EDID information, return status. */ grub_vbe_status_t -grub_vbe_bios_read_edid (struct grub_vbe_edid_info *edid_data); +grub_vbe_bios_read_edid (struct grub_video_edid_info *edid_data); grub_vbe_status_t grub_vbe_bios_getset_dac_palette_width (int set, int *width); diff --git a/include/grub/video.h b/include/grub/video.h index 97bd85bd1..2cf1424c4 100644 --- a/include/grub/video.h +++ b/include/grub/video.h @@ -210,6 +210,66 @@ struct grub_video_palette_data grub_uint8_t a; /* Reserved bits value (0-255). */ }; +struct grub_video_edid_info +{ + grub_uint8_t header[8]; + grub_uint16_t manufacturer_id; + grub_uint16_t product_id; + grub_uint32_t serial_number; + grub_uint8_t week_of_manufacture; + grub_uint8_t year_of_manufacture; + grub_uint8_t version; + grub_uint8_t revision; + + grub_uint8_t video_input_definition; + grub_uint8_t max_horizontal_image_size; + grub_uint8_t max_vertical_image_size; + grub_uint8_t display_gamma; + grub_uint8_t feature_support; +#define GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE (1 << 1) + + grub_uint8_t red_green_lo; + grub_uint8_t blue_white_lo; + grub_uint8_t red_x_hi; + grub_uint8_t red_y_hi; + grub_uint8_t green_x_hi; + grub_uint8_t green_y_hi; + grub_uint8_t blue_x_hi; + grub_uint8_t blue_y_hi; + grub_uint8_t white_x_hi; + grub_uint8_t white_y_hi; + + grub_uint8_t established_timings_1; + grub_uint8_t established_timings_2; + grub_uint8_t manufacturer_reserved_timings; + + grub_uint16_t standard_timings[8]; + + struct { + grub_uint16_t pixel_clock; + /* Only valid if the pixel clock is non-null. */ + grub_uint8_t horizontal_active_lo; + grub_uint8_t horizontal_blanking_lo; + grub_uint8_t horizontal_hi; + grub_uint8_t vertical_active_lo; + grub_uint8_t vertical_blanking_lo; + grub_uint8_t vertical_hi; + grub_uint8_t horizontal_sync_offset_lo; + grub_uint8_t horizontal_sync_pulse_width_lo; + grub_uint8_t vertical_sync_lo; + grub_uint8_t sync_hi; + grub_uint8_t horizontal_image_size_lo; + grub_uint8_t vertical_image_size_lo; + grub_uint8_t image_size_hi; + grub_uint8_t horizontal_border; + grub_uint8_t vertical_border; + grub_uint8_t flags; + } detailed_timings[4]; + + grub_uint8_t extension_flag; + grub_uint8_t checksum; +} __attribute__ ((packed)); + typedef enum grub_video_driver_id { GRUB_VIDEO_DRIVER_NONE, @@ -423,6 +483,8 @@ grub_err_t EXPORT_FUNC (grub_video_set_active_render_target) (struct grub_video_ grub_err_t grub_video_get_active_render_target (struct grub_video_render_target **target); +grub_err_t grub_video_edid_checksum (struct grub_video_edid_info *edid_info); + grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring, unsigned int modemask, unsigned int modevalue);