summaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
authorSemwal, Sumit <sumit.semwal@ti.com>2010-08-02 12:47:13 +0530
committerRicardo Perez Olivares <x0081762@ti.com>2010-09-14 19:26:41 -0500
commit4a6a105425ee54e7e50020906f7f7d40052e2703 (patch)
treea591325443699afc0f5c4098c318ae7bf7e6372c /drivers/media
parentef18da1e5a7f55194035fb842bc2fcd26c9491a3 (diff)
V4L2 Add Tiler Support in vout.c
Adds uv_addr for NV12. Changes video_mode_to_dss_mode API Signed-off-by: Lajos Molnar <molnar@ti.com Signed-off-by: Guruswamy Senthilvadivu <svadivu@ti.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/omap/omap_vout.c374
-rw-r--r--drivers/media/video/omap/omap_voutdef.h6
2 files changed, 350 insertions, 30 deletions
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index f573719a961b..b692ffe16a82 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -52,10 +52,12 @@
#include "omap_voutlib.h"
#include "omap_voutdef.h"
+#include <mach/tiler.h>
MODULE_AUTHOR("Texas Instruments");
MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
MODULE_LICENSE("GPL");
+#define OMAP_VIDEO3 2
/* Driver Configuration macros */
#define VOUT_NAME "omap_vout"
@@ -74,9 +76,13 @@ enum dma_channel_state {
#define QQVGA_HEIGHT 120
/* Max Resolution supported by the driver */
+#ifdef CONFIG_ARCH_OMAP4
+#define VID_MAX_WIDTH 2048 /* Largest width */
+#define VID_MAX_HEIGHT 2048 /* Largest height */
+#else
#define VID_MAX_WIDTH 1280 /* Largest width */
#define VID_MAX_HEIGHT 720 /* Largest height */
-
+#endif
/* Mimimum requirement is 2x2 for DSS */
#define VID_MIN_WIDTH 2
#define VID_MIN_HEIGHT 2
@@ -96,6 +102,8 @@ static u32 video1_numbuffers = 3;
static u32 video2_numbuffers = 3;
static u32 video1_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
static u32 video2_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
+static u32 video3_numbuffers = 3;
+static u32 video3_bufsize = OMAP_VOUT_MAX_BUF_SIZE;
static u32 vid1_static_vrfb_alloc;
static u32 vid2_static_vrfb_alloc;
static int debug;
@@ -117,6 +125,13 @@ module_param(video2_bufsize, uint, S_IRUGO);
MODULE_PARM_DESC(video2_bufsize,
"Size of the buffer to be allocated for video2 device");
+module_param(video3_numbuffers, uint, S_IRUGO);
+MODULE_PARM_DESC(video3_numbuffers, "Number of buffers to be allocated at \
+ init time for Video3 device.");
+
+module_param(video3_bufsize, uint, S_IRUGO);
+MODULE_PARM_DESC(video1_bufsize, "Size of the buffer to be allocated for \
+ video3 device");
module_param(vid1_static_vrfb_alloc, bool, S_IRUGO);
MODULE_PARM_DESC(vid1_static_vrfb_alloc,
"Static allocation of the VRFB buffer for video1 device");
@@ -128,6 +143,10 @@ MODULE_PARM_DESC(vid2_static_vrfb_alloc,
module_param(debug, bool, S_IRUGO);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
+
+static enum omap_color_mode video_mode_to_dss_mode(
+ struct v4l2_pix_format *pix);
+
/* list of image formats supported by OMAP2 video pipelines */
const static struct v4l2_fmtdesc omap_formats[] = {
{
@@ -167,6 +186,10 @@ const static struct v4l2_fmtdesc omap_formats[] = {
.description = "UYVY, packed",
.pixelformat = V4L2_PIX_FMT_UYVY,
},
+ {
+ .description = "NV12 - YUV420 format",
+ .pixelformat = V4L2_PIX_FMT_NV12,
+ },
};
#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
@@ -199,7 +222,8 @@ static unsigned long omap_vout_alloc_buffer(u32 buf_size, u32 *phys_addr)
/*
* Free buffers
*/
-static void omap_vout_free_buffer(unsigned long virtaddr, u32 buf_size)
+static void omap_vout_free_buffer(unsigned long virtaddr, u32 phys_addr,
+ u32 buf_size)
{
u32 order, size;
unsigned long addr = virtaddr;
@@ -294,10 +318,19 @@ static int omap_vout_try_format(struct v4l2_pix_format *pix)
pix->colorspace = V4L2_COLORSPACE_SRGB;
bpp = RGB32_BPP;
break;
+ case V4L2_PIX_FMT_NV12:
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+ bpp = 1; /* TODO: check this? */
+ break;
}
+ /* :NOTE: NV12 has width bytes per line in both Y and UV sections */
pix->bytesperline = pix->width * bpp;
+ pix->bytesperline = (pix->bytesperline + PAGE_SIZE - 1) &
+ ~(PAGE_SIZE - 1);
+ /* :TODO: add 2-pixel round restrictions to YUYV and NV12 formats */
pix->sizeimage = pix->bytesperline * pix->height;
-
+ if (V4L2_PIX_FMT_NV12 == pix->pixelformat)
+ pix->sizeimage += pix->sizeimage >> 1;
return bpp;
}
@@ -406,6 +439,8 @@ static inline int calc_rotation(const struct omap_vout_device *vout)
default:
return dss_rotation_180_degree;
}
+#else
+ return vout->rotation;
#endif
return dss_rotation_180_degree;
}
@@ -418,12 +453,17 @@ static void omap_vout_free_buffers(struct omap_vout_device *vout)
int i, numbuffers;
/* Allocate memory for the buffers */
- numbuffers = (vout->vid) ? video2_numbuffers : video1_numbuffers;
- vout->buffer_size = (vout->vid) ? video2_bufsize : video1_bufsize;
+ if (OMAP_VIDEO3 == vout->vid) {
+ numbuffers = video3_numbuffers;
+ vout->buffer_size = video3_bufsize;
+ } else {
+ numbuffers = (vout->vid) ? video2_numbuffers : video1_numbuffers;
+ vout->buffer_size = (vout->vid) ? video2_bufsize : video1_bufsize;
+ }
for (i = 0; i < numbuffers; i++) {
omap_vout_free_buffer(vout->buf_virt_addr[i],
- vout->buffer_size);
+ vout->buf_phy_addr[i], vout->buffer_size);
vout->buf_phy_addr[i] = 0;
vout->buf_virt_addr[i] = 0;
}
@@ -477,8 +517,105 @@ static int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout,
}
#endif
-/*
- * Convert V4L2 rotation to DSS rotation
+static void omap_vout_tiler_buffer_free(struct omap_vout_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.
+ */
+static int omap_vout_tiler_buffer_setup(struct omap_vout_device *vout,
+ unsigned int *count, unsigned int startindex,
+ struct v4l2_pix_format *pix)
+{
+ int i, aligned = 1;
+ enum tiler_fmt fmt;
+
+ /* 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;
+ int bpp = omap_vout_try_format(pix);
+
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "tiler buffer alloc:\n"
+ "count - %d, start -%d :\n", *count, startindex);
+
+ /* special allocation scheme for NV12 format */
+ if (OMAP_DSS_COLOR_NV12 == video_mode_to_dss_mode(pix)) {
+ tiler_alloc_packed_nv12(&n_alloc, pix->width,
+ 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)
+ return -ENOMEM;
+
+ tiler_alloc_packed(&n_alloc, fmt, pix->width,
+ pix->height,
+ (void **) vout->buf_phy_addr + start,
+ (void **) vout->buf_phy_addr_alloced + start,
+ aligned);
+ }
+
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
+ "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 */
+ omap_vout_tiler_buffer_free(vout, n_alloc, start);
+ *count = 0;
+ return -ENOMEM;
+ }
+ }
+
+ for (i = start; i < start + n_alloc; i++) {
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
+ "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;
+
+ return 0;
+}
+/* Free tiler buffers */
+static void omap_vout_free_tiler_buffers(struct omap_vout_device *vout)
+{
+ omap_vout_tiler_buffer_free(vout, vout->buffer_allocated, 0);
+ vout->buffer_allocated = 0;
+}
+/* Convert V4L2 rotation to DSS rotation
* V4L2 understand 0, 90, 180, 270.
* Convert to 0, 1, 2 and 3 repsectively for DSS
*/
@@ -528,7 +665,9 @@ static int omap_vout_calculate_offset(struct omap_vout_device *vout)
int temp_ps = 2;
int offset = 0;
#endif
+ int *cropped_uv_offset = &vout->cropped_uv_offset;
int ctop = 0, cleft = 0, line_length = 0;
+ unsigned long addr = 0, uv_addr = 0;
ovid = &vout->vid_info;
ovl = ovid->overlays[0];
@@ -629,6 +768,21 @@ static int omap_vout_calculate_offset(struct omap_vout_device *vout)
((crop->width / vr_ps) - 1) * ps;
break;
}
+#else
+ /* :TODO: change v4l2 to send TSPtr as tiled addresses to DSS2 */
+ addr = tiler_get_natural_addr(vout->queued_buf_addr[vout->cur_frm->i]);
+
+ if (OMAP_DSS_COLOR_NV12 == vout->dss_mode) {
+ *cropped_offset = tiler_stride(addr) * crop->top + crop->left;
+ uv_addr = tiler_get_natural_addr(
+ vout->queued_buf_uv_addr[vout->cur_frm->i]);
+ /* :TODO: only allow even crops for NV12 */
+ *cropped_uv_offset = tiler_stride(uv_addr) * (crop->top >> 1)
+ + (crop->left & ~1);
+ } else {
+ *cropped_offset =
+ tiler_stride(addr) * crop->top + crop->left * ps;
+ }
#endif
v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n",
__func__, *cropped_offset);
@@ -638,8 +792,9 @@ static int omap_vout_calculate_offset(struct omap_vout_device *vout)
/*
* Convert V4L2 pixel format to DSS pixel format
*/
-static int video_mode_to_dss_mode(struct omap_vout_device *vout)
+static int video_mode_to_dss_mode(struct v4l2_pix_format *pix)
{
+#if 0 /* TODO: Take care of OMAP2,OMAP3 Video1 also */
struct omap_overlay *ovl;
struct omapvideo_info *ovid;
struct v4l2_pix_format *pix = &vout->pix;
@@ -647,8 +802,13 @@ static int video_mode_to_dss_mode(struct omap_vout_device *vout)
ovid = &vout->vid_info;
ovl = ovid->overlays[0];
-
+#else
+ enum omap_color_mode mode;
+#endif
switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_NV12:
+ mode = OMAP_DSS_COLOR_NV12;
+ break;
case 0:
break;
case V4L2_PIX_FMT_YUYV:
@@ -664,8 +824,11 @@ static int video_mode_to_dss_mode(struct omap_vout_device *vout)
mode = OMAP_DSS_COLOR_RGB24P;
break;
case V4L2_PIX_FMT_RGB32:
+#if 0 /* TODO: Take care of OMAP2,OMAP3 Video1 also */
mode = (ovl->id == OMAP_DSS_VIDEO1) ?
OMAP_DSS_COLOR_RGB24U : OMAP_DSS_COLOR_ARGB32;
+#endif
+ mode = OMAP_DSS_COLOR_ARGB32;
break;
case V4L2_PIX_FMT_BGR32:
mode = OMAP_DSS_COLOR_RGBX32;
@@ -676,12 +839,25 @@ static int video_mode_to_dss_mode(struct omap_vout_device *vout)
return mode;
}
+#if 0 /* Used for non Tiler NV12 */
+/* helper function: for NV12, returns uv buffer address given single buffer
+ * for yuv - y buffer will still be in the input.
+ * used only for non-TILER case
+*/
+u32 omapvid_get_uvbase_nv12(u32 paddr, int height, int width)
+{
+ u32 puv_addr = 0;
+
+ puv_addr = (paddr + (height * width));
+ return puv_addr;
+}
+#endif
/*
* Setup the overlay
*/
int omapvid_setup_overlay(struct omap_vout_device *vout,
struct omap_overlay *ovl, int posx, int posy, int outw,
- int outh, u32 addr)
+ int outh, u32 addr, u32 uv_addr)
{
int ret = 0;
struct omap_overlay_info info;
@@ -693,7 +869,7 @@ int omapvid_setup_overlay(struct omap_vout_device *vout,
goto setup_ovl_err;
}
- vout->dss_mode = video_mode_to_dss_mode(vout);
+ vout->dss_mode = video_mode_to_dss_mode(&vout->pix);
if (vout->dss_mode == -EINVAL) {
ret = -EINVAL;
goto setup_ovl_err;
@@ -715,7 +891,12 @@ int omapvid_setup_overlay(struct omap_vout_device *vout,
}
ovl->get_overlay_info(ovl, &info);
- info.paddr = addr;
+ if (addr)
+ info.paddr = addr;
+ if (OMAP_DSS_COLOR_NV12 == vout->dss_mode)
+ info.p_uv_addr = uv_addr;
+ else
+ info.p_uv_addr = (u32) NULL;
info.vaddr = NULL;
info.width = cropwidth;
info.height = cropheight;
@@ -736,6 +917,10 @@ int omapvid_setup_overlay(struct omap_vout_device *vout,
info.rotation_type = OMAP_DSS_ROT_VRFB;
info.screen_width = 2048;
}
+#else
+ info.rotation_type = OMAP_DSS_ROT_TILER;
+ info.screen_width = pixwidth;
+ info.rotation = vout->rotation;
#endif
v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
@@ -747,6 +932,8 @@ int omapvid_setup_overlay(struct omap_vout_device *vout,
info.pos_y, info.out_width, info.out_height, info.rotation_type,
info.screen_width);
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "info.puvaddr=%x\n",
+ info.p_uv_addr);
ret = ovl->set_overlay_info(ovl, &info);
if (ret)
goto setup_ovl_err;
@@ -761,7 +948,7 @@ setup_ovl_err:
/*
* Initialize the overlay structure
*/
-int omapvid_init(struct omap_vout_device *vout, u32 addr)
+int omapvid_init(struct omap_vout_device *vout, u32 addr, u32 uv_addr)
{
int ret = 0, i;
struct v4l2_window *win;
@@ -820,7 +1007,7 @@ int omapvid_init(struct omap_vout_device *vout, u32 addr)
}
ret = omapvid_setup_overlay(vout, ovl, posx, posy,
- outw, outh, addr);
+ outw, outh, addr, uv_addr);
if (ret)
goto omapvid_init_err;
}
@@ -854,11 +1041,13 @@ void omap_vout_isr(void *arg, unsigned int irqstatus)
{
int ret;
u32 addr, fid;
+ u32 uv_addr;
struct omap_overlay *ovl;
struct timeval timevalue;
struct omapvideo_info *ovid;
struct omap_dss_device *cur_display;
struct omap_vout_device *vout = (struct omap_vout_device *)arg;
+ u32 flags;
if (!vout->streaming)
return;
@@ -871,7 +1060,7 @@ void omap_vout_isr(void *arg, unsigned int irqstatus)
cur_display = ovl->manager->device;
- spin_lock(&vout->vbq_lock);
+ spin_lock_irqsave(&vout->vbq_lock, flags);
do_gettimeofday(&timevalue);
if (cur_display->type == OMAP_DISPLAY_TYPE_DPI) {
if (!(irqstatus & DISPC_IRQ_VSYNC))
@@ -897,7 +1086,7 @@ void omap_vout_isr(void *arg, unsigned int irqstatus)
+ vout->cropped_offset;
/* First save the configuration in ovelray structure */
- ret = omapvid_init(vout, addr);
+ ret = omapvid_init(vout, addr, uv_addr);
if (ret)
printk(KERN_ERR VOUT_NAME
"failed to set overlay info\n");
@@ -947,7 +1136,7 @@ void omap_vout_isr(void *arg, unsigned int irqstatus)
vout->queued_buf_addr[vout->next_frm->i] +
vout->cropped_offset;
/* First save the configuration in ovelray structure */
- ret = omapvid_init(vout, addr);
+ ret = omapvid_init(vout, addr, uv_addr);
if (ret)
printk(KERN_ERR VOUT_NAME
"failed to set overlay info\n");
@@ -961,7 +1150,7 @@ void omap_vout_isr(void *arg, unsigned int irqstatus)
}
vout_isr_err:
- spin_unlock(&vout->vbq_lock);
+ spin_unlock_irqrestore(&vout->vbq_lock, flags);
}
@@ -976,8 +1165,9 @@ vout_isr_err:
static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
unsigned int *size)
{
+ int i;
#ifndef CONFIG_ARCH_OMAP4
- int startindex = 0, i, j;
+ int startindex = 0, j;
u32 phy_addr = 0, virt_addr = 0;
#endif
struct omap_vout_device *vout = q->priv_data;
@@ -1032,6 +1222,28 @@ static int omap_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
}
*count = vout->buffer_allocated = i;
+#else
+
+ /* tiler_alloc_buf to be called here
+ pre-requisites: rotation, format?
+ based on that buffers will be allocated.
+ */
+ /* Now allocated the V4L2 buffers */
+ /* i is the block-width - either 4K or 8K, depending upon input width*/
+ i = (vout->pix.width * vout->bpp +
+ TILER_PAGE - 1) & ~(TILER_PAGE - 1);
+
+ /* for NV12 format, buffer is height + height / 2*/
+ if (OMAP_DSS_COLOR_NV12 == vout->dss_mode)
+ *size = vout->buffer_size = (vout->pix.height * 3/2 * i);
+ else
+ *size = vout->buffer_size = (vout->pix.height * i);
+
+ v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
+ "\nheight=%d, size = %d, vout->buffer_sz=%d\n",
+ vout->pix.height, *size, vout->buffer_size);
+ if (omap_vout_tiler_buffer_setup(vout, count, 0, &vout->pix))
+ return -ENOMEM;
#endif
if (V4L2_MEMORY_MMAP != vout->memory)
return 0;
@@ -1175,6 +1387,14 @@ static int omap_vout_buffer_prepare(struct videobuf_queue *q,
* from this array will be used to configure DSS */
vout->queued_buf_addr[vb->i] = (u8 *)
vout->vrfb_context[vb->i].paddr[rotation];
+#else /* TILER to be used */
+
+ /* Here, we need to use the physical addresses given by Tiler:
+ */
+ dmabuf = vout->buf_phy_addr[vb->i];
+ vout->queued_buf_addr[vb->i] = (u8 *) vout->buf_phy_addr[vb->i];
+ vout->queued_buf_uv_addr[vb->i] = (u8 *) vout->buf_phy_uv_addr[vb->i];
+
#endif
return 0;
}
@@ -1247,6 +1467,7 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
#endif
struct omap_vout_device *vout = file->private_data;
struct videobuf_queue *q = &vout->vbq;
+ int j = 0, k = 0, m = 0, p = 0, m_increment = 0;
v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
" %s pgoff=0x%lx, start=0x%lx, end=0x%lx\n", __func__,
@@ -1286,7 +1507,79 @@ static int omap_vout_mmap(struct file *file, struct vm_area_struct *vma)
pos += PAGE_SIZE;
size -= PAGE_SIZE;
}
+#else /* Tiler remapping */
+ pos = (void *) vout->buf_phy_addr[i];
+ /* get line width */
+ /* for NV12, Y buffer is 1bpp*/
+ if (OMAP_DSS_COLOR_NV12 == vout->dss_mode) {
+ p = (vout->pix.width +
+ TILER_PAGE - 1) & ~(TILER_PAGE - 1);
+ m_increment = 64 * TILER_WIDTH;
+ } else {
+ p = (vout->pix.width * vout->bpp +
+ TILER_PAGE - 1) & ~(TILER_PAGE - 1);
+
+ if (vout->bpp > 1)
+ m_increment = 2*64*TILER_WIDTH;
+ else
+ m_increment = 64 * TILER_WIDTH;
+ }
+
+ for (j = 0; j < vout->pix.height; j++) {
+ /* map each page of the line */
+ #if 0
+ if (0)
+ printk(KERN_NOTICE
+ "Y buffer %s::%s():%d: vm_start+%d = 0x%lx,"
+ "dma->vmalloc+%d = 0x%lx, w=0x%x\n",
+ __FILE__, __func__, __LINE__,
+ k, vma->vm_start + k, m,
+ (pos + m), p);
+ #endif
+ vma->vm_pgoff =
+ ((unsigned long)pos + m) >> PAGE_SHIFT;
+
+ if (remap_pfn_range(vma, vma->vm_start + k,
+ ((unsigned long)pos + m) >> PAGE_SHIFT,
+ p, vma->vm_page_prot))
+ return -EAGAIN;
+ k += p;
+ m += m_increment;
+ }
+ m = 0;
+
+ /* UV Buffer in case of NV12 format */
+ if (OMAP_DSS_COLOR_NV12 == vout->dss_mode) {
+ pos = (void *) vout->buf_phy_uv_addr[i];
+ /* UV buffer is 2 bpp, but half size, so p remains */
+ m_increment = 2*64*TILER_WIDTH;
+
+ /* UV buffer is height / 2*/
+ for (j = 0; j < vout->pix.height / 2; j++) {
+ /* map each page of the line */
+ #if 0
+ if (0)
+ printk(KERN_NOTICE
+ "UV buffer %s::%s():%d: vm_start+%d = 0x%lx,"
+ "dma->vmalloc+%d = 0x%lx, w=0x%x\n",
+ __FILE__, __func__, __LINE__,
+ k, vma->vm_start + k, m,
+ (pos + m), p);
+ #endif
+ vma->vm_pgoff =
+ ((unsigned long)pos + m) >> PAGE_SHIFT;
+
+ if (remap_pfn_range(vma, vma->vm_start + k,
+ ((unsigned long)pos + m) >> PAGE_SHIFT,
+ p, vma->vm_page_prot))
+ return -EAGAIN;
+ k += p;
+ m += m_increment;
+ }
+ }
+
#endif
+ vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
vout->mmap_count++;
v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "Exiting %s\n", __func__);
@@ -1326,6 +1619,8 @@ static int omap_vout_release(struct file *file)
/* Free all buffers */
#ifndef CONFIG_ARCH_OMAP4
omap_vout_free_allbuffers(vout);
+#else
+ omap_vout_free_tiler_buffers(vout);
#endif
videobuf_mmap_free(q);
@@ -1507,7 +1802,11 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
/* change to samller size is OK */
bpp = omap_vout_try_format(&f->fmt.pix);
- f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * bpp;
+ if (V4L2_PIX_FMT_NV12 == f->fmt.pix.pixelformat)
+ f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * 3/2;
+ else
+ f->fmt.pix.sizeimage = f->fmt.pix.width *
+ f->fmt.pix.height * bpp;
/* try & set the new output format */
vout->bpp = bpp;
@@ -1523,7 +1822,7 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win);
/* Save the changes in the overlay strcuture */
- ret = omapvid_init(vout, 0);
+ ret = omapvid_init(vout, 0, 0);
if (ret) {
v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n");
goto s_fmt_vid_out_exit;
@@ -1868,11 +2167,14 @@ static int vidioc_reqbufs(struct file *file, void *fh,
video1_numbuffers : video2_numbuffers;
for (i = num_buffers; i < vout->buffer_allocated; i++) {
omap_vout_free_buffer(vout->buf_virt_addr[i],
- vout->buffer_size);
+ dmabuf->bus_addr, vout->buffer_size);
vout->buf_virt_addr[i] = 0;
vout->buf_phy_addr[i] = 0;
}
vout->buffer_allocated = num_buffers;
+#else
+ omap_vout_tiler_buffer_free(vout, vout->buffer_allocated, 0);
+ vout->buffer_allocated = 0;
#endif
videobuf_mmap_free(q);
} else if (q->bufs[0] && (V4L2_MEMORY_USERPTR == q->bufs[0]->memory)) {
@@ -1960,6 +2262,7 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
{
int ret = 0, j;
u32 addr = 0, mask = 0;
+ u32 uv_addr = 0;
struct omap_vout_device *vout = fh;
struct videobuf_queue *q = &vout->vbq;
struct omapvideo_info *ovid = &vout->vid_info;
@@ -2001,6 +2304,8 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
}
addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i]
+ vout->cropped_offset;
+ uv_addr = (unsigned long) vout->queued_buf_uv_addr[vout->cur_frm->i]
+ + vout->cropped_uv_offset;
mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD;
@@ -2014,6 +2319,7 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
ovl->get_overlay_info(ovl, &info);
info.enabled = 1;
info.paddr = addr;
+ info.p_uv_addr = uv_addr;
if (ovl->set_overlay_info(ovl, &info)) {
ret = -EINVAL;
goto streamon_err1;
@@ -2022,7 +2328,7 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
}
/* First save the configuration in ovelray structure */
- ret = omapvid_init(vout, addr);
+ ret = omapvid_init(vout, addr, uv_addr);
if (ret)
v4l2_err(&vout->vid_dev->v4l2_dev,
"failed to set overlay info\n");
@@ -2394,7 +2700,7 @@ release_vrfb_ctx:
free_buffers:
for (i = 0; i < numbuffers; i++) {
omap_vout_free_buffer(vout->buf_virt_addr[i],
- vout->buffer_size);
+ vout->buf_phy_addr[i], vout->buffer_size);
vout->buf_virt_addr[i] = 0;
vout->buf_phy_addr[i] = 0;
}
@@ -2427,11 +2733,17 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
vid_dev->vouts[k] = vout;
vout->vid_dev = vid_dev;
/* Select video2 if only 1 overlay is controlled by V4L2 */
- if (pdev->num_resources == 1)
- vout->vid_info.overlays[0] = vid_dev->overlays[k + 2];
- else
+ if (!cpu_is_omap44xx()) {
+ if (pdev->num_resources == 1)
+ vout->vid_info.overlays[0] = vid_dev->overlays[k + 2];
+ else
/* Else select video1 and video2 one by one. */
- vout->vid_info.overlays[0] = vid_dev->overlays[k + 1];
+ vout->vid_info.overlays[0] = vid_dev->overlays[k + 1];
+ } else {
+ vout->vid_info.overlays[0] =
+ vid_dev->overlays[
+ k + (4 - pdev->num_resources)];
+ }
vout->vid_info.num_overlays = 1;
vout->vid_info.id = k + 1;
@@ -2463,7 +2775,7 @@ static int __init omap_vout_create_video_devices(struct platform_device *pdev)
video_set_drvdata(vfd, vout);
/* Configure the overlay structure */
- ret = omapvid_init(vid_dev->vouts[k], 0);
+ ret = omapvid_init(vid_dev->vouts[k], 0, 0);
if (!ret)
goto success;
@@ -2522,6 +2834,8 @@ static void omap_vout_cleanup_device(struct omap_vout_device *vout)
*/
if (vout->vrfb_static_allocation)
omap_vout_free_vrfb_buffers(vout);
+#else
+ omap_vout_free_tiler_buffers(vout);
#endif
kfree(vout);
}
diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h
index ea3a047f8bca..802a66c2a69e 100644
--- a/drivers/media/video/omap/omap_voutdef.h
+++ b/drivers/media/video/omap/omap_voutdef.h
@@ -22,9 +22,15 @@
#define RGB_VRFB_BPP 1
#define MAX_CID 3
#define MAC_VRFB_CTXS 4
+#ifdef CONFIG_ARCH_OMAP4
+#define MAX_VOUT_DEV 3
+#define MAX_OVLS 4
+#define MAX_DISPLAYS 4
+#else
#define MAX_VOUT_DEV 2
#define MAX_OVLS 3
#define MAX_DISPLAYS 3
+#endif
#define MAX_MANAGERS 3
/* Enum for Rotation