intel/display: report more connector/display info

- Physical width/height of connected display in mm
- Current mode per connector

Issue #5264
This commit is contained in:
Alexander Boettcher 2024-08-19 12:55:33 +02:00 committed by Christian Helmuth
parent 0ca2fdb2de
commit 61e2c630b1
4 changed files with 74 additions and 37 deletions

View File

@ -70,13 +70,13 @@ in the configuration as follows:
The exported report has the following format:
! <connectors>
! <connector name="eDP-1" connected="true" brightness="50">
! <mode width="1920" height="1080" hz="60" mode_id="1" preferred="true"/>
! <connector name="eDP-1" connected="true" brightness="50" width_mm="290" height_mm="170">
! <mode width="1920" height="1080" hz="60" mode_id="1" preferred="true" used="true" width_mm="288" height_mm="165"/>
! ...
! </connector>
! <connector name="DP-1" connected="true">
! <mode width="1920" height="1200" hz="60" mode_id="1" preferred="true"/>
! <mode width="1920" height="1080" hz="60" mode_id="2"/>
! <connector name="DP-1" connected="true" width_mm="280" height_mm="160">
! <mode width="1920" height="1200" hz="60" mode_id="1" preferred="true" width_mm="280" height_mm="160"/>
! <mode width="1920" height="1080" hz="60" mode_id="2" used="true" width_mm="278" height_mm="158"/>
! <mode width="1280" height="1024" hz="60" mode_id="3"/>
! <mode width="1024" height="768" hz="60" mode_id="4"/>
! ...
@ -84,5 +84,10 @@ The exported report has the following format:
! <connector name="HDMI-A-1" connected="false"/>
! </connectors>
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.

View File

@ -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 *);

View File

@ -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);

View File

@ -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<Driver> 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 <typename T>
@ -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_generator *>(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;
}