From 80981dbefbfb5f980097368bedf4ee70132ef180 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Thu, 9 Jun 2022 12:48:37 +0200 Subject: [PATCH] intel_fb: re-evalute max resolution on unplug On connector unplug the overall resolution of all available active connectors can shrink and must be considered to potentially re-create the Capture connection with smaller resolution size. Additionally, update the documentation. Issue #4531 --- .../src/drivers/framebuffer/intel/pc/README | 19 ++++++-- .../drivers/framebuffer/intel/pc/lx_user.c | 48 ++++++++++++------- repos/pc/src/test/framebuffer/intel/main.cc | 2 +- 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/repos/pc/src/drivers/framebuffer/intel/pc/README b/repos/pc/src/drivers/framebuffer/intel/pc/README index 0a6212b01f..4d78cf1f63 100644 --- a/repos/pc/src/drivers/framebuffer/intel/pc/README +++ b/repos/pc/src/drivers/framebuffer/intel/pc/README @@ -20,9 +20,14 @@ Each of the connectors can be configured explicitly in terms of resolution and whether it should be enabled or not. This looks like the following: ! -! +! +! ! +The resolution can be configured exactly by the reported mode_id or by +the width/height/hz attributes. In the latter case the driver will take the +first matching mode out of multiple matching modes potentially. + When the configuration changes during runtime, the driver will adapt to it. In this case, it will also change the current virtual resolution to the maximum of the configured resolutions in width and height, and it will inform its client @@ -47,12 +52,18 @@ in the configuration as follows: The exported report has the following format: ! -! -! +! +! +! ... +! +! +! +! +! +! ! ... ! ! -! ! The brightness attribute is reported only if the hardware supports it. diff --git a/repos/pc/src/drivers/framebuffer/intel/pc/lx_user.c b/repos/pc/src/drivers/framebuffer/intel/pc/lx_user.c index 9799e7e1bb..ab8864a6a5 100644 --- a/repos/pc/src/drivers/framebuffer/intel/pc/lx_user.c +++ b/repos/pc/src/drivers/framebuffer/intel/pc/lx_user.c @@ -50,7 +50,25 @@ static void preferred_mode(struct drm_display_mode *prefer) /* check for connector configuration on Genode side */ lx_emul_i915_connector_config(connector->name, &conf_mode); - if (!conf_mode.enabled || !conf_mode.width || !conf_mode.height) + if (!conf_mode.enabled) + continue; + + if (conf_mode.id) { + unsigned mode_id = 0; + list_for_each_entry(mode, &connector->modes, head) { + mode_id ++; + + if (!mode || conf_mode.id != mode_id) + continue; + + conf_mode.width = mode->hdisplay; + conf_mode.height = mode->vdisplay; + + break; + } + } + + if (!conf_mode.width || !conf_mode.height) continue; if (conf_mode.width * conf_mode.height > prefer->hdisplay * prefer->vdisplay) { @@ -154,6 +172,10 @@ static bool reconfigure(void * data) /* data is adjusted if virtual resolution is not same size as physical fb */ report_fb_info = *i915_fb()->fbdev; + if (mode_preferred.hdisplay && mode_preferred.vdisplay) { + report_fb_info.var.xres_virtual = mode_preferred.hdisplay; + report_fb_info.var.yres_virtual = mode_preferred.vdisplay; + } drm_client_for_each_modeset(mode_set, &(i915_fb()->client)) { struct drm_display_mode *mode_match = NULL; @@ -182,7 +204,10 @@ static bool reconfigure(void * data) continue; /* use mode id if configured and matches exactly */ - if (conf_mode.id && (conf_mode.id == mode_id)) { + if (conf_mode.id) { + if (conf_mode.id != mode_id) + continue; + mode_match = mode; break; } @@ -225,16 +250,9 @@ static bool reconfigure(void * data) if (!mode_match) { /* use first mode */ mode_match = mode; - /* set up preferred resolution as virtual, if nothing is enforced */ - if (!conf_mode.preferred && - mode_preferred.hdisplay && - mode_preferred.vdisplay) { - conf_mode.preferred = 1; - conf_mode.width = mode_preferred.hdisplay; - conf_mode.height = mode_preferred.vdisplay; - } - no_match = mode->hdisplay != conf_mode.width || - mode->vdisplay != conf_mode.height; + + if (conf_mode.enabled) + no_match = true; } if (mode_match != mode) @@ -267,12 +285,6 @@ static bool reconfigure(void * data) retry = true; else { report_fb = true; - - /* report forced resolution */ - if (conf_mode.preferred) { - report_fb_info.var.xres_virtual = conf_mode.width; - report_fb_info.var.yres_virtual = conf_mode.height; - } } } diff --git a/repos/pc/src/test/framebuffer/intel/main.cc b/repos/pc/src/test/framebuffer/intel/main.cc index e50fe5cb14..d3ee857e9a 100644 --- a/repos/pc/src/test/framebuffer/intel/main.cc +++ b/repos/pc/src/test/framebuffer/intel/main.cc @@ -79,7 +79,7 @@ void Framebuffer_controller::_update_connector_config(Xml_generator & xml, w = mode.attribute_value("width", 0); h = mode.attribute_value("height", 0); z = mode.attribute_value("hz", 0); - if (w >= width) { + if (w * h >= width * height) { width = w; height = h; if (z > hz)