summaryrefslogtreecommitdiff
path: root/drivers/media/video/tiler
diff options
context:
space:
mode:
authorLajos Molnar <molnar@ti.com>2011-04-07 08:41:40 +0100
committerAndy Green <andy.green@linaro.org>2011-04-07 08:41:40 +0100
commitcaffc47daba167c0b44ff8d83106f30776569286 (patch)
treef731b5d7464df600e55b09f991d8737a369b67b1 /drivers/media/video/tiler
parent8dacacbfbb26713b180161f96cf4b8393e457c57 (diff)
TILER: Better abstracted geometric manipulations.
Created tiler_view_t to abstract a view on a tiler 2d rectangle. Manipulations include crop, rotate and mirror, and provide access to horizontal and vertical increments to be used by other subsystems. Fixed issue with tiler_ops->xy that returned incorrect x, y coordinates (it returned them thinking of an x & y-mirrored view.) Simplified macro names in tiler-geom.c. Separated ioctl definitions in tiler.h. Signed-off-by: Lajos Molnar <molnar@ti.com> Signed-off-by: David Sin <davidsin@ti.com>
Diffstat (limited to 'drivers/media/video/tiler')
-rw-r--r--drivers/media/video/tiler/_tiler.h5
-rw-r--r--drivers/media/video/tiler/tiler-def.h1
-rw-r--r--drivers/media/video/tiler/tiler-geom.c258
-rw-r--r--drivers/media/video/tiler/tiler-main.c5
4 files changed, 163 insertions, 106 deletions
diff --git a/drivers/media/video/tiler/_tiler.h b/drivers/media/video/tiler/_tiler.h
index ab6bfec8cf5..a14d7ae0265 100644
--- a/drivers/media/video/tiler/_tiler.h
+++ b/drivers/media/video/tiler/_tiler.h
@@ -103,9 +103,8 @@ struct tiler_ops {
void (*cleanup) (void);
/* geometry operations */
- void (*xy) (u32 tsptr, u32 *x, u32 *y);
- u32 (*addr) (struct tiler_view_orient orient, enum tiler_fmt fmt,
- u32 x, u32 y);
+ void (*xy) (u32 ssptr, u32 *x, u32 *y);
+ u32 (*addr) (enum tiler_fmt fmt, u32 x, u32 y);
const struct tiler_geom * (*geom) (enum tiler_fmt fmt);
/* additional info */
diff --git a/drivers/media/video/tiler/tiler-def.h b/drivers/media/video/tiler/tiler-def.h
index 611b81dc60b..99b7a1f53bb 100644
--- a/drivers/media/video/tiler/tiler-def.h
+++ b/drivers/media/video/tiler/tiler-def.h
@@ -21,6 +21,5 @@
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define TILER_FORMATS (TILFMT_MAX - TILFMT_MIN + 1)
-#define TILER_ALIAS_BASE 0x60000000u
#endif
diff --git a/drivers/media/video/tiler/tiler-geom.c b/drivers/media/video/tiler/tiler-geom.c
index ba6db872814..b4b5a1e979f 100644
--- a/drivers/media/video/tiler/tiler-geom.c
+++ b/drivers/media/video/tiler/tiler-geom.c
@@ -1,18 +1,18 @@
/*
- * tiler_rot.c
- *
- * TILER driver support functions for TI OMAP processors.
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * This package is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
+* tiler_rot.c
+*
+* TILER driver support functions for TI OMAP processors.
+*
+* Copyright (C) 2009-2010 Texas Instruments, Inc.
+*
+* This package is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+*/
#include <linux/init.h>
#include <linux/module.h>
@@ -25,6 +25,9 @@
#define SLOT_WIDTH_BITS 6
#define SLOT_HEIGHT_BITS 6
+#define CONT_WIDTH_BITS 14
+#define CONT_HEIGHT_BITS 13
+
static struct tiler_geom geom[TILER_FORMATS] = {
{
.x_shft = 0,
@@ -44,13 +47,11 @@ static struct tiler_geom geom[TILER_FORMATS] = {
},
};
-#define DMM_ROTATION_SHIFT 31
-#define DMM_Y_INVERT_SHIFT 30
-#define DMM_X_INVERT_SHIFT 29
-#define DMM_ACC_MODE_SHIFT 27
-#define DMM_ACC_MODE_MASK 3
-#define CONT_WIDTH_BITS 14
-#define CONT_HEIGHT_BITS 13
+#define MASK_XY_FLIP (1 << 31)
+#define MASK_Y_INVERT (1 << 30)
+#define MASK_X_INVERT (1 << 29)
+#define SHIFT_ACC_MODE 27
+#define MASK_ACC_MODE 3
#define TILER_PAGE (1 << (SLOT_WIDTH_BITS + SLOT_HEIGHT_BITS))
#define TILER_WIDTH (1 << (CONT_WIDTH_BITS - SLOT_WIDTH_BITS))
@@ -61,37 +62,31 @@ static struct tiler_geom geom[TILER_FORMATS] = {
#define MASK(bits) ((1 << (bits)) - 1)
-#define TILER_GET_ACC_MODE(x) ((enum tiler_fmt) \
- ((x >> DMM_ACC_MODE_SHIFT) & DMM_ACC_MODE_MASK))
-#define DMM_IS_X_INVERTED(x) ((x >> DMM_X_INVERT_SHIFT) & 1)
-#define DMM_IS_Y_INVERTED(x) ((x >> DMM_Y_INVERT_SHIFT) & 1)
-#define DMM_IS_ROTATED(x) ((x >> DMM_ROTATION_SHIFT) & 1)
+#define TILER_FMT(x) ((enum tiler_fmt) \
+ ((x >> SHIFT_ACC_MODE) & MASK_ACC_MODE))
-#define DMM_ALIAS_VIEW_CLEAR (~((1 << DMM_X_INVERT_SHIFT) | \
- (1 << DMM_Y_INVERT_SHIFT) | (1 << DMM_ROTATION_SHIFT)))
+#define MASK_VIEW (MASK_X_INVERT | MASK_Y_INVERT | MASK_XY_FLIP)
-#define TILVIEW_8BIT TILER_ALIAS_BASE
+#define TILVIEW_8BIT 0x60000000u
#define TILVIEW_16BIT (TILVIEW_8BIT + VIEW_SIZE)
#define TILVIEW_32BIT (TILVIEW_16BIT + VIEW_SIZE)
#define TILVIEW_PAGE (TILVIEW_32BIT + VIEW_SIZE)
#define TILVIEW_END (TILVIEW_PAGE + VIEW_SIZE)
-#define TIL_ADDR(x, r, yi, xi, a)\
- ((u32) x | (((r) ? 1 : 0) << DMM_ROTATION_SHIFT) | \
- (((yi) ? 1 : 0) << DMM_Y_INVERT_SHIFT) | \
- (((xi) ? 1 : 0) << DMM_X_INVERT_SHIFT) | ((a) << DMM_ACC_MODE_SHIFT))
+#define TIL_ADDR(x, orient, a)\
+ ((u32) (x) | (orient) | ((a) << SHIFT_ACC_MODE))
/*
- * TILER Memory model query method
- */
+* TILER Memory model query method
+*/
bool is_tiler_addr(u32 phys)
{
return phys >= TILVIEW_8BIT && phys < TILVIEW_END;
}
/*
- * TILER block query method
- */
+* TILER block query method
+*/
u32 tiler_bpp(const struct tiler_block_t *b)
{
@@ -103,14 +98,16 @@ u32 tiler_bpp(const struct tiler_block_t *b)
}
EXPORT_SYMBOL(tiler_bpp);
-static inline u32 tiler_stride(enum tiler_fmt fmt, bool rotated)
+static inline s32 tiler_stride(u32 tsptr)
{
+ enum tiler_fmt fmt = TILER_FMT(tsptr);
+
if (fmt == TILFMT_PAGE)
return 0;
-
- return rotated ?
- 1 << (CONT_HEIGHT_BITS + geom[fmt].x_shft) :
- 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
+ else if (tsptr & MASK_XY_FLIP)
+ return 1 << (CONT_HEIGHT_BITS + geom[fmt].x_shft);
+ else
+ return 1 << (CONT_WIDTH_BITS + geom[fmt].y_shft);
}
u32 tiler_pstride(const struct tiler_block_t *b)
@@ -122,7 +119,7 @@ u32 tiler_pstride(const struct tiler_block_t *b)
if (fmt == TILFMT_PAGE)
return tiler_vstride(b);
- return tiler_stride(fmt, 0);
+ return tiler_stride(b->phys & ~MASK_VIEW);
}
EXPORT_SYMBOL(tiler_pstride);
@@ -131,7 +128,7 @@ enum tiler_fmt tiler_fmt(u32 phys)
if (!is_tiler_addr(phys))
return TILFMT_INVALID;
- return TILER_GET_ACC_MODE(phys);
+ return TILER_FMT(phys);
}
EXPORT_SYMBOL(tiler_fmt);
@@ -147,13 +144,13 @@ static void tiler_get_natural_xy(u32 tsptr, u32 *x, u32 *y)
u32 x_bits, y_bits, offset;
enum tiler_fmt fmt;
- fmt = TILER_GET_ACC_MODE(tsptr);
+ fmt = TILER_FMT(tsptr);
x_bits = CONT_WIDTH_BITS - geom[fmt].x_shft;
y_bits = CONT_HEIGHT_BITS - geom[fmt].y_shft;
offset = (tsptr & VIEW_MASK) >> (geom[fmt].x_shft + geom[fmt].y_shft);
- if (DMM_IS_ROTATED(tsptr)) {
+ if (tsptr & MASK_XY_FLIP) {
*x = offset >> y_bits;
*y = offset & MASK(y_bits);
} else {
@@ -161,14 +158,13 @@ static void tiler_get_natural_xy(u32 tsptr, u32 *x, u32 *y)
*y = offset >> x_bits;
}
- if (DMM_IS_X_INVERTED(tsptr))
+ if (tsptr & MASK_X_INVERT)
*x ^= MASK(x_bits);
- if (DMM_IS_Y_INVERTED(tsptr))
+ if (tsptr & MASK_Y_INVERT)
*y ^= MASK(y_bits);
}
-static u32 tiler_get_address(struct tiler_view_orient orient,
- enum tiler_fmt fmt, u32 x, u32 y)
+static u32 tiler_get_address(u32 orient, enum tiler_fmt fmt, u32 x, u32 y)
{
u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment;
@@ -181,90 +177,154 @@ static u32 tiler_get_address(struct tiler_view_orient orient,
if (x < 0 || x > x_mask || y < 0 || y > y_mask)
return 0;
- if (orient.x_invert)
+ if (orient & MASK_X_INVERT)
x ^= x_mask;
- if (orient.y_invert)
+ if (orient & MASK_Y_INVERT)
y ^= y_mask;
- if (orient.rotate_90)
+ if (orient & MASK_XY_FLIP)
tmp = ((x << y_bits) + y);
else
tmp = ((y << x_bits) + x);
- return TIL_ADDR((tmp << alignment), orient.rotate_90,
- orient.y_invert, orient.x_invert, fmt);
+ return TIL_ADDR((tmp << alignment), orient, fmt);
}
-u32 tiler_reorient_addr(u32 tsptr, struct tiler_view_orient orient)
+void tilview_get(struct tiler_view_t *view, struct tiler_block_t *blk)
{
- u32 x, y;
-
- tiler_get_natural_xy(tsptr, &x, &y);
- return tiler_get_address(orient, TILER_GET_ACC_MODE(tsptr), x, y);
+ view->tsptr = blk->phys & ~MASK_VIEW;
+ view->bpp = tiler_bpp(blk);
+ view->width = blk->width;
+ view->height = blk->height;
+ view->h_inc = view->bpp;
+ view->v_inc = tiler_stride(view->tsptr);
}
-EXPORT_SYMBOL(tiler_reorient_addr);
+EXPORT_SYMBOL(tilview_get);
-u32 tiler_get_natural_addr(void *sys_ptr)
+s32 tilview_crop(struct tiler_view_t *view, u32 left, u32 top, u32 width,
+ u32 height)
{
- return (u32)sys_ptr & DMM_ALIAS_VIEW_CLEAR;
+ /* check for valid crop */
+ if (left + width < left || left + width > view->width ||
+ top + height < top || top + height > view->height)
+ return -EINVAL;
+
+ view->tsptr += left * view->h_inc + top * view->v_inc;
+ view->width = width;
+ view->height = height;
+ return 0;
}
-EXPORT_SYMBOL(tiler_get_natural_addr);
+EXPORT_SYMBOL(tilview_crop);
-u32 tiler_topleft(u32 tsptr, u32 width, u32 height)
+/* adjust view orientation after top-left has been adjusted */
+static void reorient(struct tiler_view_t *view, u32 orient)
{
u32 x, y;
- enum tiler_fmt fmt = TILER_GET_ACC_MODE(tsptr);
- struct tiler_view_orient orient;
- orient.x_invert = DMM_IS_X_INVERTED(tsptr);
- orient.y_invert = DMM_IS_Y_INVERTED(tsptr);
- orient.rotate_90 = DMM_IS_ROTATED(tsptr);
-
- tiler_get_natural_xy(tsptr, &x, &y);
-
- if (DMM_IS_X_INVERTED(tsptr))
- x += width - 1;
- if (DMM_IS_Y_INVERTED(tsptr))
- y += height - 1;
-
- return tiler_get_address(orient, fmt, x, y);
+ tiler_get_natural_xy(view->tsptr, &x, &y);
+ view->tsptr = tiler_get_address(orient,
+ TILER_FMT(view->tsptr), x, y);
+ view->v_inc = tiler_stride(view->tsptr);
}
-EXPORT_SYMBOL(tiler_topleft);
-u32 tiler_offset_addr(u32 tsptr, u32 x, u32 y)
+s32 tilview_rotate(struct tiler_view_t *view, s32 rotation)
{
- enum tiler_fmt fmt = TILER_GET_ACC_MODE(tsptr);
- bool rotated = DMM_IS_ROTATED(tsptr);
+ u32 orient;
- return tsptr + x * geom[fmt].bpp_m + y * tiler_stride(fmt, rotated);
-}
-EXPORT_SYMBOL(tiler_offset_addr);
+ if (rotation % 90)
+ return -EINVAL;
-void tiler_rotate_view(struct tiler_view_orient *orient, u32 rotation)
-{
+ /* normalize rotation to quarters */
rotation = (rotation / 90) & 3;
-
+ if (!rotation)
+ return 0; /* nothing to do */
+
+ /* PAGE mode view cannot be rotated */
+ if (TILER_FMT(view->tsptr) == TILFMT_PAGE)
+ return -EPERM;
+
+ /*
+ * first adjust top-left corner. NOTE: it rotates counter-clockwise:
+ * 0 < 3
+ * v ^
+ * 1 > 2
+ */
+ if (rotation < 3)
+ view->tsptr += (view->height - 1) * view->v_inc;
+ if (rotation > 1)
+ view->tsptr += (view->width - 1) * view->h_inc;
+
+ /* then rotate view itself */
+ orient = view->tsptr & MASK_VIEW;
+
+ /* rotate first 2 quarters */
if (rotation & 2) {
- orient->x_invert = !orient->x_invert;
- orient->y_invert = !orient->y_invert;
+ orient ^= MASK_X_INVERT;
+ orient ^= MASK_Y_INVERT;
}
+ /* rotate last quarter */
if (rotation & 1) {
- if (orient->rotate_90)
- orient->y_invert = !orient->y_invert;
- else
- orient->x_invert = !orient->x_invert;
- orient->rotate_90 = !orient->rotate_90;
+ orient ^= (orient & MASK_XY_FLIP) ?
+ MASK_Y_INVERT : MASK_X_INVERT;
+
+ /* swap x & y */
+ orient ^= MASK_XY_FLIP;
+ swap(view->height, view->width);
}
+
+ /* finally reorient view */
+ reorient(view, orient);
+ return 0;
+}
+EXPORT_SYMBOL(tilview_rotate);
+
+s32 tilview_flip(struct tiler_view_t *view, bool flip_x, bool flip_y)
+{
+ u32 orient;
+ orient = view->tsptr & MASK_VIEW;
+
+ if (!flip_x && !flip_y)
+ return 0; /* nothing to do */
+
+ /* PAGE mode view cannot be flipped */
+ if (TILER_FMT(view->tsptr) == TILFMT_PAGE)
+ return -EPERM;
+
+ /* adjust top-left corner */
+ if (flip_x) {
+ orient ^= MASK_X_INVERT;
+ view->tsptr += (view->width - 1) * view->h_inc;
+ }
+ if (flip_y) {
+ orient ^= MASK_Y_INVERT;
+ view->tsptr += (view->height - 1) * view->v_inc;
+ }
+
+ /* finally reorient view */
+ reorient(view, orient);
+ return 0;
+}
+EXPORT_SYMBOL(tilview_flip);
+
+/* return the alias address for a coordinate */
+static inline u32 alias_address(enum tiler_fmt fmt, u32 x, u32 y)
+{
+ return tiler_get_address(0, fmt, x, y) + TILVIEW_8BIT;
+}
+
+/* get the coordinates for an alias address */
+static inline void alias_xy(u32 ssptr, u32 *x, u32 *y)
+{
+ tiler_get_natural_xy(ssptr & ~MASK_VIEW, x, y);
}
-EXPORT_SYMBOL(tiler_rotate_view);
void tiler_geom_init(struct tiler_ops *tiler)
{
struct tiler_geom *g;
- tiler->xy = tiler_get_natural_xy;
- tiler->addr = tiler_get_address;
+ tiler->xy = alias_xy;
+ tiler->addr = alias_address;
tiler->geom = get_geom;
tiler->page = TILER_PAGE;
diff --git a/drivers/media/video/tiler/tiler-main.c b/drivers/media/video/tiler/tiler-main.c
index ff05e2d356c..eef958a3881 100644
--- a/drivers/media/video/tiler/tiler-main.c
+++ b/drivers/media/video/tiler/tiler-main.c
@@ -839,7 +839,6 @@ static struct mem_info *__get_area(enum tiler_fmt fmt, u32 width, u32 height,
{
u16 x, y, band, in_offs = 0;
struct mem_info *mi = NULL;
- struct tiler_view_orient orient = {0};
const struct tiler_geom *g = tiler.geom(fmt);
/* calculate dimensions, band, offs and alignment in slots */
@@ -876,9 +875,9 @@ static struct mem_info *__get_area(enum tiler_fmt fmt, u32 width, u32 height,
gi->refs--;
mutex_unlock(&mtx);
- mi->blk.phys = tiler.addr(orient, fmt,
+ mi->blk.phys = tiler.addr(fmt,
mi->area.p0.x * g->slot_w, mi->area.p0.y * g->slot_h)
- + TILER_ALIAS_BASE + in_offs;
+ + in_offs;
return mi;
}