diff options
| author | Boris Brezillon <boris.brezillon@bootlin.com> | 2018-12-07 03:36:06 -0500 |
|---|---|---|
| committer | Boris Brezillon <boris.brezillon@bootlin.com> | 2018-12-08 07:27:36 -0500 |
| commit | 7cd3cf3540a37072c647b8b5120a80de5bb3d199 (patch) | |
| tree | 2adeed20293228c412322cbe9aec44f81c05e5b1 /drivers/gpu/drm | |
| parent | 8e75d582db02bcb171d65ec71eecbd3072a5fd3a (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.c | 59 |
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 | } |
