summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/sun4i/sun4i_frontend.c
diff options
context:
space:
mode:
authorPaul Kocialkowski <paul.kocialkowski@bootlin.com>2019-01-18 15:51:23 +0100
committerMaxime Ripard <maxime.ripard@bootlin.com>2019-01-18 19:17:31 +0100
commit9042e3fb7e22d04420fbb6607879ae2365e947a0 (patch)
tree8f083fc4af7f0c625284f78f516c5fa7fe441ca4 /drivers/gpu/drm/sun4i/sun4i_frontend.c
parent172b789977acb79734802b7722bd12d4c7973c7b (diff)
drm/sun4i: Add buffer stride and offset configuration for tiling mode
This introduces stride and offset configuration for the VPU tiling mode. Stride is calculated differently than it is for linear formats and an offset is calculated, for which new register definitions are introduced. Signed-off-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com> Acked-by: Maxime Ripard <maxime.ripard@bootlin.com> Signed-off-by: Maxime Ripard <maxime.ripard@bootlin.com> Link: https://patchwork.freedesktop.org/patch/msgid/20190118145133.21281-14-paul.kocialkowski@bootlin.com
Diffstat (limited to 'drivers/gpu/drm/sun4i/sun4i_frontend.c')
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_frontend.c49
1 files changed, 46 insertions, 3 deletions
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c
index e950370792ce..6ede40aab515 100644
--- a/drivers/gpu/drm/sun4i/sun4i_frontend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c
@@ -126,21 +126,64 @@ void sun4i_frontend_update_buffer(struct sun4i_frontend *frontend,
{
struct drm_plane_state *state = plane->state;
struct drm_framebuffer *fb = state->fb;
+ unsigned int strides[3] = {};
+
dma_addr_t paddr;
bool swap;
+ if (fb->modifier == DRM_FORMAT_MOD_ALLWINNER_TILED) {
+ unsigned int width = state->src_w >> 16;
+ unsigned int offset;
+
+ strides[0] = SUN4I_FRONTEND_LINESTRD_TILED(fb->pitches[0]);
+
+ /*
+ * The X1 offset is the offset to the bottom-right point in the
+ * end tile, which is the final pixel (at offset width - 1)
+ * within the end tile (with a 32-byte mask).
+ */
+ offset = (width - 1) & (32 - 1);
+
+ regmap_write(frontend->regs, SUN4I_FRONTEND_TB_OFF0_REG,
+ SUN4I_FRONTEND_TB_OFF_X1(offset));
+
+ if (fb->format->num_planes > 1) {
+ strides[1] =
+ SUN4I_FRONTEND_LINESTRD_TILED(fb->pitches[1]);
+
+ regmap_write(frontend->regs, SUN4I_FRONTEND_TB_OFF1_REG,
+ SUN4I_FRONTEND_TB_OFF_X1(offset));
+ }
+
+ if (fb->format->num_planes > 2) {
+ strides[2] =
+ SUN4I_FRONTEND_LINESTRD_TILED(fb->pitches[2]);
+
+ regmap_write(frontend->regs, SUN4I_FRONTEND_TB_OFF2_REG,
+ SUN4I_FRONTEND_TB_OFF_X1(offset));
+ }
+ } else {
+ strides[0] = fb->pitches[0];
+
+ if (fb->format->num_planes > 1)
+ strides[1] = fb->pitches[1];
+
+ if (fb->format->num_planes > 2)
+ strides[2] = fb->pitches[2];
+ }
+
/* Set the line width */
DRM_DEBUG_DRIVER("Frontend stride: %d bytes\n", fb->pitches[0]);
regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD0_REG,
- fb->pitches[0]);
+ strides[0]);
if (fb->format->num_planes > 1)
regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD1_REG,
- fb->pitches[1]);
+ strides[1]);
if (fb->format->num_planes > 2)
regmap_write(frontend->regs, SUN4I_FRONTEND_LINESTRD2_REG,
- fb->pitches[2]);
+ strides[2]);
/* Some planar formats require chroma channel swapping by hand. */
swap = sun4i_frontend_format_chroma_requires_swap(fb->format->format);