From 37e1b129113100fb3314fe3980776ee5dd69a804 Mon Sep 17 00:00:00 2001 From: PulkoMandy Date: Sat, 10 Jun 2023 12:17:43 +0200 Subject: [PATCH] framebuffer: report display EDID data This allows to see the display in Screen preferences, and know its DPI and physical size (as much as EDID data can be trusted). This information could be used to compute the default font size, for example, so it's important that all drivers provide it whenever possible. Change-Id: Ic3d04e53cf5fcb24e22d35661d2b364a257947da Reviewed-on: https://review.haiku-os.org/c/haiku/+/6576 Tested-by: Commit checker robot Reviewed-by: Adrien Destugues --- headers/private/graphics/common/edid.h | 4 +-- .../kernel/platform/efi/protocol/edid.h | 31 +++++++++++++++++++ .../framebuffer/accelerant_protos.h | 1 + src/add-ons/accelerants/framebuffer/hooks.cpp | 2 ++ src/add-ons/accelerants/framebuffer/mode.cpp | 16 ++++++++++ .../graphics/framebuffer/framebuffer.cpp | 7 +++++ src/system/boot/platform/efi/Jamfile | 4 +++ src/system/boot/platform/efi/video.cpp | 26 +++++++++++++--- 8 files changed, 84 insertions(+), 7 deletions(-) create mode 100644 headers/private/kernel/platform/efi/protocol/edid.h diff --git a/headers/private/graphics/common/edid.h b/headers/private/graphics/common/edid.h index 5fdd6824c9..32a04b3ddb 100644 --- a/headers/private/graphics/common/edid.h +++ b/headers/private/graphics/common/edid.h @@ -150,10 +150,10 @@ typedef struct displayid_info { } displayid_info; // EDID data block -typedef struct edid1_info { +typedef struct edid1_info { edid1_vendor vendor; edid1_version version; - edid1_display display; + edid1_display display; edid1_established_timing established_timing; edid1_std_timing std_timing[EDID1_NUM_STD_TIMING]; diff --git a/headers/private/kernel/platform/efi/protocol/edid.h b/headers/private/kernel/platform/efi/protocol/edid.h new file mode 100644 index 0000000000..bf81734cb3 --- /dev/null +++ b/headers/private/kernel/platform/efi/protocol/edid.h @@ -0,0 +1,31 @@ +/* + * Copyright 2023 Adrien Destugues + * Distributed under terms of the MIT license. + */ + +#pragma once + + +#include + + +#define EFI_EDID_DISCOVERED_PROTOCOL_GUID \ + {0x1c0c34f6, 0xd380, 0x41fa, {0xa0, 0x49, 0x8a, 0xd0, 0x6c, 0x1a, 0x66, 0xaa}} + +#define EFI_EDID_ACTIVE_PROTOCOL_GUID \ + {0xbd8c1056, 0x9f36, 0x44ec, {0x92, 0xa8, 0xa6, 0x33, 0x7f, 0x81, 0x79, 0x86}} + +#define EFI_EDID_OVERRIDE_PROTOCOL_GUID \ + {0x48ecb431, 0xfb72, 0x45c0, {0xa9, 0x22, 0xf4, 0x58, 0xfe, 0x04, 0x0b, 0xd5}} + + +struct efi_edid_protocol { + uint32_t SizeOfEdid; + uint8_t* Edid; +}; + + +struct efi_edid_override_protocol { + efi_status (*GetEdid) (struct efi_edid_override_protocol* self, efi_handle* child, + uint32_t* attributes, size_t* edidSize, uint8_t** edid) EFIAPI; +}; diff --git a/src/add-ons/accelerants/framebuffer/accelerant_protos.h b/src/add-ons/accelerants/framebuffer/accelerant_protos.h index b29724022e..4cdbf331d6 100644 --- a/src/add-ons/accelerants/framebuffer/accelerant_protos.h +++ b/src/add-ons/accelerants/framebuffer/accelerant_protos.h @@ -29,6 +29,7 @@ uint32 framebuffer_accelerant_mode_count(void); status_t framebuffer_get_mode_list(display_mode *dm); status_t framebuffer_set_display_mode(display_mode *modeToSet); status_t framebuffer_get_display_mode(display_mode *currentMode); +status_t framebuffer_get_edid_info(void *info, size_t size, uint32 *_version); status_t framebuffer_get_frame_buffer_config(frame_buffer_config *config); status_t framebuffer_get_pixel_clock_limits(display_mode *dm, uint32 *low, uint32 *high); diff --git a/src/add-ons/accelerants/framebuffer/hooks.cpp b/src/add-ons/accelerants/framebuffer/hooks.cpp index c0363868ea..cfc69af37c 100644 --- a/src/add-ons/accelerants/framebuffer/hooks.cpp +++ b/src/add-ons/accelerants/framebuffer/hooks.cpp @@ -40,6 +40,8 @@ get_accelerant_hook(uint32 feature, void* data) return (void*)framebuffer_set_display_mode; case B_GET_DISPLAY_MODE: return (void*)framebuffer_get_display_mode; + case B_GET_EDID_INFO: + return (void*)framebuffer_get_edid_info; case B_GET_FRAME_BUFFER_CONFIG: return (void*)framebuffer_get_frame_buffer_config; case B_GET_PIXEL_CLOCK_LIMITS: diff --git a/src/add-ons/accelerants/framebuffer/mode.cpp b/src/add-ons/accelerants/framebuffer/mode.cpp index 476a2b7754..2e7a2b67f2 100644 --- a/src/add-ons/accelerants/framebuffer/mode.cpp +++ b/src/add-ons/accelerants/framebuffer/mode.cpp @@ -113,6 +113,22 @@ framebuffer_get_display_mode(display_mode* _currentMode) } +status_t +framebuffer_get_edid_info(void* info, size_t size, uint32* _version) +{ + TRACE(("framebuffer_get_edid_info()\n")); + + if (!gInfo->shared_info->has_edid) + return B_ERROR; + if (size < sizeof(struct edid1_info)) + return B_BUFFER_OVERFLOW; + + memcpy(info, &gInfo->shared_info->edid_info, sizeof(struct edid1_info)); + *_version = EDID_VERSION_1; + return B_OK; +} + + status_t framebuffer_get_frame_buffer_config(frame_buffer_config* config) { diff --git a/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer.cpp b/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer.cpp index 50d75af59d..8aee703fd5 100644 --- a/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer.cpp +++ b/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer.cpp @@ -197,6 +197,13 @@ framebuffer_init(framebuffer_info& info) sharedInfo.current_mode.space = get_color_space_for_depth( bufferInfo->depth); + edid1_info* edidInfo = (edid1_info*)get_boot_item(VESA_EDID_BOOT_INFO, + NULL); + if (edidInfo != NULL) { + sharedInfo.has_edid = true; + memcpy(&sharedInfo.edid_info, edidInfo, sizeof(edid1_info)); + } + dprintf(DEVICE_NAME ": framebuffer_init() completed successfully!\n"); return B_OK; } diff --git a/src/system/boot/platform/efi/Jamfile b/src/system/boot/platform/efi/Jamfile index 7600f937d1..b77e9b6e99 100644 --- a/src/system/boot/platform/efi/Jamfile +++ b/src/system/boot/platform/efi/Jamfile @@ -1,5 +1,6 @@ SubDir HAIKU_TOP src system boot platform efi ; +UsePrivateHeaders [ FDirName graphics common ] ; UsePrivateHeaders [ FDirName kernel boot ] ; UsePrivateHeaders [ FDirName kernel platform ] ; UsePrivateHeaders [ FDirName kernel boot platform efi ] ; @@ -38,6 +39,8 @@ local platform_src = quirks.cpp smp.cpp serial.cpp + + decode_edid.c ; local support_libs ; @@ -50,6 +53,7 @@ if $(TARGET_ARCH) != x86_64 && $(TARGET_ARCH) != x86 { local platform ; for platform in [ MultiBootSubDirSetup efi ] { on $(platform) { + SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ; BootMergeObject boot_platform_efi_common.o : $(platform_src) diff --git a/src/system/boot/platform/efi/video.cpp b/src/system/boot/platform/efi/video.cpp index 168dd825d8..9e0b012e11 100644 --- a/src/system/boot/platform/efi/video.cpp +++ b/src/system/boot/platform/efi/video.cpp @@ -15,9 +15,11 @@ #include #include #include +#include #include #include "efi_platform.h" +#include #include @@ -37,7 +39,9 @@ struct video_mode { static efi_guid sGraphicsOutputGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; +static efi_guid sEdidActiveGuid = EFI_EDID_ACTIVE_PROTOCOL_GUID; static efi_graphics_output_protocol *sGraphicsOutput; +static efi_edid_protocol *sEdidActiveProtocol; static size_t sGraphicsMode; static struct list sModeList; static uint32 sModeCount; @@ -151,15 +155,16 @@ platform_init_video(void) { list_init(&sModeList); - // we don't support VESA modes or EDID + // we don't support VESA modes gKernelArgs.vesa_modes = NULL; gKernelArgs.vesa_modes_size = 0; + gKernelArgs.edid_info = NULL; - // make a guess at the best video mode to use, and save the mode ID - // for switching to graphics mode - efi_status status = kBootServices->LocateProtocol(&sGraphicsOutputGuid, - NULL, (void **)&sGraphicsOutput); + // make a guess at the best video mode to use, and save the mode ID for switching to graphics + // mode + efi_status status = kBootServices->LocateProtocol(&sGraphicsOutputGuid, NULL, + (void **)&sGraphicsOutput); if (sGraphicsOutput == NULL || status != EFI_SUCCESS) { dprintf("GOP protocol not found\n"); gKernelArgs.frame_buffer.enabled = false; @@ -228,6 +233,17 @@ platform_init_video(void) gKernelArgs.frame_buffer.enabled = true; sModeChosen = false; sSettingsLoaded = false; + + status = kBootServices->LocateProtocol(&sEdidActiveGuid, NULL, (void **)&sEdidActiveProtocol); + if ((sEdidActiveProtocol != NULL) && (status == EFI_SUCCESS) + && (sEdidActiveProtocol->SizeOfEdid) != 0) { + edid1_info* edid_info = (edid1_info*)kernel_args_malloc(sizeof(edid1_info)); + if (edid_info != NULL) { + edid_decode(edid_info, (edid1_raw*)sEdidActiveProtocol->Edid); + gKernelArgs.edid_info = edid_info; + } + } + return B_OK; }