From: Lajos Molnar <molnar@xxxxxx> 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 <molnar@xxxxxx> Signed-off-by: David Sin <davidsin@xxxxxx> --- drivers/media/video/tiler/_tiler.h | 51 +++++ drivers/media/video/tiler/tiler-geom.c | 360 ++++++++++++++++++++++++++++++++ 2 files changed, 411 insertions(+), 0 deletions(-) create mode 100644 drivers/media/video/tiler/_tiler.h create mode 100644 drivers/media/video/tiler/tiler-geom.c diff --git a/drivers/media/video/tiler/_tiler.h b/drivers/media/video/tiler/_tiler.h new file mode 100644 index 0000000..38fff3b --- /dev/null +++ b/drivers/media/video/tiler/_tiler.h @@ -0,0 +1,51 @@ +/* + * _tiler.h + * + * TI TILER driver internal shared definitions. + * + * Author: Lajos Molnar <molnar@xxxxxx> + * + * 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. + */ + +#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/media/video/tiler/tiler-geom.c b/drivers/media/video/tiler/tiler-geom.c new file mode 100644 index 0000000..619413f --- /dev/null +++ b/drivers/media/video/tiler/tiler-geom.c @@ -0,0 +1,360 @@ +/* + * tiler-geom.c + * + * TILER geometry functions for TI TILER hardware block. + * + * Author: Lajos Molnar <molnar@xxxxxx> + * + * 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/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) { + 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); +} + +/* 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.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html