From d1e20b4f3b8eea5f567bdf3316b3886cab8d7489 Mon Sep 17 00:00:00 2001 From: Wayne Zou Date: Mon, 21 Jan 2013 13:36:10 +0800 Subject: [PATCH] ENGR00240972-2 IPU: Add vdic double frame rate feature Add vdic double frame rate feature It depends on the which frame(0 or 1), and interlace field format(top or bottom) to do VDI process Signed-off-by: Wayne Zou --- drivers/mxc/ipu3/ipu_device.c | 81 ++++++++++++++++++++++++++++------- drivers/mxc/ipu3/ipu_ic.c | 9 ++-- 2 files changed, 71 insertions(+), 19 deletions(-) diff --git a/drivers/mxc/ipu3/ipu_device.c b/drivers/mxc/ipu3/ipu_device.c index be1725129ce2..8c58ba1c3f59 100644 --- a/drivers/mxc/ipu3/ipu_device.c +++ b/drivers/mxc/ipu3/ipu_device.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -1856,6 +1856,7 @@ static int init_ic(struct ipu_soc *ipu, struct ipu_task_entry *t) int out_uoff = 0, out_voff = 0, out_rot; int out_w = 0, out_h = 0, out_stride; int out_fmt; + u32 vdi_frame_idx = 0; memset(¶ms, 0, sizeof(params)); @@ -1908,6 +1909,19 @@ static int init_ic(struct ipu_soc *ipu, struct ipu_task_entry *t) } } + if (t->input.deinterlace.enable) { + if (t->input.deinterlace.field_fmt & IPU_DEINTERLACE_FIELD_MASK) + params.mem_prp_vf_mem.field_fmt = + IPU_DEINTERLACE_FIELD_BOTTOM; + else + params.mem_prp_vf_mem.field_fmt = + IPU_DEINTERLACE_FIELD_TOP; + + if (t->input.deinterlace.field_fmt & IPU_DEINTERLACE_RATE_EN) + vdi_frame_idx = t->input.deinterlace.field_fmt & + IPU_DEINTERLACE_RATE_FRAME1; + } + if (t->set.mode & VDOA_MODE) ipu->vdoa_en = 1; @@ -1921,13 +1935,6 @@ static int init_ic(struct ipu_soc *ipu, struct ipu_task_entry *t) } if (deinterlace_3_field(t)) { - if (IPU_DEINTERLACE_FIELD_TOP == t->input.deinterlace.field_fmt) - params.mem_prp_vf_mem.field_fmt = V4L2_FIELD_INTERLACED_TB; - else if (IPU_DEINTERLACE_FIELD_BOTTOM == t->input.deinterlace.field_fmt) - params.mem_prp_vf_mem.field_fmt = V4L2_FIELD_INTERLACED_BT; - else - dev_err(t->dev, "ERR[no-0x%x]invalid field fmt:0x%x!\n", - t->task_no, t->input.deinterlace.field_fmt); ret = ipu_init_channel(ipu, t->set.vdi_ic_p_chan, ¶ms); if (ret < 0) { t->state = STATE_INIT_CHAN_FAIL; @@ -1949,13 +1956,57 @@ static int init_ic(struct ipu_soc *ipu, struct ipu_task_entry *t) } else { if ((deinterlace_3_field(t)) && (IPU_PIX_FMT_TILED_NV12F != t->input.format)) { - inbuf_p = t->input.paddr + t->set.istride + - t->set.i_off; - inbuf = t->input.paddr_n + t->set.i_off; - inbuf_n = t->input.paddr_n + t->set.istride + - t->set.i_off; - } else - inbuf = t->input.paddr + t->set.i_off; + if (params.mem_prp_vf_mem.field_fmt == + IPU_DEINTERLACE_FIELD_TOP) { + if (vdi_frame_idx) { + inbuf_p = t->input.paddr + t->set.istride + + t->set.i_off; + inbuf = t->input.paddr_n + t->set.i_off; + inbuf_n = t->input.paddr_n + t->set.istride + + t->set.i_off; + params.mem_prp_vf_mem.field_fmt = + IPU_DEINTERLACE_FIELD_BOTTOM; + } else { + inbuf_p = t->input.paddr + t->set.i_off; + inbuf = t->input.paddr + t->set.istride + t->set.i_off; + inbuf_n = t->input.paddr_n + t->set.i_off; + } + } else { + if (vdi_frame_idx) { + inbuf_p = t->input.paddr + t->set.i_off; + inbuf = t->input.paddr_n + t->set.istride + t->set.i_off; + inbuf_n = t->input.paddr_n + t->set.i_off; + params.mem_prp_vf_mem.field_fmt = + IPU_DEINTERLACE_FIELD_TOP; + } else { + inbuf_p = t->input.paddr + t->set.istride + + t->set.i_off; + inbuf = t->input.paddr + t->set.i_off; + inbuf_n = t->input.paddr_n + t->set.istride + + t->set.i_off; + } + } + } else { + if (t->input.deinterlace.enable) { + if (params.mem_prp_vf_mem.field_fmt == + IPU_DEINTERLACE_FIELD_TOP) { + if (vdi_frame_idx) { + inbuf = t->input.paddr + t->set.istride + t->set.i_off; + params.mem_prp_vf_mem.field_fmt = + IPU_DEINTERLACE_FIELD_BOTTOM; + } else + inbuf = t->input.paddr + t->set.i_off; + } else { + if (vdi_frame_idx) { + inbuf = t->input.paddr + t->set.i_off; + params.mem_prp_vf_mem.field_fmt = + IPU_DEINTERLACE_FIELD_TOP; + } else + inbuf = t->input.paddr + t->set.istride + t->set.i_off; + } + } else + inbuf = t->input.paddr + t->set.i_off; + } if (t->overlay_en) ovbuf = t->overlay.paddr + t->set.ov_off; diff --git a/drivers/mxc/ipu3/ipu_ic.c b/drivers/mxc/ipu3/ipu_ic.c index b0b79add39a6..0f528d078b32 100644 --- a/drivers/mxc/ipu3/ipu_ic.c +++ b/drivers/mxc/ipu3/ipu_ic.c @@ -1,5 +1,5 @@ /* - * Copyright 2005-2012 Freescale Semiconductor, Inc. All Rights Reserved. + * Copyright 2005-2013 Freescale Semiconductor, Inc. All Rights Reserved. */ /* @@ -69,6 +69,7 @@ void _ipu_vdi_set_motion(struct ipu_soc *ipu, ipu_motion_sel motion_sel) reg |= VDI_C_MOT_SEL_LOW; ipu_vdi_write(ipu, reg, VDI_C); + dev_dbg(ipu->dev, "VDI_C = \t0x%08X\n", reg); } void ic_dump_register(struct ipu_soc *ipu) @@ -215,10 +216,10 @@ void _ipu_vdi_init(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_param } ipu_vdi_write(ipu, reg, VDI_C); - if (params->mem_prp_vf_mem.field_fmt == V4L2_FIELD_INTERLACED_TB) - _ipu_vdi_set_top_field_man(ipu, false); - else if (params->mem_prp_vf_mem.field_fmt == V4L2_FIELD_INTERLACED_BT) + if (params->mem_prp_vf_mem.field_fmt == IPU_DEINTERLACE_FIELD_TOP) _ipu_vdi_set_top_field_man(ipu, true); + else if (params->mem_prp_vf_mem.field_fmt == IPU_DEINTERLACE_FIELD_BOTTOM) + _ipu_vdi_set_top_field_man(ipu, false); _ipu_vdi_set_motion(ipu, params->mem_prp_vf_mem.motion_sel); -- 2.39.5