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 <[email protected]>
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
PulkoMandy
2023-06-11 11:23:01 +00:00
committed by Adrien Destugues
parent 29f8da76d7
commit 37e1b12911
8 changed files with 84 additions and 7 deletions
@@ -0,0 +1,31 @@
/*
* Copyright 2023 Adrien Destugues <[email protected]>
* Distributed under terms of the MIT license.
*/
#pragma once
#include <efi/types.h>
#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;
};
@@ -29,6 +29,7 @@ uint32 framebuffer_accelerant_mode_count(void);
status_t framebuffer_get_mode_list(display_mode *dm); status_t framebuffer_get_mode_list(display_mode *dm);
status_t framebuffer_set_display_mode(display_mode *modeToSet); status_t framebuffer_set_display_mode(display_mode *modeToSet);
status_t framebuffer_get_display_mode(display_mode *currentMode); 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_frame_buffer_config(frame_buffer_config *config);
status_t framebuffer_get_pixel_clock_limits(display_mode *dm, uint32 *low, status_t framebuffer_get_pixel_clock_limits(display_mode *dm, uint32 *low,
uint32 *high); uint32 *high);
@@ -40,6 +40,8 @@ get_accelerant_hook(uint32 feature, void* data)
return (void*)framebuffer_set_display_mode; return (void*)framebuffer_set_display_mode;
case B_GET_DISPLAY_MODE: case B_GET_DISPLAY_MODE:
return (void*)framebuffer_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: case B_GET_FRAME_BUFFER_CONFIG:
return (void*)framebuffer_get_frame_buffer_config; return (void*)framebuffer_get_frame_buffer_config;
case B_GET_PIXEL_CLOCK_LIMITS: case B_GET_PIXEL_CLOCK_LIMITS:
@@ -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 status_t
framebuffer_get_frame_buffer_config(frame_buffer_config* config) framebuffer_get_frame_buffer_config(frame_buffer_config* config)
{ {
@@ -197,6 +197,13 @@ framebuffer_init(framebuffer_info& info)
sharedInfo.current_mode.space = get_color_space_for_depth( sharedInfo.current_mode.space = get_color_space_for_depth(
bufferInfo->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"); dprintf(DEVICE_NAME ": framebuffer_init() completed successfully!\n");
return B_OK; return B_OK;
} }
+4
View File
@@ -1,5 +1,6 @@
SubDir HAIKU_TOP src system boot platform efi ; SubDir HAIKU_TOP src system boot platform efi ;
UsePrivateHeaders [ FDirName graphics common ] ;
UsePrivateHeaders [ FDirName kernel boot ] ; UsePrivateHeaders [ FDirName kernel boot ] ;
UsePrivateHeaders [ FDirName kernel platform ] ; UsePrivateHeaders [ FDirName kernel platform ] ;
UsePrivateHeaders [ FDirName kernel boot platform efi ] ; UsePrivateHeaders [ FDirName kernel boot platform efi ] ;
@@ -38,6 +39,8 @@ local platform_src =
quirks.cpp quirks.cpp
smp.cpp smp.cpp
serial.cpp serial.cpp
decode_edid.c
; ;
local support_libs ; local support_libs ;
@@ -50,6 +53,7 @@ if $(TARGET_ARCH) != x86_64 && $(TARGET_ARCH) != x86 {
local platform ; local platform ;
for platform in [ MultiBootSubDirSetup efi ] { for platform in [ MultiBootSubDirSetup efi ] {
on $(platform) { on $(platform) {
SEARCH_SOURCE += [ FDirName $(HAIKU_TOP) src add-ons accelerants common ] ;
BootMergeObject boot_platform_efi_common.o : BootMergeObject boot_platform_efi_common.o :
$(platform_src) $(platform_src)
+21 -5
View File
@@ -15,9 +15,11 @@
#include <boot/stage2.h> #include <boot/stage2.h>
#include <boot/stdio.h> #include <boot/stdio.h>
#include <drivers/driver_settings.h> #include <drivers/driver_settings.h>
#include <edid.h>
#include <util/list.h> #include <util/list.h>
#include "efi_platform.h" #include "efi_platform.h"
#include <efi/protocol/edid.h>
#include <efi/protocol/graphics-output.h> #include <efi/protocol/graphics-output.h>
@@ -37,7 +39,9 @@ struct video_mode {
static efi_guid sGraphicsOutputGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; 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_graphics_output_protocol *sGraphicsOutput;
static efi_edid_protocol *sEdidActiveProtocol;
static size_t sGraphicsMode; static size_t sGraphicsMode;
static struct list sModeList; static struct list sModeList;
static uint32 sModeCount; static uint32 sModeCount;
@@ -151,15 +155,16 @@ platform_init_video(void)
{ {
list_init(&sModeList); list_init(&sModeList);
// we don't support VESA modes or EDID // we don't support VESA modes
gKernelArgs.vesa_modes = NULL; gKernelArgs.vesa_modes = NULL;
gKernelArgs.vesa_modes_size = 0; gKernelArgs.vesa_modes_size = 0;
gKernelArgs.edid_info = NULL; gKernelArgs.edid_info = NULL;
// make a guess at the best video mode to use, and save the mode ID // make a guess at the best video mode to use, and save the mode ID for switching to graphics
// for switching to graphics mode // mode
efi_status status = kBootServices->LocateProtocol(&sGraphicsOutputGuid, efi_status status = kBootServices->LocateProtocol(&sGraphicsOutputGuid, NULL,
NULL, (void **)&sGraphicsOutput); (void **)&sGraphicsOutput);
if (sGraphicsOutput == NULL || status != EFI_SUCCESS) { if (sGraphicsOutput == NULL || status != EFI_SUCCESS) {
dprintf("GOP protocol not found\n"); dprintf("GOP protocol not found\n");
gKernelArgs.frame_buffer.enabled = false; gKernelArgs.frame_buffer.enabled = false;
@@ -228,6 +233,17 @@ platform_init_video(void)
gKernelArgs.frame_buffer.enabled = true; gKernelArgs.frame_buffer.enabled = true;
sModeChosen = false; sModeChosen = false;
sSettingsLoaded = 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; return B_OK;
} }