summaryrefslogtreecommitdiff
path: root/drivers/media
diff options
context:
space:
mode:
authorLajos Molnar <molnar@ti.com>2010-07-27 20:46:51 +0530
committerRicardo Perez Olivares <x0081762@ti.com>2010-09-14 19:26:41 -0500
commitdc3b2bd2f439dac6a3205ee67d031a82ce125e1c (patch)
tree3bc350748c445eea24767decc538362e82b30f44 /drivers/media
parent978e5839df5b3b52e64e2688ca2217d2c006be31 (diff)
V4L2 crop support with streaming
Adds the crop support while STREAMON Signed-off-by: Archit Taneja <archit@ti.com> Signed-off-by: Guruswamy Senthilvadivu <svadivu@ti.com>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/omap/omap_vout.c41
-rw-r--r--drivers/media/video/omap/omap_voutdef.h4
2 files changed, 27 insertions, 18 deletions
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c
index 30f2c13e115d..745a52396e3e 100644
--- a/drivers/media/video/omap/omap_vout.c
+++ b/drivers/media/video/omap/omap_vout.c
@@ -48,6 +48,7 @@
#include <plat/vram.h>
#include <plat/vrfb.h>
#include <plat/display.h>
+#include <plat/cpu.h>
#include "omap_voutlib.h"
#include "omap_voutdef.h"
@@ -57,7 +58,6 @@ 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"
@@ -65,6 +65,7 @@ MODULE_LICENSE("GPL");
enum omap_vout_channels {
OMAP_VIDEO1,
OMAP_VIDEO2,
+ OMAP_VIDEO3,
};
enum dma_channel_state {
@@ -648,7 +649,7 @@ static int v4l2_rot_to_dss_rot(int v4l2_rotation,
* start. This offset calculation is mainly required because of
* the VRFB 32 pixels alignment with rotation.
*/
-static int omap_vout_calculate_offset(struct omap_vout_device *vout)
+static int omap_vout_calculate_offset(struct omap_vout_device *vout, int idx)
{
struct omap_overlay *ovl;
enum dss_rotation rotation;
@@ -659,13 +660,13 @@ static int omap_vout_calculate_offset(struct omap_vout_device *vout)
struct omap_dss_device *cur_display;
struct v4l2_rect *crop = &vout->crop;
struct v4l2_pix_format *pix = &vout->pix;
- int *cropped_offset = &vout->cropped_offset;
+ int *cropped_offset = vout->cropped_offset + idx;
int vr_ps = 1, ps = 2;
#ifndef CONFIG_ARCH_OMAP4
int temp_ps = 2;
int offset = 0;
#endif
- int *cropped_uv_offset = &vout->cropped_uv_offset;
+ int *cropped_uv_offset = vout->cropped_uv_offset + idx;
int ctop = 0, cleft = 0, line_length = 0;
unsigned long addr = 0, uv_addr = 0;
@@ -770,12 +771,12 @@ static int omap_vout_calculate_offset(struct omap_vout_device *vout)
}
#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]);
+ addr = tiler_get_natural_addr(vout->queued_buf_addr[idx]);
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]);
+ vout->queued_buf_uv_addr[idx]);
/* :TODO: only allow even crops for NV12 */
*cropped_uv_offset = tiler_stride(uv_addr) * (crop->top >> 1)
+ (crop->left & ~1);
@@ -1871,8 +1872,9 @@ static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
if (!ret) {
- /* Video1 plane does not support global alpha */
- if (ovl->id == OMAP_DSS_VIDEO1)
+ /* Video1 plane does not support global alpha for OMAP 2/3 */
+ if ((cpu_is_omap24xx() || cpu_is_omap34xx()) &&
+ ovl->id == OMAP_DSS_VIDEO1)
vout->win.global_alpha = 255;
else
vout->win.global_alpha = f->fmt.win.global_alpha;
@@ -1963,7 +1965,11 @@ static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
struct omap_overlay *ovl;
struct omap_video_timings *timing;
- if (vout->streaming)
+ /* Currently we only allow changing the crop position while
+ streaming. */
+ if (vout->streaming &&
+ (crop->c.height != vout->crop.height ||
+ crop->c.width != vout->crop.width))
return -EBUSY;
mutex_lock(&vout->lock);
@@ -2220,6 +2226,7 @@ static int vidioc_qbuf(struct file *file, void *fh,
{
struct omap_vout_device *vout = fh;
struct videobuf_queue *q = &vout->vbq;
+ int ret = 0;
if ((V4L2_BUF_TYPE_VIDEO_OUTPUT != buffer->type) ||
(buffer->index >= vout->buffer_allocated) ||
@@ -2241,7 +2248,13 @@ static int vidioc_qbuf(struct file *file, void *fh,
return -EINVAL;
}
#endif
- return videobuf_qbuf(q, buffer);
+ ret = videobuf_qbuf(q, buffer);
+ /* record buffer offset from crop window */
+ if (omap_vout_calculate_offset(vout, buffer->index)) {
+ printk(KERN_ERR "Could not calculate buffer offset\n");
+ return -EINVAL;
+ }
+ return ret;
}
static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
@@ -2300,14 +2313,10 @@ static int vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
vout->first_int = 1;
- if (omap_vout_calculate_offset(vout)) {
- ret = -EINVAL;
- goto streamon_err1;
- }
addr = (unsigned long) vout->queued_buf_addr[vout->cur_frm->i]
- + vout->cropped_offset;
+ + vout->cropped_offset[vout->cur_frm->i];
uv_addr = (unsigned long) vout->queued_buf_uv_addr[vout->cur_frm->i]
- + vout->cropped_uv_offset;
+ + vout->cropped_uv_offset[vout->cur_frm->i];
mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN |
DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_FRAMEDONE |
diff --git a/drivers/media/video/omap/omap_voutdef.h b/drivers/media/video/omap/omap_voutdef.h
index a9bc59aae16f..d1a5409aaab1 100644
--- a/drivers/media/video/omap/omap_voutdef.h
+++ b/drivers/media/video/omap/omap_voutdef.h
@@ -146,8 +146,8 @@ struct omap_vout_device {
struct videobuf_buffer *cur_frm, *next_frm;
struct list_head dma_queue;
u8 *queued_buf_addr[VIDEO_MAX_FRAME];
- u32 cropped_offset;
- u32 cropped_uv_offset;
+ u32 cropped_offset[VIDEO_MAX_FRAME];
+ u32 cropped_uv_offset[VIDEO_MAX_FRAME];
s32 tv_field1_offset;
void *isr_handle;