aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/omapgfx/gfx_tiler.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/omapgfx/gfx_tiler.c')
-rw-r--r--drivers/media/video/omapgfx/gfx_tiler.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/drivers/media/video/omapgfx/gfx_tiler.c b/drivers/media/video/omapgfx/gfx_tiler.c
new file mode 100644
index 0000000..1e77983
--- /dev/null
+++ b/drivers/media/video/omapgfx/gfx_tiler.c
@@ -0,0 +1,152 @@
+/*
+ * drivers/media/video/omap/gfx_tiler.c
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+
+#include "v4gfx.h"
+#include "gfx_bc.h"
+
+#ifdef CONFIG_TILER_OMAP
+#include <mach/tiler.h>
+#define TILER_ALLOCATE_V4L2
+#endif
+
+void v4gfx_tiler_buffer_free(struct v4gfx_device *vout, unsigned int count,
+ unsigned int startindex)
+{
+ int i;
+
+ if (startindex < 0)
+ startindex = 0;
+ if (startindex + count > VIDEO_MAX_FRAME)
+ count = VIDEO_MAX_FRAME - startindex;
+
+ for (i = startindex; i < startindex + count; i++) {
+ if (vout->buf_phy_addr_alloced[i])
+ tiler_free(vout->buf_phy_addr_alloced[i]);
+ if (vout->buf_phy_uv_addr_alloced[i])
+ tiler_free(vout->buf_phy_uv_addr_alloced[i]);
+ vout->buf_phy_addr[i] = 0;
+ vout->buf_phy_addr_alloced[i] = 0;
+ vout->buf_phy_uv_addr[i] = 0;
+ vout->buf_phy_uv_addr_alloced[i] = 0;
+ }
+}
+
+/* Allocate the buffers for TILER space. Ideally, the buffers will be ONLY
+ in tiler space, with different rotated views available by just a convert.
+ */
+int v4gfx_tiler_buffer_setup(struct v4gfx_device *vout,
+ unsigned int *count, unsigned int startindex,
+ struct v4l2_pix_format *pix)
+{
+ /* startindex is always passed as 0, possibly tidy up? */
+ int i, aligned = 1, bpp;
+ enum tiler_fmt fmt;
+ int rv = 0;
+
+ /* normalize buffers to allocate so we stay within bounds */
+ int start = (startindex < 0) ? 0 : startindex;
+ int n_alloc = (start + *count > VIDEO_MAX_FRAME) ?
+ VIDEO_MAX_FRAME - start : *count;
+
+ GFXLOG(1, V4L2DEV(vout), "+%s\n", __func__);
+ bpp = v4gfx_try_format(pix);
+ if (bpp <= 0) {
+ rv = bpp; /* error condition */
+ goto end;
+ }
+
+ GFXLOG(1, V4L2DEV(vout), "tiler buffer alloc: "
+ "count = %d, start = %d :\n", *count, startindex);
+
+ /* special allocation scheme for NV12 format */
+ if (V4L2_PIX_FMT_NV12 == pix->pixelformat) {
+
+ tiler_alloc_packed_nv12(&n_alloc, ALIGN(pix->width, 128),
+ pix->height,
+ (void **) vout->buf_phy_addr + start,
+ (void **) vout->buf_phy_uv_addr + start,
+ (void **) vout->buf_phy_addr_alloced + start,
+ (void **) vout->buf_phy_uv_addr_alloced + start,
+ aligned);
+
+ } else {
+ /* Only bpp of 1, 2, and 4 is supported by tiler */
+ fmt = (bpp == 1 ? TILFMT_8BIT :
+ bpp == 2 ? TILFMT_16BIT :
+ bpp == 4 ? TILFMT_32BIT : TILFMT_INVALID);
+ if (fmt == TILFMT_INVALID) {
+ rv = -ENOMEM;
+ goto end;
+ }
+
+ tiler_alloc_packed(&n_alloc, fmt, ALIGN(pix->width, 128 / bpp),
+ pix->height,
+ (void **) vout->buf_phy_addr + start,
+ (void **) vout->buf_phy_addr_alloced + start,
+ aligned);
+ }
+
+ GFXLOG(1, V4L2DEV(vout),
+ "allocated %d buffers\n", n_alloc);
+
+ if (n_alloc < *count) {
+ if (n_alloc && (startindex == -1 ||
+ V4L2_MEMORY_MMAP != vout->memory)) {
+ /* TODO: check this condition's logic */
+ v4gfx_tiler_buffer_free(vout, n_alloc, start);
+ *count = 0;
+ rv = -ENOMEM;
+ goto end;
+ }
+ }
+
+ for (i = start; i < start + n_alloc; i++) {
+ GFXLOG(1, V4L2DEV(vout),
+ "y=%08lx (%d) uv=%08lx (%d)\n",
+ vout->buf_phy_addr[i],
+ vout->buf_phy_addr_alloced[i] ? 1 : 0,
+ vout->buf_phy_uv_addr[i],
+ vout->buf_phy_uv_addr_alloced[i] ? 1 : 0);
+ }
+
+ *count = n_alloc;
+end:
+ GFXLOG(1, V4L2DEV(vout), "-%s [%d]\n", __func__, rv);
+ return rv;
+}
+
+void v4gfx_tiler_image_incr(struct v4gfx_device *vout, int *cpu_pgwidth,
+ int *tiler_increment)
+{
+ /* for NV12, Y buffer is 1bpp*/
+ if (V4L2_PIX_FMT_NV12 == vout->pix.pixelformat) {
+ *cpu_pgwidth =
+ (vout->pix.width + TILER_PAGE - 1) & ~(TILER_PAGE - 1);
+ *tiler_increment = 64 * TILER_WIDTH;
+ } else {
+ *cpu_pgwidth = (vout->pix.width * vout->bpp + TILER_PAGE - 1) &
+ ~(TILER_PAGE - 1);
+ if (vout->bpp > 1)
+ *tiler_increment = 2 * 64 * TILER_WIDTH;
+ else
+ *tiler_increment = 64 * TILER_WIDTH;
+ }
+}
+
+void v4gfx_tiler_image_incr_uv(struct v4gfx_device *vout, int *tiler_increment)
+{
+ if (vout->pix.pixelformat == V4L2_PIX_FMT_NV12)
+ *tiler_increment = 2 * 64 * TILER_WIDTH;
+ /* Otherwise do nothing */
+}