Commit cd740777 authored by Dmitry Osipenko's avatar Dmitry Osipenko Committed by Thierry Reding

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: default avatarDmitry Osipenko <digetx@gmail.com>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent e9e476f7
...@@ -368,6 +368,12 @@ static void tegra_dc_setup_window(struct tegra_plane *plane, ...@@ -368,6 +368,12 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
h_size = window->src.w * bpp; h_size = window->src.w * bpp;
v_size = window->src.h; v_size = window->src.h;
if (window->reflect_x)
h_offset += (window->src.w - 1) * bpp;
if (window->reflect_y)
v_offset += window->src.h - 1;
value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size); value = V_PRESCALED_SIZE(v_size) | H_PRESCALED_SIZE(h_size);
tegra_plane_writel(plane, value, DC_WIN_PRESCALED_SIZE); tegra_plane_writel(plane, value, DC_WIN_PRESCALED_SIZE);
...@@ -404,9 +410,6 @@ static void tegra_dc_setup_window(struct tegra_plane *plane, ...@@ -404,9 +410,6 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
tegra_plane_writel(plane, window->stride[0], DC_WIN_LINE_STRIDE); tegra_plane_writel(plane, window->stride[0], DC_WIN_LINE_STRIDE);
} }
if (window->reflect_y)
v_offset += window->src.h - 1;
tegra_plane_writel(plane, h_offset, DC_WINBUF_ADDR_H_OFFSET); tegra_plane_writel(plane, h_offset, DC_WINBUF_ADDR_H_OFFSET);
tegra_plane_writel(plane, v_offset, DC_WINBUF_ADDR_V_OFFSET); tegra_plane_writel(plane, v_offset, DC_WINBUF_ADDR_V_OFFSET);
...@@ -470,6 +473,9 @@ static void tegra_dc_setup_window(struct tegra_plane *plane, ...@@ -470,6 +473,9 @@ static void tegra_dc_setup_window(struct tegra_plane *plane,
value |= COLOR_EXPAND; value |= COLOR_EXPAND;
} }
if (window->reflect_x)
value |= H_DIRECTION;
if (window->reflect_y) if (window->reflect_y)
value |= V_DIRECTION; value |= V_DIRECTION;
...@@ -601,7 +607,10 @@ static int tegra_plane_atomic_check(struct drm_plane *plane, ...@@ -601,7 +607,10 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state) struct drm_plane_state *state)
{ {
struct tegra_plane_state *plane_state = to_tegra_plane_state(state); struct tegra_plane_state *plane_state = to_tegra_plane_state(state);
unsigned int rotation = DRM_MODE_ROTATE_0 | DRM_MODE_REFLECT_Y; unsigned int supported_rotation = DRM_MODE_ROTATE_0 |
DRM_MODE_REFLECT_X |
DRM_MODE_REFLECT_Y;
unsigned int rotation = state->rotation;
struct tegra_bo_tiling *tiling = &plane_state->tiling; struct tegra_bo_tiling *tiling = &plane_state->tiling;
struct tegra_plane *tegra = to_tegra_plane(plane); struct tegra_plane *tegra = to_tegra_plane(plane);
struct tegra_dc *dc = to_tegra_dc(state->crtc); struct tegra_dc *dc = to_tegra_dc(state->crtc);
...@@ -639,7 +648,21 @@ static int tegra_plane_atomic_check(struct drm_plane *plane, ...@@ -639,7 +648,21 @@ static int tegra_plane_atomic_check(struct drm_plane *plane,
return -EINVAL; return -EINVAL;
} }
rotation = drm_rotation_simplify(state->rotation, rotation); /*
* Older userspace used custom BO flag in order to specify the Y
* reflection, while modern userspace uses the generic DRM rotation
* property in order to achieve the same result. The legacy BO flag
* duplicates the DRM rotation property when both are set.
*/
if (tegra_fb_is_bottom_up(state->fb))
rotation |= DRM_MODE_REFLECT_Y;
rotation = drm_rotation_simplify(rotation, supported_rotation);
if (rotation & DRM_MODE_REFLECT_X)
plane_state->reflect_x = true;
else
plane_state->reflect_x = false;
if (rotation & DRM_MODE_REFLECT_Y) if (rotation & DRM_MODE_REFLECT_Y)
plane_state->reflect_y = true; plane_state->reflect_y = true;
...@@ -706,7 +729,8 @@ static void tegra_plane_atomic_update(struct drm_plane *plane, ...@@ -706,7 +729,8 @@ static void tegra_plane_atomic_update(struct drm_plane *plane,
window.dst.w = drm_rect_width(&plane->state->dst); window.dst.w = drm_rect_width(&plane->state->dst);
window.dst.h = drm_rect_height(&plane->state->dst); window.dst.h = drm_rect_height(&plane->state->dst);
window.bits_per_pixel = fb->format->cpp[0] * 8; window.bits_per_pixel = fb->format->cpp[0] * 8;
window.reflect_y = tegra_fb_is_bottom_up(fb) || state->reflect_y; window.reflect_x = state->reflect_x;
window.reflect_y = state->reflect_y;
/* copy from state */ /* copy from state */
window.zpos = plane->state->normalized_zpos; window.zpos = plane->state->normalized_zpos;
...@@ -792,6 +816,7 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm, ...@@ -792,6 +816,7 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
err = drm_plane_create_rotation_property(&plane->base, err = drm_plane_create_rotation_property(&plane->base,
DRM_MODE_ROTATE_0, DRM_MODE_ROTATE_0,
DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_0 |
DRM_MODE_REFLECT_X |
DRM_MODE_REFLECT_Y); DRM_MODE_REFLECT_Y);
if (err < 0) if (err < 0)
dev_err(dc->dev, "failed to create rotation property: %d\n", 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, ...@@ -1080,6 +1105,7 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
err = drm_plane_create_rotation_property(&plane->base, err = drm_plane_create_rotation_property(&plane->base,
DRM_MODE_ROTATE_0, DRM_MODE_ROTATE_0,
DRM_MODE_ROTATE_0 | DRM_MODE_ROTATE_0 |
DRM_MODE_REFLECT_X |
DRM_MODE_REFLECT_Y); DRM_MODE_REFLECT_Y);
if (err < 0) if (err < 0)
dev_err(dc->dev, "failed to create rotation property: %d\n", dev_err(dc->dev, "failed to create rotation property: %d\n",
......
...@@ -136,6 +136,7 @@ struct tegra_dc_window { ...@@ -136,6 +136,7 @@ struct tegra_dc_window {
unsigned int stride[2]; unsigned int stride[2];
unsigned long base[3]; unsigned long base[3];
unsigned int zpos; unsigned int zpos;
bool reflect_x;
bool reflect_y; bool reflect_y;
struct tegra_bo_tiling tiling; struct tegra_bo_tiling tiling;
......
...@@ -61,6 +61,7 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane) ...@@ -61,6 +61,7 @@ tegra_plane_atomic_duplicate_state(struct drm_plane *plane)
copy->tiling = state->tiling; copy->tiling = state->tiling;
copy->format = state->format; copy->format = state->format;
copy->swap = state->swap; copy->swap = state->swap;
copy->reflect_x = state->reflect_x;
copy->reflect_y = state->reflect_y; copy->reflect_y = state->reflect_y;
copy->opaque = state->opaque; copy->opaque = state->opaque;
......
...@@ -46,6 +46,7 @@ struct tegra_plane_state { ...@@ -46,6 +46,7 @@ struct tegra_plane_state {
u32 format; u32 format;
u32 swap; u32 swap;
bool reflect_x;
bool reflect_y; bool reflect_y;
/* used for legacy blending support only */ /* used for legacy blending support only */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment