intel_fb: request copy of Intel opregion

acpica and the Intel display driver tries to use the Intel Opregion
simultaneously on Genode, which is not supported nor wanted for IO_MEM region as
which it is handled.

Attempts to remove the access to the region was not successful, since some
SSDT table contains ACPI AML code which is executed regularly and read/write
the Opregion.

The patch adds support to read in a copy of the Intel Opregion done by the
acpi_drv component. The copy was sufficient to make the Intel display driver
working to find and lookup the Intel VBT (video bios table) information to
setup all connectors on a Fujitsu U7411 docking station.

Fixes #4531
This commit is contained in:
Alexander Boettcher
2022-05-20 14:11:48 +02:00
committed by Christian Helmuth
parent c2d9fbca9b
commit 88118b133a
6 changed files with 80 additions and 1 deletions

View File

@@ -68,6 +68,9 @@ append config {
<route>
<service name="Report"> <child name="report_rom"/> </service>
<service name="Platform"> <child name="platform_drv" label="intel_fb_drv"/> </service>
<service name="ROM" label="intel_fb_drv -> intel_opregion">
<child name="acpi_report_rom" label="intel_fb_drv -> intel_opregion"/>
</service>
<any-service> <parent/> <any-child/> </any-service>
</route>
<config prio_levels="2">

View File

@@ -215,6 +215,9 @@ void intel_gt_init_early(struct intel_gt * gt, struct drm_i915_private * i915)
init_llist_head(&gt->watchdog.list);
lx_emul_trace(__func__);
/* disable panel self refresh (required for FUJITSU S937/S938) */
i915->params.enable_psr = 0;
}
@@ -242,7 +245,7 @@ void * memremap(resource_size_t offset, size_t size, unsigned long flags)
{
lx_emul_trace(__func__);
return NULL;
return intel_io_mem_map(offset, size);
}

View File

@@ -39,6 +39,7 @@ unsigned int lx_emul_io_port_inl(unsigned short port);
void *emul_alloc_shmem_file_buffer(unsigned long);
void * intel_io_mem_map(unsigned long offset, unsigned long size);
#include "lx_i915.h"

View File

@@ -0,0 +1,70 @@
/*
* \brief Linux emulation environment specific to this driver - Intel opregion
* \author Alexander Boettcher
* \date 2022-01-21
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is distributed under the terms of the GNU General Public License
* version 2.
*/
#include <base/log.h>
#include <lx_kit/env.h>
#include <base/attached_io_mem_dataspace.h>
#include <base/attached_rom_dataspace.h>
#include <region_map/client.h>
#include <rm_session/connection.h>
#include <rom_session/connection.h>
extern "C" void * intel_io_mem_map(unsigned long const phys,
unsigned long const size)
{
using namespace Genode;
static Constructible<Attached_rom_dataspace> rom_opregion { };
static addr_t opregion_start = 0;
static addr_t opregion_size = 0;
if (!rom_opregion.constructed()) {
try {
rom_opregion.construct(Lx_kit::env().env, "intel_opregion");
Dataspace_client ds_client(rom_opregion->cap());
auto mem_local = rom_opregion->local_addr<char>();
opregion_start = *(addr_t*)(mem_local + ds_client.size() - sizeof(addr_t) * 2);
opregion_size = *(addr_t*)(mem_local + ds_client.size() - sizeof(addr_t));
if (opregion_size > ds_client.size())
opregion_size = ds_client.size();
} catch (...) {
error("Intel opregion ROM lookup failed");
if (rom_opregion.constructed())
rom_opregion.destruct();
return nullptr;
}
}
if ((opregion_start <= phys) &&
(phys + size <= opregion_start + opregion_size)) {
try {
auto ptr = ((addr_t)rom_opregion->local_addr<void>())
+ (phys - opregion_start) + (phys & 0xffful);
return (void *)ptr;
} catch (...) {
error("Intel opregion lookup failed");
return nullptr;
}
}
warning("Unknown memremap range ", Hex_range(phys, size));
return nullptr;
}

View File

@@ -11,6 +11,7 @@ INC_DIR += $(REL_PRG_DIR)/shadow
SRC_CC += main.cc
SRC_CC += misc.cc
SRC_CC += emul.cc
SRC_CC += opregion_io_mem.cc
SRC_C += dummies.c
SRC_C += lx_emul.c
SRC_C += $(notdir $(wildcard $(REL_PRG_DIR)/generated_dummies.c))