On Thu, Apr 11, 2019 at 03:22:41PM +0200, Maxime Ripard wrote: > Rotations and reflections setup are needed in some scenarios to initialise > properly the initial framebuffer. Some drivers already had a bunch of > quirks to deal with this, such as either a private kernel command line > parameter (omapdss) or on the device tree (various panels). > > In order to accomodate this, let's create a video mode parameter to deal > with the rotation and reflexion. > > Signed-off-by: Maxime Ripard <maxime.rip...@bootlin.com> > --- > drivers/gpu/drm/drm_fb_helper.c | 4 +- > drivers/gpu/drm/drm_modes.c | 110 +++++++++++++++++++++++++++------ > include/drm/drm_connector.h | 1 +- > 3 files changed, 95 insertions(+), 20 deletions(-) > > diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c > index b3a5d79436ae..8781897559b2 100644 > --- a/drivers/gpu/drm/drm_fb_helper.c > +++ b/drivers/gpu/drm/drm_fb_helper.c > @@ -2521,6 +2521,7 @@ static void drm_setup_crtc_rotation(struct > drm_fb_helper *fb_helper, > struct drm_connector *connector) > { > struct drm_plane *plane = fb_crtc->mode_set.crtc->primary; > + struct drm_cmdline_mode *mode = &connector->cmdline_mode; > uint64_t valid_mask = 0; > int i, rotation; > > @@ -2540,6 +2541,9 @@ static void drm_setup_crtc_rotation(struct > drm_fb_helper *fb_helper, > rotation = DRM_MODE_ROTATE_0; > } > > + if (mode->rotation != DRM_MODE_ROTATE_0) > + fb_crtc->rotation = mode->rotation;
Hm, kinda awkward that we have to tie all this to the fbdev helpers. But that's already the case with the old stuff, so mea culpa I guess. > + > /* > * TODO: support 90 / 270 degree hardware rotation, > * depending on the hardware this may require the framebuffer > diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c > index 9613c1a28487..ac8d70b92b62 100644 > --- a/drivers/gpu/drm/drm_modes.c > +++ b/drivers/gpu/drm/drm_modes.c > @@ -1531,6 +1531,71 @@ static int drm_mode_parse_cmdline_res_mode(const char > *str, unsigned int length, > return 0; > } > > +static int drm_mode_parse_cmdline_options(char *str, size_t len, > + struct drm_connector *connector, > + struct drm_cmdline_mode *mode) > +{ > + unsigned int rotation = 0; > + char *sep = str; > + > + while ((sep = strchr(sep, ','))) { > + char *delim, *option; > + > + option = sep + 1; > + delim = strchr(option, '='); > + if (!delim) { > + delim = strchr(option, ','); > + > + if (!delim) > + delim = str + len; > + } > + > + if (!strncmp(option, "rotate", delim - option)) { > + const char *value = delim + 1; > + unsigned int deg; > + > + deg = simple_strtol(value, &sep, 10); > + > + /* Make sure we have parsed something */ > + if (sep == value) > + return -EINVAL; > + > + switch (deg) { > + case 0: > + rotation |= DRM_MODE_ROTATE_0; > + break; > + > + case 90: > + rotation |= DRM_MODE_ROTATE_90; > + break; > + > + case 180: > + rotation |= DRM_MODE_ROTATE_180; > + break; > + > + case 270: > + rotation |= DRM_MODE_ROTATE_270; > + break; > + > + default: > + return -EINVAL; > + } > + } else if (!strncmp(option, "reflect_x", delim - option)) { > + rotation |= DRM_MODE_REFLECT_X; > + sep = delim; > + } else if (!strncmp(option, "reflect_y", delim - option)) { > + rotation |= DRM_MODE_REFLECT_Y; > + sep = delim; > + } else { > + return -EINVAL; > + } > + } > + > + mode->rotation = rotation; > + > + return 0; > +} > + > /** > * drm_mode_parse_command_line_for_connector - parse command line modeline > for connector > * @mode_option: optional per connector mode option > @@ -1558,9 +1623,10 @@ bool drm_mode_parse_command_line_for_connector(const > char *mode_option, > { > const char *name; > bool named_mode = false, parse_extras = false; > - unsigned int bpp_off = 0, refresh_off = 0; > + unsigned int bpp_off = 0, refresh_off = 0, options_off = 0; > unsigned int mode_end = 0; > char *bpp_ptr = NULL, *refresh_ptr = NULL, *extra_ptr = NULL; > + char *options_ptr = NULL; > char *bpp_end_ptr = NULL, *refresh_end_ptr = NULL; > int ret; > > @@ -1601,13 +1667,18 @@ bool drm_mode_parse_command_line_for_connector(const > char *mode_option, > mode->refresh_specified = true; > } > > + /* Locate the start of named options */ > + options_ptr = strchr(name, ','); > + if (options_ptr) > + options_off = options_ptr - name; > + > /* Locate the end of the name / resolution, and parse it */ > - if (bpp_ptr && refresh_ptr) { > - mode_end = min(bpp_off, refresh_off); > - } else if (bpp_ptr) { > + if (bpp_ptr) { > mode_end = bpp_off; > } else if (refresh_ptr) { > mode_end = refresh_off; > + } else if (options_ptr) { > + mode_end = options_off; > } else { > mode_end = strlen(name); > parse_extras = true; > @@ -1649,24 +1720,23 @@ bool drm_mode_parse_command_line_for_connector(const > char *mode_option, > else if (refresh_ptr) > extra_ptr = refresh_end_ptr; > > - if (extra_ptr) { > - if (!named_mode) { > - int len = strlen(name) - (extra_ptr - name); > + if (extra_ptr && > + extra_ptr != options_ptr) { > + int len = strlen(name) - (extra_ptr - name); > > - ret = drm_mode_parse_cmdline_extra(extra_ptr, len, > - connector, mode); > - if (ret) > - return false; > - } else { > - int remaining = strlen(name) - (extra_ptr - name); > + ret = drm_mode_parse_cmdline_extra(extra_ptr, len, > + connector, mode); > + if (ret) > + return false; > + } > > - /* > - * We still have characters to process, while > - * we shouldn't have any > - */ > - if (remaining > 0) > - return false; > - } > + if (options_ptr) { > + int len = strlen(name) - (options_ptr - name); > + > + ret = drm_mode_parse_cmdline_options(options_ptr, len, > + connector, mode); > + if (ret) > + return false; > } > > return true; > diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h > index 06aa3b9cb920..dfe7f2304b35 100644 > --- a/include/drm/drm_connector.h > +++ b/include/drm/drm_connector.h > @@ -907,6 +907,7 @@ struct drm_cmdline_mode { > bool interlace; > bool cvt; > bool margins; > + unsigned int rotation; > enum drm_connector_force force; Kerneldoc for this would be neat. -Daniel > }; > > -- > git-series 0.9.1 > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel -- Daniel Vetter Software Engineer, Intel Corporation http://blog.ffwll.ch _______________________________________________ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel