summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorLajos Molnar <molnar@ti.com>2011-04-07 08:40:55 +0100
committerAndy Green <andy.green@linaro.org>2011-04-07 08:40:55 +0100
commit05c3da97cc30410af2d4bf13d80cd65ed937714e (patch)
treed69d0c9410dacc93587094febf7f376ede05118f /drivers
parent9f922790aae7510fc53f1c02219448170a56cc7c (diff)
TILER: Added support for multiple containers and PAT instances.
Added instance support for DMM PAT programming (dmm.c) Created TMM interface for flexible tiler memory management (PAT or not). Added instance support to DMM PAT memory pages management (dmm_mem.c) Removed unused get_page/free_page methods. Fixed TILER_GET_ACC_MODE macro to return correct tiler_fmt values. Fixed a few sizeof style errors, and simplified dmm_mem.c Signed-off-by: Lajos Molnar <molnar@ti.com> Signed-off-by: David Sin <davidsin@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/dmm/dmm.c84
-rw-r--r--drivers/media/video/dmm/dmm.h128
-rw-r--r--drivers/media/video/dmm/dmm_mem.c215
-rw-r--r--drivers/media/video/dmm/dmm_mem.h73
-rw-r--r--drivers/media/video/tiler/tiler.c153
-rw-r--r--drivers/media/video/tiler/tiler.h116
-rw-r--r--drivers/media/video/tiler/tiler_def.h4
-rw-r--r--drivers/media/video/tiler/tiler_pack.c2
-rw-r--r--drivers/media/video/tiler/tiler_rot.c8
9 files changed, 339 insertions, 444 deletions
diff --git a/drivers/media/video/dmm/dmm.c b/drivers/media/video/dmm/dmm.c
index 613121a0269..8b5283236ac 100644
--- a/drivers/media/video/dmm/dmm.c
+++ b/drivers/media/video/dmm/dmm.c
@@ -25,7 +25,7 @@
#include <linux/io.h> /* ioremap() */
#include <linux/errno.h>
-#include "dmm.h"
+#include <mach/dmm.h>
#include "dmm_mem.h"
#undef __DEBUG__
@@ -43,7 +43,6 @@
static s32 dmm_major;
static s32 dmm_minor;
-void __iomem *dmm_base;
struct dmm_dev {
struct cdev cdev;
@@ -62,7 +61,7 @@ static struct platform_driver dmm_driver_ldm = {
.remove = NULL,
};
-s32 dmm_pat_refill(struct pat *pd, enum pat_mode mode)
+s32 dmm_pat_refill(struct dmm *dmm, struct pat *pd, enum pat_mode mode)
{
void __iomem *r = NULL;
u32 v = -1, w = -1;
@@ -75,7 +74,7 @@ s32 dmm_pat_refill(struct pat *pd, enum pat_mode mode)
* Check that the DMM_PAT_STATUS register
* has not reported an error.
*/
- r = (void __iomem *)((u32)dmm_base | DMM_PAT_STATUS__0);
+ r = (void __iomem *)((u32)dmm->base | DMM_PAT_STATUS__0);
v = __raw_readl(r);
if ((v & 0xFC00) != 0) {
while (1)
@@ -83,13 +82,13 @@ s32 dmm_pat_refill(struct pat *pd, enum pat_mode mode)
}
/* Set "next" register to NULL */
- r = (void __iomem *)((u32)dmm_base | DMM_PAT_DESCR__0);
+ r = (void __iomem *)((u32)dmm->base | DMM_PAT_DESCR__0);
v = __raw_readl(r);
w = (v & (~(BF(31, 4)))) | ((((u32)NULL) << 4) & BF(31, 4));
__raw_writel(w, r);
/* Set area to be refilled */
- r = (void __iomem *)((u32)dmm_base | DMM_PAT_AREA__0);
+ r = (void __iomem *)((u32)dmm->base | DMM_PAT_AREA__0);
v = __raw_readl(r);
w = (v & (~(BF(30, 24)))) | ((((s8)pd->area.y1) << 24) & BF(30, 24));
__raw_writel(w, r);
@@ -116,11 +115,11 @@ s32 dmm_pat_refill(struct pat *pd, enum pat_mode mode)
#endif
/* First, clear the DMM_PAT_IRQSTATUS register */
- r = (void __iomem *)((u32)dmm_base | (u32)DMM_PAT_IRQSTATUS);
+ r = (void __iomem *)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS);
__raw_writel(0xFFFFFFFF, r);
dsb();
- r = (void __iomem *)((u32)dmm_base | (u32)DMM_PAT_IRQSTATUS_RAW);
+ r = (void __iomem *)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS_RAW);
v = 0xFFFFFFFF;
while (v != 0x0) {
@@ -129,7 +128,7 @@ s32 dmm_pat_refill(struct pat *pd, enum pat_mode mode)
}
/* Fill data register */
- r = (void __iomem *)((u32)dmm_base | DMM_PAT_DATA__0);
+ r = (void __iomem *)((u32)dmm->base | DMM_PAT_DATA__0);
v = __raw_readl(r);
/* Apply 4 bit left shft to counter the 4 bit right shift */
@@ -144,7 +143,7 @@ s32 dmm_pat_refill(struct pat *pd, enum pat_mode mode)
DEBUG("DMM_PAT_DATA__0", v);
}
- r = (void __iomem *)((u32)dmm_base | (u32)DMM_PAT_CTRL__0);
+ r = (void __iomem *)((u32)dmm->base | (u32)DMM_PAT_CTRL__0);
v = __raw_readl(r);
w = (v & (~(BF(31, 28)))) | ((((u32)pd->ctrl.ini) << 28) & BF(31, 28));
@@ -171,7 +170,7 @@ s32 dmm_pat_refill(struct pat *pd, enum pat_mode mode)
* Now, check if PAT_IRQSTATUS_RAW has been
* set after the PAT has been refilled
*/
- r = (void __iomem *)((u32)dmm_base | (u32)DMM_PAT_IRQSTATUS_RAW);
+ r = (void __iomem *)((u32)dmm->base | (u32)DMM_PAT_IRQSTATUS_RAW);
v = 0x0;
while ((v & 0x3) != 0x3) {
v = __raw_readl(r);
@@ -197,6 +196,54 @@ static const struct file_operations dmm_fops = {
.release = dmm_release,
};
+struct dmm *dmm_pat_init(u32 id)
+{
+ u32 base = 0;
+ struct dmm *dmm = NULL;
+ switch (id) {
+ case 0:
+ /* only support id 0 for now */
+ base = DMM_BASE;
+ break;
+ default:
+ return NULL;
+ }
+
+ dmm = kmalloc(sizeof(*dmm), GFP_KERNEL);
+ if (!dmm)
+ return NULL;
+
+ dmm->base = ioremap(base, DMM_SIZE);
+ if (!dmm->base) {
+ kfree(dmm);
+ return NULL;
+ }
+
+ __raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__0);
+ __raw_writel(0x88888888, dmm->base + DMM_PAT_VIEW__1);
+ __raw_writel(0x80808080, dmm->base + DMM_PAT_VIEW_MAP__0);
+ __raw_writel(0x80000000, dmm->base + DMM_PAT_VIEW_MAP_BASE);
+ __raw_writel(0x88888888, dmm->base + DMM_TILER_OR__0);
+ __raw_writel(0x88888888, dmm->base + DMM_TILER_OR__1);
+
+ return dmm;
+}
+EXPORT_SYMBOL(dmm_pat_init);
+
+/**
+ * Clean up the physical address translator.
+ * @param dmm Device data
+ * @return an error status.
+ */
+void dmm_pat_release(struct dmm *dmm)
+{
+ if (dmm) {
+ iounmap(dmm->base);
+ kfree(dmm);
+ }
+}
+EXPORT_SYMBOL(dmm_pat_release);
+
static s32 __init dmm_init(void)
{
dev_t dev = 0;
@@ -239,27 +286,12 @@ static s32 __init dmm_init(void)
r = platform_driver_register(&dmm_driver_ldm);
- dmm_base = ioremap(DMM_BASE, DMM_SIZE);
- if (!dmm_base)
- return -ENOMEM;
-
- __raw_writel(0x88888888, dmm_base + DMM_PAT_VIEW__0);
- __raw_writel(0x88888888, dmm_base + DMM_PAT_VIEW__1);
- __raw_writel(0x80808080, dmm_base + DMM_PAT_VIEW_MAP__0);
- __raw_writel(0x80000000, dmm_base + DMM_PAT_VIEW_MAP_BASE);
- __raw_writel(0x88888888, dmm_base + DMM_TILER_OR__0);
- __raw_writel(0x88888888, dmm_base + DMM_TILER_OR__1);
-
- if (dmm_init_mem())
- return -ENOMEM;
EXIT:
return r;
}
static void __exit dmm_exit(void)
{
- dmm_release_mem();
- iounmap(dmm_base);
platform_driver_unregister(&dmm_driver_ldm);
cdev_del(&dmm_device->cdev);
kfree(dmm_device);
diff --git a/drivers/media/video/dmm/dmm.h b/drivers/media/video/dmm/dmm.h
deleted file mode 100644
index a3adddbf9fd..00000000000
--- a/drivers/media/video/dmm/dmm.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * dmm.h
- *
- * DMM driver support functions for TI OMAP processors.
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * This package is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef DMM_H
-#define DMM_H
-
-#define DMM_BASE 0x4E000000
-#define DMM_SIZE 0x800
-
-#define DMM_REVISION 0x000
-#define DMM_HWINFO 0x004
-#define DMM_LISA_HWINFO 0x008
-#define DMM_DMM_SYSCONFIG 0x010
-#define DMM_LISA_LOCK 0x01C
-#define DMM_LISA_MAP__0 0x040
-#define DMM_LISA_MAP__1 0x044
-#define DMM_TILER_HWINFO 0x208
-#define DMM_TILER_OR__0 0x220
-#define DMM_TILER_OR__1 0x224
-#define DMM_PAT_HWINFO 0x408
-#define DMM_PAT_GEOMETRY 0x40C
-#define DMM_PAT_CONFIG 0x410
-#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_IRQ_EOI 0x478
-#define DMM_PAT_IRQSTATUS_RAW 0x480
-#define DMM_PAT_IRQSTATUS 0x490
-#define DMM_PAT_IRQENABLE_SET 0x4A0
-#define DMM_PAT_IRQENABLE_CLR 0x4B0
-#define DMM_PAT_STATUS__0 0x4C0
-#define DMM_PAT_STATUS__1 0x4C4
-#define DMM_PAT_STATUS__2 0x4C8
-#define DMM_PAT_STATUS__3 0x4CC
-#define DMM_PAT_DESCR__0 0x500
-#define DMM_PAT_AREA__0 0x504
-#define DMM_PAT_CTRL__0 0x508
-#define DMM_PAT_DATA__0 0x50C
-#define DMM_PEG_HWINFO 0x608
-#define DMM_PEG_PRIO 0x620
-#define DMM_PEG_PRIO_PAT 0x640
-
-/**
- * PAT refill programming mode.
- */
-enum pat_mode {
- MANUAL,
- AUTO
-};
-
-/**
- * Area definition for DMM physical address translator.
- */
-struct pat_area {
- s32 x0:8;
- s32 y0:8;
- s32 x1:8;
- s32 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;
-};
-
-/**
- * PAT descriptor.
- */
-struct pat {
- struct pat *next;
- struct pat_area area;
- struct pat_ctrl ctrl;
- u32 data;
-};
-
-/**
- * Program the physical address translator.
- * @param desc
- * @param mode
- * @return an error status.
- */
-s32 dmm_pat_refill(struct pat *desc, enum pat_mode mode);
-
-/**
- * Request a page from the DMM free page stack.
- * @return a physical page address.
- */
-u32 dmm_get_page(void);
-
-/**
- * Return a used page to the DMM free page stack.
- * @param page_addr a physical page address.
- */
-void dmm_free_page(u32 page_addr);
-
-/**
- * Request a set of pages from the DMM free page stack.
- * @return a pointer to a list of physical page addresses.
- */
-u32 *dmm_get_pages(s32 n);
-
-/**
- * Return a set of used pages to the DMM free page stack.
- * @param list a pointer to a list of physical page addresses.
- */
-void dmm_free_pages(u32 *list);
-
-#endif
diff --git a/drivers/media/video/dmm/dmm_mem.c b/drivers/media/video/dmm/dmm_mem.c
index 488522aa94d..8849cc9f387 100644
--- a/drivers/media/video/dmm/dmm_mem.c
+++ b/drivers/media/video/dmm/dmm_mem.c
@@ -36,7 +36,7 @@
*/
struct fast {
struct list_head list;
- u32 *mem;
+ struct mem **mem;
u32 *pa;
u32 num;
};
@@ -51,10 +51,16 @@ struct mem {
u32 pa;
};
-static struct fast fast_list;
-static struct mem free_list;
-static struct mem used_list;
-static struct mutex mtx;
+/**
+ * TMM PAT private structure
+ */
+struct dmm_mem {
+ struct fast fast_list;
+ struct mem free_list;
+ struct mem used_list;
+ struct mutex mtx;
+ struct dmm *dmm;
+};
static void dmm_free_fast_list(struct fast *fast)
{
@@ -62,22 +68,19 @@ static void dmm_free_fast_list(struct fast *fast)
struct fast *f = NULL;
s32 i = 0;
- mutex_lock(&mtx);
+ /* mutex is locked */
list_for_each_safe(pos, q, &fast->list) {
f = list_entry(pos, struct fast, list);
- for (i = 0; i < f->num; i++) {
- list_add(&((struct mem *)f->mem[i])->list,
- &free_list.list);
- }
+ for (i = 0; i < f->num; i++)
+ __free_page(f->mem[i]->pg);
kfree(f->pa);
kfree(f->mem);
list_del(pos);
kfree(f);
}
- mutex_unlock(&mtx);
}
-static u32 fill_page_stack(struct mem *mem)
+static u32 fill_page_stack(struct mem *mem, struct mutex *mtx)
{
s32 i = 0;
struct mem *m = NULL;
@@ -104,9 +107,9 @@ static u32 fill_page_stack(struct mem *mem)
(void *)page_address(m->pg) + DMM_PAGE);
outer_flush_range(m->pa, m->pa + DMM_PAGE);
- mutex_lock(&mtx);
+ mutex_lock(mtx);
list_add(&m->list, &mem->list);
- mutex_unlock(&mtx);
+ mutex_unlock(mtx);
}
return 0x0;
}
@@ -116,95 +119,39 @@ static void dmm_free_page_stack(struct mem *mem)
struct list_head *pos = NULL, *q = NULL;
struct mem *m = NULL;
- mutex_lock(&mtx);
+ /* mutex is locked */
list_for_each_safe(pos, q, &mem->list) {
m = list_entry(pos, struct mem, list);
__free_page(m->pg);
list_del(pos);
kfree(m);
}
- mutex_unlock(&mtx);
-}
-
-u32 dmm_get_page(void)
-{
- struct list_head *pos = NULL, *q = NULL;
- struct mem *m = NULL;
-
- if (list_empty_careful(&free_list.list))
- if (fill_page_stack(&free_list))
- return 0;
-
- mutex_lock(&mtx);
- pos = NULL;
- q = NULL;
- list_for_each_safe(pos, q, &free_list.list) {
- m = list_entry(pos, struct mem, list);
- list_move(&m->list, &used_list.list);
- break;
- }
- mutex_unlock(&mtx);
-
- if (m != NULL)
- return m->pa;
- else
- return 0x0;
-}
-EXPORT_SYMBOL(dmm_get_page);
-
-void dmm_free_page(u32 page_addr)
-{
- struct list_head *pos = NULL, *q = NULL;
- struct mem *m = NULL;
-
- mutex_lock(&mtx);
- pos = NULL;
- q = NULL;
- list_for_each_safe(pos, q, &used_list.list) {
- m = list_entry(pos, struct mem, list);
- if (m->pa == page_addr) {
- list_move(&m->list, &free_list.list);
- break;
- }
- }
- mutex_unlock(&mtx);
}
-EXPORT_SYMBOL(dmm_free_page);
-u32 dmm_init_mem()
+static void tmm_pat_deinit(struct tmm *tmm)
{
- INIT_LIST_HEAD(&free_list.list);
- INIT_LIST_HEAD(&used_list.list);
- INIT_LIST_HEAD(&fast_list.list);
- mutex_init(&mtx);
-
- if (list_empty_careful(&free_list.list))
- if (fill_page_stack(&free_list))
- return -ENOMEM;
+ struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
- return 0;
+ mutex_lock(&pvt->mtx);
+ dmm_free_fast_list(&pvt->fast_list);
+ dmm_free_page_stack(&pvt->free_list);
+ dmm_free_page_stack(&pvt->used_list);
+ mutex_destroy(&pvt->mtx);
}
-void dmm_release_mem()
-{
- dmm_free_fast_list(&fast_list);
- dmm_free_page_stack(&free_list);
- dmm_free_page_stack(&used_list);
- mutex_destroy(&mtx);
-}
-
-u32 *dmm_get_pages(s32 n)
+static u32 *tmm_pat_get_pages(struct tmm *tmm, s32 n)
{
s32 i = 0;
struct list_head *pos = NULL, *q = NULL;
struct mem *m = NULL;
struct fast *f = NULL;
+ struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
if (n <= 0 || n > 0x8000)
return NULL;
- if (list_empty_careful(&free_list.list))
- if (fill_page_stack(&free_list))
+ if (list_empty_careful(&pvt->free_list.list))
+ if (fill_page_stack(&pvt->free_list, &pvt->mtx))
return NULL;
f = kmalloc(sizeof(*f), GFP_KERNEL);
@@ -213,18 +160,18 @@ u32 *dmm_get_pages(s32 n)
memset(f, 0x0, sizeof(*f));
/* array of mem struct pointers */
- f->mem = kmalloc(n * 4, GFP_KERNEL);
+ f->mem = kmalloc(n * sizeof(*f->mem), GFP_KERNEL);
if (!f->mem) {
kfree(f); return NULL;
}
- memset(f->mem, 0x0, n * 4);
+ memset(f->mem, 0x0, n * sizeof(*f->mem));
/* array of physical addresses */
- f->pa = kmalloc(n * 4, GFP_KERNEL);
+ f->pa = kmalloc(n * sizeof(*f->pa), GFP_KERNEL);
if (!f->pa) {
kfree(f->mem); kfree(f); return NULL;
}
- memset(f->pa, 0x0, n * 4);
+ memset(f->pa, 0x0, n * sizeof(*f->pa));
/*
* store the number of mem structs so that we
@@ -233,11 +180,11 @@ u32 *dmm_get_pages(s32 n)
f->num = n;
for (i = 0; i < n; i++) {
- if (list_empty_careful(&free_list.list))
- if (fill_page_stack(&free_list))
+ if (list_empty_careful(&pvt->free_list.list))
+ if (fill_page_stack(&pvt->free_list, &pvt->mtx))
goto cleanup;
- mutex_lock(&mtx);
+ mutex_lock(&pvt->mtx);
pos = NULL;
q = NULL;
@@ -245,13 +192,13 @@ u32 *dmm_get_pages(s32 n)
* remove one mem struct from the free list and
* add the address to the fast struct mem array
*/
- list_for_each_safe(pos, q, &free_list.list) {
+ list_for_each_safe(pos, q, &pvt->free_list.list) {
m = list_entry(pos, struct mem, list);
- f->mem[i] = (u32)m;
+ f->mem[i] = m;
list_del(pos);
break;
}
- mutex_unlock(&mtx);
+ mutex_unlock(&pvt->mtx);
if (m != NULL)
f->pa[i] = m->pa;
@@ -259,40 +206,40 @@ u32 *dmm_get_pages(s32 n)
goto cleanup;
}
- mutex_lock(&mtx);
- list_add(&f->list, &fast_list.list);
- mutex_unlock(&mtx);
+ mutex_lock(&pvt->mtx);
+ list_add(&f->list, &pvt->fast_list.list);
+ mutex_unlock(&pvt->mtx);
if (f != NULL)
return f->pa;
cleanup:
for (; i > 0; i--) {
- mutex_lock(&mtx);
- list_add(&((struct mem *)f->mem[i - 1])->list, &free_list.list);
- mutex_unlock(&mtx);
+ mutex_lock(&pvt->mtx);
+ list_add(&f->mem[i - 1]->list, &pvt->free_list.list);
+ mutex_unlock(&pvt->mtx);
}
kfree(f->pa);
kfree(f->mem);
kfree(f);
return NULL;
}
-EXPORT_SYMBOL(dmm_get_pages);
-void dmm_free_pages(u32 *list)
+static void tmm_pat_free_pages(struct tmm *tmm, u32 *list)
{
+ struct dmm_mem *pvt = (struct dmm_mem *) tmm->pvt;
struct list_head *pos = NULL, *q = NULL;
struct fast *f = NULL;
s32 i = 0;
- mutex_lock(&mtx);
+ mutex_lock(&pvt->mtx);
pos = NULL;
q = NULL;
- list_for_each_safe(pos, q, &fast_list.list) {
+ list_for_each_safe(pos, q, &pvt->fast_list.list) {
f = list_entry(pos, struct fast, list);
if (f->pa[0] == list[0]) {
for (i = 0; i < f->num; i++) {
list_add(&((struct mem *)f->mem[i])->list,
- &free_list.list);
+ &pvt->free_list.list);
}
list_del(pos);
kfree(f->pa);
@@ -301,7 +248,65 @@ void dmm_free_pages(u32 *list)
break;
}
}
- mutex_unlock(&mtx);
+ mutex_unlock(&pvt->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 = {0};
+
+ /* 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 = kmalloc(sizeof(*tmm), GFP_KERNEL);
+ if (tmm)
+ pvt = kmalloc(sizeof(*pvt), GFP_KERNEL);
+ if (pvt) {
+ /* private data */
+ pvt->dmm = dmm;
+ INIT_LIST_HEAD(&pvt->free_list.list);
+ INIT_LIST_HEAD(&pvt->used_list.list);
+ INIT_LIST_HEAD(&pvt->fast_list.list);
+ mutex_init(&pvt->mtx);
+
+ if (list_empty_careful(&pvt->free_list.list))
+ if (fill_page_stack(&pvt->free_list, &pvt->mtx))
+ goto error;
+
+ /* 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;
+
+ return tmm;
+ }
+
+error:
+ kfree(pvt);
+ kfree(tmm);
+ dmm_pat_release(dmm);
+ return NULL;
}
-EXPORT_SYMBOL(dmm_free_pages);
+EXPORT_SYMBOL(tmm_pat_init);
diff --git a/drivers/media/video/dmm/dmm_mem.h b/drivers/media/video/dmm/dmm_mem.h
index 9a80df5e09b..a4c8a68ca6f 100644
--- a/drivers/media/video/dmm/dmm_mem.h
+++ b/drivers/media/video/dmm/dmm_mem.h
@@ -16,15 +16,78 @@
#ifndef DMM_MEM_H
#define DMM_MEM_H
+#include <mach/dmm.h>
/**
- * Initialize the DMM page stacks.
- * @return an error status.
+ * TMM interface
*/
-u32 dmm_init_mem(void);
+struct tmm {
+ void *pvt;
+
+ /* function table */
+ u32 *(*get) (struct tmm *tmm, s32 num_pages);
+ void (*free) (struct tmm *tmm, u32 *pages);
+ s32 (*map) (struct tmm *tmm, struct pat_area area, u32 page_pa);
+ 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, s32 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.
+ * @param list a pointer to a list of physical page addresses.
+ */
+static inline
+void tmm_free(struct tmm *tmm, u32 *pages)
+{
+ if (tmm && tmm->pvt)
+ tmm->free(tmm, pages);
+}
+
+/**
+ * Program the physical address translator.
+ * @param area PAT area
+ * @param list of pages
+ */
+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;
+}
+
+/**
+ * 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);
+}
/**
- * Free the DMM page stacks.
+ * Initialize TMM for PAT with given id.
*/
-void dmm_release_mem(void);
+struct tmm *tmm_pat_init(u32 pat_id);
#endif
diff --git a/drivers/media/video/tiler/tiler.c b/drivers/media/video/tiler/tiler.c
index 4bc5ba929b8..0e6b9fbcc9f 100644
--- a/drivers/media/video/tiler/tiler.c
+++ b/drivers/media/video/tiler/tiler.c
@@ -31,10 +31,10 @@
#include <linux/dma-mapping.h>
#include <linux/pagemap.h> /* page_cache_release() */
-#include "tiler.h"
+#include <mach/tiler.h>
+#include <mach/dmm.h>
+#include "../dmm/dmm_mem.h"
#include "tiler_def.h"
-#include "../dmm/dmm.h"
-
#include "tcm/tcm_sita.h" /* Algo Specific header */
struct tiler_dev {
@@ -66,6 +66,8 @@ struct mem_info {
u32 *mem; /* list of alloced phys addresses */
};
+#define TILER_FORMATS 4
+
static s32 tiler_major;
static s32 tiler_minor;
static struct tiler_dev *tiler_device;
@@ -74,7 +76,15 @@ static u32 id;
static struct __buf_info buf_list;
static struct mem_info mem_list;
static struct mutex mtx;
-static struct tcm *tcm;
+static struct tcm *tcm[TILER_FORMATS];
+static struct tmm *tmm[TILER_FORMATS];
+
+#define TCM(fmt) tcm[(fmt) - TILFMT_8BIT]
+#define TCM_SS(ssptr) TCM(TILER_GET_ACC_MODE(ssptr))
+#define TCM_SET(fmt, i) tcm[(fmt) - TILFMT_8BIT] = i
+#define TMM(fmt) tmm[(fmt) - TILFMT_8BIT]
+#define TMM_SS(ssptr) TMM(TILER_GET_ACC_MODE(ssptr))
+#define TMM_SET(fmt, i) tmm[(fmt) - TILFMT_8BIT] = i
static s32 __adjust_area(enum tiler_fmt fmt, u32 width, u32 height, u16 *x_area,
u16 *y_area)
@@ -127,7 +137,7 @@ static s32 get_area(u32 sys_addr, u32 *x_area, u32 *y_area)
sys_addr &= TILER_ALIAS_VIEW_CLEAR;
fmt = TILER_GET_ACC_MODE(sys_addr);
- switch (fmt + 1) {
+ switch (fmt) {
case TILFMT_8BIT:
*x_area = DMM_HOR_X_PAGE_COOR_GET_8(sys_addr);
*y_area = DMM_HOR_Y_PAGE_COOR_GET_8(sys_addr);
@@ -237,40 +247,30 @@ static s32 tiler_mmap(struct file *filp, struct vm_area_struct *vma)
return 0;
}
-static s32 tiler_pat_refill(struct tcm_area *area, u32 *ptr)
+static s32 tiler_pat_refill(struct tmm *tmm, struct tcm_area *area, u32 *ptr)
{
s32 res = 0;
s32 size = tcm_sizeof(*area) * sizeof(*ptr);
u32 *page;
dma_addr_t page_pa;
- struct pat pat_desc = {0};
+ struct pat_area p_area = {0};
struct tcm_area slice, area_s;
+ /* must be a 16-byte aligned physical address */
page = dma_alloc_coherent(NULL, size, &page_pa, GFP_ATOMIC);
if (!page)
return -ENOMEM;
- /* 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.next = NULL;
-
- /* must be a 16-byte aligned physical address */
- pat_desc.data = page_pa;
-
tcm_for_each_slice(slice, *area, area_s) {
- pat_desc.area.x0 = slice.p0.x;
- pat_desc.area.y0 = slice.p0.y;
- pat_desc.area.x1 = slice.p1.x;
- pat_desc.area.y1 = slice.p1.y;
+ p_area.x0 = slice.p0.x;
+ p_area.y0 = slice.p0.y;
+ p_area.x1 = slice.p1.x;
+ p_area.y1 = slice.p1.y;
memcpy(page, ptr, sizeof(*ptr) * tcm_sizeof(slice));
ptr += tcm_sizeof(slice);
- if (dmm_pat_refill(&pat_desc, MANUAL)) {
+ if (tmm_map(tmm, p_area, page_pa)) {
res = -EFAULT;
break;
}
@@ -295,7 +295,11 @@ static s32 map_buffer(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr,
/* we only support mapping a user buffer in page mode */
if (fmt != TILFMT_PAGE)
- return -EFAULT;
+ return -EPERM;
+
+ /* check if mapping is supported by tmm */
+ if (!tmm_can_map(TMM(fmt)))
+ return -EPERM;
/* reserve area in tiler container */
if (__adjust_area(fmt, width, height, &x_area, &y_area))
@@ -306,7 +310,7 @@ static s32 map_buffer(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr,
return -ENOMEM;
memset(mi, 0x0, sizeof(*mi));
- if (tcm_reserve_1d(tcm, x_area * y_area, &mi->area)) {
+ if (tcm_reserve_1d(TCM(fmt), x_area * y_area, &mi->area)) {
kfree(mi);
return -ENOMEM;
}
@@ -376,7 +380,7 @@ static s32 map_buffer(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr,
list_add(&mi->list, &mem_list.list);
mutex_unlock(&mtx);
- if (tiler_pat_refill(&mi->area, mi->mem))
+ if (tiler_pat_refill(TMM(fmt), &mi->area, mi->mem))
goto release;
/* for safety */
@@ -428,7 +432,7 @@ s32 tiler_free(u32 sys_addr)
}
kfree(mi->pg_ptr);
} else {
- dmm_free_pages(mi->mem);
+ tmm_free(TMM_SS(mi->sys_addr), mi->mem);
}
list_del(pos);
kfree(mi);
@@ -461,14 +465,14 @@ s32 tiler_find_buf(u32 sys_addr, struct tiler_block_info *blk)
memset(&area, 0, sizeof(area));
pt.x = x_area;
pt.y = y_area;
- if (tcm_get_parent(tcm, &pt, &area))
+ if (tcm_get_parent(TCM_SS(sys_addr), &pt, &area))
return -EFAULT;
x_page = area.p1.x - area.p0.x + 1;
y_page = area.p1.y - area.p0.y + 1;
blk->ptr = NULL;
mode = TILER_GET_ACC_MODE(sys_addr);
- blk->fmt = (mode + 1);
+ blk->fmt = (mode);
if (blk->fmt == TILFMT_PAGE) {
blk->dim.len = x_page * y_page * TILER_PAGE;
if (blk->dim.len == 0)
@@ -693,13 +697,13 @@ s32 tiler_alloc(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr)
case TILFMT_16BIT:
case TILFMT_32BIT:
band = fmt == TILFMT_8BIT ? ALIGN_64 : ALIGN_32;
- if (tcm_reserve_2d(tcm, x_area, y_area, band, &mi->area)) {
+ if (tcm_reserve_2d(TCM(fmt), x_area, y_area, band, &mi->area)) {
kfree(mi);
return -ENOMEM;
}
break;
case TILFMT_PAGE:
- if (tcm_reserve_1d(tcm, x_area * y_area, &mi->area)) {
+ if (tcm_reserve_1d(TCM(fmt), x_area * y_area, &mi->area)) {
kfree(mi);
return -ENOMEM;
}
@@ -711,23 +715,25 @@ s32 tiler_alloc(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr)
/* formulate system space address */
*sys_addr = __get_alias_addr(fmt, mi->area.p0.x, mi->area.p0.y);
+ mi->sys_addr = *sys_addr;
- /* allocate pages */
- mi->num_pg = tcm_sizeof(mi->area);
+ /* allocate and map if mapping is supported */
+ if (tmm_can_map(TMM(fmt))) {
+ mi->num_pg = tcm_sizeof(mi->area);
- mi->mem = dmm_get_pages(mi->num_pg);
- if (!mi->mem)
- goto cleanup;
+ mi->mem = tmm_get(TMM(fmt), mi->num_pg);
+ if (!mi->mem)
+ goto cleanup;
- mi->sys_addr = *sys_addr;
+ /* program PAT */
+ if (tiler_pat_refill(TMM(fmt), &mi->area, mi->mem))
+ goto cleanup;
+ }
mutex_lock(&mtx);
list_add(&(mi->list), &mem_list.list);
mutex_unlock(&mtx);
-
- /* program PAT */
- if (0 == tiler_pat_refill(&mi->area, mi->mem))
- return 0x0;
+ return 0;
cleanup:
kfree(mi->mem);
@@ -741,8 +747,8 @@ static void __exit tiler_exit(void)
struct __buf_info *_b = NULL;
struct mem_info *mi = NULL;
struct list_head *pos = NULL, *q = NULL;
+ int i, j;
- tcm_deinit(tcm);
/* remove any leftover info structs that haven't been unregistered */
mutex_lock(&mtx);
pos = NULL, q = NULL;
@@ -759,12 +765,25 @@ static void __exit tiler_exit(void)
list_for_each_safe(pos, q, &mem_list.list) {
mi = list_entry(pos, struct mem_info, list);
if (!mi->pg_ptr)
- dmm_free_pages(mi->mem);
+ tmm_free(TMM_SS(mi->sys_addr), mi->mem);
list_del(pos);
kfree(mi);
}
mutex_unlock(&mtx);
+ /* close containers only once */
+ for (i = TILFMT_8BIT; i <= TILFMT_MAX; i++) {
+ /* remove identical containers (tmm is unique per 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);
platform_driver_unregister(&tiler_driver_ldm);
cdev_del(&tiler_device->cdev);
@@ -796,7 +815,33 @@ static s32 __init tiler_init(void)
s32 r = -1;
struct device *device = NULL;
struct tcm_pt div_pt;
+ struct tcm *sita = NULL;
+ struct tmm *tmm_pat = NULL;
+
+ /* Allocate tiler container manager (we share 1 on OMAP4) */
+ div_pt.x = 192; /* hardcoded default */
+ div_pt.y = 96;
+ sita = sita_init(256, 128, (void *)&div_pt);
+
+ TCM_SET(TILFMT_8BIT, sita);
+ TCM_SET(TILFMT_16BIT, sita);
+ TCM_SET(TILFMT_32BIT, sita);
+ TCM_SET(TILFMT_PAGE, sita);
+
+ /* Allocate tiler memory manager (must have 1 unique TMM per TCM ) */
+ tmm_pat = tmm_pat_init(0);
+ TMM_SET(TILFMT_8BIT, tmm_pat);
+ TMM_SET(TILFMT_16BIT, tmm_pat);
+ TMM_SET(TILFMT_32BIT, tmm_pat);
+ TMM_SET(TILFMT_PAGE, tmm_pat);
+
+ tiler_device = kmalloc(sizeof(*tiler_device), GFP_KERNEL);
+ if (!tiler_device || !sita || !tmm_pat) {
+ r = -ENOMEM;
+ goto error;
+ }
+ memset(tiler_device, 0x0, sizeof(*tiler_device));
if (tiler_major) {
dev = MKDEV(tiler_major, tiler_minor);
r = register_chrdev_region(dev, 1, "tiler");
@@ -805,13 +850,6 @@ static s32 __init tiler_init(void)
tiler_major = MAJOR(dev);
}
- tiler_device = kmalloc(sizeof(*tiler_device), GFP_KERNEL);
- if (!tiler_device) {
- unregister_chrdev_region(dev, 1);
- return -ENOMEM;
- }
- memset(tiler_device, 0x0, sizeof(*tiler_device));
-
cdev_init(&tiler_device->cdev, &tiler_fops);
tiler_device->cdev.owner = THIS_MODULE;
tiler_device->cdev.ops = &tiler_fops;
@@ -824,7 +862,7 @@ static s32 __init tiler_init(void)
if (IS_ERR(tilerdev_class)) {
printk(KERN_ERR "class_create():failed\n");
- goto EXIT;
+ goto error;
}
device = device_create(tilerdev_class, NULL, dev, NULL, "tiler");
@@ -838,13 +876,14 @@ static s32 __init tiler_init(void)
INIT_LIST_HEAD(&mem_list.list);
id = 0xda7a000;
- /* Hardcoded for testing */
- div_pt.x = 192;
- div_pt.y = 96;
- tcm = sita_init(256, 128, (void *)&div_pt);
- /*To Do: Error Checking */
+error:
+ /* TODO: error handling for device registration */
+ if (r) {
+ kfree(tiler_device);
+ tcm_deinit(sita);
+ tmm_deinit(tmm_pat);
+ }
-EXIT:
return r;
}
diff --git a/drivers/media/video/tiler/tiler.h b/drivers/media/video/tiler/tiler.h
deleted file mode 100644
index b8adf1439b6..00000000000
--- a/drivers/media/video/tiler/tiler.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * tiler.h
- *
- * TILER driver support functions for TI OMAP processors.
- *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
- *
- * This package is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef TILER_H
-#define TILER_H
-
-#define TILER_PAGE 0x1000
-#define TILER_WIDTH 256
-#define TILER_HEIGHT 128
-#define TILER_BLOCK_WIDTH 64
-#define TILER_BLOCK_HEIGHT 64
-#define TILER_LENGTH (TILER_WIDTH * TILER_HEIGHT * TILER_PAGE)
-
-#define TILER_MAX_NUM_BLOCKS 16
-
-#define TILIOC_GBUF _IOWR('z', 100, u32)
-#define TILIOC_FBUF _IOWR('z', 101, u32)
-#define TILIOC_GSSP _IOWR('z', 102, u32)
-#define TILIOC_MBUF _IOWR('z', 103, u32)
-#define TILIOC_UMBUF _IOWR('z', 104, u32)
-#define TILIOC_QBUF _IOWR('z', 105, u32)
-#define TILIOC_RBUF _IOWR('z', 106, u32)
-#define TILIOC_URBUF _IOWR('z', 107, u32)
-#define TILIOC_QUERY_BLK _IOWR('z', 108, u32)
-
-enum tiler_fmt {
- TILFMT_MIN = -1,
- TILFMT_INVALID = -1,
- TILFMT_NONE = 0,
- TILFMT_8BIT = 1,
- TILFMT_16BIT = 2,
- TILFMT_32BIT = 3,
- TILFMT_PAGE = 4,
- TILFMT_MAX = 4
-};
-
-struct area {
- u16 width;
- u16 height;
-};
-
-struct tiler_block_info {
- enum tiler_fmt fmt;
- union {
- struct area area;
- u32 len;
- } dim;
- u32 stride;
- void *ptr;
- u32 ssptr;
-};
-
-struct tiler_buf_info {
- s32 num_blocks;
- struct tiler_block_info blocks[TILER_MAX_NUM_BLOCKS];
- s32 offset;
-};
-
-struct tiler_view_orient {
- u8 rotate_90;
- u8 x_invert;
- u8 y_invert;
-};
-
-/**
- * Request a 1-D or 2-D TILER buffer.
- *
- * @param fmt TILER bit mode.
- * @param width buffer width.
- * @param height buffer height.
- * @param sys_addr system space (L3) address.
- *
- * @return an error status.
- */
-s32 tiler_alloc(enum tiler_fmt fmt, u32 width, u32 height, u32 *sys_addr);
-
-/**
- * Free TILER memory.
- * @param sys_addr system space (L3) address.
- * @return an error status.
- */
-s32 tiler_free(u32 sys_addr);
-
-u32 tiler_reorient_addr(u32 tsptr, struct tiler_view_orient orient);
-
-u32 tiler_get_natural_addr(void *sys_ptr);
-
-u32 tiler_reorient_topleft(u32 tsptr, struct tiler_view_orient orient,
- u32 width, u32 height);
-
-u32 tiler_stride(u32 tsptr);
-
-void tiler_rotate_view(struct tiler_view_orient *orient, u32 rotation);
-
-void tiler_alloc_packed(s32 *count, enum tiler_fmt fmt, u32 width, u32 height,
- void **sysptr, void **allocptr, s32 aligned);
-
-void tiler_alloc_packed_nv12(s32 *count, u32 width, u32 height, void **y_sysptr,
- void **uv_sysptr, void **y_allocptr,
- void **uv_allocptr, s32 aligned);
-
-#endif
-
diff --git a/drivers/media/video/tiler/tiler_def.h b/drivers/media/video/tiler/tiler_def.h
index de73b8eccb4..d92bfde8e45 100644
--- a/drivers/media/video/tiler/tiler_def.h
+++ b/drivers/media/video/tiler/tiler_def.h
@@ -25,8 +25,8 @@
#define TILER_ACC_MODE_SHIFT (27)
#define TILER_ACC_MODE_MASK (3)
-#define TILER_GET_ACC_MODE(x) ((enum tiler_fmt)\
-(((u32)x & (TILER_ACC_MODE_MASK<<TILER_ACC_MODE_SHIFT))>>TILER_ACC_MODE_SHIFT))
+#define TILER_GET_ACC_MODE(x) ((enum tiler_fmt) (1 + \
+(((u32)x & (TILER_ACC_MODE_MASK<<TILER_ACC_MODE_SHIFT))>>TILER_ACC_MODE_SHIFT)))
#define TILER_ALIAS_BASE (0x60000000)
#define TILER_ACC_MODE_SHIFT (27)
diff --git a/drivers/media/video/tiler/tiler_pack.c b/drivers/media/video/tiler/tiler_pack.c
index 7c3c6d95ca0..3de786bfeda 100644
--- a/drivers/media/video/tiler/tiler_pack.c
+++ b/drivers/media/video/tiler/tiler_pack.c
@@ -16,7 +16,7 @@
#include <linux/init.h>
#include <linux/module.h>
-#include "tiler.h"
+#include <mach/tiler.h>
#include "tiler_def.h"
void tiler_alloc_packed(s32 *count, enum tiler_fmt fmt, u32 width, u32 height,
diff --git a/drivers/media/video/tiler/tiler_rot.c b/drivers/media/video/tiler/tiler_rot.c
index e82257e47d0..ff7f219f95c 100644
--- a/drivers/media/video/tiler/tiler_rot.c
+++ b/drivers/media/video/tiler/tiler_rot.c
@@ -16,7 +16,7 @@
#include <linux/init.h>
#include <linux/module.h>
-#include "tiler.h"
+#include <mach/tiler.h>
#include "tiler_def.h"
#define DMM_SHIFT_PER_X_8 0
@@ -70,7 +70,7 @@ void tiler_get_natural_xy(u32 tsptr, u32 *x, u32 *y)
fmt = TILER_GET_ACC_MODE(tsptr);
- switch (fmt + 1) {
+ switch (fmt) {
case TILFMT_8BIT:
x_bits = DMM_TILER_CONT_WIDTH_BITS_(8);
y_bits = DMM_TILER_CONT_HEIGHT_BITS_(8);
@@ -113,7 +113,7 @@ u32 tiler_get_address(struct tiler_view_orient orient,
{
u32 x_bits, y_bits, tmp, x_mask, y_mask, alignment;
- switch (fmt + 1) {
+ switch (fmt) {
case TILFMT_8BIT:
x_bits = DMM_TILER_CONT_WIDTH_BITS_(8);
y_bits = DMM_TILER_CONT_HEIGHT_BITS_(8);
@@ -203,7 +203,7 @@ u32 tiler_stride(u32 tsptr)
fmt = TILER_GET_ACC_MODE(tsptr);
- switch (fmt + 1) {
+ switch (fmt) {
case TILFMT_8BIT:
return DMM_GET_ROTATED(tsptr) ?
DMM_TILER_STRIDE_90_(8) : DMM_TILER_STRIDE_0_(8);