summaryrefslogtreecommitdiff
path: root/drivers/media/video
diff options
context:
space:
mode:
authorLajos Molnar <molnar@ti.com>2009-12-16 00:45:50 -0600
committerSantosh Shilimkar <santosh.shilimkar@ti.com>2009-12-17 21:47:12 +0530
commit7f69f6980f694809209084a6d62e8f6440fd95d8 (patch)
treef8396e8434d8079490808b6c162be879ac068349 /drivers/media/video
parent897df67901117ff31c0eabbc4d1cd33fba0925a0 (diff)
TILER: Create API to pack multiple 2D buffers.
Create API to pack multiple 2D buffers more optimally into 64- multiple width areas. Signed-off-by: Lajos Molnar <molnar@ti.com>
Diffstat (limited to 'drivers/media/video')
-rwxr-xr-xdrivers/media/video/tiler/dmm.c278
-rw-r--r--[-rwxr-xr-x]drivers/media/video/tiler/tiler.h19
2 files changed, 290 insertions, 7 deletions
diff --git a/drivers/media/video/tiler/dmm.c b/drivers/media/video/tiler/dmm.c
index b5f9b904181b..f5f00a6e1be3 100755
--- a/drivers/media/video/tiler/dmm.c
+++ b/drivers/media/video/tiler/dmm.c
@@ -66,11 +66,11 @@ static void pat_area_set(struct pat_area *area, char id);
static void pat_data_set(unsigned long data, char id);
static void pat_ctrl_set(struct pat_ctrl *ctrl, char id);
static void pat_desc_set(struct pat_desc *desc, char id);
-static void hwinfo_get();
-static void pat_view_set();
-static void pat_view_map_set();
-static void pat_view_map_base_set();
-static void tiler_or_set();
+static void hwinfo_get(void);
+static void pat_view_set(void);
+static void pat_view_map_set(void);
+static void pat_view_map_base_set(void);
+static void tiler_or_set(void);
static void tiler_or_set() /* (struct tiler_or *or, char id) */
{
@@ -545,7 +545,7 @@ __init dmm_init(void)
#else
void __iomem *reg = NULL;
dmm_base = ioremap(DMM_BASE, 0x1000);
- printk(KERN_NOTICE "dmm_base = 0x%lx", dmm_base);
+ printk(KERN_NOTICE "dmm_base = %p", dmm_base);
reg = (void __iomem *)(
(unsigned long)dmm_base | (unsigned long)LISA_MAP__0);
@@ -1344,7 +1344,7 @@ tiler_reorient_topleft(unsigned long tsptr,
unsigned int height)
{
enum dmmMemoryAccessT accessModeM;
- unsigned long x_pagew, y_pagew, x, y;
+ unsigned long x, y;
accessModeM = DMM_GET_ACC_MODE(tsptr);
@@ -1403,6 +1403,270 @@ tiler_rotate_view(struct dmmViewOrientT *orient, unsigned long rotation)
}
EXPORT_SYMBOL(tiler_rotate_view);
+#define ROUND_UP_2P(a, b) (((a) + (b) - 1) & ~((b) - 1))
+#define DIVIDE_UP(a, b) (((a) + (b) - 1) / (b))
+#define ROUND_UP(a, b) (DIVIDE_UP(a, b) * (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+void tiler_packed_alloc_buf(int *count,
+ enum tiler_fmt fmt,
+ unsigned long width,
+ unsigned long height,
+ void **sysptr,
+ void **allocptr,
+ int aligned)
+{
+ int til_width, bpp, bpt, buf_width, alloc_width, map_width;
+ int buf_map_width, n_per_m, m_per_a, i = 0, m, n;
+
+ /* Check input parameters for correctness */
+ if (!width || !height || !sysptr || !allocptr || !count ||
+ *count <= 0 || fmt < TILFMT_8BIT || fmt > TILFMT_32BIT) {
+ if (count)
+ *count = 0;
+ return;
+ }
+
+ /* tiler page width in pixels, bytes per pixel, tiler page in bytes */
+ til_width = fmt == TILFMT_32BIT ? 32 : 64;
+ bpp = 1 << (fmt - TILFMT_8BIT);
+ bpt = til_width * bpp;
+
+ /* width of buffer in tiled pages */
+ buf_width = DIVIDE_UP(width, til_width);
+
+ /* :TODO: for now tiler allocation width is 64-multiple */
+ alloc_width = ROUND_UP_2P(buf_width, 64);
+ map_width = TILER_PAGESIZE / bpt;
+
+ /* ensure alignment if needed */
+ buf_map_width = ROUND_UP_2P(buf_width, map_width);
+
+ /* number of buffers in a map window */
+ n_per_m = aligned ? 1 : (buf_map_width / buf_width);
+
+ /* number of map windows per allocation */
+ m_per_a = alloc_width / buf_map_width;
+
+ printk(KERN_INFO "packing %d*%d buffers into an allocation\n",
+ n_per_m, m_per_a);
+
+ while (i < *count) {
+ /* allocate required width of a frame to fit remaining
+ frames */
+ int n_alloc, m_alloc, tiles, res;
+ void *base;
+
+ n_alloc = MIN(*count - i, m_per_a * n_per_m);
+ m_alloc = DIVIDE_UP(n_alloc, n_per_m);
+ tiles = ((m_alloc - 1) * map_width +
+ buf_width * (n_alloc - (m_alloc - 1) * m_per_a));
+
+ res = tiler_alloc_buf(fmt, til_width * tiles, height,
+ sysptr + i);
+ if (res != DMM_NO_ERROR)
+ break;
+
+ /* mark allocation */
+ base = allocptr[i] = sysptr[i];
+ i++;
+
+ /* portion out remaining buffers */
+ for (m = 0; m < m_per_a; m++, base += bpt * buf_map_width) {
+ for (n = 0; n < n_per_m; n++) {
+ /* first buffer is already allocated */
+ if (n + m == 0)
+ continue;
+
+ /* stop if we are done */
+ if (i == *count)
+ break;
+
+ /* set buffer address */
+ sysptr[i] = base + bpt * n * buf_width;
+ allocptr[i++] = NULL;
+ }
+ }
+ }
+
+ /* mark how many buffers we allocated */
+ *count = i;
+}
+EXPORT_SYMBOL(tiler_packed_alloc_buf);
+
+static int layout_packed_nv12(char *offsets, int y_width, int uv_width,
+ void **buf, int blocks, int i,
+ void **y_sysptr, void **uv_sysptr,
+ void **y_allocptr, void **uv_allocptr)
+{
+ int j;
+ for (j = 0; j < blocks; j++, offsets += 3) {
+ int page_offset = (63 & (int) offsets[0])
+ + y_width * ((int) offsets[1])
+ + uv_width * (int) offsets[2];
+ void *base = buf[offsets[0] >> 6] + 64 * page_offset;
+
+ if (j & 1) {
+ /* convert 8-bit to 16-bit view */
+ /* this formula only works for even ys */
+ uv_sysptr[i] = base + (0x3FFF & (unsigned long) base)
+ + 0x8000000;
+ uv_allocptr[i] = page_offset ? NULL : uv_sysptr[i];
+ i++;
+ } else {
+ y_sysptr[i] = base;
+ y_allocptr[i] = page_offset ? NULL : y_sysptr[i];
+ }
+ }
+ return i;
+}
+
+void tiler_packed_alloc_nv12_buf(int *count,
+ unsigned long width,
+ unsigned long height,
+ void **y_sysptr,
+ void **uv_sysptr,
+ void **y_allocptr,
+ void **uv_allocptr,
+ int aligned)
+{
+ /* optimized packing table */
+ /* we read this table from beginning to end, and determine whether
+ the optimization meets our requirement (e.g. allocating at least
+ i buffers, with max w y-width, and alignment a. If not, we get
+ to the next element. Otherwise we do the allocation. The table
+ is constructed in such a way that if an interim tiler allocation
+ fails, the next matching rule for the scenario will be able to
+ use the buffers already allocated. */
+
+#define MAX_BUFS_TO_PACK 3
+ void *buf[MAX_BUFS_TO_PACK];
+ int n_buf, buf_w[MAX_BUFS_TO_PACK];
+
+ char packing[] = {
+ /* min(i), max(w), aligned, buffers to alloc */
+ 5, 16, 0, 2,
+ /* buffer widths in a + b * w(y) + c * w(uv) */
+ 64, 0, 0, 64, 0, 0,
+ /* tiler-page offsets in
+ a + b * w(y) + c * w(uv) */
+ 0, 0, 0, 32, 0, 0,
+ 16, 0, 0, 40, 0, 0,
+ 64, 0, 0, 96, 0, 0,
+ 80, 0, 0, 104, 0, 0,
+ 112, 0, 0, 56, 0, 0,
+
+ 2, 16, 0, 1,
+ 32, 0, 2,
+ 0, 0, 0, 32, 0, 0,
+ 0, 0, 2, 32, 0, 1,
+
+ 2, 20, 0, 1,
+ 42, 1, 0,
+ 0, 0, 0, 32, 0, 0,
+ 42, 0, 0, 21, 0, 0,
+
+ 3, 24, 0, 2,
+ 48, 0, 1, 32, 1, 0,
+ 0, 0, 0, 64, 0, 0,
+ 24, 0, 0, 76, 0, 0,
+ 96, 0, 0, 48, 0, 0,
+
+ 4, 32, 0, 3,
+ 48, 0, 1, 32, 1, 0, 32, 1, 0,
+ 0, 0, 0, 32, 0, 0,
+ 96, 0, 0, 48, 0, 0,
+ 64, 0, 0, 128, 0, 0,
+ 160, 0, 0, 144, 0, 0,
+
+ /* this is needed for soft landing if prior allocation fails
+ after two buffers */
+ 2, 32, 1, 2,
+ 32, 0, 1, 32, 0, 1,
+ 0, 0, 0, 32, 0, 0,
+ 64, 0, 0, 96, 0, 0,
+
+ 1, 32, 1, 1,
+ 32, 0, 1,
+ 0, 0, 0, 32, 0, 0,
+
+ 2, 64, 1, 3,
+ 0, 1, 0, 32, 0, 1, 0, 1, 0,
+ 0, 0, 0, 64, 0, 0,
+ 128, 0, 0, 96, 0, 0,
+ /* this is the basic NV12 allocation using 2 buffers */
+ 1, 0, 1, 2,
+ 0, 1, 0, 0, 0, 1,
+ 0, 0, 0, 64, 0, 0,
+ 0 };
+ int y_width, uv_width, i = 0;
+
+ /* Check input parameters for correctness */
+ if (!width || !height || !y_sysptr || !y_allocptr || !count ||
+ !uv_sysptr || !uv_allocptr || *count <= 0) {
+ if (count)
+ *count = 0;
+ }
+
+ y_width = DIVIDE_UP(width, 64);
+ uv_width = DIVIDE_UP(width >> 1, 64);
+
+ while (i < *count) {
+ int n_alloc = *count - i;
+ char *p = packing;
+ n_buf = 0;
+
+ /* skip packings that do not apply */
+ while (*p) {
+ /* see if this packing applies */
+ if (p[0] <= n_alloc &&
+ (!p[1] || p[1] >= y_width) &&
+ (!aligned || p[2])) {
+
+ /* allocate buffers */
+ while (n_buf < p[3]) {
+ buf_w[n_buf] = p[4 + 3 * n_buf] +
+ y_width * p[5 + 3 * n_buf] +
+ uv_width * p[6 + 3 * n_buf];
+
+ if (DMM_NO_ERROR != tiler_alloc_buf(
+ TILFMT_8BIT, buf_w[n_buf] * 64,
+ height, buf + n_buf))
+ break;
+ n_buf++;
+ }
+
+ /* if successfully allocated buffers */
+ if (n_buf >= p[3]) {
+ i = layout_packed_nv12(p + 4 + 3 * p[3],
+ y_width,
+ uv_width,
+ buf, 2 * p[0], i,
+ y_sysptr,
+ uv_sysptr,
+ y_allocptr,
+ uv_allocptr);
+ break;
+ }
+ }
+
+ p += 4 + 3 * p[3] + 6 * p[0];
+ }
+
+ /* if allocation failed free any outstanding buffers and stop */
+ if (!*p) {
+ while (n_buf > 0)
+ tiler_free_buf((unsigned long)(buf[--n_buf]));
+ break;
+ }
+ }
+
+ /* mark how many buffers we allocated */
+ *count = i;
+}
+EXPORT_SYMBOL(tiler_packed_alloc_nv12_buf);
+
static int createlist(struct node **listhead)
{
int error = -1;
diff --git a/drivers/media/video/tiler/tiler.h b/drivers/media/video/tiler/tiler.h
index 13ef468d77c9..e86adfcda49f 100755..100644
--- a/drivers/media/video/tiler/tiler.h
+++ b/drivers/media/video/tiler/tiler.h
@@ -112,4 +112,23 @@ tiler_rotate_view(struct dmmViewOrientT *orient, unsigned long rotation);
unsigned long
tiler_stride(unsigned long tsptr);
+void
+tiler_packed_alloc_nv12_buf(int *count,
+ unsigned long width,
+ unsigned long height,
+ void **y_sysptr,
+ void **uv_sysptr,
+ void **y_allocptr,
+ void **uv_allocptr,
+ int aligned);
+
+void
+tiler_packed_alloc_buf(int *count,
+ enum tiler_fmt fmt,
+ unsigned long width,
+ unsigned long height,
+ void **sysptr,
+ void **allocptr,
+ int aligned);
+
#endif