Skip to content

Commit cd74077

Browse files
digetxthierryreding
authored andcommitted
drm/tegra: plane: Support horizontal reflection
Support horizontal reflection mode which will allow to support 180° rotation mode when combined with the vertical reflection. Signed-off-by: Dmitry Osipenko <[email protected]> Signed-off-by: Thierry Reding <[email protected]>
1 parent e9e476f commit cd74077

File tree

4 files changed

+35
-6
lines changed

4 files changed

+35
-6
lines changed

drivers/gpu/drm/tegra/dc.c

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,12 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
368368
h_size = window->src.w * bpp;
369369
v_size = window->src.h;
370370

371+
if (window->reflect_x)
372+
h_offset += (window->src.w - 1) * bpp;
373+
374+
if (window->reflect_y)
375+
v_offset += window->src.h - 1;
376+
371377
value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
372378
tegra_plane_writel(plane, value, DC_WIN_PRESCALED_SIZE);
373379

@@ -404,9 +410,6 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
404410
tegra_plane_writel(plane, window->stride[0], DC_WIN_LINE_STRIDE);
405411
}
406412

407-
if (window->reflect_y)
408-
v_offset += window->src.h - 1;
409-
410413
tegra_plane_writel(plane, h_offset, DC_WINBUF_ADDR_H_OFFSET);
411414
tegra_plane_writel(plane, v_offset, DC_WINBUF_ADDR_V_OFFSET);
412415

@@ -470,6 +473,9 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
470473
value |= COLOR_EXPAND;
471474
}
472475

476+
if (window->reflect_x)
477+
value |= H_DIRECTION;
478+
473479
if (window->reflect_y)
474480
value |= V_DIRECTION;
475481

@@ -601,7 +607,10 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
601607
struct drm_plane_state *state)
602608
{
603609
struct tegra_plane_state *plane_state = to_tegra_plane_state(state);
604-
unsigned int rotation = DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y;
610+
unsigned int supported_rotation = DRM_MODE_ROTATE_0 |
611+
DRM_MODE_REFLECT_X |
612+
DRM_MODE_REFLECT_Y;
613+
unsigned int rotation = state->rotation;
605614
struct tegra_bo_tiling *tiling = &plane_state->tiling;
606615
struct tegra_plane *tegra = to_tegra_plane(plane);
607616
struct tegra_dc *dc = to_tegra_dc(state->crtc);
@@ -639,7 +648,21 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
639648
return -EINVAL;
640649
}
641650

642-
rotation = drm_rotation_simplify(state->rotation, rotation);
651+
/*
652+
* Older userspace used custom BO flag in order to specify the Y
653+
* reflection, while modern userspace uses the generic DRM rotation
654+
* property in order to achieve the same result. The legacy BO flag
655+
* duplicates the DRM rotation property when both are set.
656+
*/
657+
if (tegra_fb_is_bottom_up(state->fb))
658+
rotation |= DRM_MODE_REFLECT_Y;
659+
660+
rotation = drm_rotation_simplify(rotation, supported_rotation);
661+
662+
if (rotation & DRM_MODE_REFLECT_X)
663+
plane_state->reflect_x = true;
664+
else
665+
plane_state->reflect_x = false;
643666

644667
if (rotation & DRM_MODE_REFLECT_Y)
645668
plane_state->reflect_y = true;
@@ -706,7 +729,8 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
706729
window.dst.w = drm_rect_width(&plane->state->dst);
707730
window.dst.h = drm_rect_height(&plane->state->dst);
708731
window.bits_per_pixel = fb->format->cpp[0] * 8;
709-
window.reflect_y = tegra_fb_is_bottom_up(fb) || state->reflect_y;
732+
window.reflect_x = state->reflect_x;
733+
window.reflect_y = state->reflect_y;
710734

711735
/* copy from state */
712736
window.zpos = plane->state->normalized_zpos;
@@ -792,6 +816,7 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
792816
err = drm_plane_create_rotation_property(&plane->base,
793817
DRM_MODE_ROTATE_0,
794818
DRM_MODE_ROTATE_0 |
819+
DRM_MODE_REFLECT_X |
795820
DRM_MODE_REFLECT_Y);
796821
if (err < 0)
797822
dev_err(dc->dev, "failed to create rotation property: %d\n",
@@ -1080,6 +1105,7 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
10801105
err = drm_plane_create_rotation_property(&plane->base,
10811106
DRM_MODE_ROTATE_0,
10821107
DRM_MODE_ROTATE_0 |
1108+
DRM_MODE_REFLECT_X |
10831109
DRM_MODE_REFLECT_Y);
10841110
if (err < 0)
10851111
dev_err(dc->dev, "failed to create rotation property: %d\n",

drivers/gpu/drm/tegra/dc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ struct tegra_dc_window {
136136
unsigned int stride[2];
137137
unsigned long base[3];
138138
unsigned int zpos;
139+
bool reflect_x;
139140
bool reflect_y;
140141

141142
struct tegra_bo_tiling tiling;

drivers/gpu/drm/tegra/plane.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
6161
copy->tiling = state->tiling;
6262
copy->format = state->format;
6363
copy->swap = state->swap;
64+
copy->reflect_x = state->reflect_x;
6465
copy->reflect_y = state->reflect_y;
6566
copy->opaque = state->opaque;
6667

drivers/gpu/drm/tegra/plane.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct tegra_plane_state {
4646
u32 format;
4747
u32 swap;
4848

49+
bool reflect_x;
4950
bool reflect_y;
5051

5152
/* used for legacy blending support only */

0 commit comments

Comments
 (0)