summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayne Zou <b36644@freescale.com>2012-04-13 08:28:06 +0800
committerFrank Li <Frank.Li@freescale.com>2012-04-13 18:56:42 +0800
commit1e8285867ebe0e2de141f47eec1aa8e57b078fbf (patch)
tree667d5519a56f90bef3b26aed905a750d09adfb21
parent4d5c8d7aa0d5137d337048dd82c71c77c3954fa5 (diff)
ENGR00179513-3 V4L2: Add VDOA tiled format support
Support for VDOA tiled format IPU_PIX_FMT_TILED_NV12 up to 1080p progressive streams, and IPU_PIX_FMT_TILED_NV12F tiled format up to xga interlaced streams currently. Signed-off-by: Wayne Zou <b36644@freescale.com>
-rw-r--r--drivers/media/video/mxc/output/mxc_vout.c118
1 files changed, 110 insertions, 8 deletions
diff --git a/drivers/media/video/mxc/output/mxc_vout.c b/drivers/media/video/mxc/output/mxc_vout.c
index 43b53678d5ca..f0e15232b2d2 100644
--- a/drivers/media/video/mxc/output/mxc_vout.c
+++ b/drivers/media/video/mxc/output/mxc_vout.c
@@ -30,6 +30,13 @@
#define MAX_FB_NUM 6
#define FB_BUFS 3
+#define FRAME_HEIGHT_1080P (1088)
+#define MAX_INTERLACED_WIDTH (1024)
+#define CHECK_TILED_1080P(vout) \
+ ((vout->task.input.format == IPU_PIX_FMT_TILED_NV12) && \
+ (vout->task.input.width == vout->task.output.crop.w) && \
+ (vout->task.input.height == FRAME_HEIGHT_1080P) && \
+ (vout->task.output.crop.h == 1080))
struct mxc_vout_fb {
char *name;
@@ -97,7 +104,7 @@ static int video_nr = 16;
/* Module parameters */
module_param(video_nr, int, S_IRUGO);
MODULE_PARM_DESC(video_nr, "video device numbers");
-module_param(debug, bool, S_IRUGO);
+module_param(debug, int, 0600);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
const static struct v4l2_fmtdesc mxc_formats[] = {
@@ -145,6 +152,14 @@ const static struct v4l2_fmtdesc mxc_formats[] = {
.description = "YUV420",
.pixelformat = V4L2_PIX_FMT_YUV420,
},
+ {
+ .description = "TILED NV12P",
+ .pixelformat = IPU_PIX_FMT_TILED_NV12,
+ },
+ {
+ .description = "TILED NV12F",
+ .pixelformat = IPU_PIX_FMT_TILED_NV12F,
+ },
};
#define NUM_MXC_VOUT_FORMATS (ARRAY_SIZE(mxc_formats))
@@ -158,6 +173,24 @@ static struct mxc_vout_fb g_fb_setting[MAX_FB_NUM];
static int config_disp_output(struct mxc_vout_output *vout);
static void release_disp_output(struct mxc_vout_output *vout);
+static unsigned int get_frame_size(struct mxc_vout_output *vout)
+{
+ unsigned int size;
+
+ if (IPU_PIX_FMT_TILED_NV12 == vout->task.input.format)
+ size = TILED_NV12_FRAME_SIZE(vout->task.input.width,
+ vout->task.input.height);
+ else if (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format) {
+ size = TILED_NV12_FRAME_SIZE(vout->task.input.width,
+ vout->task.input.height/2);
+ size *= 2;
+ } else
+ size = vout->task.input.width * vout->task.input.height *
+ fmt_to_bpp(vout->task.input.format)/8;
+
+ return size;
+}
+
static ipu_channel_t get_ipu_channel(struct fb_info *fbi)
{
ipu_channel_t ipu_ch = CHAN_NONE;
@@ -315,6 +348,9 @@ static bool deinterlace_3_field(struct mxc_vout_output *vout)
static bool is_pp_bypass(struct mxc_vout_output *vout)
{
+ if ((IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) ||
+ (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format))
+ return false;
if ((vout->task.input.width == vout->task.output.width) &&
(vout->task.input.height == vout->task.output.height) &&
(vout->task.input.crop.w == vout->task.output.crop.w) &&
@@ -374,6 +410,8 @@ static int show_buf(struct mxc_vout_output *vout, int idx,
struct fb_info *fbi = vout->fbi;
struct fb_var_screeninfo var;
int ret;
+ u32 is_1080p;
+ u32 yres = 0;
memcpy(&var, &fbi->var, sizeof(var));
@@ -390,9 +428,17 @@ static int show_buf(struct mxc_vout_output *vout, int idx,
ret = fb_pan_display(fbi, &var);
console_unlock();
} else {
- var.yoffset = idx * fbi->var.yres;
console_lock();
+ is_1080p = CHECK_TILED_1080P(vout);
+ if (is_1080p) {
+ yres = fbi->var.yres;
+ fbi->var.yres = FRAME_HEIGHT_1080P;
+ }
+
+ var.yoffset = idx * fbi->var.yres;
ret = fb_pan_display(fbi, &var);
+ if (is_1080p)
+ fbi->var.yres = yres;
console_unlock();
}
@@ -408,6 +454,8 @@ static void disp_work_func(struct work_struct *work)
unsigned long flags = 0;
struct ipu_pos ipos;
int ret = 0;
+ u32 is_1080p;
+ u32 ocrop_h = 0;
v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work begin one frame\n");
@@ -458,11 +506,21 @@ static void disp_work_func(struct work_struct *work)
}
vout->task.output.paddr =
vout->disp_bufs[vout->frame_count % FB_BUFS];
+
+ is_1080p = CHECK_TILED_1080P(vout);
+ if (is_1080p) {
+ vout->task.input.crop.h = FRAME_HEIGHT_1080P;
+ vout->task.output.height = FRAME_HEIGHT_1080P;
+ ocrop_h = vout->task.output.crop.h;
+ vout->task.output.crop.h = FRAME_HEIGHT_1080P;
+ }
ret = ipu_queue_task(&vout->task);
if (ret < 0) {
mutex_unlock(&vout->task_lock);
goto err;
}
+ if (is_1080p)
+ vout->task.output.crop.h = ocrop_h;
}
mutex_unlock(&vout->task_lock);
@@ -569,6 +627,7 @@ static int mxc_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
unsigned int *size)
{
struct mxc_vout_output *vout = q->priv_data;
+ unsigned int frame_size;
if (!vout)
return -EINVAL;
@@ -576,8 +635,8 @@ static int mxc_vout_buffer_setup(struct videobuf_queue *q, unsigned int *count,
if (V4L2_BUF_TYPE_VIDEO_OUTPUT != q->type)
return -EINVAL;
- *size = PAGE_ALIGN(vout->task.input.width * vout->task.input.height *
- fmt_to_bpp(vout->task.input.format)/8);
+ frame_size = get_frame_size(vout);
+ *size = PAGE_ALIGN(frame_size);
return 0;
}
@@ -758,8 +817,7 @@ static int mxc_vidioc_g_fmt_vid_out(struct file *file, void *fh,
f->fmt.pix.width = vout->task.input.width;
f->fmt.pix.height = vout->task.input.height;
f->fmt.pix.pixelformat = vout->task.input.format;
- f->fmt.pix.sizeimage = vout->task.input.width * vout->task.input.height *
- fmt_to_bpp(vout->task.input.format)/8;
+ f->fmt.pix.sizeimage = get_frame_size(vout);
if (f->fmt.pix.priv) {
rect = (struct v4l2_rect *)f->fmt.pix.priv;
@@ -768,6 +826,10 @@ static int mxc_vidioc_g_fmt_vid_out(struct file *file, void *fh,
rect->width = vout->task.input.crop.w;
rect->height = vout->task.input.crop.h;
}
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "frame_size:0x%x, pix_fmt:0x%x\n",
+ f->fmt.pix.sizeimage,
+ vout->task.input.format);
return 0;
}
@@ -839,6 +901,11 @@ static int mxc_vout_try_task(struct mxc_vout_output *vout)
else
vout->task.output.format = IPU_PIX_FMT_RGB565;
}
+
+ if ((IPU_PIX_FMT_TILED_NV12 == vout->task.input.format) ||
+ (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format))
+ vout->task.output.format = IPU_PIX_FMT_NV12;
+
ret = ipu_try_task(vout);
}
@@ -849,11 +916,23 @@ static int mxc_vout_try_format(struct mxc_vout_output *vout, struct v4l2_format
{
int ret = 0;
struct v4l2_rect *rect = NULL;
+ u32 o_height = 0;
+ u32 ocrop_h = 0;
+ u32 is_1080p;
vout->task.input.width = f->fmt.pix.width;
vout->task.input.height = f->fmt.pix.height;
vout->task.input.format = f->fmt.pix.pixelformat;
+ if (IPU_PIX_FMT_TILED_NV12F == vout->task.input.format) {
+ if (vout->task.input.width > MAX_INTERLACED_WIDTH)
+ return -EINVAL;
+ v4l2_info(vout->vfd->v4l2_dev,
+ "tiled fmt enable deinterlace.\n");
+ vout->task.input.deinterlace.enable = true;
+ vout->task.input.deinterlace.field_fmt =
+ IPU_DEINTERLACE_FIELD_TOP;
+ }
switch (f->fmt.pix.field) {
/* Images are in progressive format, not interlaced */
case V4L2_FIELD_NONE:
@@ -893,6 +972,15 @@ static int mxc_vout_try_format(struct mxc_vout_output *vout, struct v4l2_format
vout->task.input.crop.h = f->fmt.pix.height;
}
+ is_1080p = CHECK_TILED_1080P(vout);
+ if (is_1080p) {
+ vout->task.input.crop.h = FRAME_HEIGHT_1080P;
+ o_height = vout->task.output.height;
+ ocrop_h = vout->task.output.crop.h;
+ vout->task.output.height = FRAME_HEIGHT_1080P;
+ vout->task.output.crop.h = FRAME_HEIGHT_1080P;
+ }
+
ret = mxc_vout_try_task(vout);
if (!ret) {
if (rect) {
@@ -904,6 +992,11 @@ static int mxc_vout_try_format(struct mxc_vout_output *vout, struct v4l2_format
}
}
+ if (is_1080p) {
+ vout->task.output.height = o_height;
+ vout->task.output.crop.h = ocrop_h;
+ }
+
return ret;
}
@@ -1311,6 +1404,7 @@ static int config_disp_output(struct mxc_vout_output *vout)
struct fb_info *fbi = vout->fbi;
struct fb_var_screeninfo var;
int i, display_buf_size, fb_num, ret;
+ u32 is_1080p;
memcpy(&var, &fbi->var, sizeof(var));
@@ -1332,7 +1426,11 @@ static int config_disp_output(struct mxc_vout_output *vout)
} else {
fb_num = FB_BUFS;
var.xres_virtual = var.xres;
- var.yres_virtual = fb_num * var.yres;
+ is_1080p = CHECK_TILED_1080P(vout);
+ if (is_1080p)
+ var.yres_virtual = fb_num * FRAME_HEIGHT_1080P;
+ else
+ var.yres_virtual = fb_num * var.yres;
var.vmode &= ~FB_VMODE_YWRAP;
}
var.bits_per_pixel = fmt_to_bpp(vout->task.output.format);
@@ -1357,7 +1455,11 @@ static int config_disp_output(struct mxc_vout_output *vout)
if (ret < 0)
return ret;
- display_buf_size = fbi->fix.line_length * fbi->var.yres;
+ is_1080p = CHECK_TILED_1080P(vout);
+ if (is_1080p)
+ display_buf_size = fbi->fix.line_length * FRAME_HEIGHT_1080P;
+ else
+ display_buf_size = fbi->fix.line_length * fbi->var.yres;
for (i = 0; i < fb_num; i++)
vout->disp_bufs[i] = fbi->fix.smem_start + i * display_buf_size;