Pushed tod rm-misc-next, thanks a lot Dave all the feedback and reviews. Regards Manasi On Wed, Nov 13, 2019 at 02:29:52PM -0800, Manasi Navare wrote: > In case of tiled displays, if we hotplug just one connector, > fbcon currently just selects the preferred mode and if it is > tiled mode then that becomes a problem if rest of the tiles are > not present. > So in the fbdev driver on hotplug when we probe the client modeset, > if we dont find all the connectors for all tiles, then on a connector > with one tile, just fallback to the first available non tiled mode > to display over a single connector. > On the hotplug of the consecutive tiled connectors, if the tiled mode > no longer exists because of fbcon size limitation, then return > no modes for consecutive tiles but retain the non tiled mode > on the 0th tile. > Use the same logic in case of connected boot case as well. > This has been tested with Dell UP328K tiled monitor. > > v2: > * Set the modes on consecutive hotplugged tiles to no mode > if tiled mode is pruned (Dave) > v1: > * Just handle the 1st connector hotplug case > * v1 Reviewed-by: Dave Airlie <airlied@xxxxxxxxxx> > > Suggested-by: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > Suggested-by: Dave Airlie <airlied@xxxxxxxxxx> > Cc: Ville Syrjälä <ville.syrjala@xxxxxxxxxxxxxxx> > Cc: Dave Airlie <airlied@xxxxxxxxxx> > Signed-off-by: Manasi Navare <manasi.d.navare@xxxxxxxxx> > Reviewed-by: Dave Airlie <airlied@xxxxxxxxxx> > --- > drivers/gpu/drm/drm_client_modeset.c | 70 ++++++++++++++++++++++++++++ > 1 file changed, 70 insertions(+) > > diff --git a/drivers/gpu/drm/drm_client_modeset.c b/drivers/gpu/drm/drm_client_modeset.c > index 895b73f23079..f2150a0bac4c 100644 > --- a/drivers/gpu/drm/drm_client_modeset.c > +++ b/drivers/gpu/drm/drm_client_modeset.c > @@ -114,6 +114,33 @@ drm_client_find_modeset(struct drm_client_dev *client, struct drm_crtc *crtc) > return NULL; > } > > +static struct drm_display_mode * > +drm_connector_get_tiled_mode(struct drm_connector *connector) > +{ > + struct drm_display_mode *mode; > + > + list_for_each_entry(mode, &connector->modes, head) { > + if (mode->hdisplay == connector->tile_h_size && > + mode->vdisplay == connector->tile_v_size) > + return mode; > + } > + return NULL; > +} > + > +static struct drm_display_mode * > +drm_connector_fallback_non_tiled_mode(struct drm_connector *connector) > +{ > + struct drm_display_mode *mode; > + > + list_for_each_entry(mode, &connector->modes, head) { > + if (mode->hdisplay == connector->tile_h_size && > + mode->vdisplay == connector->tile_v_size) > + continue; > + return mode; > + } > + return NULL; > +} > + > static struct drm_display_mode * > drm_connector_has_preferred_mode(struct drm_connector *connector, int width, int height) > { > @@ -348,8 +375,14 @@ static bool drm_client_target_preferred(struct drm_connector **connectors, > struct drm_connector *connector; > u64 conn_configured = 0; > int tile_pass = 0; > + int num_tiled_conns = 0; > int i; > > + for (i = 0; i < connector_count; i++) { > + if (connectors[i]->has_tile) > + num_tiled_conns++; > + } > + > retry: > for (i = 0; i < connector_count; i++) { > connector = connectors[i]; > @@ -399,6 +432,28 @@ static bool drm_client_target_preferred(struct drm_connector **connectors, > list_for_each_entry(modes[i], &connector->modes, head) > break; > } > + /* > + * In case of tiled mode if all tiles not present fallback to > + * first available non tiled mode. > + * After all tiles are present, try to find the tiled mode > + * for all and if tiled mode not present due to fbcon size > + * limitations, use first non tiled mode only for > + * tile 0,0 and set to no mode for all other tiles. > + */ > + if (connector->has_tile) { > + if (num_tiled_conns < > + connector->num_h_tile * connector->num_v_tile || > + (connector->tile_h_loc == 0 && > + connector->tile_v_loc == 0 && > + !drm_connector_get_tiled_mode(connector))) { > + DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n", > + connector->base.id); > + modes[i] = drm_connector_fallback_non_tiled_mode(connector); > + } else { > + modes[i] = drm_connector_get_tiled_mode(connector); > + } > + } > + > DRM_DEBUG_KMS("found mode %s\n", modes[i] ? modes[i]->name : > "none"); > conn_configured |= BIT_ULL(i); > @@ -515,6 +570,7 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, > bool fallback = true, ret = true; > int num_connectors_enabled = 0; > int num_connectors_detected = 0; > + int num_tiled_conns = 0; > struct drm_modeset_acquire_ctx ctx; > > if (!drm_drv_uses_atomic_modeset(dev)) > @@ -532,6 +588,10 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, > memcpy(save_enabled, enabled, count); > mask = GENMASK(count - 1, 0); > conn_configured = 0; > + for (i = 0; i < count; i++) { > + if (connectors[i]->has_tile) > + num_tiled_conns++; > + } > retry: > conn_seq = conn_configured; > for (i = 0; i < count; i++) { > @@ -631,6 +691,16 @@ static bool drm_client_firmware_config(struct drm_client_dev *client, > connector->name); > modes[i] = &connector->state->crtc->mode; > } > + /* > + * In case of tiled modes, if all tiles are not present > + * then fallback to a non tiled mode. > + */ > + if (connector->has_tile && > + num_tiled_conns < connector->num_h_tile * connector->num_v_tile) { > + DRM_DEBUG_KMS("Falling back to non tiled mode on Connector %d\n", > + connector->base.id); > + modes[i] = drm_connector_fallback_non_tiled_mode(connector); > + } > crtcs[i] = new_crtc; > > DRM_DEBUG_KMS("connector %s on [CRTC:%d:%s]: %dx%d%s\n", > -- > 2.19.1 > _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel