move more EDID-handling functions to generic code, and make videoinfo display EDID information
This commit is contained in:
parent
25d884a52a
commit
129185cfaa
5 changed files with 108 additions and 23 deletions
|
@ -3,24 +3,33 @@
|
||||||
Preferred resolution detection for VBE.
|
Preferred resolution detection for VBE.
|
||||||
|
|
||||||
* grub-core/video/video.c (grub_video_edid_checksum): New function.
|
* grub-core/video/video.c (grub_video_edid_checksum): New function.
|
||||||
|
(grub_video_get_edid): Likewise.
|
||||||
|
(grub_video_edid_preferred_mode): Likewise. Try EDID followed by
|
||||||
|
the Flat Panel extension, in line with the X.org VESA driver.
|
||||||
* grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info):
|
* grub-core/video/i386/pc/vbe.c (grub_vbe_bios_get_flat_panel_info):
|
||||||
Likewise.
|
New function.
|
||||||
(grub_vbe_bios_get_ddc_capabilities): Likewise.
|
(grub_vbe_bios_get_ddc_capabilities): Likewise.
|
||||||
(grub_vbe_bios_read_edid): Likewise.
|
(grub_vbe_bios_read_edid): Likewise.
|
||||||
(grub_vbe_get_preferred_mode): Likewise. Try EDID followed by the
|
(grub_vbe_get_preferred_mode): Likewise.
|
||||||
Flat Panel extension, in line with the X.org VESA driver.
|
|
||||||
(grub_video_vbe_setup): When the mode is "auto", try to get the
|
(grub_video_vbe_setup): When the mode is "auto", try to get the
|
||||||
preferred mode from VBE, and use the largest mode that is no larger
|
preferred mode from VBE, and use the largest mode that is no larger
|
||||||
than the preferred mode (some BIOSes expose a preferred mode that is
|
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
|
not in their mode list!). If this fails, fall back to 640x480 as a
|
||||||
safe conservative choice.
|
safe conservative choice.
|
||||||
|
(grub_video_vbe_get_edid): New function.
|
||||||
|
(grub_video_vbe_adapter): Add get_edid.
|
||||||
* include/grub/video.h (struct grub_vbe_edid_info): New structure.
|
* include/grub/video.h (struct grub_vbe_edid_info): New structure.
|
||||||
(grub_video_edid_checksum): Add prototype.
|
(grub_video_edid_checksum): Add prototype.
|
||||||
|
(grub_video_get_edid): Likewise.
|
||||||
|
(grub_video_edid_preferred_mode): Likewise.
|
||||||
* include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New
|
* include/grub/i386/pc/vbe.h (struct grub_vbe_flat_panel_info): New
|
||||||
structure.
|
structure.
|
||||||
(grub_vbe_bios_get_flat_panel_info): Add prototype.
|
(grub_vbe_bios_get_flat_panel_info): Add prototype.
|
||||||
(grub_vbe_bios_get_ddc_capabilities): Likewise.
|
(grub_vbe_bios_get_ddc_capabilities): Likewise.
|
||||||
(grub_vbe_bios_read_edid): Likewise.
|
(grub_vbe_bios_read_edid): Likewise.
|
||||||
|
|
||||||
|
* grub-core/commands/videoinfo.c (print_edid): New function.
|
||||||
|
(grub_cmd_videoinfo): Print EDID if available.
|
||||||
|
|
||||||
* util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This
|
* util/grub.d/00_header.in (GRUB_GFXMODE): Default to "auto". This
|
||||||
is more appropriate on a wider range of platforms than 640x480.
|
is more appropriate on a wider range of platforms than 640x480.
|
||||||
|
|
|
@ -77,6 +77,30 @@ hook (const struct grub_video_mode_info *info)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_edid (struct grub_video_edid_info *edid_info)
|
||||||
|
{
|
||||||
|
unsigned int edid_width, edid_height;
|
||||||
|
|
||||||
|
if (grub_video_edid_checksum (edid_info))
|
||||||
|
{
|
||||||
|
grub_printf (" EDID checksum invalid\n");
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_printf (" EDID version: %u.%u\n",
|
||||||
|
edid_info->version, edid_info->revision);
|
||||||
|
if (grub_video_edid_preferred_mode (edid_info, &edid_width, &edid_height)
|
||||||
|
== GRUB_ERR_NONE)
|
||||||
|
grub_printf (" Preferred mode: %ux%u\n", edid_width, edid_height);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
grub_printf (" No preferred mode available\n");
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
|
grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
|
||||||
int argc, char **args)
|
int argc, char **args)
|
||||||
|
@ -120,6 +144,8 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
|
||||||
FOR_VIDEO_ADAPTERS (adapter)
|
FOR_VIDEO_ADAPTERS (adapter)
|
||||||
{
|
{
|
||||||
|
struct grub_video_edid_info edid_info;
|
||||||
|
|
||||||
grub_printf ("Adapter '%s':\n", adapter->name);
|
grub_printf ("Adapter '%s':\n", adapter->name);
|
||||||
|
|
||||||
if (!adapter->iterate)
|
if (!adapter->iterate)
|
||||||
|
@ -143,6 +169,11 @@ grub_cmd_videoinfo (grub_command_t cmd __attribute__ ((unused)),
|
||||||
|
|
||||||
adapter->iterate (hook);
|
adapter->iterate (hook);
|
||||||
|
|
||||||
|
if (adapter->get_edid (&edid_info) == GRUB_ERR_NONE)
|
||||||
|
print_edid (&edid_info);
|
||||||
|
else
|
||||||
|
grub_errno = GRUB_ERR_NONE;
|
||||||
|
|
||||||
if (adapter->id != id)
|
if (adapter->id != id)
|
||||||
{
|
{
|
||||||
if (adapter->fini ())
|
if (adapter->fini ())
|
||||||
|
|
|
@ -389,26 +389,12 @@ grub_vbe_get_preferred_mode (unsigned int *width, unsigned int *height)
|
||||||
&& (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff)
|
&& (grub_vbe_bios_get_ddc_capabilities (&ddc_level) & 0xff)
|
||||||
== GRUB_VBE_STATUS_OK)
|
== GRUB_VBE_STATUS_OK)
|
||||||
{
|
{
|
||||||
status = grub_vbe_bios_read_edid (&edid_info);
|
if (grub_video_get_edid (&edid_info) == GRUB_ERR_NONE
|
||||||
/* Bit 1 in the Feature Support field indicates that the first
|
&& grub_video_edid_preferred_mode (&edid_info, width, height)
|
||||||
Detailed Timing Description is the preferred timing mode. */
|
== GRUB_ERR_NONE)
|
||||||
if (status == GRUB_VBE_STATUS_OK
|
return GRUB_ERR_NONE;
|
||||||
&& grub_video_edid_checksum (&edid_info) == GRUB_ERR_NONE
|
|
||||||
&& edid_info.version == 1 /* we don't understand later versions */
|
grub_errno = GRUB_ERR_NONE;
|
||||||
&& (edid_info.feature_support
|
|
||||||
& GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE)
|
|
||||||
&& edid_info.detailed_timings[0].pixel_clock)
|
|
||||||
{
|
|
||||||
*width = edid_info.detailed_timings[0].horizontal_active_lo
|
|
||||||
| (((unsigned int)
|
|
||||||
(edid_info.detailed_timings[0].horizontal_hi & 0xf0))
|
|
||||||
<< 4);
|
|
||||||
*height = edid_info.detailed_timings[0].vertical_active_lo
|
|
||||||
| (((unsigned int)
|
|
||||||
(edid_info.detailed_timings[0].vertical_hi & 0xf0))
|
|
||||||
<< 4);
|
|
||||||
return GRUB_ERR_NONE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
status = grub_vbe_bios_get_flat_panel_info (&flat_panel_info);
|
status = grub_vbe_bios_get_flat_panel_info (&flat_panel_info);
|
||||||
|
@ -978,6 +964,15 @@ grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info,
|
||||||
return grub_video_fb_get_info_and_fini (mode_info, framebuf);
|
return grub_video_fb_get_info_and_fini (mode_info, framebuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static grub_err_t
|
||||||
|
grub_video_vbe_get_edid (struct grub_video_edid_info *edid_info)
|
||||||
|
{
|
||||||
|
if (grub_vbe_bios_read_edid (edid_info) != GRUB_VBE_STATUS_OK)
|
||||||
|
return grub_error (GRUB_ERR_BAD_DEVICE, "EDID information not available");
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
grub_video_vbe_print_adapter_specific_info (void)
|
grub_video_vbe_print_adapter_specific_info (void)
|
||||||
{
|
{
|
||||||
|
@ -1022,6 +1017,7 @@ static struct grub_video_adapter grub_video_vbe_adapter =
|
||||||
.set_active_render_target = grub_video_fb_set_active_render_target,
|
.set_active_render_target = grub_video_fb_set_active_render_target,
|
||||||
.get_active_render_target = grub_video_fb_get_active_render_target,
|
.get_active_render_target = grub_video_fb_get_active_render_target,
|
||||||
.iterate = grub_video_vbe_iterate,
|
.iterate = grub_video_vbe_iterate,
|
||||||
|
.get_edid = grub_video_vbe_get_edid,
|
||||||
.print_adapter_specific_info = grub_video_vbe_print_adapter_specific_info,
|
.print_adapter_specific_info = grub_video_vbe_print_adapter_specific_info,
|
||||||
|
|
||||||
.next = 0
|
.next = 0
|
||||||
|
|
|
@ -393,6 +393,49 @@ grub_video_edid_checksum (struct grub_video_edid_info *edid_info)
|
||||||
return grub_errno;
|
return grub_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_video_get_edid (struct grub_video_edid_info *edid_info)
|
||||||
|
{
|
||||||
|
if (! grub_video_adapter_active)
|
||||||
|
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
|
||||||
|
|
||||||
|
if (! grub_video_adapter_active->get_edid)
|
||||||
|
return grub_error (GRUB_ERR_BAD_DEVICE,
|
||||||
|
"EDID information unavailable for this video mode");
|
||||||
|
|
||||||
|
if (grub_video_adapter_active->get_edid (edid_info) != GRUB_ERR_NONE)
|
||||||
|
return grub_errno;
|
||||||
|
if (grub_video_edid_checksum (edid_info) != GRUB_ERR_NONE)
|
||||||
|
return grub_errno;
|
||||||
|
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
grub_err_t
|
||||||
|
grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info,
|
||||||
|
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 (edid_info->version == 1 /* we don't understand later versions */
|
||||||
|
&& (edid_info->feature_support
|
||||||
|
& GRUB_VIDEO_EDID_FEATURE_PREFERRED_TIMING_MODE)
|
||||||
|
&& edid_info->detailed_timings[0].pixel_clock)
|
||||||
|
{
|
||||||
|
*width = edid_info->detailed_timings[0].horizontal_active_lo
|
||||||
|
| (((unsigned int)
|
||||||
|
(edid_info->detailed_timings[0].horizontal_hi & 0xf0))
|
||||||
|
<< 4);
|
||||||
|
*height = edid_info->detailed_timings[0].vertical_active_lo
|
||||||
|
| (((unsigned int)
|
||||||
|
(edid_info->detailed_timings[0].vertical_hi & 0xf0))
|
||||||
|
<< 4);
|
||||||
|
return GRUB_ERR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return grub_error (GRUB_ERR_BAD_DEVICE, "no preferred mode available");
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse <width>x<height>[x<depth>]*/
|
/* Parse <width>x<height>[x<depth>]*/
|
||||||
static grub_err_t
|
static grub_err_t
|
||||||
parse_modespec (const char *current_mode, int *width, int *height, int *depth)
|
parse_modespec (const char *current_mode, int *width, int *height, int *depth)
|
||||||
|
|
|
@ -371,6 +371,8 @@ struct grub_video_adapter
|
||||||
|
|
||||||
int (*iterate) (int (*hook) (const struct grub_video_mode_info *info));
|
int (*iterate) (int (*hook) (const struct grub_video_mode_info *info));
|
||||||
|
|
||||||
|
grub_err_t (*get_edid) (struct grub_video_edid_info *edid_info);
|
||||||
|
|
||||||
void (*print_adapter_specific_info) (void);
|
void (*print_adapter_specific_info) (void);
|
||||||
};
|
};
|
||||||
typedef struct grub_video_adapter *grub_video_adapter_t;
|
typedef struct grub_video_adapter *grub_video_adapter_t;
|
||||||
|
@ -484,6 +486,10 @@ 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_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 grub_video_edid_checksum (struct grub_video_edid_info *edid_info);
|
||||||
|
grub_err_t grub_video_get_edid (struct grub_video_edid_info *edid_info);
|
||||||
|
grub_err_t grub_video_edid_preferred_mode (struct grub_video_edid_info *edid_info,
|
||||||
|
unsigned int *width,
|
||||||
|
unsigned int *height);
|
||||||
|
|
||||||
grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring,
|
grub_err_t EXPORT_FUNC (grub_video_set_mode) (const char *modestring,
|
||||||
unsigned int modemask,
|
unsigned int modemask,
|
||||||
|
|
Loading…
Reference in a new issue