lkml.org 
[lkml]   [2010]   [Nov]   [30]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[RFC v2 6/8] TILER-DMM: Geometry and view manipulation functions
    Date
    From: Lajos Molnar <molnar@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 <molnar@ti.com>
    Signed-off-by: David Sin <davidsin@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


    \
     
     \ /
      Last update: 2010-11-30 20:49    [W:0.043 / U:149.604 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site