From 9b312054f5d7b33ff50f7e86a4babde9fc79a608 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Mon, 9 Oct 2023 14:53:11 +0200 Subject: [PATCH] intel/display: support force_* and configured mode Up to now, when using force_*, all other configured modes of a connector got overwritten and the force_* got enforced. With the commit, the connector mode is considered (if below max_*) and the resulting framebuffer may be larger then the dimension of force_*. --- repos/pc/run/intel_fb.run | 2 +- .../drivers/framebuffer/intel/pc/lx_i915.h | 2 + .../drivers/framebuffer/intel/pc/lx_user.c | 57 +++++++++++++------ .../src/drivers/framebuffer/intel/pc/main.cc | 7 +-- 4 files changed, 46 insertions(+), 22 deletions(-) diff --git a/repos/pc/run/intel_fb.run b/repos/pc/run/intel_fb.run index e78129fdd9..46e9f6ebe5 100644 --- a/repos/pc/run/intel_fb.run +++ b/repos/pc/run/intel_fb.run @@ -304,7 +304,7 @@ append_if $use_top boot_modules { top } build_boot_image $boot_modules if { [get_cmd_switch --autopilot] } { - run_genode_until {\[init -\> init_dynamic -\> intel_fb_drv\] HDMI-A-2: enable.*} 30 + run_genode_until {\[init -\> init_dynamic -\> intel_fb_drv\] HDMI-A-2: enable.*} 30 } else { run_genode_until forever } diff --git a/repos/pc/src/drivers/framebuffer/intel/pc/lx_i915.h b/repos/pc/src/drivers/framebuffer/intel/pc/lx_i915.h index 3b67e0338e..46cf4a925a 100644 --- a/repos/pc/src/drivers/framebuffer/intel/pc/lx_i915.h +++ b/repos/pc/src/drivers/framebuffer/intel/pc/lx_i915.h @@ -17,6 +17,8 @@ struct genode_mode { unsigned width; unsigned height; + unsigned force_width; + unsigned force_height; unsigned max_width; unsigned max_height; unsigned hz; 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 4f35bb43ce..e9b6cf1fc5 100644 --- a/repos/pc/src/drivers/framebuffer/intel/pc/lx_user.c +++ b/repos/pc/src/drivers/framebuffer/intel/pc/lx_user.c @@ -59,14 +59,22 @@ static inline bool mode_larger(struct drm_display_mode const * const x, } -static inline bool conf_smaller_mode(struct genode_mode const * const g, - struct drm_display_mode const * const p) +static inline bool conf_smaller_max_mode(struct genode_mode const * const g, + struct drm_display_mode const * const p) { return (uint64_t)g->max_width * (uint64_t)g->max_height < (uint64_t)p->hdisplay * (uint64_t)p->vdisplay; } +static inline bool conf_larger_mode(struct genode_mode const * const g, + struct drm_display_mode const * const p) +{ + return (uint64_t)g->width * (uint64_t)g->height > + (uint64_t)p->hdisplay * (uint64_t)p->vdisplay; +} + + static inline bool fb_smaller_mode(struct fb_info const * const info, struct drm_display_mode const * const mode) { @@ -135,18 +143,34 @@ static void preferred_mode(struct drm_device const * const dev, if (mode_id && mode_larger(&smallest, min_mode)) *min_mode = smallest; + if (conf_mode.force_width && conf_mode.force_height) { + /* + * Even so the force_* mode is selected, a configured mode for + * a connector is considered, effectively the framebuffer content + * will be shown smaller in the upper corner of the monitor + */ + if (conf_larger_mode(&conf_mode, min_mode)) { + min_mode->hdisplay = conf_mode.width; + min_mode->vdisplay = conf_mode.height; + } + + /* enforce the force mode */ + conf_mode.width = conf_mode.force_width; + conf_mode.height = conf_mode.force_height; + } + /* maximal resolution enforcement */ if (conf_mode.max_width && conf_mode.max_height) { max_enforcement.hdisplay = conf_mode.max_width; max_enforcement.vdisplay = conf_mode.max_height; - if (conf_smaller_mode(&conf_mode, prefer)) + if (conf_smaller_max_mode(&conf_mode, prefer)) continue; } if (!conf_mode.width || !conf_mode.height) continue; - if (!conf_smaller_mode(&conf_mode, prefer)) { + if (conf_larger_mode(&conf_mode, prefer)) { prefer->hdisplay = conf_mode.width; prefer->vdisplay = conf_mode.height; } @@ -232,7 +256,7 @@ static bool reconfigure(struct drm_client_dev * const dev) struct drm_display_mode mode_preferred = {}; struct drm_display_mode mode_minimum = {}; - struct drm_display_mode mode_real = {}; + struct drm_display_mode framebuffer = {}; struct drm_mode_modeinfo user_mode = {}; struct drm_display_mode *mode = NULL; struct drm_mode_set *mode_set = NULL; @@ -256,22 +280,21 @@ static bool reconfigure(struct drm_client_dev * const dev) mode_preferred = mode_minimum; } - if (mode_larger(&mode_preferred, &mode_minimum)) - mode_real = mode_preferred; + framebuffer = mode_preferred; else - mode_real = mode_minimum; + framebuffer = mode_minimum; { int const err = check_resize_fb(dev, &gem_dumb, &dumb_fb, - mode_real.hdisplay, - mode_real.vdisplay); + framebuffer.hdisplay, + framebuffer.vdisplay); if (err) { printk("setting up framebuffer of %ux%u failed - error=%d\n", - mode_real.hdisplay, mode_real.vdisplay, err); + framebuffer.hdisplay, framebuffer.vdisplay, err); return true; } @@ -282,8 +305,8 @@ static bool reconfigure(struct drm_client_dev * const dev) return retry; /* prepare fb info for register_framebuffer() evaluated by Genode side */ - report_fb_info.var.xres = mode_real.hdisplay; - report_fb_info.var.yres = mode_real.vdisplay; + report_fb_info.var.xres = framebuffer.hdisplay; + report_fb_info.var.yres = framebuffer.vdisplay; report_fb_info.var.xres_virtual = mode_preferred.hdisplay; report_fb_info.var.yres_virtual = mode_preferred.vdisplay; @@ -397,12 +420,14 @@ static bool reconfigure(struct drm_client_dev * const dev) } /* diagnostics */ - printk("%s: %s name='%s' id=%u %ux%u@%u%s", + printk("%10s: %s name='%9s' id=%u%s mode=%4ux%4u@%u%s fb=%4ux%4u%s", connector->name ? connector->name : "unnamed", conf_mode.enabled ? " enable" : "disable", mode->name ? mode->name : "noname", - mode_id, mode->hdisplay, + mode_id, mode_id < 10 ? " " : "", mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), + drm_mode_vrefresh(mode) < 100 ? " ": "", + framebuffer.hdisplay, framebuffer.vdisplay, (err || no_match) ? "" : "\n"); if (no_match) @@ -512,7 +537,7 @@ void lx_emul_i915_iterate_modes(void * lx_data, void * genode_data) .preferred = mode->type & (DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DEFAULT), .hz = drm_mode_vrefresh(mode), .id = mode_id, - .enabled = !max_mode || !conf_smaller_mode(&conf_max_mode, mode) + .enabled = !max_mode || !conf_smaller_max_mode(&conf_max_mode, mode) }; static_assert(sizeof(conf_mode.name) == DRM_DISPLAY_MODE_LEN); diff --git a/repos/pc/src/drivers/framebuffer/intel/pc/main.cc b/repos/pc/src/drivers/framebuffer/intel/pc/main.cc index 6121832d92..0d3e6170d9 100644 --- a/repos/pc/src/drivers/framebuffer/intel/pc/main.cc +++ b/repos/pc/src/drivers/framebuffer/intel/pc/main.cc @@ -256,12 +256,9 @@ void Framebuffer::Driver::lookup_config(char const * const name, mode.id = node.attribute_value("mode_id", 0U); }); - mode.preferred = false; with_force([&](unsigned const width, unsigned const height) { - mode.preferred = true; - mode.width = width; - mode.height = height; - mode.id = 0; + mode.force_width = width; + mode.force_height = height; }); with_max_enforcement([&](unsigned const width, unsigned const height) {