[PATCH v2] drm/fbdev: Fallback to non tiled mode if all tiles not present

Dave Airlie airlied at gmail.com
Tue Nov 12 21:42:24 UTC 2019


LGTM, thanks,

Reviewed-by: Dave Airlie <airlied at redhat.com>

On Sat, 9 Nov 2019 at 10:52, Manasi Navare <manasi.d.navare at intel.com> 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 at redhat.com>
>
> Suggested-by: Ville Syrjälä <ville.syrjala at linux.intel.com>
> Suggested-by: Dave Airlie <airlied at redhat.com>
> Cc: Ville Syrjälä <ville.syrjala at linux.intel.com>
> Cc: Dave Airlie <airlied at redhat.com>
> Signed-off-by: Manasi Navare <manasi.d.navare at intel.com>
> ---
>  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 at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel


More information about the dri-devel mailing list