From 61e2c630b1bc95a8a9b9b8d16722a3498793d2ba Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Mon, 19 Aug 2024 12:55:33 +0200 Subject: [PATCH] intel/display: report more connector/display info - Physical width/height of connected display in mm - Current mode per connector Issue #5264 --- .../pc/src/driver/framebuffer/intel/pc/README | 15 ++++-- .../src/driver/framebuffer/intel/pc/lx_i915.h | 10 ++-- .../src/driver/framebuffer/intel/pc/lx_user.c | 35 ++++++++----- .../src/driver/framebuffer/intel/pc/main.cc | 51 +++++++++++++------ 4 files changed, 74 insertions(+), 37 deletions(-) diff --git a/repos/pc/src/driver/framebuffer/intel/pc/README b/repos/pc/src/driver/framebuffer/intel/pc/README index 9154856e12..e40a311dec 100644 --- a/repos/pc/src/driver/framebuffer/intel/pc/README +++ b/repos/pc/src/driver/framebuffer/intel/pc/README @@ -70,13 +70,13 @@ in the configuration as follows: The exported report has the following format: ! -! -! +! +! ! ... ! -! -! -! +! +! +! ! ! ! ... @@ -84,5 +84,10 @@ The exported report has the following format: ! ! +The physical dimension of the display is reported as width_mm and height_mm +in millimeter per connector and if available, also per mode. The values can +be used as input to DPI calculations. The currently used mode of the connector +is tagged in the report explicitly. + The brightness attribute is reported only if the hardware supports it. diff --git a/repos/pc/src/driver/framebuffer/intel/pc/lx_i915.h b/repos/pc/src/driver/framebuffer/intel/pc/lx_i915.h index 46cf4a925a..2ae68b1228 100644 --- a/repos/pc/src/driver/framebuffer/intel/pc/lx_i915.h +++ b/repos/pc/src/driver/framebuffer/intel/pc/lx_i915.h @@ -21,19 +21,23 @@ struct genode_mode { unsigned force_height; unsigned max_width; unsigned max_height; + unsigned width_mm; + unsigned height_mm; unsigned hz; unsigned brightness; unsigned enabled; unsigned preferred; + unsigned inuse; unsigned id; char name[32]; }; -void lx_emul_i915_report(void * lx_data, void * genode_xml); -void lx_emul_i915_hotplug_connector(void * lx_data); +void lx_emul_i915_report(void * genode_xml); +void lx_emul_i915_hotplug_connector(void); void lx_emul_i915_report_connector(void * lx_data, void * genode_xml, char const *name, char connected, - unsigned brightness); + unsigned brightness, + unsigned width_mm, unsigned height_mm); void lx_emul_i915_iterate_modes(void *lx_data, void * genode_data); void lx_emul_i915_report_modes(void * genode_xml, struct genode_mode *); void lx_emul_i915_connector_config(char * name, struct genode_mode *); diff --git a/repos/pc/src/driver/framebuffer/intel/pc/lx_user.c b/repos/pc/src/driver/framebuffer/intel/pc/lx_user.c index 169ee65dbe..3d6b3b81bd 100644 --- a/repos/pc/src/driver/framebuffer/intel/pc/lx_user.c +++ b/repos/pc/src/driver/framebuffer/intel/pc/lx_user.c @@ -481,13 +481,11 @@ void lx_user_init(void) } -void lx_emul_i915_report(void * lx_data, void * genode_data) +void lx_emul_i915_report(void * genode_data) { - struct drm_client_dev *client = lx_data; - struct drm_connector_list_iter conn_iter; - struct drm_device const *dev = client->dev; + struct drm_device const *dev = dev_client->dev; struct drm_connector *connector = NULL; drm_connector_list_iter_begin(dev, &conn_iter); @@ -495,7 +493,9 @@ void lx_emul_i915_report(void * lx_data, void * genode_data) lx_emul_i915_report_connector(connector, genode_data, connector->name, connector->status != connector_status_disconnected, - get_brightness(connector, INVALID_BRIGHTNESS)); + get_brightness(connector, INVALID_BRIGHTNESS), + connector->display_info.width_mm, + connector->display_info.height_mm); } drm_connector_list_iter_end(&conn_iter); } @@ -530,15 +530,24 @@ void lx_emul_i915_iterate_modes(void * lx_data, void * genode_data) } if (!skip) { - bool const max_mode = conf_max_mode.max_width && conf_max_mode.max_height; + bool const max_mode = conf_max_mode.max_width && + conf_max_mode.max_height; + bool const inuse = connector->state && connector->state->crtc && + connector->state->crtc->state && + drm_mode_equal(&connector->state->crtc->state->mode, mode); struct genode_mode conf_mode = { - .width = mode->hdisplay, - .height = mode->vdisplay, - .preferred = mode->type & (DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DEFAULT), - .hz = drm_mode_vrefresh(mode), - .id = mode_id, - .enabled = !max_mode || !conf_smaller_max_mode(&conf_max_mode, mode) + .width = mode->hdisplay, + .height = mode->vdisplay, + .width_mm = mode->width_mm, + .height_mm = mode->height_mm, + .preferred = mode->type & (DRM_MODE_TYPE_PREFERRED | + DRM_MODE_TYPE_DEFAULT), + .inuse = inuse, + .hz = drm_mode_vrefresh(mode), + .id = mode_id, + .enabled = !max_mode || + !conf_smaller_max_mode(&conf_max_mode, mode) }; static_assert(sizeof(conf_mode.name) == DRM_DISPLAY_MODE_LEN); @@ -608,7 +617,7 @@ static int fb_client_hotplug(struct drm_client_dev *client) } /* notify Genode side */ - lx_emul_i915_hotplug_connector(client); + lx_emul_i915_hotplug_connector(); if (fb) drm_framebuffer_put(fb); diff --git a/repos/pc/src/driver/framebuffer/intel/pc/main.cc b/repos/pc/src/driver/framebuffer/intel/pc/main.cc index 9f6bd8cf7e..d480048568 100644 --- a/repos/pc/src/driver/framebuffer/intel/pc/main.cc +++ b/repos/pc/src/driver/framebuffer/intel/pc/main.cc @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2022 Genode Labs GmbH + * Copyright (C) 2022-2024 Genode Labs GmbH * * This file is distributed under the terms of the GNU General Public License * version 2. @@ -60,9 +60,10 @@ struct Framebuffer::Driver Signal_handler system_handler { env.ep(), *this, &Driver::system_update }; - bool update_in_progress { false }; - bool new_config_rom { false }; - bool disable_all { false }; + bool update_in_progress { false }; + bool new_config_rom { false }; + bool disable_all { false }; + bool disable_report_once { false }; class Fb { @@ -110,7 +111,7 @@ struct Framebuffer::Driver void config_update(); void system_update(); - void generate_report(void *); + void generate_report(); void lookup_config(char const *, struct genode_mode &mode); void handle_timer() @@ -161,16 +162,14 @@ struct Framebuffer::Driver timer.trigger_periodic(20*1000); } - void report_updated() + bool apply_config_on_hotplug() const { bool apply_config = true; if (config.valid()) apply_config = config.xml().attribute_value("apply_on_hotplug", apply_config); - /* trigger re-read config on connector change */ - if (apply_config) - Genode::Signal_transmitter(config_handler).submit(); + return apply_config; } template @@ -281,11 +280,17 @@ static Framebuffer::Driver & driver(Genode::Env & env) } -void Framebuffer::Driver::generate_report(void *lx_data) +void Framebuffer::Driver::generate_report() { if (!config.valid()) return; + if (apply_config_on_hotplug() && !disable_report_once) { + disable_report_once = true; + Genode::Signal_transmitter(config_handler).submit(); + return; + } + /* check for report configuration option */ config.xml().with_optional_sub_node("report", [&](auto const &node) { @@ -304,11 +309,11 @@ void Framebuffer::Driver::generate_report(void *lx_data) xml.attribute("force_height", height); }); - lx_emul_i915_report(lx_data, &xml); + lx_emul_i915_report(&xml); }); - - driver(Lx_kit::env().env).report_updated(); }); + + disable_report_once = false; } @@ -395,16 +400,17 @@ extern "C" void lx_emul_framebuffer_ready(void * base, unsigned long, } -extern "C" void lx_emul_i915_hotplug_connector(void *data) +extern "C" void lx_emul_i915_hotplug_connector() { Genode::Env &env = Lx_kit::env().env; - driver(env).generate_report(data); + driver(env).generate_report(); } void lx_emul_i915_report_connector(void * lx_data, void * genode_xml, char const *name, char const connected, - unsigned brightness) + unsigned brightness, unsigned width_mm, + unsigned height_mm) { auto &xml = *reinterpret_cast(genode_xml); @@ -412,6 +418,10 @@ void lx_emul_i915_report_connector(void * lx_data, void * genode_xml, { xml.attribute("name", name); xml.attribute("connected", !!connected); + if (width_mm) + xml.attribute("width_mm" , width_mm); + if (height_mm) + xml.attribute("height_mm", height_mm); /* insane values means no brightness support - we use percentage */ if (brightness <= MAX_BRIGHTNESS) @@ -436,10 +446,16 @@ void lx_emul_i915_report_modes(void * genode_xml, struct genode_mode *mode) xml.attribute("hz", mode->hz); xml.attribute("mode_id", mode->id); xml.attribute("mode_name", mode->name); + if (mode->width_mm) + xml.attribute("width_mm", mode->width_mm); + if (mode->height_mm) + xml.attribute("height_mm", mode->height_mm); if (!mode->enabled) xml.attribute("unavailable", true); if (mode->preferred) xml.attribute("preferred", true); + if (mode->inuse) + xml.attribute("used", true); }); } @@ -468,6 +484,9 @@ int lx_emul_i915_config_done_and_block(void) Lx_kit::env().env.parent().exit(0); } + if (!new_config) + driver(Lx_kit::env().env).generate_report(); + /* true if linux task should block, otherwise continue due to new config */ return !new_config; }