Add support for X/Y reflection when the plane is using linear or T-tiled formats. X/Y reflection hasn't been tested on SAND formats, so we reject them until proper testing/debugging has been done.
Signed-off-by: Boris Brezillon boris.brezillon@bootlin.com --- drivers/gpu/drm/vc4/vc4_plane.c | 55 ++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 75db62cbe468..bdcccf65cde0 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -492,7 +492,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, bool mix_plane_alpha; bool covers_screen; u32 scl0, scl1, pitch0; - u32 tiling; + u32 tiling, src_y; u32 hvs_format = format->hvs; int ret, i;
@@ -520,6 +520,11 @@ static int vc4_plane_mode_set(struct drm_plane *plane, h_subsample = drm_format_horz_chroma_subsampling(format->drm); v_subsample = drm_format_vert_chroma_subsampling(format->drm);
+ /* We must point to the last line when Y reflection is enabled. */ + src_y = vc4_state->src_y; + if (state->rotation & DRM_MODE_REFLECT_Y) + src_y += vc4_state->src_h[0] - 1; + switch (base_format_mod) { case DRM_FORMAT_MOD_LINEAR: tiling = SCALER_CTL0_TILING_LINEAR; @@ -529,9 +534,10 @@ static int vc4_plane_mode_set(struct drm_plane *plane, * out. */ for (i = 0; i < num_planes; i++) { - vc4_state->offsets[i] += vc4_state->src_y / + vc4_state->offsets[i] += src_y / (i ? v_subsample : 1) * fb->pitches[i]; + vc4_state->offsets[i] += vc4_state->src_x / (i ? h_subsample : 1) * fb->format->cpp[i]; @@ -557,22 +563,38 @@ static int vc4_plane_mode_set(struct drm_plane *plane, u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift); u32 tiles_l = vc4_state->src_x >> tile_w_shift; u32 tiles_r = tiles_w - tiles_l; - u32 tiles_t = vc4_state->src_y >> tile_h_shift; + u32 tiles_t = src_y >> tile_h_shift; /* Intra-tile offsets, which modify the base address (the * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that * base address). */ - u32 tile_y = (vc4_state->src_y >> 4) & 1; - u32 subtile_y = (vc4_state->src_y >> 2) & 3; - u32 utile_y = vc4_state->src_y & 3; + u32 tile_y = (src_y >> 4) & 1; + u32 subtile_y = (src_y >> 2) & 3; + u32 utile_y = src_y & 3; u32 x_off = vc4_state->src_x & tile_w_mask; - u32 y_off = vc4_state->src_y & tile_h_mask; + u32 y_off = src_y & tile_h_mask; + + /* When Y reflection is requested we must set the + * SCALER_PITCH0_TILE_LINE_DIR flag to tell HVS that all lines + * after the initial one should be fetched in descending order, + * which makes sense since we start from the last line and go + * backward. + * Don't know why we need y_off = max_y_off - y_off, but it's + * definitely required (I guess it's also related to the "going + * backward" situation). + */ + if (state->rotation & DRM_MODE_REFLECT_Y) { + y_off = tile_h_mask - y_off; + pitch0 = SCALER_PITCH0_TILE_LINE_DIR; + } else { + pitch0 = 0; + }
tiling = SCALER_CTL0_TILING_256B_OR_T; - pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) | - VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) | - VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) | - VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R)); + pitch0 |= (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) | + VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) | + VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) | + VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R)); vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift); vc4_state->offsets[0] += subtile_y << 8; vc4_state->offsets[0] += utile_y << 4; @@ -611,6 +633,11 @@ static int vc4_plane_mode_set(struct drm_plane *plane, } }
+ if (state->rotation & DRM_MODE_REFLECT_MASK) { + DRM_DEBUG_KMS("X/Y reflection not supported on SAND formats\n"); + return -ENOTSUPP; + } + switch (base_format_mod) { case DRM_FORMAT_MOD_BROADCOM_SAND64: tiling = SCALER_CTL0_TILING_64B; @@ -643,6 +670,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane, /* Control word */ vc4_dlist_write(vc4_state, SCALER_CTL0_VALID | + (state->rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) | + (state->rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) | VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) | (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) | (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | @@ -1123,6 +1152,10 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
drm_plane_create_alpha_property(plane); + drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0, + DRM_MODE_ROTATE_0 | + DRM_MODE_REFLECT_X | + DRM_MODE_REFLECT_Y);
return plane; }
On Mon, Dec 03, 2018 at 02:34:12PM +0100, Boris Brezillon wrote:
Add support for X/Y reflection when the plane is using linear or T-tiled formats. X/Y reflection hasn't been tested on SAND formats, so we reject them until proper testing/debugging has been done.
BTW you could also expose 180 degress easily. See drm_rotation_simplify().
Signed-off-by: Boris Brezillon boris.brezillon@bootlin.com
drivers/gpu/drm/vc4/vc4_plane.c | 55 ++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 75db62cbe468..bdcccf65cde0 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -492,7 +492,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, bool mix_plane_alpha; bool covers_screen; u32 scl0, scl1, pitch0;
- u32 tiling;
- u32 tiling, src_y; u32 hvs_format = format->hvs; int ret, i;
@@ -520,6 +520,11 @@ static int vc4_plane_mode_set(struct drm_plane *plane, h_subsample = drm_format_horz_chroma_subsampling(format->drm); v_subsample = drm_format_vert_chroma_subsampling(format->drm);
- /* We must point to the last line when Y reflection is enabled. */
- src_y = vc4_state->src_y;
- if (state->rotation & DRM_MODE_REFLECT_Y)
src_y += vc4_state->src_h[0] - 1;
- switch (base_format_mod) { case DRM_FORMAT_MOD_LINEAR: tiling = SCALER_CTL0_TILING_LINEAR;
@@ -529,9 +534,10 @@ static int vc4_plane_mode_set(struct drm_plane *plane, * out. */ for (i = 0; i < num_planes; i++) {
vc4_state->offsets[i] += vc4_state->src_y /
vc4_state->offsets[i] += src_y / (i ? v_subsample : 1) * fb->pitches[i];
vc4_state->offsets[i] += vc4_state->src_x / (i ? h_subsample : 1) * fb->format->cpp[i];
@@ -557,22 +563,38 @@ static int vc4_plane_mode_set(struct drm_plane *plane, u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift); u32 tiles_l = vc4_state->src_x >> tile_w_shift; u32 tiles_r = tiles_w - tiles_l;
u32 tiles_t = vc4_state->src_y >> tile_h_shift;
/* Intra-tile offsets, which modify the base address (theu32 tiles_t = src_y >> tile_h_shift;
*/
- SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that
- base address).
u32 tile_y = (vc4_state->src_y >> 4) & 1;
u32 subtile_y = (vc4_state->src_y >> 2) & 3;
u32 utile_y = vc4_state->src_y & 3;
u32 tile_y = (src_y >> 4) & 1;
u32 subtile_y = (src_y >> 2) & 3;
u32 x_off = vc4_state->src_x & tile_w_mask;u32 utile_y = src_y & 3;
u32 y_off = vc4_state->src_y & tile_h_mask;
u32 y_off = src_y & tile_h_mask;
/* When Y reflection is requested we must set the
* SCALER_PITCH0_TILE_LINE_DIR flag to tell HVS that all lines
* after the initial one should be fetched in descending order,
* which makes sense since we start from the last line and go
* backward.
* Don't know why we need y_off = max_y_off - y_off, but it's
* definitely required (I guess it's also related to the "going
* backward" situation).
*/
if (state->rotation & DRM_MODE_REFLECT_Y) {
y_off = tile_h_mask - y_off;
pitch0 = SCALER_PITCH0_TILE_LINE_DIR;
} else {
pitch0 = 0;
}
tiling = SCALER_CTL0_TILING_256B_OR_T;
pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
pitch0 |= (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift); vc4_state->offsets[0] += subtile_y << 8; vc4_state->offsets[0] += utile_y << 4;VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
@@ -611,6 +633,11 @@ static int vc4_plane_mode_set(struct drm_plane *plane, } }
if (state->rotation & DRM_MODE_REFLECT_MASK) {
DRM_DEBUG_KMS("X/Y reflection not supported on SAND formats\n");
return -ENOTSUPP;
}
- switch (base_format_mod) { case DRM_FORMAT_MOD_BROADCOM_SAND64: tiling = SCALER_CTL0_TILING_64B;
@@ -643,6 +670,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane, /* Control word */ vc4_dlist_write(vc4_state, SCALER_CTL0_VALID |
(state->rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) |
(state->rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) | VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) | (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) | (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
@@ -1123,6 +1152,10 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
drm_plane_create_alpha_property(plane);
drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
DRM_MODE_ROTATE_0 |
DRM_MODE_REFLECT_X |
DRM_MODE_REFLECT_Y);
return plane;
}
2.17.1
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
On Mon, 3 Dec 2018 15:50:26 +0200 Ville Syrjälä ville.syrjala@linux.intel.com wrote:
On Mon, Dec 03, 2018 at 02:34:12PM +0100, Boris Brezillon wrote:
Add support for X/Y reflection when the plane is using linear or T-tiled formats. X/Y reflection hasn't been tested on SAND formats, so we reject them until proper testing/debugging has been done.
BTW you could also expose 180 degress easily. See drm_rotation_simplify().
Thanks for the tip. I'll add it in v2.
Boris Brezillon boris.brezillon@bootlin.com writes:
Add support for X/Y reflection when the plane is using linear or T-tiled formats. X/Y reflection hasn't been tested on SAND formats, so we reject them until proper testing/debugging has been done.
Reviewed-by: Eric Anholt eric@anholt.net
dri-devel@lists.freedesktop.org