intel/display: handle configuration with no merge

node at all. Fixes a regression. W/o the commit, discrete only
configurations may not work properly, e.g. not showing content on
any display.

Issue #5415
This commit is contained in:
Alexander Boettcher 2025-01-14 13:22:06 +01:00 committed by Norman Feske
parent f9eea846fa
commit 60b3619a1b

View File

@ -455,28 +455,24 @@ static struct drm_display_mode * best_mode(struct genode_mode const * const
} }
static void reconfigure(struct drm_client_dev * const dev) struct meta_data_mirror {
{
static struct drm_mode_create_dumb * gem_mirror = NULL;
static struct drm_mode_fb_cmd2 * mirror_fb_cmd = NULL;
struct drm_connector_list_iter conn_iter;
struct drm_connector * connector = NULL;
struct drm_display_mode mirror_force = {};
struct drm_display_mode mirror_compound = {};
struct drm_display_mode mirror_minimum = {};
struct drm_display_mode mirror_fb = {};
struct {
struct fb_info info; struct fb_info info;
struct drm_display_mode mode;
unsigned width_mm; unsigned width_mm;
unsigned height_mm; unsigned height_mm;
bool report; bool report;
} mirror = { { }, 0, 0, false }; };
gem_mirror = &states[CONNECTOR_ID_MIRROR].fb_dumb;
mirror_fb_cmd = &states[CONNECTOR_ID_MIRROR].fb_cmd; static void handle_mirror(struct drm_client_dev * const dev,
struct meta_data_mirror * const mirror)
{
struct drm_display_mode mirror_force = {};
struct drm_display_mode mirror_compound = {};
struct drm_display_mode mirror_minimum = {};
struct drm_mode_create_dumb * gem_mirror = &states[CONNECTOR_ID_MIRROR].fb_dumb;
struct drm_mode_fb_cmd2 * mirror_fb_cmd = &states[CONNECTOR_ID_MIRROR].fb_cmd;
if (!dev || !dev->dev || !gem_mirror || !mirror_fb_cmd) if (!dev || !dev->dev || !gem_mirror || !mirror_fb_cmd)
return; return;
@ -496,9 +492,9 @@ static void reconfigure(struct drm_client_dev * const dev)
} }
if (mode_larger(&mirror_compound, &mirror_minimum)) if (mode_larger(&mirror_compound, &mirror_minimum))
mirror_fb = mirror_compound; mirror->mode = mirror_compound;
else else
mirror_fb = mirror_minimum; mirror->mode = mirror_minimum;
{ {
struct state * state_mirror = &states[CONNECTOR_ID_MIRROR]; struct state * state_mirror = &states[CONNECTOR_ID_MIRROR];
@ -508,12 +504,12 @@ static void reconfigure(struct drm_client_dev * const dev)
gem_mirror, gem_mirror,
mirror_fb_cmd, mirror_fb_cmd,
&resized, &resized,
mirror_fb.hdisplay, mirror->mode.hdisplay,
mirror_fb.vdisplay); mirror->mode.vdisplay);
if (err) { if (err) {
printk("setting up mirrored framebuffer of %ux%u failed - error=%d\n", printk("setting up mirrored framebuffer of %ux%u failed - error=%d\n",
mirror_fb.hdisplay, mirror_fb.vdisplay, err); mirror->mode.hdisplay, mirror->mode.vdisplay, err);
return; return;
} }
@ -522,7 +518,7 @@ static void reconfigure(struct drm_client_dev * const dev)
printk("mirror: compound %ux%u force=%ux%u fb=%ux%u\n", printk("mirror: compound %ux%u force=%ux%u fb=%ux%u\n",
mirror_compound.hdisplay, mirror_compound.vdisplay, mirror_compound.hdisplay, mirror_compound.vdisplay,
mirror_force.hdisplay, mirror_force.vdisplay, mirror_force.hdisplay, mirror_force.vdisplay,
mirror_fb.hdisplay, mirror_fb.vdisplay); mirror->mode.hdisplay, mirror->mode.vdisplay);
} }
/* if mirrored fb changed, drop reference and get new framebuffer */ /* if mirrored fb changed, drop reference and get new framebuffer */
@ -534,19 +530,28 @@ static void reconfigure(struct drm_client_dev * const dev)
mirror_fb_cmd->fb_id); mirror_fb_cmd->fb_id);
} }
mirror.info.var.xres = mirror_fb.hdisplay; mirror->info.var.xres = mirror->mode.hdisplay;
mirror.info.var.yres = mirror_fb.vdisplay; mirror->info.var.yres = mirror->mode.vdisplay;
mirror.info.var.xres_virtual = mirror_force.hdisplay ? : mirror_compound.hdisplay; mirror->info.var.xres_virtual = mirror_force.hdisplay ? : mirror_compound.hdisplay;
mirror.info.var.yres_virtual = mirror_force.vdisplay ? : mirror_compound.vdisplay; mirror->info.var.yres_virtual = mirror_force.vdisplay ? : mirror_compound.vdisplay;
mirror.info.node = CONNECTOR_ID_MIRROR; mirror->info.node = CONNECTOR_ID_MIRROR;
mirror.info.par = "mirror_capture"; mirror->info.par = "mirror_capture";
} }
}
/* without fb handle created by check_resize_fb we can't proceed */
if (!mirror_fb_cmd->fb_id) { static void reconfigure(struct drm_client_dev * const dev)
printk("%s:%u no mirror fb id\n", __func__, __LINE__); {
struct drm_connector_list_iter conn_iter;
struct drm_connector * connector = NULL;
struct meta_data_mirror mirror = {};
if (!dev || !dev->dev)
return; return;
}
/* handle mirror/merge connectors */
handle_mirror(dev, &mirror);
drm_connector_list_iter_begin(dev_client->dev, &conn_iter); drm_connector_list_iter_begin(dev_client->dev, &conn_iter);
drm_client_for_each_connector_iter(connector, &conn_iter) { drm_client_for_each_connector_iter(connector, &conn_iter) {
@ -577,7 +582,7 @@ static void reconfigure(struct drm_client_dev * const dev)
} }
/* lookup next mode */ /* lookup next mode */
mode = best_mode(&conf_mode, connector, &mirror_fb, &no_match, &mode_id); mode = best_mode(&conf_mode, connector, &mirror.mode, &no_match, &mode_id);
/* reduce flickering if in same state */ /* reduce flickering if in same state */
same_state = conf_mode.mirror == state->mirrored && same_state = conf_mode.mirror == state->mirrored &&
@ -639,6 +644,7 @@ static void reconfigure(struct drm_client_dev * const dev)
} }
if (conf_mode.mirror) { if (conf_mode.mirror) {
struct drm_mode_fb_cmd2 * mirror_fb_cmd = &states[CONNECTOR_ID_MIRROR].fb_cmd;
/* get new fb reference for mirrored fb */ /* get new fb reference for mirrored fb */
state->fbs = drm_framebuffer_lookup(dev->dev, dev->file, state->fbs = drm_framebuffer_lookup(dev->dev, dev->file,
mirror_fb_cmd->fb_id); mirror_fb_cmd->fb_id);