aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@bootlin.com>2018-12-07 03:36:06 -0500
committerBoris Brezillon <boris.brezillon@bootlin.com>2018-12-08 07:27:36 -0500
commit7cd3cf3540a37072c647b8b5120a80de5bb3d199 (patch)
tree2adeed20293228c412322cbe9aec44f81c05e5b1 /drivers/gpu/drm
parent8e75d582db02bcb171d65ec71eecbd3072a5fd3a (diff)
drm/vc4: Add support for X/Y reflection
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> Reviewed-by: Eric Anholt <eric@anholt.net> Link: https://patchwork.freedesktop.org/patch/msgid/20181207083606.15449-2-boris.brezillon@bootlin.com
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/vc4/vc4_plane.c59
1 files changed, 47 insertions, 12 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c
index fb1214b91a25..283abd7d1e9b 100644
--- a/drivers/gpu/drm/vc4/vc4_plane.c
+++ b/drivers/gpu/drm/vc4/vc4_plane.c
@@ -492,8 +492,9 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
492 bool mix_plane_alpha; 492 bool mix_plane_alpha;
493 bool covers_screen; 493 bool covers_screen;
494 u32 scl0, scl1, pitch0; 494 u32 scl0, scl1, pitch0;
495 u32 tiling; 495 u32 tiling, src_y;
496 u32 hvs_format = format->hvs; 496 u32 hvs_format = format->hvs;
497 unsigned int rotation;
497 int ret, i; 498 int ret, i;
498 499
499 if (vc4_state->dlist_initialized) 500 if (vc4_state->dlist_initialized)
@@ -520,6 +521,16 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
520 h_subsample = drm_format_horz_chroma_subsampling(format->drm); 521 h_subsample = drm_format_horz_chroma_subsampling(format->drm);
521 v_subsample = drm_format_vert_chroma_subsampling(format->drm); 522 v_subsample = drm_format_vert_chroma_subsampling(format->drm);
522 523
524 rotation = drm_rotation_simplify(state->rotation,
525 DRM_MODE_ROTATE_0 |
526 DRM_MODE_REFLECT_X |
527 DRM_MODE_REFLECT_Y);
528
529 /* We must point to the last line when Y reflection is enabled. */
530 src_y = vc4_state->src_y;
531 if (rotation & DRM_MODE_REFLECT_Y)
532 src_y += vc4_state->src_h[0] - 1;
533
523 switch (base_format_mod) { 534 switch (base_format_mod) {
524 case DRM_FORMAT_MOD_LINEAR: 535 case DRM_FORMAT_MOD_LINEAR:
525 tiling = SCALER_CTL0_TILING_LINEAR; 536 tiling = SCALER_CTL0_TILING_LINEAR;
@@ -529,9 +540,10 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
529 * out. 540 * out.
530 */ 541 */
531 for (i = 0; i < num_planes; i++) { 542 for (i = 0; i < num_planes; i++) {
532 vc4_state->offsets[i] += vc4_state->src_y / 543 vc4_state->offsets[i] += src_y /
533 (i ? v_subsample : 1) * 544 (i ? v_subsample : 1) *
534 fb->pitches[i]; 545 fb->pitches[i];
546
535 vc4_state->offsets[i] += vc4_state->src_x / 547 vc4_state->offsets[i] += vc4_state->src_x /
536 (i ? h_subsample : 1) * 548 (i ? h_subsample : 1) *
537 fb->format->cpp[i]; 549 fb->format->cpp[i];
@@ -557,22 +569,38 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
557 u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift); 569 u32 tiles_w = fb->pitches[0] >> (tile_size_shift - tile_h_shift);
558 u32 tiles_l = vc4_state->src_x >> tile_w_shift; 570 u32 tiles_l = vc4_state->src_x >> tile_w_shift;
559 u32 tiles_r = tiles_w - tiles_l; 571 u32 tiles_r = tiles_w - tiles_l;
560 u32 tiles_t = vc4_state->src_y >> tile_h_shift; 572 u32 tiles_t = src_y >> tile_h_shift;
561 /* Intra-tile offsets, which modify the base address (the 573 /* Intra-tile offsets, which modify the base address (the
562 * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that 574 * SCALER_PITCH0_TILE_Y_OFFSET tells HVS how to walk from that
563 * base address). 575 * base address).
564 */ 576 */
565 u32 tile_y = (vc4_state->src_y >> 4) & 1; 577 u32 tile_y = (src_y >> 4) & 1;
566 u32 subtile_y = (vc4_state->src_y >> 2) & 3; 578 u32 subtile_y = (src_y >> 2) & 3;
567 u32 utile_y = vc4_state->src_y & 3; 579 u32 utile_y = src_y & 3;
568 u32 x_off = vc4_state->src_x & tile_w_mask; 580 u32 x_off = vc4_state->src_x & tile_w_mask;
569 u32 y_off = vc4_state->src_y & tile_h_mask; 581 u32 y_off = src_y & tile_h_mask;
582
583 /* When Y reflection is requested we must set the
584 * SCALER_PITCH0_TILE_LINE_DIR flag to tell HVS that all lines
585 * after the initial one should be fetched in descending order,
586 * which makes sense since we start from the last line and go
587 * backward.
588 * Don't know why we need y_off = max_y_off - y_off, but it's
589 * definitely required (I guess it's also related to the "going
590 * backward" situation).
591 */
592 if (rotation & DRM_MODE_REFLECT_Y) {
593 y_off = tile_h_mask - y_off;
594 pitch0 = SCALER_PITCH0_TILE_LINE_DIR;
595 } else {
596 pitch0 = 0;
597 }
570 598
571 tiling = SCALER_CTL0_TILING_256B_OR_T; 599 tiling = SCALER_CTL0_TILING_256B_OR_T;
572 pitch0 = (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) | 600 pitch0 |= (VC4_SET_FIELD(x_off, SCALER_PITCH0_SINK_PIX) |
573 VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) | 601 VC4_SET_FIELD(y_off, SCALER_PITCH0_TILE_Y_OFFSET) |
574 VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) | 602 VC4_SET_FIELD(tiles_l, SCALER_PITCH0_TILE_WIDTH_L) |
575 VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R)); 603 VC4_SET_FIELD(tiles_r, SCALER_PITCH0_TILE_WIDTH_R));
576 vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift); 604 vc4_state->offsets[0] += tiles_t * (tiles_w << tile_size_shift);
577 vc4_state->offsets[0] += subtile_y << 8; 605 vc4_state->offsets[0] += subtile_y << 8;
578 vc4_state->offsets[0] += utile_y << 4; 606 vc4_state->offsets[0] += utile_y << 4;
@@ -643,7 +671,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
643 */ 671 */
644 for (i = 0; i < num_planes; i++) { 672 for (i = 0; i < num_planes; i++) {
645 vc4_state->offsets[i] += param * tile_w * tile; 673 vc4_state->offsets[i] += param * tile_w * tile;
646 vc4_state->offsets[i] += vc4_state->src_y / 674 vc4_state->offsets[i] += src_y /
647 (i ? v_subsample : 1) * 675 (i ? v_subsample : 1) *
648 tile_w; 676 tile_w;
649 vc4_state->offsets[i] += x_off / 677 vc4_state->offsets[i] += x_off /
@@ -664,6 +692,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
664 /* Control word */ 692 /* Control word */
665 vc4_dlist_write(vc4_state, 693 vc4_dlist_write(vc4_state,
666 SCALER_CTL0_VALID | 694 SCALER_CTL0_VALID |
695 (rotation & DRM_MODE_REFLECT_X ? SCALER_CTL0_HFLIP : 0) |
696 (rotation & DRM_MODE_REFLECT_Y ? SCALER_CTL0_VFLIP : 0) |
667 VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) | 697 VC4_SET_FIELD(SCALER_CTL0_RGBA_EXPAND_ROUND, SCALER_CTL0_RGBA_EXPAND) |
668 (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) | 698 (format->pixel_order << SCALER_CTL0_ORDER_SHIFT) |
669 (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) | 699 (hvs_format << SCALER_CTL0_PIXEL_FORMAT_SHIFT) |
@@ -1144,6 +1174,11 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
1144 drm_plane_helper_add(plane, &vc4_plane_helper_funcs); 1174 drm_plane_helper_add(plane, &vc4_plane_helper_funcs);
1145 1175
1146 drm_plane_create_alpha_property(plane); 1176 drm_plane_create_alpha_property(plane);
1177 drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
1178 DRM_MODE_ROTATE_0 |
1179 DRM_MODE_ROTATE_180 |
1180 DRM_MODE_REFLECT_X |
1181 DRM_MODE_REFLECT_Y);
1147 1182
1148 return plane; 1183 return plane;
1149} 1184}