aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorAndy Gross <andy.gross@ti.com>2012-01-12 19:08:36 +0100
committerZiyann <jaraidaniel@gmail.com>2014-10-01 12:57:24 +0200
commitaa56c7eddfafeed7246193036903f6f4ba827767 (patch)
tree1ce12762a3de54dd4a15e5fe10c2bff0a316f94f /drivers/media
parent7385e913875d6292ea599d863a09cc0e01f954f9 (diff)
downloadkernel_samsung_tuna-aa56c7eddfafeed7246193036903f6f4ba827767.tar.gz
kernel_samsung_tuna-aa56c7eddfafeed7246193036903f6f4ba827767.tar.bz2
kernel_samsung_tuna-aa56c7eddfafeed7246193036903f6f4ba827767.zip
OMAP4: TILER: Add offset parameter for allocation
Add offset parameter for use in tiler_alloc_block_area_aligned. This allows a user to get a tiler allocation with a specific alignment and offset. Change-Id: I8b1b9dd17bc9def124ea92cbbede2f3c56823387 Signed-off-by: Andy Gross <andy.gross@ti.com> Signed-off-by: Tony Zlatinski <x0146664@ti.com> Signed-off-by: Atanas (Tony) Zlatinski <zlatinski@gmail.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/tiler/_tiler.h7
-rw-r--r--drivers/media/video/tiler/tiler-iface.c2
-rw-r--r--drivers/media/video/tiler/tiler-ioctl.c2
-rw-r--r--drivers/media/video/tiler/tiler-main.c89
-rw-r--r--drivers/media/video/tiler/tiler-nv12.c8
-rw-r--r--drivers/media/video/tiler/tiler-reserve.c9
6 files changed, 70 insertions, 47 deletions
diff --git a/drivers/media/video/tiler/_tiler.h b/drivers/media/video/tiler/_tiler.h
index 784e66b8f4e..382239de316 100644
--- a/drivers/media/video/tiler/_tiler.h
+++ b/drivers/media/video/tiler/_tiler.h
@@ -126,7 +126,7 @@ struct tiler_ops {
void (*reserve_nv12) (u32 n, u32 width, u32 height,
u32 gid, struct security_info *si);
void (*reserve) (u32 n, enum tiler_fmt fmt, u32 width, u32 height,
- u32 gid, struct security_info *si);
+ u32 align, u32 offs, u32 gid, struct security_info *si);
void (*unreserve) (u32 gid, struct security_info *si);
/* block access operations */
@@ -136,7 +136,7 @@ struct tiler_ops {
void (*unlock_free) (struct mem_info *mi, bool free);
s32 (*lay_2d) (enum tiler_fmt fmt, u16 n, u16 w, u16 h, u16 band,
- u16 align, struct gid_info *gi,
+ u16 align, u16 offs, struct gid_info *gi,
struct list_head *pos);
#ifdef CONFIG_TILER_ENABLE_NV12
s32 (*lay_nv12) (int n, u16 w, u16 w1, u16 h, struct gid_info *gi,
@@ -153,7 +153,8 @@ struct tiler_ops {
/* area operations */
s32 (*analize) (enum tiler_fmt fmt, u32 width, u32 height,
- u16 *x_area, u16 *y_area, u16 *band, u16 *align);
+ u16 *x_area, u16 *y_area, u16 *band, u16 *align,
+ u16 *offs, u16 *remainder);
/* process operations */
void (*cleanup) (void);
diff --git a/drivers/media/video/tiler/tiler-iface.c b/drivers/media/video/tiler/tiler-iface.c
index 8d81f918bcd..3d5917f3fec 100644
--- a/drivers/media/video/tiler/tiler-iface.c
+++ b/drivers/media/video/tiler/tiler-iface.c
@@ -175,7 +175,7 @@ void tiler_reservex(u32 n, enum tiler_fmt fmt, u32 width, u32 height,
struct security_info *si = __get_si(pid, true, SECURE_BY_PID);
if (si)
- ops->reserve(n, fmt, width, height, gid, si);
+ ops->reserve(n, fmt, width, height, PAGE_SIZE, 0, gid, si);
}
EXPORT_SYMBOL(tiler_reservex);
diff --git a/drivers/media/video/tiler/tiler-ioctl.c b/drivers/media/video/tiler/tiler-ioctl.c
index c39dd0fe946..99f8ad4afc6 100644
--- a/drivers/media/video/tiler/tiler-ioctl.c
+++ b/drivers/media/video/tiler/tiler-ioctl.c
@@ -422,6 +422,8 @@ static long tiler_ioctl(struct file *filp, u32 cmd, unsigned long arg)
block_info.fmt,
block_info.dim.area.width,
block_info.dim.area.height,
+ PAGE_SIZE,
+ 0,
block_info.group_id, si);
break;
/* unreserve blocks */
diff --git a/drivers/media/video/tiler/tiler-main.c b/drivers/media/video/tiler/tiler-main.c
index 0c281663b52..f7887d4a561 100644
--- a/drivers/media/video/tiler/tiler-main.c
+++ b/drivers/media/video/tiler/tiler-main.c
@@ -457,10 +457,11 @@ static inline void _m_area_free(struct area_info *ai)
}
static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height,
- u16 *x_area, u16 *y_area, u16 *band, u16 *align)
+ u16 *x_area, u16 *y_area, u16 *band, u16 *align,
+ u16 *offs, u16 *remainder)
{
- /* input: width, height is in pixels, align */
- /* output: x_area, y_area, band */
+ /* input: width, height is in pixels, align, offs in bytes */
+ /* output: x_area, y_area, band, offs in slots, remaining bytes */
/* slot width, height, and row size */
u32 slot_row, min_align;
@@ -477,9 +478,11 @@ static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height,
if (fmt == TILFMT_PAGE) {
/* adjust size to accomodate offset, only do page alignment */
*align = PAGE_SIZE;
+ *remainder = *offs & ~PAGE_MASK; /* calculate remainder */
+ width += *remainder;
/* for 1D area keep the height (1), width is in tiler slots */
- *x_area = DIV_ROUND_UP(width, tiler.page);
+ *x_area = DIV_ROUND_UP(width , tiler.page);
*y_area = *band = 1;
if (*x_area * *y_area > tiler.width * tiler.height)
@@ -487,6 +490,8 @@ static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height,
return 0;
}
+ *remainder = 0;
+
/* format must be valid */
g = tiler.geom(fmt);
if (!g)
@@ -500,15 +505,26 @@ static s32 __analize_area(enum tiler_fmt fmt, u32 width, u32 height,
/* minimum alignment is at least 1 slot */
min_align = max(slot_row, granularity);
-
- /* set alignment to page size by default and enforce minumum cache
- line size */
*align = ALIGN(*align ? : PAGE_SIZE, 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;
+
+ *offs &= ~(min_align - 1);
+
+ /* 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;
+ *offs /= slot_row;
if (*x_area > tiler.width || *y_area > tiler.height)
return -ENOMEM;
@@ -564,10 +580,10 @@ void fill_virt_array(struct tiler_block_t *blk, u32 *virt_array)
*
* (must have mutex)
*/
-static u16 _m_blk_find_fit(u16 w, u16 align,
+static u16 _m_blk_find_fit(u16 w, u16 align, u16 offs,
struct area_info *ai, struct list_head **before)
{
- int x = ai->area.p0.x + w;
+ int x = ai->area.p0.x + w + offs;
struct mem_info *mi;
/* area blocks are sorted by x */
@@ -577,7 +593,7 @@ static u16 _m_blk_find_fit(u16 w, u16 align,
*before = &mi->by_area;
return x;
}
- x = ALIGN(mi->area.p1.x + 1, align) + w;
+ x = ALIGN(mi->area.p1.x + 1 -offs, align) + w + offs;
}
*before = &ai->blocks;
@@ -599,7 +615,7 @@ struct mem_info *_m_add2area(struct mem_info *mi, struct area_info *ai,
return mi;
}
-static struct mem_info *get_2d_area(u16 w, u16 h, u16 align, u16 band,
+static struct mem_info *get_2d_area(u16 w, u16 h, u16 align, u16 offs, u16 band,
struct gid_info *gi, struct tcm *tcm)
{
struct area_info *ai = NULL;
@@ -615,7 +631,7 @@ static struct mem_info *get_2d_area(u16 w, u16 h, u16 align, u16 band,
if (mi->area.tcm == tcm &&
tcm_aheight(mi->area) == h &&
tcm_awidth(mi->area) == w &&
- (mi->area.p0.x & (align - 1)) == 0) {
+ (mi->area.p0.x & (align - 1)) == offs) {
/* this area is already set up */
/* remove from reserved list */
@@ -646,7 +662,7 @@ static struct mem_info *get_2d_area(u16 w, u16 h, u16 align, u16 band,
list_for_each_entry(ai, &gi->areas, by_gid) {
if (ai->area.tcm == tcm &&
tcm_aheight(ai->area) == h) {
- x = _m_blk_find_fit(w, align, ai, &before);
+ x = _m_blk_find_fit(w, align, offs, ai, &before);
if (x) {
_m_add2area(mi, ai, x - w, w, before);
@@ -666,10 +682,10 @@ static struct mem_info *get_2d_area(u16 w, u16 h, u16 align, u16 band,
mutex_unlock(&mtx);
/* if no area fit, reserve a new one */
- ai = area_new_m(ALIGN(w, max(band, align)), h,
+ ai = area_new_m(ALIGN(w + offs, max(band, align)), h,
max(band, align), tcm, gi);
if (ai) {
- _m_add2area(mi, ai, ai->area.p0.x, w, &ai->blocks);
+ _m_add2area(mi, ai, ai->area.p0.x + offs, w, &ai->blocks);
if (tiler_alloc_debug & 1)
printk(KERN_ERR "(+2d (%d-%d,%d-%d) in (%d-%d,%d-%d) new)\n",
mi->area.p0.x, mi->area.p1.x,
@@ -688,9 +704,9 @@ done:
}
/* layout reserved 2d blocks in a larger area */
-/* NOTE: band, w, h, a(lign) is in slots */
+/* NOTE: band, w, h, a(lign), o(ffs) is in slots */
static s32 lay_2d(enum tiler_fmt fmt, u16 n, u16 w, u16 h, u16 band,
- u16 align, struct gid_info *gi,
+ u16 align, u16 offs, struct gid_info *gi,
struct list_head *pos)
{
u16 x, x0, e = ALIGN(w, align), w_res = (n - 1) * e + w;
@@ -700,15 +716,15 @@ static s32 lay_2d(enum tiler_fmt fmt, u16 n, u16 w, u16 h, u16 band,
printk(KERN_INFO "packing %u %u buffers into %u width\n",
n, w, w_res);
- /* calculate dimensions, band, and alignment in slots */
+ /* calculate dimensions, band, offs, and alignment in slots */
/* reserve an area */
- ai = area_new_m(ALIGN(w_res, max(band, align)), h,
+ ai = area_new_m(ALIGN(w_res + offs, max(band, align)), h,
max(band, align), tcm[fmt], gi);
if (!ai)
return -ENOMEM;
/* lay out blocks in the reserved area */
- for (n = 0, x = 0; x < w_res; x += e, n++) {
+ for (n = 0, x = offs; x < w_res; x += e, n++) {
/* reserve a block struct */
mi = kmalloc(sizeof(*mi), GFP_KERNEL);
if (!mi)
@@ -1095,14 +1111,15 @@ static void fill_block_info(struct mem_info *i, struct tiler_block_info *blk)
* ==========================================================================
*/
static struct mem_info *alloc_area(enum tiler_fmt fmt, u32 width, u32 height,
- struct gid_info *gi, u16 align)
+ struct gid_info *gi, u16 align, u16 offs)
{
- u16 x, y, band;
+ u16 x, y, band, remainder = 0;
struct mem_info *mi = NULL;
const struct tiler_geom *g = tiler.geom(fmt);
/* calculate dimensions, band, and alignment in slots */
- if (__analize_area(fmt, width, height, &x, &y, &band, &align))
+ if (__analize_area(fmt, width, height, &x, &y, &band, &align, &offs,
+ &remainder))
return NULL;
if (fmt == TILFMT_PAGE) {
@@ -1126,7 +1143,7 @@ static struct mem_info *alloc_area(enum tiler_fmt fmt, u32 width, u32 height,
mi->parent = gi;
list_add(&mi->by_area, &gi->onedim);
} else {
- mi = get_2d_area(x, y, align, band, gi, tcm[fmt]);
+ mi = get_2d_area(x, y, align, offs, band, gi, tcm[fmt]);
if (!mi)
return NULL;
@@ -1140,19 +1157,20 @@ static struct mem_info *alloc_area(enum tiler_fmt fmt, u32 width, u32 height,
mutex_unlock(&mtx);
mi->blk.phys = tiler.addr(fmt,
- mi->area.p0.x * g->slot_w, mi->area.p0.y * g->slot_h);
+ mi->area.p0.x * g->slot_w,
+ mi->area.p0.y * g->slot_h) + remainder;
return mi;
}
static struct mem_info *alloc_block_area(enum tiler_fmt fmt, u32 width,
u32 height, u32 key, u32 gid,
- struct security_info *si, u16 align)
+ struct security_info *si, u16 align, u16 offs)
{
struct mem_info *mi = NULL;
struct gid_info *gi = NULL;
/* validate parameters */
- if (!si)
+ if (!si || align > PAGE_SIZE || offs >= (align ? : PAGE_SIZE))
return ERR_PTR(-EINVAL);
/* get group context */
@@ -1164,7 +1182,7 @@ static struct mem_info *alloc_block_area(enum tiler_fmt fmt, u32 width,
return ERR_PTR(-ENOMEM);
/* reserve area in tiler container */
- mi = alloc_area(fmt, width, height, gi, align);
+ mi = alloc_area(fmt, width, height, gi, align, offs);
if (!mi) {
mutex_lock(&mtx);
gi->refs--;
@@ -1255,7 +1273,7 @@ static s32 alloc_block(enum tiler_fmt fmt, u32 width, u32 height,
*info = NULL;
/* allocate tiler container area */
- mi = alloc_block_area(fmt, width, height, key, gid, si, PAGE_SIZE);
+ mi = alloc_block_area(fmt, width, height, key, gid, si, PAGE_SIZE, 0);
if (IS_ERR_OR_NULL(mi))
return mi ? -ENOMEM : PTR_ERR(mi);
@@ -1398,7 +1416,7 @@ static s32 pin_any_block(enum tiler_fmt fmt, u32 width, u32 height,
goto done;
/* get allocation area */
- mi = alloc_block_area(fmt, width, height, key, gid, si, PAGE_SIZE);
+ mi = alloc_block_area(fmt, width, height, key, gid, si, PAGE_SIZE, 0);
if (IS_ERR_OR_NULL(mi)) {
res = mi ? PTR_ERR(mi) : -ENOMEM;
goto done;
@@ -1736,7 +1754,7 @@ tiler_blk_handle tiler_alloc_block_area(enum tiler_fmt fmt, u32 width,
return NULL;
mi = alloc_block_area(fmt, width, height, 0, 0,
- __get_si(0, true, SECURE_BY_PID), PAGE_SIZE);
+ __get_si(0, true, SECURE_BY_PID), PAGE_SIZE, 0);
if (IS_ERR_OR_NULL(mi))
goto done;
@@ -1751,7 +1769,7 @@ EXPORT_SYMBOL(tiler_alloc_block_area);
tiler_blk_handle tiler_alloc_block_area_aligned(enum tiler_fmt fmt, u32 width,
u32 height, u32 *ssptr, u32 *virt_array, u32 align,
- u32 token)
+ u32 offset, u32 token)
{
struct mem_info *mi;
*ssptr = 0;
@@ -1761,7 +1779,7 @@ tiler_blk_handle tiler_alloc_block_area_aligned(enum tiler_fmt fmt, u32 width,
return NULL;
mi = alloc_block_area(fmt, width, height, 0, 0, __get_si(token, true,
- SECURE_BY_TOKEN), align);
+ SECURE_BY_TOKEN), align, offset);
if (IS_ERR_OR_NULL(mi))
goto done;
@@ -1785,13 +1803,14 @@ EXPORT_SYMBOL(tiler_unpin_block);
s32 tiler_memsize(enum tiler_fmt fmt, u32 width, u32 height, u32 *alloc_pages,
u32 *virt_pages)
{
- u16 x, y, band, align = PAGE_SIZE;
+ u16 x, y, band, align = PAGE_SIZE, offs = 0, remainder = 0;
int res;
struct tiler_block_t blk;
*alloc_pages = *virt_pages = 0;
- res = tiler.analize(fmt, width, height, &x, &y, &band, &align);
+ res = tiler.analize(fmt, width, height, &x, &y, &band, &align, &offs,
+ &remainder);
if (!res) {
blk.height = height;
diff --git a/drivers/media/video/tiler/tiler-nv12.c b/drivers/media/video/tiler/tiler-nv12.c
index f208275eb78..2142b3acc82 100644
--- a/drivers/media/video/tiler/tiler-nv12.c
+++ b/drivers/media/video/tiler/tiler-nv12.c
@@ -336,7 +336,7 @@ static u16 nv12_together(u16 o, u16 a, u16 w, u16 n, u16 *area, u8 *packing)
static void reserve_nv12(u32 n, u32 width, u32 height,
u32 gid, struct security_info *si)
{
- u16 w, h, band, a, o = 0;
+ u16 w, h, band, a, o = 0, r = 0;
struct gid_info *gi;
int res = 0, res2, i;
u16 n_t, n_s, area_t, area_s;
@@ -349,7 +349,7 @@ static void reserve_nv12(u32 n, u32 width, u32 height,
return;
/* calculate dimensions, band, and alignment in slots */
- if (ops->analize(TILFMT_8BIT, width, height, &w, &h, &band, &a))
+ if (ops->analize(TILFMT_8BIT, width, height, &w, &h, &band, &a, &o, &r))
return;
/* get group context */
@@ -378,10 +378,10 @@ static void reserve_nv12(u32 n, u32 width, u32 height,
* able to reserve both 8- and 16-bit blocks as the
* offsets of them must match.
*/
- res = ops->lay_2d(TILFMT_8BIT, n_s, w, h, band_8, a,
+ res = ops->lay_2d(TILFMT_8BIT, n_s, w, h, band_8, a, o,
gi, &reserved);
res2 = ops->lay_2d(TILFMT_16BIT, n_s, (w + 1) >> 1, h,
- band_16, a >> 1, gi, &reserved);
+ band_16, a >> 1, o >> 1, gi, &reserved);
if (res2 < 0 || res < 0 || res != res2) {
/* clean up */
diff --git a/drivers/media/video/tiler/tiler-reserve.c b/drivers/media/video/tiler/tiler-reserve.c
index c5a4f9c3b0e..198636325a9 100644
--- a/drivers/media/video/tiler/tiler-reserve.c
+++ b/drivers/media/video/tiler/tiler-reserve.c
@@ -77,16 +77,17 @@ u32 tiler_best2pack(u16 o, u16 a, u16 b, u16 w, u16 *n, u16 *_area)
/* reserve 2d blocks */
static void reserve_blocks(u32 n, enum tiler_fmt fmt, u32 width, u32 height,
- u32 gid,
+ u32 align, u32 offs, u32 gid,
struct security_info *si)
{
u32 bpt, res = 0, i;
- u16 a, band, w, h, n_try;
+ u16 o = offs, a = align, r = 0, band, w, h, n_try;
struct gid_info *gi;
const struct tiler_geom *g;
/* Check input parameters for correctness, and support */
if (!width || !height || !n ||
+ align > PAGE_SIZE || offs >= align ||
fmt < TILFMT_8BIT || fmt > TILFMT_32BIT)
return;
@@ -99,7 +100,7 @@ static void reserve_blocks(u32 n, enum tiler_fmt fmt, u32 width, u32 height,
* sufficient. Also check for basic area info.
*/
if (width * g->bpp * 2 <= PAGE_SIZE ||
- ops->analize(fmt, width, height, &w, &h, &band, &a))
+ ops->analize(fmt, width, height, &w, &h, &band, &a, &o, &r))
return;
/* get group id */
@@ -116,7 +117,7 @@ static void reserve_blocks(u32 n, enum tiler_fmt fmt, u32 width, u32 height,
res = -1;
while (n_try > 1) {
/* adjust res so we fail on 0 return value */
- res = ops->lay_2d(fmt, n_try, w, h, band, a,
+ res = ops->lay_2d(fmt, n_try, w, h, band, a, o,
gi, &gi->reserved) - 1;
if (res >= 0)
break;