Message ID | b980759ad766658d7bc3d67c18f505c5bf727ef5.1476779323.git-series.maxime.ripard@free-electrons.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Oct 18, 2016 at 10:29:38AM +0200, Maxime Ripard wrote: > Create overscan profiles reducing the displayed zone. > > For each TV standard (PAL and NTSC so far), we create 4 more reduced modes > by steps of 5% that the user will be able to select. > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> tbh I think if we agree to do this (and that still seems an open question) I think there should be a generic helper to add these overscan modes with increased porches. Anything that only depends upon the sink (and overscanning is something the sink does) should imo be put into a suitable helper library for everyone to share. Or maybe even stash it into the probe helpers and call it for all TV connectors. Definitely not a driver-private thing. -Daniel > --- > drivers/gpu/drm/sun4i/sun4i_tv.c | 60 +++++++++++++++++++-------------- > 1 file changed, 36 insertions(+), 24 deletions(-) > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c > index f99886462cb8..9ee03ba086b6 100644 > --- a/drivers/gpu/drm/sun4i/sun4i_tv.c > +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c > @@ -301,27 +301,33 @@ static const struct tv_mode *sun4i_tv_find_tv_by_mode(const struct drm_display_m > DRM_DEBUG_DRIVER("Comparing mode %s vs %s", > mode->name, tv_mode->name); > > - if (!strcmp(mode->name, tv_mode->name)) > + if (!strncmp(mode->name, tv_mode->name, strlen(tv_mode->name))) > return tv_mode; > } > > /* Then by number of lines */ > for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { > const struct tv_mode *tv_mode = &tv_modes[i]; > + int j; > > - DRM_DEBUG_DRIVER("Comparing mode %s vs %s (X: %d vs %d)", > - mode->name, tv_mode->name, > - mode->vdisplay, tv_mode->vdisplay); > + for (j = 0; j < 20; j += 5) { > + u32 vdisplay = tv_mode->vdisplay * (100 - j) / 100; > > - if (mode->vdisplay == tv_mode->vdisplay) > - return tv_mode; > + DRM_DEBUG_DRIVER("Comparing mode with %s (%d) (X: %d vs %d)", > + tv_mode->name, j, > + vdisplay, tv_mode->vdisplay); > + > + if (vdisplay == tv_mode->vdisplay) > + return tv_mode; > + } > } > > return NULL; > } > > static void sun4i_tv_mode_to_drm_mode(const struct tv_mode *tv_mode, > - struct drm_display_mode *mode) > + struct drm_display_mode *mode, > + int overscan) > { > DRM_DEBUG_DRIVER("Creating mode %s\n", mode->name); > > @@ -329,12 +335,12 @@ static void sun4i_tv_mode_to_drm_mode(const struct tv_mode *tv_mode, > mode->clock = 13500; > mode->flags = DRM_MODE_FLAG_INTERLACE; > > - mode->hdisplay = tv_mode->hdisplay; > + mode->hdisplay = tv_mode->hdisplay * (100 - overscan) / 100; > mode->hsync_start = mode->hdisplay + tv_mode->hfront_porch; > mode->hsync_end = mode->hsync_start + tv_mode->hsync_len; > mode->htotal = mode->hsync_end + tv_mode->hback_porch; > > - mode->vdisplay = tv_mode->vdisplay; > + mode->vdisplay = tv_mode->vdisplay * (100 - overscan) / 100; > mode->vsync_start = mode->vdisplay + tv_mode->vfront_porch; > mode->vsync_end = mode->vsync_start + tv_mode->vsync_len; > mode->vtotal = mode->vsync_end + tv_mode->vback_porch; > @@ -352,10 +358,10 @@ static int sun4i_tv_atomic_check(struct drm_encoder *encoder, > return -EINVAL; > > state->display_x_size = tv_mode->hdisplay; > - state->plane_x_offset = 0; > + state->plane_x_offset = (tv_mode->hdisplay - mode->hdisplay) / 2; > > state->display_y_size = tv_mode->vdisplay; > - state->plane_y_offset = 0; > + state->plane_y_offset = (tv_mode->vdisplay - mode->vdisplay) / 2; > > return 0; > } > @@ -404,7 +410,7 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder, > struct drm_display_mode tv_drm_mode = { 0 }; > > strcpy(tv_drm_mode.name, "TV"); > - sun4i_tv_mode_to_drm_mode(tv_mode, &tv_drm_mode); > + sun4i_tv_mode_to_drm_mode(tv_mode, &tv_drm_mode, 0); > drm_mode_set_crtcinfo(&tv_drm_mode, CRTC_INTERLACE_HALVE_V); > > sun4i_tcon1_mode_set(tcon, &tv_drm_mode); > @@ -526,22 +532,28 @@ static int sun4i_tv_comp_get_modes(struct drm_connector *connector) > int i; > > for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { > - struct drm_display_mode *mode; > const struct tv_mode *tv_mode = &tv_modes[i]; > - > - mode = drm_mode_create(connector->dev); > - if (!mode) { > - DRM_ERROR("Failed to create a new display mode\n"); > - return 0; > + int j; > + > + for (j = 0; j < 20; j += 5) { > + struct drm_display_mode *mode = drm_mode_create(connector->dev); > + if (!mode) { > + DRM_ERROR("Failed to create a new display mode\n"); > + return 0; > + } > + > + if (j) > + sprintf(mode->name, "%s%d", tv_mode->name, > + j); > + else > + strcpy(mode->name, tv_mode->name); > + > + sun4i_tv_mode_to_drm_mode(tv_mode, mode, j); > + drm_mode_probed_add(connector, mode); > } > - > - strcpy(mode->name, tv_mode->name); > - > - sun4i_tv_mode_to_drm_mode(tv_mode, mode); > - drm_mode_probed_add(connector, mode); > } > > - return i; > + return i * 4; > } > > static int sun4i_tv_comp_mode_valid(struct drm_connector *connector, > -- > git-series 0.8.10 > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/dri-devel
Hi Daniel, On Tue, Nov 08, 2016 at 09:59:27AM +0100, Daniel Vetter wrote: > On Tue, Oct 18, 2016 at 10:29:38AM +0200, Maxime Ripard wrote: > > Create overscan profiles reducing the displayed zone. > > > > For each TV standard (PAL and NTSC so far), we create 4 more reduced modes > > by steps of 5% that the user will be able to select. > > > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> > > tbh I think if we agree to do this (and that still seems an open question) > I think there should be a generic helper to add these overscan modes with > increased porches. Anything that only depends upon the sink (and > overscanning is something the sink does) should imo be put into a suitable > helper library for everyone to share. > > Or maybe even stash it into the probe helpers and call it for all TV > connectors. Definitely not a driver-private thing. Last time we discussed it, my recollection was that you didn't want to have generic code for it, but I'd be happy to implement it. I'll come up with something like that. Thanks! Maxime
On Thu, Nov 10, 2016 at 03:56:30PM +0100, Maxime Ripard wrote: > Hi Daniel, > > On Tue, Nov 08, 2016 at 09:59:27AM +0100, Daniel Vetter wrote: > > On Tue, Oct 18, 2016 at 10:29:38AM +0200, Maxime Ripard wrote: > > > Create overscan profiles reducing the displayed zone. > > > > > > For each TV standard (PAL and NTSC so far), we create 4 more reduced modes > > > by steps of 5% that the user will be able to select. > > > > > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> > > > > tbh I think if we agree to do this (and that still seems an open question) > > I think there should be a generic helper to add these overscan modes with > > increased porches. Anything that only depends upon the sink (and > > overscanning is something the sink does) should imo be put into a suitable > > helper library for everyone to share. > > > > Or maybe even stash it into the probe helpers and call it for all TV > > connectors. Definitely not a driver-private thing. > > Last time we discussed it, my recollection was that you didn't want to > have generic code for it, but I'd be happy to implement it. > > I'll come up with something like that. Well I can flip-flop around with the nonsense I'm sometimes emitting ;-) Since you called me out, feel free to do whatever you want ... -Daniel
On Fri, Nov 11, 2016 at 10:17:55AM +0100, Daniel Vetter wrote: > On Thu, Nov 10, 2016 at 03:56:30PM +0100, Maxime Ripard wrote: > > Hi Daniel, > > > > On Tue, Nov 08, 2016 at 09:59:27AM +0100, Daniel Vetter wrote: > > > On Tue, Oct 18, 2016 at 10:29:38AM +0200, Maxime Ripard wrote: > > > > Create overscan profiles reducing the displayed zone. > > > > > > > > For each TV standard (PAL and NTSC so far), we create 4 more reduced modes > > > > by steps of 5% that the user will be able to select. > > > > > > > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> > > > > > > tbh I think if we agree to do this (and that still seems an open question) > > > I think there should be a generic helper to add these overscan modes with > > > increased porches. Anything that only depends upon the sink (and > > > overscanning is something the sink does) should imo be put into a suitable > > > helper library for everyone to share. > > > > > > Or maybe even stash it into the probe helpers and call it for all TV > > > connectors. Definitely not a driver-private thing. > > > > Last time we discussed it, my recollection was that you didn't want to > > have generic code for it, but I'd be happy to implement it. > > > > I'll come up with something like that. > > Well I can flip-flop around with the nonsense I'm sometimes emitting ;-) > Since you called me out, feel free to do whatever you want ... I also found the generic solution to be a much better solution, so I'll definitely implement it :) Maxime
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index f99886462cb8..9ee03ba086b6 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -301,27 +301,33 @@ static const struct tv_mode *sun4i_tv_find_tv_by_mode(const struct drm_display_m DRM_DEBUG_DRIVER("Comparing mode %s vs %s", mode->name, tv_mode->name); - if (!strcmp(mode->name, tv_mode->name)) + if (!strncmp(mode->name, tv_mode->name, strlen(tv_mode->name))) return tv_mode; } /* Then by number of lines */ for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { const struct tv_mode *tv_mode = &tv_modes[i]; + int j; - DRM_DEBUG_DRIVER("Comparing mode %s vs %s (X: %d vs %d)", - mode->name, tv_mode->name, - mode->vdisplay, tv_mode->vdisplay); + for (j = 0; j < 20; j += 5) { + u32 vdisplay = tv_mode->vdisplay * (100 - j) / 100; - if (mode->vdisplay == tv_mode->vdisplay) - return tv_mode; + DRM_DEBUG_DRIVER("Comparing mode with %s (%d) (X: %d vs %d)", + tv_mode->name, j, + vdisplay, tv_mode->vdisplay); + + if (vdisplay == tv_mode->vdisplay) + return tv_mode; + } } return NULL; } static void sun4i_tv_mode_to_drm_mode(const struct tv_mode *tv_mode, - struct drm_display_mode *mode) + struct drm_display_mode *mode, + int overscan) { DRM_DEBUG_DRIVER("Creating mode %s\n", mode->name); @@ -329,12 +335,12 @@ static void sun4i_tv_mode_to_drm_mode(const struct tv_mode *tv_mode, mode->clock = 13500; mode->flags = DRM_MODE_FLAG_INTERLACE; - mode->hdisplay = tv_mode->hdisplay; + mode->hdisplay = tv_mode->hdisplay * (100 - overscan) / 100; mode->hsync_start = mode->hdisplay + tv_mode->hfront_porch; mode->hsync_end = mode->hsync_start + tv_mode->hsync_len; mode->htotal = mode->hsync_end + tv_mode->hback_porch; - mode->vdisplay = tv_mode->vdisplay; + mode->vdisplay = tv_mode->vdisplay * (100 - overscan) / 100; mode->vsync_start = mode->vdisplay + tv_mode->vfront_porch; mode->vsync_end = mode->vsync_start + tv_mode->vsync_len; mode->vtotal = mode->vsync_end + tv_mode->vback_porch; @@ -352,10 +358,10 @@ static int sun4i_tv_atomic_check(struct drm_encoder *encoder, return -EINVAL; state->display_x_size = tv_mode->hdisplay; - state->plane_x_offset = 0; + state->plane_x_offset = (tv_mode->hdisplay - mode->hdisplay) / 2; state->display_y_size = tv_mode->vdisplay; - state->plane_y_offset = 0; + state->plane_y_offset = (tv_mode->vdisplay - mode->vdisplay) / 2; return 0; } @@ -404,7 +410,7 @@ static void sun4i_tv_mode_set(struct drm_encoder *encoder, struct drm_display_mode tv_drm_mode = { 0 }; strcpy(tv_drm_mode.name, "TV"); - sun4i_tv_mode_to_drm_mode(tv_mode, &tv_drm_mode); + sun4i_tv_mode_to_drm_mode(tv_mode, &tv_drm_mode, 0); drm_mode_set_crtcinfo(&tv_drm_mode, CRTC_INTERLACE_HALVE_V); sun4i_tcon1_mode_set(tcon, &tv_drm_mode); @@ -526,22 +532,28 @@ static int sun4i_tv_comp_get_modes(struct drm_connector *connector) int i; for (i = 0; i < ARRAY_SIZE(tv_modes); i++) { - struct drm_display_mode *mode; const struct tv_mode *tv_mode = &tv_modes[i]; - - mode = drm_mode_create(connector->dev); - if (!mode) { - DRM_ERROR("Failed to create a new display mode\n"); - return 0; + int j; + + for (j = 0; j < 20; j += 5) { + struct drm_display_mode *mode = drm_mode_create(connector->dev); + if (!mode) { + DRM_ERROR("Failed to create a new display mode\n"); + return 0; + } + + if (j) + sprintf(mode->name, "%s%d", tv_mode->name, + j); + else + strcpy(mode->name, tv_mode->name); + + sun4i_tv_mode_to_drm_mode(tv_mode, mode, j); + drm_mode_probed_add(connector, mode); } - - strcpy(mode->name, tv_mode->name); - - sun4i_tv_mode_to_drm_mode(tv_mode, mode); - drm_mode_probed_add(connector, mode); } - return i; + return i * 4; } static int sun4i_tv_comp_mode_valid(struct drm_connector *connector,
Create overscan profiles reducing the displayed zone. For each TV standard (PAL and NTSC so far), we create 4 more reduced modes by steps of 5% that the user will be able to select. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> --- drivers/gpu/drm/sun4i/sun4i_tv.c | 60 +++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 24 deletions(-)