[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 4/4] Add support for getting EDID via EFI
From: |
Matthew Garrett |
Subject: |
[PATCH 4/4] Add support for getting EDID via EFI |
Date: |
Wed, 8 Feb 2012 11:51:58 -0500 |
EFI gives a couple of defined methods for retrieving the EDID, so make use
of them. Some Apple devices don't provide these but do stash the EDID in an
nvram variable - grab it from there if it exists.
---
ChangeLog | 8 +++++
grub-core/video/efi_gop.c | 69 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 77 insertions(+), 0 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 26d779b..d46b3d1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
2012-02-08 Matthew Garrett <address@hidden>
+ * grub-core/video/efi_gop.c (grub_video_gop_get_edid): Add support for
+ retrieving the EDID via EFI. Implements the active and discovered
+ protocols, falling back to a variable for Apple devices.
+ (grub_video_gop_get_preferred_mode): Retrieve the EDID preferred mode
+ when possible.
+
+2012-02-08 Matthew Garrett <address@hidden>
+
* grub-core/video/efi_gop.c (check_protocol): Prefer GOP devices which
implement the pci_io protocol.
diff --git a/grub-core/video/efi_gop.c b/grub-core/video/efi_gop.c
index 47e3ee9..f4c563d 100644
--- a/grub-core/video/efi_gop.c
+++ b/grub-core/video/efi_gop.c
@@ -28,12 +28,16 @@
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/efi/graphics_output.h>
+#include <grub/efi/edid.h>
#include <grub/efi/pci.h>
GRUB_MOD_LICENSE ("GPLv3+");
static grub_efi_guid_t graphics_output_guid = GRUB_EFI_GOP_GUID;
+static grub_efi_guid_t active_edid_guid = GRUB_EFI_EDID_ACTIVE_GUID;
+static grub_efi_guid_t discovered_edid_guid = GRUB_EFI_EDID_DISCOVERED_GUID;
static grub_efi_guid_t pci_io_guid = GRUB_EFI_PCI_IO_GUID;
+static grub_efi_guid_t efi_var_guid = GRUB_EFI_GLOBAL_VARIABLE_GUID;
static struct grub_efi_gop *gop;
static grub_efi_handle_t gop_handle;
static unsigned old_mode;
@@ -257,6 +261,53 @@ grub_video_gop_iterate (int (*hook) (const struct
grub_video_mode_info *info))
}
static grub_err_t
+grub_video_gop_get_edid (struct grub_video_edid_info *edid_info)
+{
+ struct grub_efi_active_edid *edid;
+ grub_uint8_t edidname[] = "agp-internal-edid";
+ grub_uint8_t *data;
+
+ edid = grub_efi_open_protocol(gop_handle, &active_edid_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!edid || edid->size_of_edid == 0) {
+ edid = grub_efi_open_protocol(gop_handle, &discovered_edid_guid,
+ GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ }
+
+ if (!edid || edid->size_of_edid == 0) {
+ data = grub_efi_get_variable(edidname, &efi_var_guid);
+ if (data)
+ {
+ grub_memcpy(edid_info, data + 16, sizeof(*edid_info));
+ grub_free(data);
+ return GRUB_ERR_NONE;
+ }
+ return grub_error (GRUB_ERR_BAD_DEVICE, "EDID information not available");
+ }
+
+ grub_memcpy (&edid_info, edid->edid, sizeof(edid_info));
+
+ return GRUB_ERR_NONE;
+}
+
+static grub_err_t
+grub_gop_get_preferred_mode (unsigned int *width, unsigned int *height)
+{
+ struct grub_video_edid_info edid_info;
+
+ if (grub_video_gop_get_edid(&edid_info) == GRUB_ERR_NONE)
+ {
+ if (grub_video_edid_checksum (&edid_info) == GRUB_ERR_NONE
+ && grub_video_edid_preferred_mode (&edid_info, width, height)
+ == GRUB_ERR_NONE)
+ return GRUB_ERR_NONE;
+ else
+ grub_dprintf("video", "invalid edid");
+ }
+ return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "cannot get preferred mode");
+}
+
+static grub_err_t
grub_video_gop_setup (unsigned int width, unsigned int height,
unsigned int mode_type,
unsigned int mode_mask __attribute__ ((unused)))
@@ -268,10 +319,18 @@ grub_video_gop_setup (unsigned int width, unsigned int
height,
unsigned bpp;
int found = 0;
unsigned long long best_volume = 0;
+ int preferred_mode = 0;
depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
>> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
+ if (width == 0 && height == 0)
+ {
+ grub_gop_get_preferred_mode (&width, &height);
+ if (grub_errno == GRUB_ERR_NONE)
+ preferred_mode = 1;
+ }
+
/* Keep current mode if possible. */
if (gop->mode->info)
{
@@ -306,6 +365,15 @@ grub_video_gop_setup (unsigned int width, unsigned int
height,
grub_dprintf ("video", "GOP: mode %d: %dx%d\n", mode, info->width,
info->height);
+ if (preferred_mode)
+ {
+ if (info->width > width || info->height > height)
+ {
+ grub_dprintf ("video", "GOP: mode %d: too large\n", mode);
+ continue;
+ }
+ }
+
bpp = grub_video_gop_get_bpp (info);
if (!bpp)
{
@@ -437,6 +505,7 @@ static struct grub_video_adapter grub_video_gop_adapter =
.setup = grub_video_gop_setup,
.get_info = grub_video_fb_get_info,
.get_info_and_fini = grub_video_gop_get_info_and_fini,
+ .get_edid = grub_video_gop_get_edid,
.set_palette = grub_video_fb_set_palette,
.get_palette = grub_video_fb_get_palette,
.set_viewport = grub_video_fb_set_viewport,
--
1.7.7.6
[PATCH 4/4] Add support for getting EDID via EFI,
Matthew Garrett <=
[PATCH 3/4] Prefer GOP devices which implement the pci_io protocol, Matthew Garrett, 2012/02/08
[PATCH 1/4] Add PCI protocols, Matthew Garrett, 2012/02/08
Re: Some improvements to EFI GOP support, Keshav P R, 2012/02/08