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_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);
@@ -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:
@@ -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)
{
@@ -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;
}
+4
View File
@@ -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)
+21 -5
View File
@@ -15,9 +15,11 @@
#include <boot/stage2.h>
#include <boot/stdio.h>
#include <drivers/driver_settings.h>
#include <edid.h>
#include <util/list.h>
#include "efi_platform.h"
#include <efi/protocol/edid.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 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;
}