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; }