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