summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorXinyu Chen <xinyu.chen@freescale.com>2012-05-02 11:02:43 +0800
committerXinyu Chen <xinyu.chen@freescale.com>2012-05-02 11:02:43 +0800
commit3b9257f71a2a0dc0e0061ce2d455c504515c26d9 (patch)
tree6d19fa9ec5cf7973d4b599fce2a8e2861bd0dce9 /drivers
parent5f5288b61bc0596dbe1436a65f0bdf52b8d855cb (diff)
parent1b64ead9cdb4eae25789cfc5bbb7d8ad07dee402 (diff)
Merge remote branch 'fsl-linux-sdk/imx_3.0.15_12.04.01' into imx_3.0.15_android
Conflicts: sound/soc/imx/Makefile
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/mxc/output/mxc_vout.c140
-rw-r--r--drivers/mxc/ipu3/ipu_device.c4
-rw-r--r--drivers/mxc/ipu3/vdoa.c1
-rw-r--r--drivers/video/mxc/mxc_ipuv3_fb.c8
4 files changed, 113 insertions, 40 deletions
diff --git a/drivers/media/video/mxc/output/mxc_vout.c b/drivers/media/video/mxc/output/mxc_vout.c
index 7542ca5f2062..aebe57fda0c5 100644
--- a/drivers/media/video/mxc/output/mxc_vout.c
+++ b/drivers/media/video/mxc/output/mxc_vout.c
@@ -56,9 +56,18 @@ struct mxc_vout_fb {
bool disp_support_windows;
};
+struct dma_mem {
+ void *vaddr;
+ dma_addr_t paddr;
+ size_t size;
+};
+
struct mxc_vout_output {
int open_cnt;
struct fb_info *fbi;
+ unsigned long fb_smem_start;
+ unsigned long fb_smem_len;
+ struct fb_var_screeninfo fb_var;
struct video_device *vfd;
struct mutex mutex;
struct mutex task_lock;
@@ -77,15 +86,13 @@ struct mxc_vout_output {
bool disp_support_csc;
bool fmt_init;
+ bool release;
+ bool save_var;
bool bypass_pp;
bool is_vdoaipu_task;
struct ipu_task task;
struct ipu_task vdoa_task;
- struct vdoa_mem {
- void *vaddr;
- dma_addr_t paddr;
- size_t size;
- } vdoa_dma;
+ struct dma_mem vdoa_dma;
bool timer_stop;
struct timer_list timer;
@@ -428,6 +435,7 @@ static int show_buf(struct mxc_vout_output *vout, int idx,
int ret;
u32 is_1080p;
u32 yres = 0;
+ u32 fb_base = 0;
memcpy(&var, &fbi->var, sizeof(var));
@@ -437,11 +445,13 @@ static int show_buf(struct mxc_vout_output *vout, int idx,
* NOTE: should not do other fb operation during v4l2
*/
console_lock();
+ fb_base = fbi->fix.smem_start;
fbi->fix.smem_start = vout->task.output.paddr;
fbi->var.yoffset = ipos->y + 1;
var.xoffset = ipos->x;
var.yoffset = ipos->y;
ret = fb_pan_display(fbi, &var);
+ fbi->fix.smem_start = fb_base;
console_unlock();
} else {
console_lock();
@@ -472,6 +482,7 @@ static void disp_work_func(struct work_struct *work)
int ret = 0;
u32 is_1080p;
u32 ocrop_h = 0;
+ u32 tiled_interlaced = 0;
v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work begin one frame\n");
@@ -532,6 +543,9 @@ static void disp_work_func(struct work_struct *work)
}
if (vout->is_vdoaipu_task) {
vout->vdoa_task.input.paddr = vout->task.input.paddr;
+ if (deinterlace_3_field(vout))
+ vout->vdoa_task.input.paddr_n =
+ vout->task.input.paddr_n;
vout->vdoa_task.output.paddr = vout->vdoa_dma.paddr;
ret = ipu_queue_task(&vout->vdoa_task);
if (ret < 0) {
@@ -539,8 +553,14 @@ static void disp_work_func(struct work_struct *work)
goto err;
}
vout->task.input.paddr = vout->vdoa_task.output.paddr;
+ if (vout->task.input.deinterlace.enable) {
+ tiled_interlaced = 1;
+ vout->task.input.deinterlace.enable = 0;
+ }
}
ret = ipu_queue_task(&vout->task);
+ if (tiled_interlaced)
+ vout->task.input.deinterlace.enable = 1;
if (ret < 0) {
mutex_unlock(&vout->task_lock);
goto err;
@@ -593,6 +613,10 @@ static void disp_work_func(struct work_struct *work)
spin_unlock_irqrestore(q->irqlock, flags);
v4l2_dbg(1, debug, vout->vfd->v4l2_dev, "disp work finish one frame\n");
+ if (!vout->save_var) {
+ memcpy(&vout->fb_var, &vout->fbi->var, sizeof(vout->fb_var));
+ vout->save_var = true;
+ }
return;
err:
@@ -838,7 +862,7 @@ static int mxc_vidioc_g_fmt_vid_out(struct file *file, void *fh,
struct v4l2_format *f)
{
struct mxc_vout_output *vout = fh;
- struct v4l2_rect *rect = NULL;
+ struct v4l2_rect rect;
f->fmt.pix.width = vout->task.input.width;
f->fmt.pix.height = vout->task.input.height;
@@ -846,11 +870,13 @@ static int mxc_vidioc_g_fmt_vid_out(struct file *file, void *fh,
f->fmt.pix.sizeimage = get_frame_size(vout);
if (f->fmt.pix.priv) {
- rect = (struct v4l2_rect *)f->fmt.pix.priv;
- rect->left = vout->task.input.crop.pos.x;
- rect->top = vout->task.input.crop.pos.y;
- rect->width = vout->task.input.crop.w;
- rect->height = vout->task.input.crop.h;
+ rect.left = vout->task.input.crop.pos.x;
+ rect.top = vout->task.input.crop.pos.y;
+ rect.width = vout->task.input.crop.w;
+ rect.height = vout->task.input.crop.h;
+ if (copy_to_user((void __user *)f->fmt.pix.priv,
+ &rect, sizeof(rect)))
+ return -EFAULT;
}
v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
"frame_size:0x%x, pix_fmt:0x%x\n",
@@ -909,7 +935,10 @@ static inline int vdoaipu_try_task(struct mxc_vout_output *vout)
size_t size;
struct ipu_task *ipu_task = &vout->task;
struct ipu_task *vdoa_task = &vout->vdoa_task;
+ u32 deinterlace = 0;
+ if (vout->task.input.deinterlace.enable)
+ deinterlace = 1;
is_1080p_stream = CHECK_TILED_1080P_STREAM(vout);
if (is_1080p_stream)
ipu_task->input.crop.h = VALID_HEIGHT_1080P;
@@ -950,9 +979,12 @@ static inline int vdoaipu_try_task(struct mxc_vout_output *vout)
vout->vdoa_dma.vaddr = dma_alloc_coherent(vout->vbq.dev,
vout->vdoa_dma.size,
&vout->vdoa_dma.paddr,
- GFP_DMA | GFP_KERNEL);
- if (!vout->vdoa_dma.vaddr)
+ GFP_KERNEL);
+ if (!vout->vdoa_dma.vaddr) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "cannot get vdoa dma buf size:0x%x\n", size);
return -ENOMEM;
+ }
v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
"alloc vdoa_dma.size:0x%x, paddr:0x%x\n",
vout->vdoa_dma.size,
@@ -971,7 +1003,11 @@ static inline int vdoaipu_try_task(struct mxc_vout_output *vout)
ipu_task->input.width = vdoa_task->output.width;
ipu_task->input.crop.w = icrop_w;
}
+ if (deinterlace)
+ ipu_task->input.deinterlace.enable = 0;
ret = ipu_try_task(vout);
+ if (deinterlace)
+ ipu_task->input.deinterlace.enable = 1;
return ret;
}
@@ -1031,17 +1067,22 @@ static int mxc_vout_try_task(struct mxc_vout_output *vout)
static int mxc_vout_try_format(struct mxc_vout_output *vout, struct v4l2_format *f)
{
int ret = 0;
- struct v4l2_rect *rect = NULL;
+ struct v4l2_rect rect;
u32 o_height = 0;
u32 ocrop_h = 0;
u32 is_1080p;
+ if (f->fmt.pix.priv && copy_from_user(&rect,
+ (void __user *)f->fmt.pix.priv, sizeof(rect)))
+ return -EFAULT;
+
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)
+ if ((vout->task.input.width > MAX_INTERLACED_WIDTH) ||
+ (vout->task.input.deinterlace.motion == HIGH_MOTION))
return -EINVAL;
v4l2_info(vout->vfd->v4l2_dev,
"tiled fmt enable deinterlace.\n");
@@ -1060,13 +1101,13 @@ static int mxc_vout_try_format(struct mxc_vout_output *vout, struct v4l2_format
"V4L2_FIELD_ALTERNATE field format not supported yet!\n");
break;
case V4L2_FIELD_INTERLACED_TB:
- v4l2_info(vout->vfd->v4l2_dev, "Enable deinterlace.\n");
+ v4l2_info(vout->vfd->v4l2_dev, "Enable deinterlace TB.\n");
vout->task.input.deinterlace.enable = true;
vout->task.input.deinterlace.field_fmt =
IPU_DEINTERLACE_FIELD_TOP;
break;
case V4L2_FIELD_INTERLACED_BT:
- v4l2_info(vout->vfd->v4l2_dev, "Enable deinterlace.\n");
+ v4l2_info(vout->vfd->v4l2_dev, "Enable deinterlace BT.\n");
vout->task.input.deinterlace.enable = true;
vout->task.input.deinterlace.field_fmt =
IPU_DEINTERLACE_FIELD_BOTTOM;
@@ -1076,11 +1117,10 @@ static int mxc_vout_try_format(struct mxc_vout_output *vout, struct v4l2_format
}
if (f->fmt.pix.priv) {
- rect = (struct v4l2_rect *)f->fmt.pix.priv;
- vout->task.input.crop.pos.x = rect->left;
- vout->task.input.crop.pos.y = rect->top;
- vout->task.input.crop.w = rect->width;
- vout->task.input.crop.h = rect->height;
+ vout->task.input.crop.pos.x = rect.left;
+ vout->task.input.crop.pos.y = rect.top;
+ vout->task.input.crop.w = rect.width;
+ vout->task.input.crop.h = rect.height;
} else {
vout->task.input.crop.pos.x = 0;
vout->task.input.crop.pos.y = 0;
@@ -1099,9 +1139,12 @@ static int mxc_vout_try_format(struct mxc_vout_output *vout, struct v4l2_format
ret = mxc_vout_try_task(vout);
if (!ret) {
- if (rect) {
- rect->width = vout->task.input.crop.w;
- rect->height = vout->task.input.crop.h;
+ if (f->fmt.pix.priv) {
+ rect.width = vout->task.input.crop.w;
+ rect.height = vout->task.input.crop.h;
+ if (copy_to_user((void __user *)f->fmt.pix.priv,
+ &rect, sizeof(rect)))
+ ret = -EFAULT;
} else {
f->fmt.pix.width = vout->task.input.crop.w;
f->fmt.pix.height = vout->task.input.crop.h;
@@ -1521,8 +1564,16 @@ static int config_disp_output(struct mxc_vout_output *vout)
struct fb_var_screeninfo var;
int i, display_buf_size, fb_num, ret;
u32 is_1080p;
+ u32 fb_base;
+ u32 is_bg;
memcpy(&var, &fbi->var, sizeof(var));
+ fb_base = fbi->fix.smem_start;
+ is_bg = get_ipu_channel(fbi);
+ if (is_bg == MEM_BG_SYNC) {
+ memcpy(&vout->fb_var, &fbi->var, sizeof(var));
+ vout->save_var = true;
+ }
var.xres = vout->task.output.width;
var.yres = vout->task.output.height;
@@ -1557,8 +1608,10 @@ static int config_disp_output(struct mxc_vout_output *vout)
var.xres, var.yres);
ret = set_window_position(vout, &vout->win_pos);
- if (ret < 0)
+ if (ret < 0) {
+ v4l2_err(vout->vfd->v4l2_dev, "ERR: set_win_pos ret:%d\n", ret);
return ret;
+ }
/* Init display channel through fb API */
var.yoffset = 0;
@@ -1568,8 +1621,11 @@ static int config_disp_output(struct mxc_vout_output *vout)
ret = fb_set_var(fbi, &var);
fbi->flags &= ~FBINFO_MISC_USEREVENT;
console_unlock();
- if (ret < 0)
+ if (ret < 0) {
+ v4l2_err(vout->vfd->v4l2_dev,
+ "ERR:%s fb_set_var ret:%d\n", __func__, ret);
return ret;
+ }
is_1080p = CHECK_TILED_1080P_DISPLAY(vout);
if (is_1080p)
@@ -1579,11 +1635,22 @@ static int config_disp_output(struct mxc_vout_output *vout)
for (i = 0; i < fb_num; i++)
vout->disp_bufs[i] = fbi->fix.smem_start + i * display_buf_size;
+ vout->fb_smem_len = fbi->fix.smem_len;
+ vout->fb_smem_start = fbi->fix.smem_start;
+ if (fb_base != fbi->fix.smem_start) {
+ v4l2_dbg(1, debug, vout->vfd->v4l2_dev,
+ "realloc fb mem size:0x%x@0x%lx,old paddr @0x%x\n",
+ fbi->fix.smem_len, fbi->fix.smem_start, fb_base);
+ if (is_bg)
+ vout->save_var = false;
+ }
+
console_lock();
fbi->flags |= FBINFO_MISC_USEREVENT;
ret = fb_blank(fbi, FB_BLANK_UNBLANK);
fbi->flags &= ~FBINFO_MISC_USEREVENT;
console_unlock();
+ vout->release = false;
return ret;
}
@@ -1592,7 +1659,10 @@ static void release_disp_output(struct mxc_vout_output *vout)
{
struct fb_info *fbi = vout->fbi;
struct mxcfb_pos pos;
+ int ret;
+ if (vout->release)
+ return;
console_lock();
fbi->flags |= FBINFO_MISC_USEREVENT;
fb_blank(fbi, FB_BLANK_POWERDOWN);
@@ -1604,20 +1674,24 @@ static void release_disp_output(struct mxc_vout_output *vout)
pos.y = 0;
set_window_position(vout, &pos);
- /* fix if ic bypass crack smem_start */
- if (vout->bypass_pp) {
+ if (get_ipu_channel(fbi) == MEM_BG_SYNC) {
console_lock();
- fbi->fix.smem_start = vout->disp_bufs[0];
+ fbi->fix.smem_start = vout->fb_smem_start;
+ fbi->fix.smem_len = vout->fb_smem_len;
+ vout->fb_var.activate |= FB_ACTIVATE_FORCE;
+ fbi->flags |= FBINFO_MISC_USEREVENT;
+ ret = fb_set_var(fbi, &vout->fb_var);
+ fbi->flags &= ~FBINFO_MISC_USEREVENT;
console_unlock();
- }
-
- if (get_ipu_channel(fbi) == MEM_BG_SYNC) {
+ if (ret < 0)
+ v4l2_err(vout->vfd->v4l2_dev, "ERR: fb_set_var.\n");
console_lock();
fbi->flags |= FBINFO_MISC_USEREVENT;
fb_blank(fbi, FB_BLANK_UNBLANK);
fbi->flags &= ~FBINFO_MISC_USEREVENT;
console_unlock();
}
+ vout->release = true;
}
static int mxc_vidioc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
diff --git a/drivers/mxc/ipu3/ipu_device.c b/drivers/mxc/ipu3/ipu_device.c
index 46a9645fcf25..6810cea8f503 100644
--- a/drivers/mxc/ipu3/ipu_device.c
+++ b/drivers/mxc/ipu3/ipu_device.c
@@ -2577,7 +2577,7 @@ static void do_task(struct ipu_task_entry *t)
ipu->rot_dma[rot_idx].vaddr = dma_alloc_coherent(t->dev,
r_size,
&ipu->rot_dma[rot_idx].paddr,
- GFP_DMA | GFP_KERNEL);
+ GFP_KERNEL);
CHECK_RETCODE(ipu->rot_dma[rot_idx].vaddr == NULL,
"ic_and_rot", STATE_SYS_NO_MEM,
chan_setup, -ENOMEM);
@@ -3276,7 +3276,7 @@ static long mxc_ipu_ioctl(struct file *file,
mem->cpu_addr = dma_alloc_coherent(ipu_dev, size,
&mem->phy_addr,
- GFP_DMA);
+ GFP_KERNEL);
if (mem->cpu_addr == NULL) {
kfree(mem);
return -ENOMEM;
diff --git a/drivers/mxc/ipu3/vdoa.c b/drivers/mxc/ipu3/vdoa.c
index 2d3aaef16622..5800fc606f8c 100644
--- a/drivers/mxc/ipu3/vdoa.c
+++ b/drivers/mxc/ipu3/vdoa.c
@@ -451,7 +451,6 @@ static int vdoa_probe(struct platform_device *pdev)
ret = PTR_ERR(vdoa->clk);
goto err_clk;
}
- clk_enable(vdoa->clk);
vdoa->iram_base = iram_alloc(VDOA_IRAM_SIZE, &vdoa->iram_paddr);
if (!vdoa->iram_base) {
diff --git a/drivers/video/mxc/mxc_ipuv3_fb.c b/drivers/video/mxc/mxc_ipuv3_fb.c
index b010e943f61d..a087f3323233 100644
--- a/drivers/video/mxc/mxc_ipuv3_fb.c
+++ b/drivers/video/mxc/mxc_ipuv3_fb.c
@@ -361,13 +361,13 @@ static int mxcfb_set_par(struct fb_info *fbi)
dma_alloc_coherent(fbi->device,
alpha_mem_len,
&mxc_fbi->alpha_phy_addr0,
- GFP_DMA | GFP_KERNEL);
+ GFP_KERNEL);
mxc_fbi->alpha_virt_addr1 =
dma_alloc_coherent(fbi->device,
alpha_mem_len,
&mxc_fbi->alpha_phy_addr1,
- GFP_DMA | GFP_KERNEL);
+ GFP_KERNEL);
if (mxc_fbi->alpha_virt_addr0 == NULL ||
mxc_fbi->alpha_virt_addr1 == NULL) {
dev_err(fbi->device, "mxcfb: dma alloc for"
@@ -1037,7 +1037,7 @@ static int mxcfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
mem->cpu_addr = dma_alloc_coherent(fbi->device, size,
&mem->phy_addr,
- GFP_DMA);
+ GFP_KERNEL);
if (mem->cpu_addr == NULL) {
kfree(mem);
return -ENOMEM;
@@ -1577,7 +1577,7 @@ static int mxcfb_map_video_memory(struct fb_info *fbi)
fbi->screen_base = dma_alloc_writecombine(fbi->device,
fbi->fix.smem_len,
(dma_addr_t *)&fbi->fix.smem_start,
- GFP_DMA);
+ GFP_KERNEL);
if (fbi->screen_base == 0) {
dev_err(fbi->device, "Unable to allocate framebuffer memory\n");
fbi->fix.smem_len = 0;