From: Lajos Molnar <mol...@ti.com>

This patch contains information on TILER geometry, as well as
tiler_view_t object manipulation functions.

It also contains an internal TILER header file to share geometric
information with other TILER files.

Signed-off-by: Lajos Molnar <mol...@ti.com>
Signed-off-by: David Sin <david...@ti.com>
---
 drivers/misc/tiler/_tiler.h     |   48 +++++
 drivers/misc/tiler/tiler-geom.c |  362 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 410 insertions(+), 0 deletions(-)
 create mode 100644 drivers/misc/tiler/_tiler.h
 create mode 100644 drivers/misc/tiler/tiler-geom.c

diff --git a/drivers/misc/tiler/_tiler.h b/drivers/misc/tiler/_tiler.h
new file mode 100644
index 0000000..0f00330
--- /dev/null
+++ b/drivers/misc/tiler/_tiler.h
@@ -0,0 +1,48 @@
+/*
+ * TI TILER driver internal shared definitions.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _TILER_H
+#define _TILER_H
+
+#include <linux/kernel.h>
+#include <mach/tiler.h>
+#include "tcm.h"
+
+#define TILER_FORMATS          (TILFMT_MAX - TILFMT_MIN + 1)
+
+/* tiler geometry information */
+struct tiler_geom {
+       u32 x_shft;     /* unused X-bits (as part of bpp) */
+       u32 y_shft;     /* unused Y-bits (as part of bpp) */
+       u32 bpp;        /* bytes per pixel */
+       u32 slot_w;     /* width of each slot (in pixels) */
+       u32 slot_h;     /* height of each slot (in pixels) */
+};
+
+/* methods and variables shared between source files */
+struct tiler_ops {
+       /* geometry operations */
+       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);
+
+       u32 page;               /* page size */
+       u32 width;              /* container width */
+       u32 height;             /* container height */
+};
+
+void tiler_geom_init(struct tiler_ops *tiler);
+
+#endif
diff --git a/drivers/misc/tiler/tiler-geom.c b/drivers/misc/tiler/tiler-geom.c
new file mode 100644
index 0000000..df5fe2c
--- /dev/null
+++ b/drivers/misc/tiler/tiler-geom.c
@@ -0,0 +1,362 @@
+/*
+ * TILER geometry functions for TI TILER hardware block.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include "_tiler.h"
+
+/* bits representing the same slot in DMM-TILER hw-block */
+#define SLOT_WIDTH_BITS                6
+#define SLOT_HEIGHT_BITS       6
+
+/* bits reserved to describe coordinates in DMM-TILER hw-block */
+#define CONT_WIDTH_BITS                14
+#define CONT_HEIGHT_BITS       13
+
+static struct tiler_geom geom[TILER_FORMATS] = {
+       {
+               .x_shft = 0,
+               .y_shft = 0,
+       },
+       {
+               .x_shft = 0,
+               .y_shft = 1,
+       },
+       {
+               .x_shft = 1,
+               .y_shft = 1,
+       },
+};
+
+/* tiler space addressing bitfields */
+#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
+
+/* calculated constants */
+#define TILER_PAGE             (1 << (SLOT_WIDTH_BITS + SLOT_HEIGHT_BITS))
+#define TILER_WIDTH            (1 << (CONT_WIDTH_BITS - SLOT_WIDTH_BITS))
+#define TILER_HEIGHT           (1 << (CONT_HEIGHT_BITS - SLOT_HEIGHT_BITS))
+
+#define VIEW_SIZE              (1u << (CONT_WIDTH_BITS + CONT_HEIGHT_BITS))
+#define VIEW_MASK              (VIEW_SIZE - 1u)
+
+#define MASK(bits) ((1 << (bits)) - 1)
+
+#define TILER_FMT(x)   ((enum tiler_fmt) \
+               ((x >> SHIFT_ACC_MODE) & MASK_ACC_MODE))
+
+#define MASK_VIEW              (MASK_X_INVERT | MASK_Y_INVERT | MASK_XY_FLIP)
+
+/* location of the various tiler views in physical address space */
+#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)
+
+/* create tsptr by adding view orientation and access mode */
+#define TIL_ADDR(x, orient, a)\
+       ((u32) (x) | (orient) | ((a) << SHIFT_ACC_MODE))
+
+bool is_tiler_addr(u32 phys)
+{
+       return phys >= TILVIEW_8BIT && phys < TILVIEW_END;
+}
+EXPORT_SYMBOL(is_tiler_addr);
+
+u32 tiler_bpp(const struct tiler_block_t *b)
+{
+       enum tiler_fmt fmt = tiler_fmt(b->phys);
+       BUG_ON(fmt == TILFMT_INVALID || fmt == TILFMT_PAGE);
+
+       return geom[fmt].bpp;
+}
+EXPORT_SYMBOL(tiler_bpp);
+
+/* return the stride of a tiler-block in tiler space */
+static inline s32 tiler_stride(u32 tsptr)
+{
+       enum tiler_fmt fmt = TILER_FMT(tsptr);
+
+       if (fmt == TILFMT_PAGE)
+               return 0;
+       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)
+{
+       enum tiler_fmt fmt = tiler_fmt(b->phys);
+       BUG_ON(fmt == TILFMT_INVALID);
+
+       /* return the virtual stride for page mode */
+       if (fmt == TILFMT_PAGE)
+               return tiler_vstride(b);
+
+       return tiler_stride(b->phys & ~MASK_VIEW);
+}
+EXPORT_SYMBOL(tiler_pstride);
+
+enum tiler_fmt tiler_fmt(u32 phys)
+{
+       if (!is_tiler_addr(phys))
+               return TILFMT_INVALID;
+
+       return TILER_FMT(phys);
+}
+EXPORT_SYMBOL(tiler_fmt);
+
+/* returns the tiler geometry information for a format */
+static const struct tiler_geom *get_geom(enum tiler_fmt fmt)
+{
+       if (fmt >= TILFMT_MIN && fmt <= TILFMT_MAX)
+               return geom + fmt;
+       return NULL;
+}
+
+/*
+ * Returns the natural x and y coordinates for a pixel in tiler space address.
+ * That is, the coordinates for the same pixel in the natural (non-rotated,
+ * non-mirrored) view. This allows to uniquely identify a tiler pixel in any
+ * view orientation.
+ */
+static void tiler_get_natural_xy(u32 tsptr, u32 *x, u32 *y)
+{
+       u32 x_bits, y_bits, offset;
+       enum tiler_fmt fmt;
+
+       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);
+
+       /* separate coordinate bitfields based on view orientation */
+       if (tsptr & MASK_XY_FLIP) {
+               *x = offset >> y_bits;
+               *y = offset & MASK(y_bits);
+       } else {
+               *x = offset & MASK(x_bits);
+               *y = offset >> x_bits;
+       }
+
+       /* account for mirroring */
+       if (tsptr & MASK_X_INVERT)
+               *x ^= MASK(x_bits);
+       if (tsptr & MASK_Y_INVERT)
+               *y ^= MASK(y_bits);
+}
+
+/* calculate the tiler space address of a pixel in a view orientation */
+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;
+
+       x_bits = CONT_WIDTH_BITS - geom[fmt].x_shft;
+       y_bits = CONT_HEIGHT_BITS - geom[fmt].y_shft;
+       alignment = geom[fmt].x_shft + geom[fmt].y_shft;
+
+       /* validate coordinate */
+       x_mask = MASK(x_bits);
+       y_mask = MASK(y_bits);
+       if (x < 0 || x > x_mask || y < 0 || y > y_mask)
+               return 0;
+
+       /* account for mirroring */
+       if (orient & MASK_X_INVERT)
+               x ^= x_mask;
+       if (orient & MASK_Y_INVERT)
+               y ^= y_mask;
+
+       /* get coordinate address */
+       if (orient & MASK_XY_FLIP)
+               tmp = ((x << y_bits) + y);
+       else
+               tmp = ((y << x_bits) + x);
+
+       return TIL_ADDR((tmp << alignment), orient, fmt);
+}
+
+void tilview_create(struct tiler_view_t *view, u32 phys, u32 width, u32 height)
+{
+       BUG_ON(!is_tiler_addr(phys));
+
+       view->tsptr = phys & ~MASK_VIEW;
+       view->bpp = geom[TILER_FMT(phys)].bpp;
+       view->width = width;
+       view->height = height;
+       view->h_inc = view->bpp;
+       view->v_inc = tiler_stride(view->tsptr);
+}
+EXPORT_SYMBOL(tilview_create);
+
+void tilview_get(struct tiler_view_t *view, struct tiler_block_t *blk)
+{
+       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(tilview_get);
+
+s32 tilview_crop(struct tiler_view_t *view, u32 left, u32 top, u32 width,
+                                                               u32 height)
+{
+       /* 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(tilview_crop);
+
+/* calculate tilerspace address and stride after view orientation change */
+static void reorient(struct tiler_view_t *view, u32 orient)
+{
+       u32 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);
+}
+
+s32 tilview_rotate(struct tiler_view_t *view, s32 rotation)
+{
+       u32 orient;
+
+       if (rotation % 90)
+               return -EINVAL;
+
+       /* 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 ^= MASK_X_INVERT;
+               orient ^= MASK_Y_INVERT;
+       }
+
+       /* rotate last quarter */
+       if (rotation & 1) {
+               orient ^= (orient & MASK_XY_FLIP) ?
+                       MASK_X_INVERT : MASK_Y_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)
+               view->tsptr += (view->width - 1) * view->h_inc;
+       if (flip_y)
+               view->tsptr += (view->height - 1) * view->v_inc;
+
+       /* flip view orientation */
+       if (orient & MASK_XY_FLIP)
+               swap(flip_x, flip_y);
+
+       if (flip_x)
+               orient ^= MASK_X_INVERT;
+       if (flip_y)
+               orient ^= MASK_Y_INVERT;
+
+       /* 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);
+}
+
+/* initialize shared geometric data */
+void tiler_geom_init(struct tiler_ops *tiler)
+{
+       struct tiler_geom *g;
+
+       tiler->xy = alias_xy;
+       tiler->addr = alias_address;
+       tiler->geom = get_geom;
+
+       tiler->page   = TILER_PAGE;
+       tiler->width  = TILER_WIDTH;
+       tiler->height = TILER_HEIGHT;
+
+       /* calculate geometry */
+       for (g = geom; g < geom + TILER_FORMATS; g++) {
+               g->bpp = 1 << (g->x_shft + g->y_shft);
+               g->slot_w = 1 << (SLOT_WIDTH_BITS - g->x_shft);
+               g->slot_h = 1 << (SLOT_HEIGHT_BITS - g->y_shft);
+       }
+}
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to