Re: [PATCH v2 4/5] drm/modes: Parse overscan properties

Noralf Trønnes
2019-04-16T14:52:37Z

Den 11.04.2019 15.22, skrev Maxime Ripard:
> Properly configuring the overscan properties might be needed for the
> initial setup of the framebuffer for display that still have overscan.
> Let's allow for more properties on the kernel command line to setup each
> margin.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com>
> ---
> drivers/gpu/drm/drm_fb_helper.c | 47 ++++++++++++++++++++++++++++++++++-
> drivers/gpu/drm/drm_modes.c | 44 ++++++++++++++++++++++++++++++++-
> include/drm/drm_connector.h | 1 +-
> 3 files changed, 92 insertions(+)
>
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index 8781897559b2..4e403fe1f451 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -2567,6 +2567,51 @@ static void drm_setup_crtc_rotation(struct drm_fb_helper *fb_helper,
> fb_helper->sw_rotations |= DRM_MODE_ROTATE_0;
> }
>
> +static void drm_setup_connector_margins(struct drm_connector *connector)
> +{
> + struct drm_cmdline_mode *cmdline = &connector->cmdline_mode;
> + struct drm_modeset_acquire_ctx ctx;
> + struct drm_atomic_state *state;
> + struct drm_device *dev = connector->dev;
> + int ret;
> +
> + if (!drm_drv_uses_atomic_modeset(dev))
> + return;
> +
> + drm_modeset_acquire_init(&ctx, 0);
> +
> + state = drm_atomic_state_alloc(dev);
> + state->acquire_ctx = &ctx;
> +
> +retry:
> + drm_atomic_set_property(state, &connector->base,
> + dev->mode_config.tv_left_margin_property,
> + cmdline->overscan_left);
> +
> + drm_atomic_set_property(state, &connector->base,
> + dev->mode_config.tv_right_margin_property,
> + cmdline->overscan_right);
> +
> + drm_atomic_set_property(state, &connector->base,
> + dev->mode_config.tv_top_margin_property,
> + cmdline->overscan_top);
> +
> + drm_atomic_set_property(state, &connector->base,
> + dev->mode_config.tv_bottom_margin_property,
> + cmdline->overscan_bottom);
> +
> + ret = drm_atomic_commit(state);
> + if (ret == -EDEADLK) {
> + drm_atomic_state_clear(state);
> + drm_modeset_backoff(&ctx);
> + goto retry;
> + }
> +
> + drm_atomic_state_put(state);
> + drm_modeset_drop_locks(&ctx);
> + drm_modeset_acquire_fini(&ctx);
> +}
> +

Should we set these property values in drm_connector_init()?
I assume that DRM userspace would want to use these values as well.

Noralf.

> static void drm_setup_crtcs(struct drm_fb_helper *fb_helper,
> u32 width, u32 height)
> {
> @@ -2680,6 +2725,8 @@ static void drm_setup_crtcs_fb(struct drm_fb_helper *fb_helper)
> struct drm_connector *connector =
> fb_helper->connector_info[i]->connector;
>
> + drm_setup_connector_margins(connector);
> +
> /* use first connected connector for the physical dimensions */
> if (connector->status == connector_status_connected) {
> info->var.width = connector->display_info.width_mm;
> diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
> index ac8d70b92b62..493ba3ccde70 100644
> --- a/drivers/gpu/drm/drm_modes.c
> +++ b/drivers/gpu/drm/drm_modes.c
> @@ -1586,6 +1586,50 @@ static int drm_mode_parse_cmdline_options(char *str, size_t len,
> } else if (!strncmp(option, "reflect_y", delim - option)) {
> rotation |= DRM_MODE_REFLECT_Y;
> sep = delim;
> + } else if (!strncmp(option, "overscan_right", delim - option)) {
> + const char *value = delim + 1;
> + unsigned int margin;
> +
> + margin = simple_strtol(value, &sep, 10);
> +
> + /* Make sure we have parsed something */
> + if (sep == value)
> + return -EINVAL;
> +
> + mode->overscan_right = margin;
> + } else if (!strncmp(option, "overscan_left", delim - option)) {
> + const char *value = delim + 1;
> + unsigned int margin;
> +
> + margin = simple_strtol(value, &sep, 10);
> +
> + /* Make sure we have parsed something */
> + if (sep == value)
> + return -EINVAL;
> +
> + mode->overscan_left = margin;
> + } else if (!strncmp(option, "overscan_top", delim - option)) {
> + const char *value = delim + 1;
> + unsigned int margin;
> +
> + margin = simple_strtol(value, &sep, 10);
> +
> + /* Make sure we have parsed something */
> + if (sep == value)
> + return -EINVAL;
> +
> + mode->overscan_top = margin;
> + } else if (!strncmp(option, "overscan_bottom", delim - option)) {
> + const char *value = delim + 1;
> + unsigned int margin;
> +
> + margin = simple_strtol(value, &sep, 10);
> +
> + /* Make sure we have parsed something */
> + if (sep == value)
> + return -EINVAL;
> +
> + mode->overscan_bottom = margin;
> } else {
> return -EINVAL;
> }
> diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
> index dfe7f2304b35..44d9885dd401 100644
> --- a/include/drm/drm_connector.h
> +++ b/include/drm/drm_connector.h
> @@ -903,6 +903,7 @@ struct drm_cmdline_mode {
> int xres, yres;
> int bpp;
> int refresh;
> + int overscan_right, overscan_top, overscan_left, overscan_bottom;
> bool rb;
> bool interlace;
> bool cvt;