2010-12-06 22:16:02

by David Sin

[permalink] [raw]
Subject: [PATCH 0/9] TI DMM-TILER driver

Tiling and Isometric Lightweight Engine for Rotation (TILER) driver
=====

Dynamic Memory Manager (DMM) is a hardware block made by Texas Instruments.
Within the DMM exists at least one TILER hardware component. Its purpose is to
organize video/image memory in a 2-dimensional fashion to limit memory
bandwidth and facilitate 0 effort rotation and mirroring. The TILER driver
facilitates allocating, freeing, as well as mapping 2D blocks (areas) in the
TILER container(s). It also facilitates rotating and mirroring the allocated
blocks or its rectangular subsections.

TERMINOLOGY

"slot"

The basic TILER driver operates on blocks of slots. A slot is the granularity
of the TILER hardware device. For all current uses it is 4K, but could also be
16 or 64K. The DMM-TILER TRM refers to this as "page" but we want to separate
this concept from the MMU pages.

"page"

The granularity of the MMU, used by the kernel. This is 4K.

"block"

The TILER hardware component supports 1D and 2D blocks. A 2D block is a
rectangular arrangement of slots with arbitrary width and height in a 2D
container. A 1D block is a linear arrangement of slots with arbitrary length
in a 1D container. This TILER driver only supports 2D blocks.

"container"

The TILER driver supports an arbitrary TILER container size. However, for
all current implementations it is 256 by 128 slots. The container currently can
only be used as a 2D container.

"reserved area"

Each block resides within a reserved area in the container. This area may
be larger than the actual set of slots that a block occupies. The reason for
this is to protect access from one block into another. Since TILER container is
mmap-ped into user space as individual pages, all slots that are spanned by
that page become visible to the user. The tiler driver allows restricting the
granularity of the reserved area (default alignment) as well as the mapped
area (granularity).

Technical Reference Manual
=====
http://focus.ti.com/pdfs/wtbu/OMAP4430_ES2.x_PUBLIC_TRM_vN.zip

Changes since RFC v2: https://lkml.org/lkml/2010/11/30/352
=====
Randy Dunlap:
1) Clarify the meaning of 2^n when referring to TILER alignment and
allocation granularity

Greg KH:
1) Move tiler.h to include/linux since it's not arch specific
2) Rename _tiler.h to tiler-geom.h (ick)
3) Use WARN_ON instead of BUG_ON
4) Export symbols as 'EXPORT_SYMBOL_GPL'
5) Remove comment from Kconfig file

Santosh Shilimkar:
1) Create separate DMM OMAP device file patch (#9)

Changes since RFC v1: http://www.spinics.net/lists/linux-omap/msg33867.html
=====
Santosh Shilimkar:
1) Correct documentation location
2) Remove ioremap of RAM
3) Implement probe function and hwmod
4) Correct commenting style
5) Reduce use of barrier instances

Linus Walleij:
1) Define TCM acryonym

Russell King:
1) Implement probe function
2) Fix spelling mistake
3) Remove GFP_ATOMIC flag when calling dma_alloc_coherent for PAT array mem
4) Replace alloc_page and flush range calls with dma_alloc_coherent

Nishanth Menon:
1) Address infinite while loop when reading dmm register

Benoit Cousson:
1) Fix source file headers
2) Correct logical errors in device file

Kevin Hilman:
1) Move DMM/TILER source code into driver/misc/tiler until a recommendation
is made as to where it should go

List of pending items in proposed order:

* Determine driver source code location
(Currently, resides in drivers/misc/tiler)
* Add area packing support (multiple blocks can reside in the same band/area)
to optimize area use
* Add group-ID support (to specify which blocks can reside together in the
same area)
* Add multiple search directions to TCM-SiTA
* Add 1D block support (including adding 1D search algo to TCM-SiTA)
* Optimize mutex handling (don.t hold mutex during memory
allocation/mapping/cache flushing)
* Add block reference counting, support for sharing blocks
* Move all kernel-API-s to tiler-iface.c
* Support orphaned block support (in preparation for process cleanup support)
* Change block identification from physical address to key-ID pair
(in preparation for user space support, and process security)
* Add support for process security (blocks from separate processes never
reside in the same band)
* Support file interface (ioctl and mmap)
* Support for buffers (ordered list of blocks that are mapped to userspace
together, such as YUV420sp)
* Support 1D user buffer mapping into TILER container
* Support for block pre-reservation (to further optimize area use)

David Sin (2):
TILER-DMM: DMM-PAT driver for TI TILER
TILER-DMM: Device support for OMAP

Lajos Molnar (6):
TILER-DMM: Container manager interface and utility definitons
TILER-DMM: TILER Memory Manager interface and implementation
TILER-DMM: TILER interface file and documentation
TILER-DMM: Geometry and view manipulation functions
TILER-DMM: Main TILER driver implementation
TILER-DMM: Linking TILER driver into the Linux kernel build

Ravi Ramachandra (1):
TILER-DMM: Sample TCM implementation: Simple TILER Allocator (SiTA)

Documentation/arm/OMAP/TILER | 126 ++++++++++
arch/arm/mach-omap2/Makefile | 2 +
arch/arm/mach-omap2/dmm-omap44xx.c | 80 ++++++
arch/arm/mach-omap2/include/mach/dmm.h | 92 +++++++
drivers/misc/Kconfig | 1 +
drivers/misc/Makefile | 1 +
drivers/misc/tiler/Kconfig | 72 ++++++
drivers/misc/tiler/Makefile | 7 +
drivers/misc/tiler/dmm-main.c | 187 ++++++++++++++
drivers/misc/tiler/tcm.h | 171 +++++++++++++
drivers/misc/tiler/tcm/Makefile | 1 +
drivers/misc/tiler/tcm/_tcm-sita.h | 61 +++++
drivers/misc/tiler/tcm/tcm-sita.c | 422 ++++++++++++++++++++++++++++++++
drivers/misc/tiler/tcm/tcm-sita.h | 28 ++
drivers/misc/tiler/tcm/tcm-utils.h | 51 ++++
drivers/misc/tiler/tiler-geom.c | 362 +++++++++++++++++++++++++++
drivers/misc/tiler/tiler-geom.h | 48 ++++
drivers/misc/tiler/tiler-iface.c | 66 +++++
drivers/misc/tiler/tiler-main.c | 405 ++++++++++++++++++++++++++++++
drivers/misc/tiler/tmm-pat.c | 266 ++++++++++++++++++++
drivers/misc/tiler/tmm.h | 103 ++++++++
include/linux/tiler.h | 173 +++++++++++++
22 files changed, 2725 insertions(+), 0 deletions(-)
create mode 100644 Documentation/arm/OMAP/TILER
create mode 100644 arch/arm/mach-omap2/dmm-omap44xx.c
create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
create mode 100644 drivers/misc/tiler/Kconfig
create mode 100644 drivers/misc/tiler/Makefile
create mode 100644 drivers/misc/tiler/dmm-main.c
create mode 100644 drivers/misc/tiler/tcm.h
create mode 100644 drivers/misc/tiler/tcm/Makefile
create mode 100644 drivers/misc/tiler/tcm/_tcm-sita.h
create mode 100644 drivers/misc/tiler/tcm/tcm-sita.c
create mode 100644 drivers/misc/tiler/tcm/tcm-sita.h
create mode 100644 drivers/misc/tiler/tcm/tcm-utils.h
create mode 100644 drivers/misc/tiler/tiler-geom.c
create mode 100644 drivers/misc/tiler/tiler-geom.h
create mode 100644 drivers/misc/tiler/tiler-iface.c
create mode 100644 drivers/misc/tiler/tiler-main.c
create mode 100644 drivers/misc/tiler/tmm-pat.c
create mode 100644 drivers/misc/tiler/tmm.h
create mode 100644 include/linux/tiler.h


2010-12-06 22:15:40

by David Sin

[permalink] [raw]
Subject: [PATCH 3/9] TILER-DMM: Sample TCM implementation: Simple TILER Allocator (SiTA)

From: Ravi Ramachandra <[email protected]>

This patch implements a simple TILER Container Manager (TCM).

Signed-off-by: Ravi Ramachandra <[email protected]>
Signed-off-by: Lajos Molnar <[email protected]>
Signed-off-by: David Sin <[email protected]>
---
drivers/misc/tiler/tcm/Makefile | 1 +
drivers/misc/tiler/tcm/_tcm-sita.h | 61 +++++
drivers/misc/tiler/tcm/tcm-sita.c | 422 ++++++++++++++++++++++++++++++++++++
drivers/misc/tiler/tcm/tcm-sita.h | 28 +++
4 files changed, 512 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/tiler/tcm/Makefile
create mode 100644 drivers/misc/tiler/tcm/_tcm-sita.h
create mode 100644 drivers/misc/tiler/tcm/tcm-sita.c
create mode 100644 drivers/misc/tiler/tcm/tcm-sita.h

diff --git a/drivers/misc/tiler/tcm/Makefile b/drivers/misc/tiler/tcm/Makefile
new file mode 100644
index 0000000..8434607
--- /dev/null
+++ b/drivers/misc/tiler/tcm/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_TI_TILER) += tcm-sita.o
diff --git a/drivers/misc/tiler/tcm/_tcm-sita.h b/drivers/misc/tiler/tcm/_tcm-sita.h
new file mode 100644
index 0000000..6e4d292
--- /dev/null
+++ b/drivers/misc/tiler/tcm/_tcm-sita.h
@@ -0,0 +1,61 @@
+/*
+ * SImple Tiler Allocator (SiTA) private structures.
+ *
+ * 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 _TCM_SITA_H
+#define _TCM_SITA_H
+
+#include "../tcm.h"
+
+/* length between two coordinates */
+#define LEN(a, b) ((a) > (b) ? (a) - (b) + 1 : (b) - (a) + 1)
+
+enum criteria {
+ CR_MAX_NEIGHS = 0x01,
+ CR_FIRST_FOUND = 0x10,
+ CR_BIAS_HORIZONTAL = 0x20,
+ CR_BIAS_VERTICAL = 0x40,
+ CR_DIAGONAL_BALANCE = 0x80
+};
+
+/* nearness to the beginning of the search field from 0 to 1000 */
+struct nearness_factor {
+ s32 x;
+ s32 y;
+};
+
+/*
+ * Statistics on immediately neighboring slots. Edge is the number of
+ * border segments that are also border segments of the scan field. Busy
+ * refers to the number of neighbors that are occupied.
+ */
+struct neighbor_stats {
+ u16 edge;
+ u16 busy;
+};
+
+/* structure to keep the score of a potential allocation */
+struct score {
+ struct nearness_factor f;
+ struct neighbor_stats n;
+ struct tcm_area a;
+ u16 neighs; /* number of busy neighbors */
+};
+
+struct sita_pvt {
+ struct mutex mtx;
+ struct tcm_area ***map; /* pointers to the parent area for each slot */
+};
+
+#endif
diff --git a/drivers/misc/tiler/tcm/tcm-sita.c b/drivers/misc/tiler/tcm/tcm-sita.c
new file mode 100644
index 0000000..a7ceac4
--- /dev/null
+++ b/drivers/misc/tiler/tcm/tcm-sita.c
@@ -0,0 +1,422 @@
+/*
+ * SImple Tiler Allocator (SiTA): 2D and 1D allocation(reservation) algorithm
+ *
+ * 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/slab.h>
+
+#include "_tcm-sita.h"
+#include "tcm-sita.h"
+
+#define TCM_ALG_NAME "tcm_sita"
+#include "tcm-utils.h"
+
+#define ALIGN_DOWN(value, align) ((value) & ~((align) - 1))
+
+/* Individual selection criteria for different scan areas */
+static s32 CR_L2R_T2B = CR_BIAS_HORIZONTAL;
+
+/*
+ * TCM API - Sita Implementation
+ */
+static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
+ struct tcm_area *area);
+static s32 sita_free(struct tcm *tcm, struct tcm_area *area);
+static void sita_deinit(struct tcm *tcm);
+
+/*
+ * Main Scanner functions
+ */
+static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
+ struct tcm_area *area);
+
+static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
+ struct tcm_area *field, struct tcm_area *area);
+
+/*
+ * Support Infrastructure Methods
+ */
+static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h);
+
+static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
+ struct tcm_area *field, s32 criteria,
+ struct score *best);
+
+static void get_nearness_factor(struct tcm_area *field,
+ struct tcm_area *candidate,
+ struct nearness_factor *nf);
+
+static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
+ struct neighbor_stats *stat);
+
+static void fill_area(struct tcm *tcm,
+ struct tcm_area *area, struct tcm_area *parent);
+
+/*
+ * Utility Methods
+ */
+struct tcm *sita_init(u16 width, u16 height, void *attr)
+{
+ struct tcm *tcm;
+ struct sita_pvt *pvt;
+ struct tcm_area area = {NULL};
+ s32 i;
+
+ if (width == 0 || height == 0)
+ return NULL;
+
+ tcm = kzalloc(sizeof(*tcm), GFP_KERNEL);
+ pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
+ if (!tcm || !pvt)
+ goto error;
+
+ /* Updating the pointers to SiTA implementation APIs */
+ tcm->height = height;
+ tcm->width = width;
+ tcm->reserve_2d = sita_reserve_2d;
+ tcm->free = sita_free;
+ tcm->deinit = sita_deinit;
+ tcm->pvt = (void *)pvt;
+
+ mutex_init(&(pvt->mtx));
+
+ /* Creating tam map */
+ pvt->map = kzalloc(sizeof(*pvt->map) * tcm->width, GFP_KERNEL);
+ if (!pvt->map)
+ goto error;
+
+ for (i = 0; i < tcm->width; i++) {
+ pvt->map[i] =
+ kzalloc(sizeof(**pvt->map) * tcm->height,
+ GFP_KERNEL);
+ if (pvt->map[i] == NULL) {
+ while (i--)
+ kfree(pvt->map[i]);
+ kfree(pvt->map);
+ goto error;
+ }
+ }
+
+ mutex_lock(&(pvt->mtx));
+ assign(&area, 0, 0, width - 1, height - 1);
+ fill_area(tcm, &area, NULL);
+ mutex_unlock(&(pvt->mtx));
+ return tcm;
+
+error:
+ kfree(tcm);
+ kfree(pvt);
+ return NULL;
+}
+
+static void sita_deinit(struct tcm *tcm)
+{
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+ struct tcm_area area = {NULL};
+ s32 i;
+
+ area.p1.x = tcm->width - 1;
+ area.p1.y = tcm->height - 1;
+
+ mutex_lock(&(pvt->mtx));
+ fill_area(tcm, &area, NULL);
+ mutex_unlock(&(pvt->mtx));
+
+ mutex_destroy(&(pvt->mtx));
+
+ for (i = 0; i < tcm->height; i++)
+ kfree(pvt->map[i]);
+ kfree(pvt->map);
+ kfree(pvt);
+}
+
+/*
+ * Reserve a 2D area in the container
+ */
+static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u8 align,
+ struct tcm_area *area)
+{
+ s32 ret;
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+ /* not supporting more than 64 as alignment */
+ if (align > 64)
+ return -EINVAL;
+
+ /* we prefer 1, 32 and 64 as alignment */
+ align = align <= 1 ? 1 : align <= 32 ? 32 : 64;
+
+ mutex_lock(&(pvt->mtx));
+ ret = scan_areas_and_find_fit(tcm, w, h, align, area);
+ if (!ret)
+ /* update map */
+ fill_area(tcm, area, area);
+
+ mutex_unlock(&(pvt->mtx));
+ return ret;
+}
+
+/*
+ * Unreserve a previously allocated 2D or 1D area
+ */
+static s32 sita_free(struct tcm *tcm, struct tcm_area *area)
+{
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+ mutex_lock(&(pvt->mtx));
+
+ /* Clear the contents of the associated tiles in the map */
+ fill_area(tcm, area, NULL);
+
+ mutex_unlock(&(pvt->mtx));
+
+ return 0;
+}
+
+/*
+ * Note: In general the cordinates in the scan field area relevant to the can
+ * sweep directions. The scan origin (e.g. top-left corner) will always be
+ * the p0 member of the field. Therfore, for a scan from top-left p0.x <= p1.x
+ * and p0.y <= p1.y; whereas, for a scan from bottom-right p1.x <= p0.x and p1.y
+ * <= p0.y
+ */
+
+/*
+ * Raster scan horizontally left to right from top to bottom to find a place for
+ * a 2D area of given size inside a scan field.
+ */
+static s32 scan_l2r_t2b(struct tcm *tcm, u16 w, u16 h, u16 align,
+ struct tcm_area *field, struct tcm_area *area)
+{
+ s32 x, y;
+ s16 start_x, end_x, start_y, end_y;
+ struct tcm_area ***map = ((struct sita_pvt *)tcm->pvt)->map;
+ struct score best = {{0}, {0}, {NULL}, 0};
+
+ PA(2, "scan_l2r_t2b:", field);
+
+ start_x = field->p0.x;
+ end_x = field->p1.x;
+ start_y = field->p0.y;
+ end_y = field->p1.y;
+
+ /* check scan area co-ordinates */
+ if (field->p1.x < field->p0.x ||
+ field->p1.y < field->p0.y)
+ return -EINVAL;
+
+ /* check if allocation would fit in scan area */
+ if (w > LEN(end_x, start_x) || h > LEN(end_y, start_y))
+ return -ENOSPC;
+
+ start_x = ALIGN(start_x, align);
+
+ /* check if allocation would still fit in scan area */
+ if (w > LEN(end_x, start_x))
+ return -ENOSPC;
+
+ /* adjust end_x and end_y, as allocation would not fit beyond */
+ end_x = end_x - w + 1; /* + 1 to be inclusive */
+ end_y = end_y - h + 1;
+
+ P2("ali=%d x=%d..%d y=%d..%d", align, start_x, end_x, start_y, end_y);
+
+ /* scan field top-to-bottom, left-to-right */
+ for (y = start_y; y <= end_y; y++) {
+ for (x = start_x; x <= end_x; x += align) {
+ if (is_area_free(map, x, y, w, h)) {
+ P3("found shoulder: %d,%d", x, y);
+
+ /* update best candidate */
+ if (update_candidate(tcm, x, y, w, h, field,
+ CR_L2R_T2B, &best))
+ goto done;
+ break;
+ } else if (map[x][y]) {
+ /* step over 2D areas */
+ x = ALIGN_DOWN(map[x][y]->p1.x, align);
+ P3("moving to: %d,%d", x, y);
+ }
+ }
+ }
+
+ if (!best.a.tcm)
+ return -ENOSPC;
+done:
+ assign(area, best.a.p0.x, best.a.p0.y, best.a.p1.x, best.a.p1.y);
+ return 0;
+}
+
+/*
+ * Find a place for a 2D area of given size inside a scan field based on its
+ * alignment needs.
+ */
+static s32 scan_areas_and_find_fit(struct tcm *tcm, u16 w, u16 h, u16 align,
+ struct tcm_area *area)
+{
+ struct tcm_area field = {NULL};
+
+ /* scan whole container left to right, top to bottom */
+ assign(&field, 0, 0, tcm->width - 1, tcm->height - 1);
+ return scan_l2r_t2b(tcm, w, h, align, &field, area);
+}
+
+/* check if an entire area is free */
+static s32 is_area_free(struct tcm_area ***map, u16 x0, u16 y0, u16 w, u16 h)
+{
+ u16 x = 0, y = 0;
+ for (y = y0; y < y0 + h; y++) {
+ for (x = x0; x < x0 + w; x++) {
+ if (map[x][y])
+ return false;
+ }
+ }
+ return true;
+}
+
+/* fills an area with a parent tcm_area */
+static void fill_area(struct tcm *tcm, struct tcm_area *area,
+ struct tcm_area *parent)
+{
+ s32 x, y;
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+ PA(2, "fill 2d area", area);
+ for (x = area->p0.x; x <= area->p1.x; ++x)
+ for (y = area->p0.y; y <= area->p1.y; ++y)
+ pvt->map[x][y] = parent;
+}
+
+/*
+ * Compares a candidate area to the current best area, and if it is a better
+ * fit, it updates the best to this one. Return 1 (true) if the candidate area
+ * is known to be the final best, so no more searching should be performed
+ */
+static s32 update_candidate(struct tcm *tcm, u16 x0, u16 y0, u16 w, u16 h,
+ struct tcm_area *field, s32 criteria,
+ struct score *best)
+{
+ struct score me; /* score for area */
+
+ /*
+ * If first found is enabled then we stop looking
+ * NOTE: For horizontal bias we always give the first found, because our
+ * scan is horizontal-raster-based and the first candidate will always
+ * have the horizontal bias.
+ */
+ bool first = criteria & (CR_FIRST_FOUND | CR_BIAS_HORIZONTAL);
+
+ assign(&me.a, x0, y0, x0 + w - 1, y0 + h - 1);
+
+ /* calculate score for current candidate */
+ if (!first) {
+ get_neighbor_stats(tcm, &me.a, &me.n);
+ me.neighs = me.n.edge + me.n.busy;
+ get_nearness_factor(field, &me.a, &me.f);
+ }
+
+ /* the 1st candidate is always the best */
+ if (!best->a.tcm)
+ goto better;
+
+ /* see if this are is better than the best so far */
+
+ /* neighbor check */
+ if ((criteria & CR_MAX_NEIGHS) &&
+ me.neighs > best->neighs)
+ goto better;
+
+ /* vertical bias check */
+ if ((criteria & CR_BIAS_VERTICAL) &&
+ /*
+ * NOTE: not checking if lengths are same, because that does not
+ * find new shoulders on the same row after a fit
+ */
+ LEN(me.a.p0.y, field->p0.y) >
+ LEN(best->a.p0.y, field->p0.y))
+ goto better;
+
+ /* diagonal balance check */
+ if ((criteria & CR_DIAGONAL_BALANCE) &&
+ best->neighs <= me.neighs &&
+ (best->neighs < me.neighs ||
+ /* this implies that neighs and occupied match */
+ best->n.busy < me.n.busy ||
+ (best->n.busy == me.n.busy &&
+ /* check the nearness factor */
+ best->f.x + best->f.y > me.f.x + me.f.y)))
+ goto better;
+
+ /* not better, keep going */
+ return 0;
+
+better:
+ /* save current area as best */
+ memcpy(best, &me, sizeof(me));
+ best->a.tcm = tcm;
+ return first;
+}
+
+/*
+ * Calculate the nearness factor of an area in a search field. The nearness
+ * factor is smaller if the area is closer to the search origin.
+ */
+static void get_nearness_factor(struct tcm_area *field, struct tcm_area *area,
+ struct nearness_factor *nf)
+{
+ /*
+ * Using signed math as field coordinates may be reversed if
+ * search direction is right-to-left or bottom-to-top.
+ */
+ nf->x = (s32)(area->p0.x - field->p0.x) * 1000 /
+ (field->p1.x - field->p0.x);
+ nf->y = (s32)(area->p0.y - field->p0.y) * 1000 /
+ (field->p1.y - field->p0.y);
+}
+
+/* get neighbor statistics */
+static void get_neighbor_stats(struct tcm *tcm, struct tcm_area *area,
+ struct neighbor_stats *stat)
+{
+ s16 x = 0, y = 0;
+ struct sita_pvt *pvt = (struct sita_pvt *)tcm->pvt;
+
+ /* Clearing any exisiting values */
+ memset(stat, 0, sizeof(*stat));
+
+ /* process top & bottom edges */
+ for (x = area->p0.x; x <= area->p1.x; x++) {
+ if (area->p0.y == 0)
+ stat->edge++;
+ else if (pvt->map[x][area->p0.y - 1])
+ stat->busy++;
+
+ if (area->p1.y == tcm->height - 1)
+ stat->edge++;
+ else if (pvt->map[x][area->p1.y + 1])
+ stat->busy++;
+ }
+
+ /* process left & right edges */
+ for (y = area->p0.y; y <= area->p1.y; ++y) {
+ if (area->p0.x == 0)
+ stat->edge++;
+ else if (pvt->map[area->p0.x - 1][y])
+ stat->busy++;
+
+ if (area->p1.x == tcm->width - 1)
+ stat->edge++;
+ else if (pvt->map[area->p1.x + 1][y])
+ stat->busy++;
+ }
+}
diff --git a/drivers/misc/tiler/tcm/tcm-sita.h b/drivers/misc/tiler/tcm/tcm-sita.h
new file mode 100644
index 0000000..a435bce
--- /dev/null
+++ b/drivers/misc/tiler/tcm/tcm-sita.h
@@ -0,0 +1,28 @@
+/*
+ * SImple Tiler Allocator (SiTA) interface.
+ *
+ * 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 TCM_SITA_H
+#define TCM_SITA_H
+
+#include "../tcm.h"
+
+/*
+ * Create a SiTA tiler container manager.
+ */
+struct tcm *sita_init(u16 width, u16 height, void *attr);
+
+TCM_INIT(sita_init, void);
+
+#endif
--
1.7.0.4

2010-12-06 22:16:09

by David Sin

[permalink] [raw]
Subject: [PATCH 5/9] TILER-DMM: TILER interface file and documentation

From: Lajos Molnar <[email protected]>

This patch contains the TILER interface file and the documentation.

Signed-off-by: Lajos Molnar <[email protected]>
Signed-off-by: David Sin <[email protected]>
---
Documentation/arm/OMAP/TILER | 126 ++++++++++++++++++++++++++++++
include/linux/tiler.h | 173 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 299 insertions(+), 0 deletions(-)
create mode 100644 Documentation/arm/OMAP/TILER
create mode 100644 include/linux/tiler.h

diff --git a/Documentation/arm/OMAP/TILER b/Documentation/arm/OMAP/TILER
new file mode 100644
index 0000000..2e94ad7
--- /dev/null
+++ b/Documentation/arm/OMAP/TILER
@@ -0,0 +1,126 @@
+Tiling and Isometric Lightweight Engine for Rotation (TILER) driver
+
+Dynamic Memory Manager (DMM) is a hardware block made by Texas Instruments.
+Within the DMM exists at least one TILER hardware component. Its purpose is to
+organize video/image memory in a 2-dimensional fashion to limit memory
+bandwidth and facilitate 0 effort rotation and mirroring. The TILER driver
+facilitates allocating, freeing, as well as mapping 2D blocks (areas) in the
+TILER container(s). It also facilitates rotating and mirroring the allocated
+blocks or its rectangular subsections.
+
+TERMINOLOGY
+
+"slot"
+
+The basic TILER driver operates on blocks of slots. A slot is the granularity
+of the TILER hardware device. For all current uses it is 4K, but could also be
+16 or 64K. The DMM-TILER TRM refers to this as "page" but we want to separate
+this concept from the MMU pages.
+
+"page"
+
+The granularity of the MMU, used by the kernel. This is 4K.
+
+"block"
+
+The TILER hardware component supports 1D and 2D blocks. A 2D block is a
+rectangular arrangement of slots with arbitrary width and height in a 2D
+container. A 1D block is a linear arrangement of slots with arbitrary length
+ in a 1D container. This TILER driver only supports 2D blocks.
+
+"container"
+
+The TILER driver supports an arbitrary TILER container size. However, for
+all current implementations it is 256 by 128 slots. The container currently can
+only be used as a 2D container.
+
+"reserved area"
+
+Each block resides within a reserved area in the container. This area may
+be larger than the actual set of slots that a block occupies. The reason for
+this is to protect access from one block into another. Since TILER container is
+mmap-ped into user space as individual pages, all slots that are spanned by
+that page become visible to the user. The tiler driver allows restricting the
+granularity of the reserved area (default alignment) as well as the mapped
+area (granularity).
+
+Using TILER driver KERNEL APIs:
+
+1. Allocating and freeing a 1080p YUV422 block
+
+ struct tiler_block_t blk = {0};
+ int res;
+
+ blk.width = 1920;
+ blk.height = 1080;
+ res = tiler_alloc(&blk, TILFMT_16BIT, 0, 0);
+
+ tiler_free(&blk);
+
+2. Allocating and freeing a 1080p YUV420p block
+
+ struct tiler_block_t blk_Y = {0}, blk_UV = {0};
+ int res;
+
+ blk_Y.width = 1920;
+ blk_Y.height = 1080;
+ blk_UV.widht = 960;
+ blk_UV.height = 540;
+ res = tiler_alloc(&blk_Y, TILFMT_8BIT, 0, 0) ? :
+ tiler_alloc(&blk_UV, TILFMT_16BIT, PAGE_SIZE,
+ blk_y->phys & ~PAGE_MASK);
+
+ tiler_free(&blk_Y);
+ tiler_free(&blk_UV);
+
+Note how we allocated the UV block at the same in-page offset as the Y buffer.
+This facilitates mmap-ping both Y and UV blocks into userspace as one
+contiguous buffer.
+
+3. Mmap-ing YUV420p block into user space
+
+ static int my_mmap(struct file *file, struct vm_area_struct *vma)
+ {
+ unsigned long size = (vma->vm_end - vma->vm_start);
+ unsigned long start = vma->vm_start;
+
+ if (size != tiler_size(&blk_Y) + tiler_size(&blk_UV))
+ return -EINVAL;
+
+ return tiler_mmap_blk(&blk_Y, 0, tiler_size(&blk_Y), vma, 0) ?
+ : tiler_mmap_blk(&blk_UV, 0, tiler_size(&blk_UV), vma,
+ tiler_size(&blk_Y));
+ }
+
+CONFIGURATIONS
+
+The TILER driver allows specifying a container manager (tcm) for each
+pixel format. The same container manager can be specified for more than
+one pixel formats.
+
+Each container manager also operates on a Physical Address Translator PAT
+ instance. One can also specify a "virtual" PAT (with a linear preassigned
+ memory space no actual PAT programming), but it is not implemented.
+
+PARAMETERS
+
+The TILER driver allows specifying:
+
+ granularity (tiler.grain, CONFIG_TILER_GRANULARITY):
+
+ Each block is mapped in width-chunks of granularity.
+
+ default alignment (tiler.align, CONFIG_TILER_ALIGNMENT):
+
+ Default alignment if aligment is not specified (0). Otherwise,
+ blocks are allocated at an address aligned to the value given plus an
+ offset within the alignment.
+
+ cache limit (tiler.cache, CONFIG_TILER_CACHE_LIMIT):
+
+ TILER driver keeps a cache of allocated pages to speed up allocation of
+ TILER blocks. You can set a limit of how much memory the TILER driver
+ should keep if there are no actual TILER allocations. This also means
+ that if there is less memory used than this limit, the pages of freed
+ tiler blocks will not actually be freed, but instead are put into this
+ cache.
diff --git a/include/linux/tiler.h b/include/linux/tiler.h
new file mode 100644
index 0000000..280f7bb
--- /dev/null
+++ b/include/linux/tiler.h
@@ -0,0 +1,173 @@
+/*
+ * TILER driver support 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.
+ */
+
+#ifndef TILER_H
+#define TILER_H
+
+#include <linux/mm.h>
+
+/* API Definitions */
+
+/* return true if physical address is in the tiler container */
+bool is_tiler_addr(u32 phys);
+
+enum tiler_fmt {
+ TILFMT_MIN = -2,
+ TILFMT_INVALID = -2,
+ TILFMT_NONE = -1,
+ TILFMT_8BIT = 0,
+ TILFMT_16BIT = 1,
+ TILFMT_32BIT = 2,
+ TILFMT_MAX = 2,
+ TILFMT_PAGE = 3, /* for completeness */
+};
+
+/* tiler block info */
+struct tiler_block_t {
+ u32 phys; /* system space (L3) tiler addr */
+ u32 width; /* width */
+ u32 height; /* height */
+};
+
+/* tiler (image/video frame) view */
+struct tiler_view_t {
+ u32 tsptr; /* tiler space addr */
+ u32 width; /* width */
+ u32 height; /* height */
+ u32 bpp; /* bytes per pixel */
+ s32 h_inc; /* horizontal increment */
+ s32 v_inc; /* vertical increment */
+};
+
+/* get tiler format for a physical address */
+enum tiler_fmt tiler_fmt(u32 phys);
+
+/* get tiler block bytes-per-pixel */
+u32 tiler_bpp(const struct tiler_block_t *b);
+
+/* get tiler block physical stride */
+u32 tiler_pstride(const struct tiler_block_t *b);
+
+/* get tiler block virtual stride */
+static inline u32 tiler_vstride(const struct tiler_block_t *b)
+{
+ return PAGE_ALIGN((b->phys & ~PAGE_MASK) + tiler_bpp(b) * b->width);
+}
+
+/* returns the virtual size of the block (for mmap) */
+static inline u32 tiler_size(const struct tiler_block_t *b)
+{
+ return b->height * tiler_vstride(b);
+}
+
+/*
+ * Reserves a 2D TILER block area and memory.
+ *
+ * @blk: pointer to tiler block data. This must be set up ('phys' member must
+ * be 0) with the tiler block information.
+ * @fmt: TILER block format
+ * @align: block alignment (default: normally PAGE_SIZE)
+ * @offs: block offset
+ *
+ */
+s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt, u32 align,
+ u32 offs);
+
+/*
+ * Mmaps a portion of a tiler block to a virtual address. Use this method in
+ * your driver's mmap function to potentially combine multiple tiler blocks as
+ * one virtual buffer.
+ *
+ * @blk: pointer to tiler block data
+ * @offs: offset from where to map (must be page aligned)
+ * @size: size of area to map (must be page aligned)
+ * @vma: VMM memory area to map to
+ * @voffs: offset (from vm_start) in the VMM memory area to start mapping at
+ *
+ */
+s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
+ struct vm_area_struct *vma, u32 voffs);
+
+/*
+ * Frees TILER memory. Since there may be multiple references for the same area
+ * if duplicated by tiler_dup, the area is only actually freed if all references
+ * have been freed.
+ *
+ * @blk: pointer to a tiler block data as filled by tiler_alloc, tiler_map
+ * or tiler_dup. 'phys' member will be set to 0 on success.
+ */
+void tiler_free(struct tiler_block_t *blk);
+
+/*
+ * Create a view based on a tiler address and width and height
+ *
+ * This method should only be used as a last resort, e.g. if tilview object
+ * cannot be passed because of incoherence with other view 2D objects that must
+ * be supported.
+ *
+ * @view: Pointer to a view where the information will be stored
+ * @ssptr: MUST BE a tiler address
+ * @width: view width
+ * @height: view height
+ */
+void tilview_create(struct tiler_view_t *view, u32 phys, u32 width, u32 height);
+
+/*
+ * Obtains the view information for a tiler block
+ *
+ * @view: Pointer to a view where the information will be stored
+ * @blk: Pointer to an existing allocated tiler block
+ */
+void tilview_get(struct tiler_view_t *view, struct tiler_block_t *blk);
+
+/*
+ * Crops a tiler view to a rectangular portion. Crop area must be fully within
+ * the orginal tiler view: 0 <= left <= left + width <= view->width, also:
+ * 0 <= top <= top + height <= view->height.
+ *
+ * @view: Pointer to tiler view to be cropped
+ * @left: x of top-left corner
+ * @top: y of top-left corner
+ * @width: crop width
+ * @height: crop height
+ *
+ * The view will be reduced to the crop region if the crop region is correct.
+ * Otherwise, no modifications are made.
+ */
+s32 tilview_crop(struct tiler_view_t *view, u32 left, u32 top, u32 width,
+ u32 height);
+
+/*
+ * Rotates a tiler view clockwise by a specified degree.
+ *
+ * @view: Pointer to tiler view to be cropped
+ * @rotate: Degree of rotation (clockwise). Must be a multiple of 90.
+ *
+ * View is not modified on error; otherwise, it is updated in place.
+ */
+s32 tilview_rotate(struct tiler_view_t *view, s32 rotation);
+
+/*
+ * Mirrors a tiler view horizontally and/or vertically.
+ *
+ * @view: Pointer to tiler view to be cropped
+ * @flip_x: Mirror horizontally (left-to-right)
+ * @flip_y: Mirror vertically (top-to-bottom)
+ *
+ * View is not modified on error; otherwise, it is updated in place.
+ */
+s32 tilview_flip(struct tiler_view_t *view, bool flip_x, bool flip_y);
+
+#endif
--
1.7.0.4

2010-12-06 22:16:16

by David Sin

[permalink] [raw]
Subject: [PATCH 7/9] TILER-DMM: Main TILER driver implementation

From: Lajos Molnar <[email protected]>

This patch contains the TILER driver and implementation of the TILER
block manipulation and mapping functions.

It also contains the makefile and config file for the TILER driver.

Signed-off-by: Lajos Molnar <[email protected]>
Signed-off-by: David Sin <[email protected]>
---
drivers/misc/tiler/Kconfig | 72 +++++++
drivers/misc/tiler/Makefile | 7 +
drivers/misc/tiler/tiler-iface.c | 66 ++++++
drivers/misc/tiler/tiler-main.c | 405 ++++++++++++++++++++++++++++++++++++++
4 files changed, 550 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/tiler/Kconfig
create mode 100644 drivers/misc/tiler/Makefile
create mode 100644 drivers/misc/tiler/tiler-iface.c
create mode 100644 drivers/misc/tiler/tiler-main.c

diff --git a/drivers/misc/tiler/Kconfig b/drivers/misc/tiler/Kconfig
new file mode 100644
index 0000000..eae4fb1
--- /dev/null
+++ b/drivers/misc/tiler/Kconfig
@@ -0,0 +1,72 @@
+config HAVE_TI_DMM
+ bool
+ default y
+ depends on ARCH_OMAP4
+
+menuconfig TI_DMM
+ tristate "TI DMM support"
+ default y
+ depends on HAVE_TI_DMM
+ help
+ DMM driver for TI chips.
+
+menuconfig TI_TILER
+ tristate "TI TILER support"
+ default y
+ depends on TI_DMM
+ help
+ TILER driver for TI chips. The TI TILER device
+ enables video rotation on certain TI chips such as OMAP4 or
+ TI816x. Video rotation will be limited without TILER support.
+
+config TILER_GRANULARITY
+ int "Allocation granularity"
+ range 1 4096
+ default 128
+ depends on TI_TILER
+ help
+ This option sets the default TILER allocation granularity. It can
+ be overriden by the tiler.grain boot argument.
+
+ The allocation granularity is the smallest TILER block size (in
+ bytes) managed distinctly by the TILER driver. TILER blocks of any
+ size are managed in chunks of at least this size.
+
+ Must be a power of 2 in the range of 1 to 4096; however, the TILER
+ driver may use a larger supported granularity.
+
+ Supported values are: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
+ 2048, 4096.
+
+config TILER_ALIGNMENT
+ int "Allocation alignment"
+ range 1 4096
+ default 4096
+ depends on TI_TILER
+ help
+ This option sets the default TILER allocation alignment. It can
+ be overriden by the tiler.align boot argument.
+
+ Must be a power of 2 in the range of 1 to 4096; however, it is
+ naturally aligned to the TILER granularity.
+
+ Supported values are: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024,
+ 2048, 4096.
+
+config TILER_CACHE_LIMIT
+ int "Memory limit to cache free pages in MBytes"
+ range 0 128
+ default 40
+ depends on TI_TILER
+ help
+ This option sets the minimum memory that TILER retains even if
+ there is less TILER allocated memory is use. The unused memory is
+ instead stored in a cache to speed up allocation and freeing of
+ physical pages.
+
+ This option can be overriden by the tiler.cache boot argument.
+
+ While initially TILER will use less memory than this limit (0), it
+ will not release any memory used until it reaches this limit.
+ Thereafter, TILER will release any unused memory immediately as
+ long as there it is above this threshold.
diff --git a/drivers/misc/tiler/Makefile b/drivers/misc/tiler/Makefile
new file mode 100644
index 0000000..7dbc828
--- /dev/null
+++ b/drivers/misc/tiler/Makefile
@@ -0,0 +1,7 @@
+obj-$(CONFIG_TI_DMM) += dmm.o
+dmm-objs = dmm-main.o
+
+obj-$(CONFIG_TI_TILER) += tcm/
+
+obj-$(CONFIG_TI_TILER) += tiler.o
+tiler-objs = tiler-geom.o tiler-main.o tiler-iface.o tmm-pat.o
diff --git a/drivers/misc/tiler/tiler-iface.c b/drivers/misc/tiler/tiler-iface.c
new file mode 100644
index 0000000..02c95c5
--- /dev/null
+++ b/drivers/misc/tiler/tiler-iface.c
@@ -0,0 +1,66 @@
+/*
+ * TILER driver interace 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 <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/mm_types.h>
+#include <asm/mach/map.h>
+
+#include "tiler-geom.h"
+
+/*
+ * Memory-Map Kernel APIs
+ */
+
+s32 tiler_mmap_blk(struct tiler_block_t *blk, u32 offs, u32 size,
+ struct vm_area_struct *vma, u32 voffs)
+{
+ u32 v, p, len;
+
+ /* don't allow mremap */
+ vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+
+ /* mapping must fit into vma */
+ WARN_ON(vma->vm_start > vma->vm_start + voffs ||
+ vma->vm_start + voffs > vma->vm_start + voffs + size ||
+ vma->vm_start + voffs + size > vma->vm_end);
+
+ /* mapping must fit into block */
+ WARN_ON(offs > offs + size || offs + size > tiler_size(blk));
+
+ v = tiler_vstride(blk);
+ p = tiler_pstride(blk);
+
+ /* remap block portion */
+ len = v - (offs % v); /* initial area to map */
+ while (size) {
+ /* restrict to size still needs mapping */
+ if (len > size)
+ len = size;
+
+ vma->vm_pgoff = (blk->phys + offs) >> PAGE_SHIFT;
+ if (remap_pfn_range(vma, vma->vm_start + voffs, vma->vm_pgoff,
+ len, vma->vm_page_prot))
+ return -EAGAIN;
+ voffs += len;
+ offs += len + p - v;
+ size -= len;
+ len = v; /* subsequent area to map */
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tiler_mmap_blk);
+
diff --git a/drivers/misc/tiler/tiler-main.c b/drivers/misc/tiler/tiler-main.c
new file mode 100644
index 0000000..ce9145d
--- /dev/null
+++ b/drivers/misc/tiler/tiler-main.c
@@ -0,0 +1,405 @@
+/*
+ * TILER driver main support 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/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+#include <linux/dma-mapping.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+
+#include <mach/dmm.h>
+#include "tmm.h"
+#include "tiler-geom.h"
+#include "tcm/tcm-sita.h"
+
+static uint default_align = CONFIG_TILER_ALIGNMENT;
+static uint granularity = CONFIG_TILER_GRANULARITY;
+
+module_param_named(align, default_align, uint, 0444);
+MODULE_PARM_DESC(align, "Default block ssptr alignment");
+module_param_named(grain, granularity, uint, 0444);
+MODULE_PARM_DESC(grain, "Granularity (bytes)");
+
+static struct tiler_ops tiler; /* shared methods and variables */
+
+static struct list_head blocks; /* all tiler blocks */
+
+static struct mutex mtx;
+static struct tcm *tcm[TILER_FORMATS];
+static struct tmm *tmm[TILER_FORMATS];
+static u32 *dmac_va;
+static dma_addr_t dmac_pa;
+
+/* info for a block */
+struct mem_info {
+ struct list_head global; /* global blocks */
+ struct tiler_block_t blk; /* block info */
+ struct tcm_area area;
+ u32 *mem; /* list of alloced phys addresses */
+};
+
+/*
+ * TILER Memory Manager (TMM) connectors
+ */
+
+/* wrapper around tmm_map */
+static s32 refill_pat(struct tmm *tmm, struct tcm_area *area, u32 *ptr)
+{
+ s32 res = 0;
+ struct pat_area p_area = {0};
+
+ p_area.x0 = area->p0.x;
+ p_area.y0 = area->p0.y;
+ p_area.x1 = area->p1.x;
+ p_area.y1 = area->p1.y;
+
+ memcpy(dmac_va, ptr, sizeof(*ptr) * tcm_sizeof(*area));
+
+ if (tmm_map(tmm, p_area, dmac_pa))
+ res = -EFAULT;
+
+ return res;
+}
+
+/* wrapper around tmm_clear */
+static void clear_pat(struct tmm *tmm, struct tcm_area *area)
+{
+ struct pat_area p_area = {0};
+
+ p_area.x0 = area->p0.x;
+ p_area.y0 = area->p0.y;
+ p_area.x1 = area->p1.x;
+ p_area.y1 = area->p1.y;
+
+ tmm_clear(tmm, p_area);
+}
+
+/*
+ * Area handling methods
+ */
+
+/* verify input params and calculate tiler container params for a block */
+static s32 __analyze_area(enum tiler_fmt fmt, u32 width, u32 height,
+ u16 *x_area, u16 *y_area, u16 *align, u16 *offs)
+{
+ /* input: width, height is in pixels, *align, *offs in bytes */
+ /* output: x_area, y_area, *align in slots */
+
+ /* slot width, height, and row size */
+ u32 slot_row, min_align;
+ const struct tiler_geom *g;
+
+ /* width and height must be positive, format must be 2D */
+ if (!width || !height || fmt == TILFMT_PAGE)
+ return -EINVAL;
+
+ /* align must be 2 power */
+ if (*align & (*align - 1))
+ return -EINVAL;
+
+ /* format must be valid */
+ g = tiler.geom(fmt);
+ if (!g)
+ return -EINVAL;
+
+ /* get the # of bytes per row in 1 slot */
+ slot_row = g->slot_w * g->bpp;
+
+ /* minimum alignment is at least 1 slot. Use default if needed */
+ min_align = max(slot_row, granularity);
+ *align = ALIGN(*align ? : default_align, min_align);
+
+ /* offset must be multiple of bpp */
+ if (*offs & (g->bpp - 1) || *offs >= *align)
+ return -EINVAL;
+
+ /* round down the offset to the nearest slot size, and increase width
+ to allow space for having the correct offset */
+ width += (*offs & (min_align - 1)) / g->bpp;
+
+ /* expand width to block size */
+ width = ALIGN(width, min_align / g->bpp);
+
+ /* adjust to slots */
+ *x_area = DIV_ROUND_UP(width, g->slot_w);
+ *y_area = DIV_ROUND_UP(height, g->slot_h);
+ *align /= slot_row;
+
+ if (*x_area > tiler.width || *y_area > tiler.height)
+ return -ENOMEM;
+ return 0;
+}
+
+/* allocate a mem_info structure and reserves a 2d container area */
+static struct mem_info *get_2d_area(u16 w, u16 h, u16 align, struct tcm *tcm)
+{
+ struct mem_info *mi = NULL;
+
+ /* reserve a block struct */
+ mi = kmalloc(sizeof(*mi), GFP_KERNEL);
+ if (!mi)
+ return mi;
+ memset(mi, 0, sizeof(*mi));
+
+ /* reserve an area */
+ if (tcm_reserve_2d(tcm, w, h, align, &mi->area)) {
+ kfree(mi);
+ return NULL;
+ }
+
+ return mi;
+}
+
+/*
+ * Block operations
+ */
+
+/* free a block */
+static s32 free_block(struct mem_info *mi)
+{
+ /* release memory */
+ if (mi->mem)
+ tmm_free(tmm[tiler_fmt(mi->blk.phys)], mi->mem);
+ clear_pat(tmm[tiler_fmt(mi->blk.phys)], &mi->area);
+
+ /* unreserve area */
+ tcm_free(&mi->area);
+
+ /* have mutex */
+
+ /* safe deletion as list may not have been assigned */
+ if (mi->global.next)
+ list_del(&mi->global);
+
+ kfree(mi);
+ return 0;
+}
+
+/* create an empty block with just an area and add it to the global list */
+static struct mem_info *get_area(enum tiler_fmt fmt, u32 width, u32 height,
+ u16 align, u16 offs)
+{
+ u16 x, y;
+ struct mem_info *mi = NULL;
+ const struct tiler_geom *g = tiler.geom(fmt);
+
+ /* calculate dimensions and alignment in slots */
+ if (__analyze_area(fmt, width, height, &x, &y, &align, &offs))
+ return NULL;
+
+ mi = get_2d_area(x, y, align, tcm[fmt]);
+ if (!mi)
+ return NULL;
+
+ /* have mutex */
+ list_add(&mi->global, &blocks);
+
+ mi->blk.phys = tiler.addr(fmt,
+ mi->area.p0.x * g->slot_w, mi->area.p0.y * g->slot_h)
+ + offs;
+ return mi;
+}
+
+/* allocate a new tiler block */
+static s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height,
+ u32 align, u32 offs, struct mem_info **info)
+{
+ struct mem_info *mi = NULL;
+
+ *info = NULL;
+
+ /* only support up to page alignment */
+ if (align > PAGE_SIZE || offs >= (align ? : default_align))
+ return -EINVAL;
+
+ mutex_lock(&mtx);
+
+ /* reserve area in tiler container */
+ mi = get_area(fmt, width, height, align, offs);
+ if (!mi)
+ goto nomem;
+
+ mi->blk.width = width;
+ mi->blk.height = height;
+
+ /* allocate and map if mapping is supported */
+ if (tmm_can_map(tmm[fmt])) {
+ mi->mem = tmm_get(tmm[fmt], tcm_sizeof(mi->area));
+ if (!mi->mem)
+ goto cleanup;
+
+ /* program PAT */
+ if (refill_pat(tmm[fmt], &mi->area, mi->mem))
+ goto cleanup;
+ }
+ *info = mi;
+ mutex_unlock(&mtx);
+ return 0;
+
+cleanup:
+ free_block(mi);
+nomem:
+ mutex_unlock(&mtx);
+ return -ENOMEM;
+}
+
+/*
+ * Driver code
+ */
+
+/* driver initialization */
+static s32 __init tiler_init(void)
+{
+ s32 r = 0;
+ struct tcm *sita = NULL;
+ struct tmm *tmm_pat = NULL;
+
+ tiler_geom_init(&tiler);
+
+ /* check module parameters for correctness */
+ if (default_align > PAGE_SIZE ||
+ default_align & (default_align - 1) ||
+ granularity < 1 || granularity > PAGE_SIZE ||
+ granularity & (granularity - 1))
+ return -EINVAL;
+
+ /*
+ * Array of physical pages for PAT programming, which must be a 16-byte
+ * aligned physical address.
+ */
+ dmac_va = dma_alloc_coherent(NULL, tiler.width * tiler.height *
+ sizeof(*dmac_va), &dmac_pa, GFP_KERNEL);
+ if (!dmac_va)
+ return -ENOMEM;
+
+ /* Allocate tiler container manager (we share 1 on OMAP4) */
+ sita = sita_init(tiler.width, tiler.height, NULL);
+
+ tcm[TILFMT_8BIT] = sita;
+ tcm[TILFMT_16BIT] = sita;
+ tcm[TILFMT_32BIT] = sita;
+
+ /* Allocate tiler memory manager (must have 1 unique TMM per TCM ) */
+ tmm_pat = tmm_pat_init(0);
+ tmm[TILFMT_8BIT] = tmm_pat;
+ tmm[TILFMT_16BIT] = tmm_pat;
+ tmm[TILFMT_32BIT] = tmm_pat;
+
+ if (!sita || !tmm_pat) {
+ r = -ENOMEM;
+ goto error;
+ }
+
+ mutex_init(&mtx);
+ INIT_LIST_HEAD(&blocks);
+
+error:
+ if (r) {
+ tcm_deinit(sita);
+ tmm_deinit(tmm_pat);
+ dma_free_coherent(NULL, tiler.width * tiler.height *
+ sizeof(*dmac_va), dmac_va, dmac_pa);
+ }
+
+ return r;
+}
+
+/* driver cleanup */
+static void __exit tiler_exit(void)
+{
+ int i, j;
+ struct mem_info *mi, *mi_;
+
+ mutex_lock(&mtx);
+
+ /* free all blocks */
+ list_for_each_entry_safe(mi, mi_, &blocks, global)
+ free_block(mi);
+
+ /* all lists should have cleared */
+ WARN_ON(!list_empty(&blocks));
+
+ mutex_unlock(&mtx);
+
+ dma_free_coherent(NULL, tiler.width * tiler.height * sizeof(*dmac_va),
+ dmac_va, dmac_pa);
+
+ /* close containers only once */
+ for (i = TILFMT_MIN; i <= TILFMT_MAX; i++) {
+ /*
+ * Remove identical containers. TILER Memory Manager (TMM)
+ * is unique per TILER Container Manager (TCM)
+ */
+ for (j = i + 1; j <= TILFMT_MAX; j++)
+ if (tcm[i] == tcm[j]) {
+ tcm[j] = NULL;
+ tmm[j] = NULL;
+ }
+
+ tcm_deinit(tcm[i]);
+ tmm_deinit(tmm[i]);
+ }
+
+ mutex_destroy(&mtx);
+}
+
+/*
+ * Block Kernel APIs
+ */
+
+s32 tiler_alloc(struct tiler_block_t *blk, enum tiler_fmt fmt,
+ u32 align, u32 offs)
+{
+ struct mem_info *mi;
+ s32 res;
+
+ /* blk must be valid, and blk->phys must be 0 */
+ WARN_ON(!blk || blk->phys);
+
+ res = alloc_block(fmt, blk->width, blk->height, align, offs, &mi);
+ if (mi)
+ blk->phys = mi->blk.phys;
+ return res;
+}
+EXPORT_SYMBOL_GPL(tiler_alloc);
+
+void tiler_free(struct tiler_block_t *blk)
+{
+ struct mem_info *mi;
+
+ mutex_lock(&mtx);
+
+ /* find block */
+ list_for_each_entry(mi, &blocks, global) {
+ if (mi->blk.phys == blk->phys) {
+ free_block(mi);
+ break;
+ }
+ }
+
+ blk->phys = 0;
+
+ mutex_unlock(&mtx);
+}
+EXPORT_SYMBOL_GPL(tiler_free);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Lajos Molnar <[email protected]>");
+MODULE_AUTHOR("David Sin <[email protected]>");
+module_init(tiler_init);
+module_exit(tiler_exit);
--
1.7.0.4

2010-12-06 22:16:22

by David Sin

[permalink] [raw]
Subject: [PATCH 9/9] TILER-DMM: Device support for OMAP

Add DMM device support for OMAP utilizing the
OMAP HWMOD framework.

Signed-off-by: Hari Kanigeri <[email protected]>
Signed-off-by: David Sin <[email protected]>
---
arch/arm/mach-omap2/Makefile | 2 +
arch/arm/mach-omap2/dmm-omap44xx.c | 80 ++++++++++++++++++++++++++++++++++++
2 files changed, 82 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-omap2/dmm-omap44xx.c

diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index 60e51bc..fc682ea 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -194,3 +194,5 @@ obj-y += $(smc91x-m) $(smc91x-y)

smsc911x-$(CONFIG_SMSC911X) := gpmc-smsc911x.o
obj-y += $(smsc911x-m) $(smsc911x-y)
+
+obj-$(CONFIG_ARCH_OMAP4) += dmm-omap44xx.o
diff --git a/arch/arm/mach-omap2/dmm-omap44xx.c b/arch/arm/mach-omap2/dmm-omap44xx.c
new file mode 100644
index 0000000..a84490c
--- /dev/null
+++ b/arch/arm/mach-omap2/dmm-omap44xx.c
@@ -0,0 +1,80 @@
+/*
+ * DMM driver support functions for TI OMAP processors.
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <mach/dmm.h>
+#include <plat/omap_device.h>
+#include <plat/omap_hwmod.h>
+#include <linux/errno.h>
+#include <linux/err.h>
+
+static struct dmm *plat_data;
+static int pdata;
+
+#ifdef CONFIG_ARCH_OMAP4
+static struct dmm omap4_plat_data[] = {
+ {
+ .oh_name = "dmm",
+ },
+};
+#define NUM_PDATA ARRAY_SIZE(omap4_plat_data)
+#else
+#define omap4_plat_data NULL
+#define NUM_PDATA 0
+#endif
+
+static struct omap_device_pm_latency omap_dmm_latency[] = {
+ [0] = {
+ .deactivate_func = omap_device_idle_hwmods,
+ .activate_func = omap_device_enable_hwmods,
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+ },
+};
+
+static s32 __init dmm_omap_init(void)
+{
+ struct omap_hwmod *oh = NULL;
+ struct omap_device *od = NULL;
+ struct omap_device_pm_latency *ohl = NULL;
+ int ohlc = 0, i = 0;
+
+ plat_data = omap4_plat_data;
+ pdata = NUM_PDATA;
+
+ for (i = 0; i < pdata; i++) {
+ struct dmm *data = &plat_data[i];
+
+ oh = omap_hwmod_lookup(data->oh_name);
+ if (!oh)
+ goto error;
+
+ data->base = oh->_mpu_rt_va;
+ ohl = omap_dmm_latency;
+ ohlc = ARRAY_SIZE(omap_dmm_latency);
+
+ od = omap_device_build(data->oh_name, i, oh, data,
+ sizeof(*data), ohl, ohlc, false);
+ if (IS_ERR(od))
+ goto error;
+ }
+ return 0;
+error:
+ return -ENODEV;
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("David Sin <[email protected]>");
+device_initcall(dmm_omap_init);
--
1.7.0.4

2010-12-06 22:16:24

by David Sin

[permalink] [raw]
Subject: [PATCH 2/9] TILER-DMM: Container manager interface and utility definitons

From: Lajos Molnar <[email protected]>

This patch defined the TILER Container Manager (TCM) interface and
provides utility methods for implementing a TCM.

Signed-off-by: Lajos Molnar <[email protected]>
Signed-off-by: David Sin <[email protected]>
Signed-off-by: Ravi Ramachandra <[email protected]>
---
drivers/misc/tiler/tcm.h | 171 ++++++++++++++++++++++++++++++++++++
drivers/misc/tiler/tcm/tcm-utils.h | 51 +++++++++++
2 files changed, 222 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/tiler/tcm.h
create mode 100644 drivers/misc/tiler/tcm/tcm-utils.h

diff --git a/drivers/misc/tiler/tcm.h b/drivers/misc/tiler/tcm.h
new file mode 100644
index 0000000..8968108
--- /dev/null
+++ b/drivers/misc/tiler/tcm.h
@@ -0,0 +1,171 @@
+/*
+ * TILER container manager specification and support functions for TI
+ * TILER driver.
+ *
+ * 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 TCM_H
+#define TCM_H
+
+struct tcm;
+
+/* point */
+struct tcm_pt {
+ u16 x;
+ u16 y;
+};
+
+/* 2d area */
+struct tcm_area {
+ struct tcm *tcm; /* parent */
+ struct tcm_pt p0;
+ struct tcm_pt p1;
+};
+
+struct tcm {
+ u16 width, height; /* container dimensions */
+
+ /*
+ * 'pvt' structure shall contain any tcm details (attr) along with
+ * linked list of allocated areas and mutex for mutually exclusive
+ * access to the list. It may also contain copies of width and height
+ * to notice any changes to the publicly available width and height
+ * fields.
+ */
+ void *pvt;
+
+ /* function table */
+ s32 (*reserve_2d)(struct tcm *tcm, u16 height, u16 width, u8 align,
+ struct tcm_area *area);
+ s32 (*free) (struct tcm *tcm, struct tcm_area *area);
+ void (*deinit) (struct tcm *tcm);
+};
+
+/*
+ * Since some basic parameter checking is done outside the TCM algorithms,
+ * TCM implementation do NOT have to check the following:
+ *
+ * area pointer is NULL
+ * width and height fits within container
+ * number of pages is more than the size of the container
+ */
+
+/*
+ * Template for <ALGO_NAME>_tcm_init method. Define as:
+ * TCM_INIT(<ALGO_NAME>_tcm_init)
+ *
+ * Allocates and initializes a tiler container manager.
+ *
+ * Pointer to the allocated and initialized container manager.
+ * NULL on failure. DO NOT leak any memory on failure!
+ */
+#define TCM_INIT(name, attr_t) \
+struct tcm *name(u16 width, u16 height, typeof(attr_t) *attr);
+
+/*
+ * Deinitialize tiler container manager.
+ *
+ * The call should free as much memory as possible and meaningful
+ * even on failure. Some error codes: -ENODEV: invalid manager.
+ */
+static inline void tcm_deinit(struct tcm *tcm)
+{
+ if (tcm)
+ tcm->deinit(tcm);
+}
+
+/*
+ * Reserves a 2D area in the container.
+ *
+ * The tcm field of the area will be set to NULL on failure.
+ * Some error codes: -ENODEV: invalid manager, -EINVAL:
+ * invalid area, -ENOMEM: not enough space for allocation.
+ */
+static inline s32 tcm_reserve_2d(struct tcm *tcm, u16 width, u16 height,
+ u16 align, struct tcm_area *area)
+{
+ /* perform rudimentary error checking */
+ s32 res = (tcm == NULL ? -ENODEV :
+ (area == NULL || width == 0 || height == 0 ||
+ /* align must be a 2 power */
+ align & (align - 1)) ? -EINVAL :
+ (height > tcm->height || width > tcm->width) ? -ENOMEM :
+ tcm->reserve_2d(tcm, height, width, align, area));
+
+ if (area)
+ area->tcm = res ? NULL : tcm;
+
+ return res;
+}
+
+/*
+ * Free a previously reserved area from the container.
+ *
+ * The tcm field of the area is set to NULL on success
+ * to avoid subsequent freeing. This call will succeed
+ * even if supplying the area from a failed reserved call.
+ */
+static inline s32 tcm_free(struct tcm_area *area)
+{
+ s32 res = 0; /* free succeeds by default */
+
+ if (area && area->tcm) {
+ res = area->tcm->free(area->tcm, area);
+ if (res == 0)
+ area->tcm = NULL;
+ }
+
+ return res;
+}
+
+/* Verify if a tcm area is logically valid */
+static inline bool tcm_area_is_valid(struct tcm_area *area)
+{
+ return area && area->tcm &&
+ /* coordinate bounds */
+ area->p1.x < area->tcm->width &&
+ area->p1.y < area->tcm->height &&
+ area->p0.y <= area->p1.y &&
+ area->p0.x <= area->p1.x;
+}
+
+/* see if a coordinate is within an area */
+static inline bool __tcm_is_in(struct tcm_pt *p, struct tcm_area *a)
+{
+ return p->x >= a->p0.x && p->x <= a->p1.x &&
+ p->y >= a->p0.y && p->y <= a->p1.y;
+}
+
+/* calculate area width */
+static inline u16 __tcm_area_width(struct tcm_area *area)
+{
+ return area->p1.x - area->p0.x + 1;
+}
+
+/* calculate area height */
+static inline u16 __tcm_area_height(struct tcm_area *area)
+{
+ return area->p1.y - area->p0.y + 1;
+}
+
+/* calculate number of slots in an area */
+static inline u16 __tcm_sizeof(struct tcm_area *area)
+{
+ return __tcm_area_width(area) * __tcm_area_height(area);
+}
+#define tcm_sizeof(area) __tcm_sizeof(&(area))
+#define tcm_awidth(area) __tcm_area_width(&(area))
+#define tcm_aheight(area) __tcm_area_height(&(area))
+#define tcm_is_in(pt, area) __tcm_is_in(&(pt), &(area))
+
+#endif
diff --git a/drivers/misc/tiler/tcm/tcm-utils.h b/drivers/misc/tiler/tcm/tcm-utils.h
new file mode 100644
index 0000000..400c2fe
--- /dev/null
+++ b/drivers/misc/tiler/tcm/tcm-utils.h
@@ -0,0 +1,51 @@
+/*
+ * Utility functions for implementing TILER container managers.
+ *
+ * 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 TCM_UTILS_H
+#define TCM_UTILS_H
+
+#include "../tcm.h"
+
+/* TCM_ALG_NAME must be defined to use the debug methods */
+
+#ifdef DEBUG
+#define IFDEBUG(x) x
+#else
+/* compile-check debug statements even if not DEBUG */
+#define IFDEBUG(x) do { if (0) x; } while (0)
+#endif
+
+#define P(level, fmt, ...) \
+ IFDEBUG(printk(level TCM_ALG_NAME ":%d:%s()" fmt "\n", \
+ __LINE__, __func__, ##__VA_ARGS__))
+
+#define P1(fmt, ...) P(KERN_NOTICE, fmt, ##__VA_ARGS__)
+#define P2(fmt, ...) P(KERN_INFO, fmt, ##__VA_ARGS__)
+#define P3(fmt, ...) P(KERN_DEBUG, fmt, ##__VA_ARGS__)
+
+#define PA(level, msg, p_area) P##level(msg " (%03d %03d)-(%03d %03d)\n", \
+ (p_area)->p0.x, (p_area)->p0.y, (p_area)->p1.x, (p_area)->p1.y)
+
+/* assign coordinates to area */
+static inline
+void assign(struct tcm_area *a, u16 x0, u16 y0, u16 x1, u16 y1)
+{
+ a->p0.x = x0;
+ a->p0.y = y0;
+ a->p1.x = x1;
+ a->p1.y = y1;
+}
+
+#endif
--
1.7.0.4

2010-12-06 22:16:26

by David Sin

[permalink] [raw]
Subject: [PATCH 6/9] TILER-DMM: Geometry and view manipulation functions

From: Lajos Molnar <[email protected]>

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 <[email protected]>
Signed-off-by: David Sin <[email protected]>
---
drivers/misc/tiler/tiler-geom.c | 362 +++++++++++++++++++++++++++++++++++++++
drivers/misc/tiler/tiler-geom.h | 48 +++++
2 files changed, 410 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/tiler/tiler-geom.c
create mode 100644 drivers/misc/tiler/tiler-geom.h

diff --git a/drivers/misc/tiler/tiler-geom.c b/drivers/misc/tiler/tiler-geom.c
new file mode 100644
index 0000000..c94193b
--- /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-geom.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_GPL(is_tiler_addr);
+
+u32 tiler_bpp(const struct tiler_block_t *b)
+{
+ enum tiler_fmt fmt = tiler_fmt(b->phys);
+ WARN_ON(fmt == TILFMT_INVALID || fmt == TILFMT_PAGE);
+
+ return geom[fmt].bpp;
+}
+EXPORT_SYMBOL_GPL(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);
+ WARN_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_GPL(tiler_pstride);
+
+enum tiler_fmt tiler_fmt(u32 phys)
+{
+ if (!is_tiler_addr(phys))
+ return TILFMT_INVALID;
+
+ return TILER_FMT(phys);
+}
+EXPORT_SYMBOL_GPL(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)
+{
+ WARN_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_GPL(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_GPL(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_GPL(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_GPL(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_GPL(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);
+ }
+}
diff --git a/drivers/misc/tiler/tiler-geom.h b/drivers/misc/tiler/tiler-geom.h
new file mode 100644
index 0000000..f73bcf2
--- /dev/null
+++ b/drivers/misc/tiler/tiler-geom.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_GEOM_H
+#define TILER_GEOM_H
+
+#include <linux/kernel.h>
+#include <linux/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
--
1.7.0.4

2010-12-06 22:16:59

by David Sin

[permalink] [raw]
Subject: [PATCH 8/9] TILER-DMM: Linking TILER driver into the Linux kernel build

From: Lajos Molnar <[email protected]>

This patch links the TILER driver into the Linux kernel build
and config system.

Signed-off-by: Lajos Molnar <[email protected]>
Signed-off-by: David Sin <[email protected]>
---
drivers/misc/Kconfig | 1 +
drivers/misc/Makefile | 1 +
2 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 4d073f1..1ebc655 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -457,5 +457,6 @@ source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
source "drivers/misc/iwmc3200top/Kconfig"
source "drivers/misc/ti-st/Kconfig"
+source "drivers/misc/tiler/Kconfig"

endif # MISC_DEVICES
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 98009cc..3716c49 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -42,3 +42,4 @@ obj-$(CONFIG_ARM_CHARLCD) += arm-charlcd.o
obj-$(CONFIG_PCH_PHUB) += pch_phub.o
obj-y += ti-st/
obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o
+obj-$(CONFIG_TI_TILER) += tiler/
--
1.7.0.4

2010-12-06 22:17:39

by David Sin

[permalink] [raw]
Subject: [PATCH 4/9] TILER-DMM: TILER Memory Manager interface and implementation

From: Lajos Molnar <[email protected]>

This patch defines the TILER Memory Manager (TMM) interface and
provides implementation for a PAT-supporting TMM.

Signed-off-by: Lajos Molnar <[email protected]>
Signed-off-by: David Sin <[email protected]>
---
drivers/misc/tiler/tmm-pat.c | 266 ++++++++++++++++++++++++++++++++++++++++++
drivers/misc/tiler/tmm.h | 103 ++++++++++++++++
2 files changed, 369 insertions(+), 0 deletions(-)
create mode 100644 drivers/misc/tiler/tmm-pat.c
create mode 100644 drivers/misc/tiler/tmm.h

diff --git a/drivers/misc/tiler/tmm-pat.c b/drivers/misc/tiler/tmm-pat.c
new file mode 100644
index 0000000..682f549
--- /dev/null
+++ b/drivers/misc/tiler/tmm-pat.c
@@ -0,0 +1,266 @@
+/*
+ * DMM driver support 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/init.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/mmzone.h>
+#include <asm/cacheflush.h>
+#include <linux/mutex.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include "tmm.h"
+
+/* Page size granularity can be 4k, 16k, or 64k */
+#define DMM_PAGE SZ_4K
+
+/* Memory limit to cache free pages. TILER will eventually use this much */
+static u32 cache_limit = CONFIG_TILER_CACHE_LIMIT << 20;
+module_param_named(cache, cache_limit, uint, 0644);
+MODULE_PARM_DESC(cache, "Cache free pages if total memory is under this limit");
+
+/* global state - statically initialized */
+static LIST_HEAD(free_list); /* page cache: list of free pages */
+static u32 total_mem; /* total memory allocated (free & used) */
+static u32 refs; /* number of tmm_pat instances */
+static DEFINE_MUTEX(mtx); /* global mutex */
+
+/* The page struct pointer and physical address of each page.*/
+struct mem {
+ struct list_head list;
+ u32 *pg; /* page struct */
+ dma_addr_t pa; /* physical address */
+};
+
+/* Used to keep track of mem per tmm_pat_get_pages call */
+struct fast {
+ struct list_head list;
+ struct mem **mem; /* array of page info */
+ u32 *pa; /* array of physical addresses */
+ u32 num; /* number of pages */
+};
+
+/* TMM PAT private structure */
+struct dmm_mem {
+ struct list_head fast_list;
+ struct dmm *dmm;
+};
+
+/*
+ * Frees pages in a fast structure. Moves pages to the free list if there
+ * are less pages used than max_to_keep. Otherwise, it frees the pages
+ */
+static void free_fast(struct fast *f)
+{
+ s32 i = 0;
+
+ /* mutex is locked */
+ for (i = 0; i < f->num; i++) {
+ if (total_mem < cache_limit) {
+ /* cache free page if under the limit */
+ list_add(&f->mem[i]->list, &free_list);
+ } else {
+ /* otherwise, free */
+ total_mem -= PAGE_SIZE;
+ dma_free_coherent(NULL, DMM_PAGE, f->mem[i]->pg,
+ f->mem[i]->pa);
+ }
+ }
+ kfree(f->pa);
+ kfree(f->mem);
+ /* remove only if element was added */
+ if (f->list.next)
+ list_del(&f->list);
+ kfree(f);
+}
+
+/* allocate and flush a page */
+static struct mem *alloc_mem(void)
+{
+ struct mem *m = kzalloc(sizeof(*m), GFP_KERNEL);
+ if (!m)
+ return NULL;
+
+ m->pg = dma_alloc_coherent(NULL, DMM_PAGE, &m->pa, GFP_KERNEL);
+ if (!m->pg) {
+ kfree(m);
+ return NULL;
+ }
+ wmb();
+
+ return m;
+}
+
+static void free_page_cache(void)
+{
+ struct mem *m, *m_;
+
+ /* mutex is locked */
+ list_for_each_entry_safe(m, m_, &free_list, list) {
+ dma_free_coherent(NULL, DMM_PAGE, m->pg, m->pa);
+ total_mem -= PAGE_SIZE;
+ list_del(&m->list);
+ kfree(m);
+ }
+}
+
+static void tmm_pat_deinit(struct tmm *tmm)
+{
+ struct fast *f, *f_;
+ struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
+
+ mutex_lock(&mtx);
+
+ /* free all outstanding used memory */
+ list_for_each_entry_safe(f, f_, &pvt->fast_list, list)
+ free_fast(f);
+
+ /* if this is the last tmm_pat, free all memory */
+ if (--refs == 0)
+ free_page_cache();
+
+ mutex_unlock(&mtx);
+}
+
+static u32 *tmm_pat_get_pages(struct tmm *tmm, u32 n)
+{
+ struct mem *m;
+ struct fast *f;
+ struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
+
+ f = kzalloc(sizeof(*f), GFP_KERNEL);
+ if (!f)
+ return NULL;
+
+ /* array of mem struct pointers */
+ f->mem = kzalloc(n * sizeof(*f->mem), GFP_KERNEL);
+
+ /* array of physical addresses */
+ f->pa = kzalloc(n * sizeof(*f->pa), GFP_KERNEL);
+
+ /* no pages have been allocated yet (needed for cleanup) */
+ f->num = 0;
+
+ if (!f->mem || !f->pa)
+ goto cleanup;
+
+ /* fill out fast struct mem array with free pages */
+ mutex_lock(&mtx);
+ while (f->num < n) {
+ /* if there is a free cached page use it */
+ if (!list_empty(&free_list)) {
+ /* unbind first element from list */
+ m = list_first_entry(&free_list, typeof(*m), list);
+ list_del(&m->list);
+ } else {
+ mutex_unlock(&mtx);
+
+ /*
+ * Unlock mutex during allocation and cache flushing.
+ */
+ m = alloc_mem();
+ if (!m)
+ goto cleanup;
+
+ mutex_lock(&mtx);
+ total_mem += PAGE_SIZE;
+ }
+
+ f->mem[f->num] = m;
+ f->pa[f->num++] = m->pa;
+ }
+
+ list_add(&f->list, &pvt->fast_list);
+ mutex_unlock(&mtx);
+ return f->pa;
+
+cleanup:
+ free_fast(f);
+ return NULL;
+}
+
+static void tmm_pat_free_pages(struct tmm *tmm, u32 *page_list)
+{
+ struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
+ struct fast *f, *f_;
+
+ mutex_lock(&mtx);
+ /* find fast struct based on 1st page */
+ list_for_each_entry_safe(f, f_, &pvt->fast_list, list) {
+ if (f->pa[0] == page_list[0]) {
+ free_fast(f);
+ break;
+ }
+ }
+ mutex_unlock(&mtx);
+}
+
+static s32 tmm_pat_map(struct tmm *tmm, struct pat_area area, u32 page_pa)
+{
+ struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
+ struct pat pat_desc = {NULL};
+
+ /* send pat descriptor to dmm driver */
+ pat_desc.ctrl.dir = 0;
+ pat_desc.ctrl.ini = 0;
+ pat_desc.ctrl.lut_id = 0;
+ pat_desc.ctrl.start = 1;
+ pat_desc.ctrl.sync = 0;
+ pat_desc.area = area;
+ pat_desc.next = NULL;
+
+ /* must be a 16-byte aligned physical address */
+ pat_desc.data = page_pa;
+ return dmm_pat_refill(pvt->dmm, &pat_desc, MANUAL);
+}
+
+struct tmm *tmm_pat_init(u32 pat_id)
+{
+ struct tmm *tmm = NULL;
+ struct dmm_mem *pvt = NULL;
+
+ struct dmm *dmm = dmm_pat_init(pat_id);
+ if (dmm)
+ tmm = kzalloc(sizeof(*tmm), GFP_KERNEL);
+ if (tmm)
+ pvt = kzalloc(sizeof(*pvt), GFP_KERNEL);
+ if (pvt) {
+ /* private data */
+ pvt->dmm = dmm;
+ INIT_LIST_HEAD(&pvt->fast_list);
+
+ /* increate tmm_pat references */
+ mutex_lock(&mtx);
+ refs++;
+ mutex_unlock(&mtx);
+
+ /* public data */
+ tmm->pvt = pvt;
+ tmm->deinit = tmm_pat_deinit;
+ tmm->get = tmm_pat_get_pages;
+ tmm->free = tmm_pat_free_pages;
+ tmm->map = tmm_pat_map;
+ tmm->clear = NULL; /* not yet supported */
+
+ return tmm;
+ }
+
+ kfree(pvt);
+ kfree(tmm);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(tmm_pat_init);
diff --git a/drivers/misc/tiler/tmm.h b/drivers/misc/tiler/tmm.h
new file mode 100644
index 0000000..cb90664
--- /dev/null
+++ b/drivers/misc/tiler/tmm.h
@@ -0,0 +1,103 @@
+/*
+ * TMM interface definition for TI TILER driver.
+ *
+ * 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 TMM_H
+#define TMM_H
+
+#include <mach/dmm.h>
+/*
+ * TMM interface
+ */
+struct tmm {
+ void *pvt;
+
+ /* function table */
+ u32 *(*get) (struct tmm *tmm, u32 num_pages);
+ void (*free) (struct tmm *tmm, u32 *pages);
+ s32 (*map) (struct tmm *tmm, struct pat_area area, u32 page_pa);
+ void (*clear) (struct tmm *tmm, struct pat_area area);
+ void (*deinit) (struct tmm *tmm);
+};
+
+/*
+ * Request a set of pages from the DMM free page stack.
+ * Return a pointer to a list of physical page addresses.
+ */
+static inline
+u32 *tmm_get(struct tmm *tmm, u32 num_pages)
+{
+ if (tmm && tmm->pvt)
+ return tmm->get(tmm, num_pages);
+ return NULL;
+}
+
+/*
+ * Return a set of used pages to the DMM free page stack.
+ */
+static inline
+void tmm_free(struct tmm *tmm, u32 *pages)
+{
+ if (tmm && tmm->pvt)
+ tmm->free(tmm, pages);
+}
+
+/*
+ * Program the physical address translator.
+ */
+static inline
+s32 tmm_map(struct tmm *tmm, struct pat_area area, u32 page_pa)
+{
+ if (tmm && tmm->map && tmm->pvt)
+ return tmm->map(tmm, area, page_pa);
+ return -ENODEV;
+}
+
+/*
+ * Clears the physical address translator.
+ */
+static inline
+void tmm_clear(struct tmm *tmm, struct pat_area area)
+{
+ if (tmm && tmm->clear && tmm->pvt)
+ tmm->clear(tmm, area);
+}
+
+/*
+ * Checks whether tiler memory manager supports mapping
+ */
+static inline
+bool tmm_can_map(struct tmm *tmm)
+{
+ return tmm && tmm->map;
+}
+
+/*
+ * Deinitialize tiler memory manager
+ */
+static inline
+void tmm_deinit(struct tmm *tmm)
+{
+ if (tmm && tmm->pvt)
+ tmm->deinit(tmm);
+}
+
+/*
+ * TMM implementation for PAT support.
+ *
+ * Initialize TMM for PAT with given id.
+ */
+struct tmm *tmm_pat_init(u32 pat_id);
+
+#endif
--
1.7.0.4

2010-12-06 22:17:24

by David Sin

[permalink] [raw]
Subject: [PATCH 1/9] TILER-DMM: DMM-PAT driver for TI TILER

This patch adds support for DMM-PAT initialization and programming.

Signed-off-by: David Sin <[email protected]>
Signed-off-by: Lajos Molnar <[email protected]>
---
arch/arm/mach-omap2/include/mach/dmm.h | 92 ++++++++++++++++
drivers/misc/tiler/dmm-main.c | 187 ++++++++++++++++++++++++++++++++
2 files changed, 279 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-omap2/include/mach/dmm.h
create mode 100644 drivers/misc/tiler/dmm-main.c

diff --git a/arch/arm/mach-omap2/include/mach/dmm.h b/arch/arm/mach-omap2/include/mach/dmm.h
new file mode 100644
index 0000000..33a1215
--- /dev/null
+++ b/arch/arm/mach-omap2/include/mach/dmm.h
@@ -0,0 +1,92 @@
+/*
+ * Dynamic Memory Manager (DMM) driver support functions for
+ * TI DMM-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.
+ */
+
+#ifndef DMM_H
+#define DMM_H
+
+#define DMM_TILER_OR__0 0x220
+#define DMM_TILER_OR__1 0x224
+#define DMM_PAT_VIEW__0 0x420
+#define DMM_PAT_VIEW__1 0x424
+#define DMM_PAT_VIEW_MAP__0 0x440
+#define DMM_PAT_VIEW_MAP_BASE 0x460
+#define DMM_PAT_IRQSTATUS_RAW 0x480
+#define DMM_PAT_IRQSTATUS 0x490
+#define DMM_PAT_STATUS__0 0x4C0
+#define DMM_PAT_DESCR__0 0x500
+#define DMM_PAT_AREA__0 0x504
+#define DMM_PAT_CTRL__0 0x508
+#define DMM_PAT_DATA__0 0x50C
+
+/*
+ * Physical Address Translator (PAT) refill programming mode
+ */
+enum pat_mode {
+ MANUAL,
+ AUTO
+};
+
+/*
+ * Area definition for DMM physical address translator
+ */
+struct pat_area {
+ s8 x0:8;
+ s8 y0:8;
+ s8 x1:8;
+ s8 y1:8;
+};
+
+/*
+ * DMM physical address translator control
+ */
+struct pat_ctrl {
+ s32 start:4;
+ s32 dir:4;
+ s32 lut_id:8;
+ s32 sync:12;
+ s32 ini:4;
+};
+
+/*
+ * Physical Address Translator (PAT) descriptor
+ */
+struct pat {
+ struct pat *next;
+ struct pat_area area;
+ struct pat_ctrl ctrl;
+ u32 data;
+};
+
+/*
+ * DMM device data
+ */
+struct dmm {
+ const char *oh_name;
+ void __iomem *base;
+ int irq;
+};
+
+/*
+ * Create and initialize the physical address translator
+ */
+struct dmm *dmm_pat_init(u32 id);
+
+/*
+ * Program the physical address translator
+ */
+int dmm_pat_refill(struct dmm *dmm, struct pat *desc, enum pat_mode mode);
+
+#endif
diff --git a/drivers/misc/tiler/dmm-main.c b/drivers/misc/tiler/dmm-main.c
new file mode 100644
index 0000000..f337bd9
--- /dev/null
+++ b/drivers/misc/tiler/dmm-main.c
@@ -0,0 +1,187 @@
+/*
+ * DMM driver support functions for TI OMAP processors.
+ *
+ * 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/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+
+#include <mach/dmm.h>
+
+#define MASK(msb, lsb) (((1 << ((msb) + 1 - (lsb))) - 1) << (lsb))
+#define SET_FLD(reg, msb, lsb, val) \
+(((reg) & ~MASK((msb), (lsb))) | (((val) << (lsb)) & MASK((msb), (lsb))))
+#define MAX_RETRY_MS 1000
+
+static struct dmm *dmm;
+
+static int dmm_probe(struct platform_device *dev)
+{
+ if (dev)
+ dmm = dev->dev.platform_data;
+
+ if (dmm && dmm->base) {
+ writel(0x88888888, dmm->base + DMM_TILER_OR__0);
+ writel(0x88888888, dmm->base + DMM_TILER_OR__1);
+ return 0;
+ }
+ return -EFAULT;
+}
+
+static int dmm_remove(struct platform_device *dev)
+{
+ return 0;
+}
+
+static struct platform_driver dmm_driver = {
+ .probe = dmm_probe,
+ .remove = dmm_remove,
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "dmm",
+ },
+};
+
+int dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode)
+{
+ void __iomem *r;
+ u32 v, i;
+
+ if (!dmm || !dmm->base || !pd)
+ return -EFAULT;
+
+ /* Only manual refill supported */
+ if (mode != MANUAL)
+ return -EFAULT;
+
+ /* Check that the DMM_PAT_STATUS register has not reported an error */
+ r = dmm->base + DMM_PAT_STATUS__0;
+ v = readl(r);
+ if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
+ return -EIO;
+
+ /* Set "next" register to NULL */
+ r = dmm->base + DMM_PAT_DESCR__0;
+ v = readl(r);
+ v = SET_FLD(v, 31, 4, (u32) NULL);
+ writel(v, r);
+
+ /* Set area to be refilled */
+ r = dmm->base + DMM_PAT_AREA__0;
+ v = readl(r);
+ v = SET_FLD(v, 30, 24, pd->area.y1);
+ v = SET_FLD(v, 23, 16, pd->area.x1);
+ v = SET_FLD(v, 14, 8, pd->area.y0);
+ v = SET_FLD(v, 7, 0, pd->area.x0);
+ writel(v, r);
+
+ /* First, clear the DMM_PAT_IRQSTATUS register */
+ writel(0xFFFFFFFF, dmm->base + DMM_PAT_IRQSTATUS);
+
+ i = 1000;
+ while (readl(dmm->base + DMM_PAT_IRQSTATUS_RAW) != 0) {
+ if (--i == 0)
+ return -EFAULT;
+ udelay(1);
+ }
+
+ /* Fill data register */
+ v = readl(dmm->base + DMM_PAT_DATA__0);
+
+ v = SET_FLD(v, 31, 4, pd->data >> 4);
+ writel(v, r);
+
+ /* Read back PAT_DATA__0 to see if write was successful */
+ i = 1000;
+ while (readl(r) != pd->data) {
+ if (--i == 0)
+ return -EFAULT;
+ udelay(1);
+ }
+
+ v = readl(dmm->base + DMM_PAT_CTRL__0);
+ v = SET_FLD(v, 31, 28, pd->ctrl.ini);
+ v = SET_FLD(v, 16, 16, pd->ctrl.sync);
+ v = SET_FLD(v, 9, 8, pd->ctrl.lut_id);
+ v = SET_FLD(v, 6, 4, pd->ctrl.dir);
+ v = SET_FLD(v, 0, 0, pd->ctrl.start);
+ writel(v, r);
+
+ /* Check if PAT_IRQSTATUS_RAW is set after the PAT has been refilled */
+ i = 1000;
+ while ((readl(dmm->base + DMM_PAT_IRQSTATUS_RAW) & 0x3) != 0x3) {
+ if (--i == 0)
+ return -EFAULT;
+ udelay(1);
+ }
+
+ /* Again, clear the DMM_PAT_IRQSTATUS register */
+ writel(0xFFFFFFFF, dmm->base + DMM_PAT_IRQSTATUS);
+
+ i = 1000;
+ while (readl(dmm->base + DMM_PAT_IRQSTATUS_RAW) != 0) {
+ if (--i == 0)
+ return -EFAULT;
+ udelay(1);
+ }
+
+ /* Again, set "next" register to NULL to clear any PAT STATUS errors */
+ v = readl(dmm->base + DMM_PAT_DESCR__0);
+ v = SET_FLD(v, 31, 4, (u32) NULL);
+ writel(v, r);
+
+ /*
+ * Now, check that the DMM_PAT_STATUS register
+ * has not reported an error before exiting.
+ */
+ v = readl(dmm->base + DMM_PAT_STATUS__0);
+ if (WARN(v & 0xFC00, KERN_ERR "dmm_pat_refill() error.\n"))
+ return -EIO;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(dmm_pat_refill);
+
+struct dmm *dmm_pat_init(u32 id)
+{
+ if (dmm && dmm->base) {
+ writel(0x88888888, dmm->base + DMM_PAT_VIEW__0);
+ writel(0x88888888, dmm->base + DMM_PAT_VIEW__1);
+ writel(0x80808080, dmm->base + DMM_PAT_VIEW_MAP__0);
+ writel(0x80000000, dmm->base + DMM_PAT_VIEW_MAP_BASE);
+ }
+
+ return dmm;
+}
+EXPORT_SYMBOL_GPL(dmm_pat_init);
+
+static s32 __init dmm_init(void)
+{
+ return platform_driver_register(&dmm_driver);
+}
+
+static void __exit dmm_exit(void)
+{
+ platform_driver_unregister(&dmm_driver);
+}
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("David Sin <[email protected]>");
+MODULE_AUTHOR("Lajos Molnar <[email protected]>");
+module_init(dmm_init);
+module_exit(dmm_exit);
--
1.7.0.4

2010-12-06 23:22:19

by Tony Lindgren

[permalink] [raw]
Subject: Re: [PATCH 7/9] TILER-DMM: Main TILER driver implementation

Hi,

* David Sin <[email protected]> [101206 14:09]:
> From: Lajos Molnar <[email protected]>
>
> This patch contains the TILER driver and implementation of the TILER
> block manipulation and mapping functions.
>
> It also contains the makefile and config file for the TILER driver.

...
> +config TILER_GRANULARITY
> + int "Allocation granularity"
> + range 1 4096
> + default 128
...
> +config TILER_ALIGNMENT
> + int "Allocation alignment"
> + range 1 4096
> + default 4096
...
> +config TILER_CACHE_LIMIT
> + int "Memory limit to cache free pages in MBytes"
> + range 0 128
> + default 40
...

Do you really need these Kconfig options? To me it seems you
should pass these in platform_data.

Regards,

Tony

2010-12-13 17:20:52

by David Sin

[permalink] [raw]
Subject: Re: [PATCH 7/9] TILER-DMM: Main TILER driver implementation

On Mon, Dec 06, 2010 at 03:21:59PM -0800, Tony Lindgren wrote:
> Hi,
>
> * David Sin <[email protected]> [101206 14:09]:
> > From: Lajos Molnar <[email protected]>
> >
> > This patch contains the TILER driver and implementation of the TILER
> > block manipulation and mapping functions.
> >
> > It also contains the makefile and config file for the TILER driver.
>
> ...
> > +config TILER_GRANULARITY
> > + int "Allocation granularity"
> > + range 1 4096
> > + default 128
> ...
> > +config TILER_ALIGNMENT
> > + int "Allocation alignment"
> > + range 1 4096
> > + default 4096
> ...
> > +config TILER_CACHE_LIMIT
> > + int "Memory limit to cache free pages in MBytes"
> > + range 0 128
> > + default 40
> ...
>
> Do you really need these Kconfig options? To me it seems you
> should pass these in platform_data.
>
> Regards,
>
> Tony
Hi Tony,
No -- we don't really need these here, but we thought that
it would be an easy way for the user to set them -- esp the
CACHE_LIMIT. We can actually remove themi, since it's not
going to change very often, and add it to plat data later.
I'll revise the patch. BTW, Are you going to be the one to
merge this code?

Regards,
--
David Sin

2010-12-16 13:35:10

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 0/9] TI DMM-TILER driver

On Monday 06 December 2010, David Sin wrote:
> Tiling and Isometric Lightweight Engine for Rotation (TILER) driver
> =====
>
> Dynamic Memory Manager (DMM) is a hardware block made by Texas Instruments.
> Within the DMM exists at least one TILER hardware component. Its purpose is to
> organize video/image memory in a 2-dimensional fashion to limit memory
> bandwidth and facilitate 0 effort rotation and mirroring. The TILER driver
> facilitates allocating, freeing, as well as mapping 2D blocks (areas) in the
> TILER container(s). It also facilitates rotating and mirroring the allocated
> blocks or its rectangular subsections.

How does this relate to DRM/GEM? I don't understand too much about graphics
drivers, but it does sound like there is some overlap in functionality.

I guess at the very least the DMM should live in drivers/gpu/ instead of
drivers/misc, but perhaps it could be integrated more closely with the
existing code there.

Arnd

2010-12-16 17:13:19

by David Sin

[permalink] [raw]
Subject: Re: [PATCH 0/9] TI DMM-TILER driver

On Thu, Dec 16, 2010 at 02:34:05PM +0100, Arnd Bergmann wrote:
> On Monday 06 December 2010, David Sin wrote:
> > Tiling and Isometric Lightweight Engine for Rotation (TILER) driver
> > =====
> >
> > Dynamic Memory Manager (DMM) is a hardware block made by Texas Instruments.
> > Within the DMM exists at least one TILER hardware component. Its purpose is to
> > organize video/image memory in a 2-dimensional fashion to limit memory
> > bandwidth and facilitate 0 effort rotation and mirroring. The TILER driver
> > facilitates allocating, freeing, as well as mapping 2D blocks (areas) in the
> > TILER container(s). It also facilitates rotating and mirroring the allocated
> > blocks or its rectangular subsections.
>
> How does this relate to DRM/GEM? I don't understand too much about graphics
> drivers, but it does sound like there is some overlap in functionality.
>
> I guess at the very least the DMM should live in drivers/gpu/ instead of
> drivers/misc, but perhaps it could be integrated more closely with the
> existing code there.
>
> Arnd
Do you know if anyone on your team is familiar with DRM/GEM (grap ext mgr)
for x86? I'm trying to understand the differences and make a case that
it's not the same as DMM/TILER.

thanks,
--
David Sin

2010-12-16 17:25:21

by David Sin

[permalink] [raw]
Subject: Re: [PATCH 0/9] TI DMM-TILER driver

On Thu, Dec 16, 2010 at 11:25:31AM -0600, David Sin wrote:
> On Thu, Dec 16, 2010 at 02:34:05PM +0100, Arnd Bergmann wrote:
> > On Monday 06 December 2010, David Sin wrote:
> > > Tiling and Isometric Lightweight Engine for Rotation (TILER) driver
> > > =====
> > >
> > > Dynamic Memory Manager (DMM) is a hardware block made by Texas Instruments.
> > > Within the DMM exists at least one TILER hardware component. Its purpose is to
> > > organize video/image memory in a 2-dimensional fashion to limit memory
> > > bandwidth and facilitate 0 effort rotation and mirroring. The TILER driver
> > > facilitates allocating, freeing, as well as mapping 2D blocks (areas) in the
> > > TILER container(s). It also facilitates rotating and mirroring the allocated
> > > blocks or its rectangular subsections.
> >
> > How does this relate to DRM/GEM? I don't understand too much about graphics
> > drivers, but it does sound like there is some overlap in functionality.
> >
> > I guess at the very least the DMM should live in drivers/gpu/ instead of
> > drivers/misc, but perhaps it could be integrated more closely with the
> > existing code there.
> >
> > Arnd
> Do you know if anyone on your team is familiar with DRM/GEM (grap ext mgr)
> for x86? I'm trying to understand the differences and make a case that
> it's not the same as DMM/TILER.
>
> thanks,
> --
> David Sin
Hi Arnd,
I'm not sure exactly how DRM/GEM works.. What functionality do you think is
overlapping? The main feature, aside from reduced page accesses, of the DMM
hw block is to provide physically contiguous 2 dimensional memory blocks for
image and video processing. This hw sits between the interconnect and the
ext memory interface in the OMAP, and contains an MMU-like address traslator
for "virtually" physically contiguous memory and sdram pages.

thank you for your comments.

BR,
--
David Sin

2010-12-16 17:44:05

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH 0/9] TI DMM-TILER driver

On Thursday 16 December 2010 18:37:38 David Sin wrote:
> I'm not sure exactly how DRM/GEM works.. What functionality do you think is
> overlapping? The main feature, aside from reduced page accesses, of the DMM
> hw block is to provide physically contiguous 2 dimensional memory blocks for
> image and video processing. This hw sits between the interconnect and the
> ext memory interface in the OMAP, and contains an MMU-like address traslator
> for "virtually" physically contiguous memory and sdram pages.

As far as I can tell, both DMM and GEM at a high level manage objects
in video memory. The IOMMU that you have on the Omap hardware seems
to resemble the GART that sits between PC-style video cards and main
memory.

I don't know any details, but google quickly finds
http://lwn.net/Articles/283798/ with a description of the
initial GEM design. My main thought when looking over the
DMM code was that this should not be tied too closely to a
specific hardware, and GEM seems to be an existing abstraction
that may fit what you need.

Arnd

2010-12-16 18:49:55

by David Sin

[permalink] [raw]
Subject: Re: [PATCH 0/9] TI DMM-TILER driver

On Thu, Dec 16, 2010 at 06:43:48PM +0100, Arnd Bergmann wrote:
> As far as I can tell, both DMM and GEM at a high level manage objects
> in video memory. The IOMMU that you have on the Omap hardware seems
> to resemble the GART that sits between PC-style video cards and main
> memory.
>
> I don't know any details, but google quickly finds
> http://lwn.net/Articles/283798/ with a description of the
> initial GEM design. My main thought when looking over the
> DMM code was that this should not be tied too closely to a
> specific hardware, and GEM seems to be an existing abstraction
> that may fit what you need.
>
> Arnd
Thanks for the pointer, Arnd. I also found a nice readme file in
the gpu/drm directory, which points to a wiki and source code.
I'll read into this and get back to you.

BR,
--
David Sin

2010-12-16 23:28:11

by Dave Airlie

[permalink] [raw]
Subject: Re: [PATCH 0/9] TI DMM-TILER driver

On Fri, Dec 17, 2010 at 5:02 AM, David Sin <[email protected]> wrote:
> On Thu, Dec 16, 2010 at 06:43:48PM +0100, Arnd Bergmann wrote:
>> As far as I can tell, both DMM and GEM at a high level manage objects
>> in video memory. The IOMMU that you have on the Omap hardware seems
>> to resemble the GART that sits between PC-style video cards and main
>> memory.
>>
>> I don't know any details, but google quickly finds
>> http://lwn.net/Articles/283798/ with a description of the
>> initial GEM design. My main thought when looking over the
>> DMM code was that this should not be tied too closely to a
>> specific hardware, and GEM seems to be an existing abstraction
>> that may fit what you need.
>>
>> ? ? ? Arnd
> Thanks for the pointer, Arnd. ?I also found a nice readme file in
> the gpu/drm directory, which points to a wiki and source code.
> I'll read into this and get back to you.

I get the impression with the ARM graphics, that you just have a lot
of separate drivers for separate IP blocks all providing some misc
random interfaces to userspace where some binary driver binds all the
functionality together into a useful whole, which seems like a really
bad design.

Generally on x86, the tiling hw is part of the GPU and is exposed as
part of a coherent GPU driver.

I'm just wonder what the use-cases for this tiler are and what open
apps can use it for?

Dave.

2010-12-22 14:22:18

by David Sin

[permalink] [raw]
Subject: Re: [PATCH 0/9] TI DMM-TILER driver

On Fri, Dec 17, 2010 at 09:28:07AM +1000, Dave Airlie wrote:
> On Fri, Dec 17, 2010 at 5:02 AM, David Sin <[email protected]> wrote:
> I get the impression with the ARM graphics, that you just have a lot
> of separate drivers for separate IP blocks all providing some misc
> random interfaces to userspace where some binary driver binds all the
> functionality together into a useful whole, which seems like a really
> bad design.
>
> Generally on x86, the tiling hw is part of the GPU and is exposed as
> part of a coherent GPU driver.
>
> I'm just wonder what the use-cases for this tiler are and what open
> apps can use it for?
>
> Dave.
Yes -- on the omap4 soc, the dmm-tiler hw block is separate from the
gpu. I've had some, but not much, past discusions on hw designs
where graphics/video related ip blocks are part of the same core. It's
a good point that you bring up and it certainly makes sense to me.
I will bring it up with some omap hw folks that I know, and see if
something that can be considered in future omap versions.

Some of the use-cases are HD video decoding and encoding. Also,
hi-res image capture -- I believe 12MP or greater. OpenMax IL components
and other multimedia frameworks can allocate video memory
through a user space tiler library. Thanks for your comments, Dave.
--
David Sin