diff options
author | Sujeet Baranwal <s-baranwal@ti.com> | 2010-09-06 10:10:50 +0530 |
---|---|---|
committer | Ricardo Perez Olivares <x0081762@ti.com> | 2010-09-14 19:27:53 -0500 |
commit | b2503c7791682300871c62f5c81defdfdd46f1af (patch) | |
tree | 99ed49daa4e66192196468c662649259c9b81258 /drivers/media | |
parent | 4429dfd0fe4655a044f55bd13a751e5ac3df5202 (diff) |
OMAP4: DSS: Interlace Support
This patch enables all 4 combinations of interlaced and progressive buffer and display devices.
1.Interlaced buffer & progressive display device
2.Interlaced buffer & Interlaced display device
3.progressive buffer & Interlaced display device
4.progressive buffer & progressive display device
Signed-off-by: Sujeet Kumar Baranwal <s-baranwal@ti.com>
Signed-off-by: Mukund Mittal <mmittal@ti.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/omap/omap_vout.c | 198 | ||||
-rw-r--r-- | drivers/media/video/omap/omap_voutlib.c | 1 |
2 files changed, 150 insertions, 49 deletions
diff --git a/drivers/media/video/omap/omap_vout.c b/drivers/media/video/omap/omap_vout.c index b1b9ab9aeb58..524a7a54d964 100644 --- a/drivers/media/video/omap/omap_vout.c +++ b/drivers/media/video/omap/omap_vout.c @@ -296,7 +296,6 @@ int omap_vout_try_format(struct v4l2_pix_format *pix) ifmt = 0; pix->pixelformat = omap_formats[ifmt].pixelformat; - pix->field = V4L2_FIELD_ANY; pix->priv = 0; switch (pix->pixelformat) { @@ -1040,6 +1039,74 @@ int omapvid_apply_changes(struct omap_vout_device *vout) return 0; } +static int interlace_display(struct omap_vout_device *vout, u32 irqstatus, + struct timeval timevalue, u32 flags) +{ + unsigned long fid; + if (vout->first_int) { + vout->first_int = 0; + spin_unlock_irqrestore(&vout->vbq_lock, flags); + return 0; + } + if (irqstatus & DISPC_IRQ_EVSYNC_ODD) { + fid = 1; + } else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) { + fid = 0; + } else { + spin_unlock_irqrestore(&vout->vbq_lock, flags); + return 0; + } + vout->field_id ^= 1; + if (fid != vout->field_id) { + if (0 == fid) + vout->field_id = fid; + + spin_unlock_irqrestore(&vout->vbq_lock, flags); + return 0; + } + if (0 == fid) { + if (vout->cur_frm == vout->next_frm) { + spin_unlock_irqrestore(&vout->vbq_lock, flags); + return 0; + } + vout->cur_frm->ts = timevalue; + vout->cur_frm->state = VIDEOBUF_DONE; + wake_up_interruptible(&vout->cur_frm->done); + vout->cur_frm = vout->next_frm; + return 1; + } else if (1 == fid) { + if (list_empty(&vout->dma_queue) || + (vout->cur_frm != vout->next_frm)) { + spin_unlock_irqrestore(&vout->vbq_lock, flags); + return 0; + } + return 2; + } + return 3; +} + +static int i_to_p_base_address_change(struct omap_vout_device *vout, + unsigned long flags) +{ + u16 *cnt; + u32 offset; + + struct omap_overlay *ovl; + struct omapvideo_info *ovid; + + ovid = &(vout->vid_info); + ovl = ovid->overlays[0]; + + cnt = get_offset_cnt(ovl->id, &offset); + change_base_address(offset, cnt, ovl->id); + if (*cnt == 1) { + *cnt = 2; + spin_unlock_irqrestore(&vout->vbq_lock, flags); + return 1; + } + return 0; +} + void omap_vout_isr(void *arg, unsigned int irqstatus) { int ret; @@ -1051,9 +1118,6 @@ void omap_vout_isr(void *arg, unsigned int irqstatus) struct omap_vout_device *vout = (struct omap_vout_device *)arg; unsigned long flags; int irq = 0; -#ifndef CONFIG_OMAP2_DSS_HDMI - u32 fid; -#endif if (!vout->streaming) return; @@ -1086,6 +1150,16 @@ void omap_vout_isr(void *arg, unsigned int irqstatus) case OMAP_DISPLAY_TYPE_DSI: if (!(irqstatus & irq)) goto vout_isr_err; + else if (ovl->info.field == IBUF_PDEV) { + if ((irq == DISPC_IRQ_FRAMEDONE) || + (irq == DISPC_IRQ_FRAMEDONE2)) { + ret = i_to_p_base_address_change(vout, flags); + if (ret == 1) { + dispc_go(cur_display->channel); + return; + } + } + } break; case OMAP_DISPLAY_TYPE_DPI: if (!(irqstatus & (DISPC_IRQ_VSYNC | DISPC_IRQ_VSYNC2))) @@ -1099,45 +1173,37 @@ void omap_vout_isr(void *arg, unsigned int irqstatus) break; #ifdef CONFIG_OMAP2_DSS_HDMI case OMAP_DISPLAY_TYPE_HDMI: - if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN)) - goto vout_isr_err; - - break; + if (ovl->info.field == PBUF_PDEV) { + if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN)) + goto vout_isr_err; + } else if (ovl->info.field == IBUF_PDEV) { + if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) { + ret = i_to_p_base_address_change(vout, flags); + if (ret == 1) { + dispc_go(cur_display->channel); + return; + } + } + } else if (ovl->info.field == IBUF_IDEV) { + ret = interlace_display(vout, irqstatus, + timevalue, flags); + if (ret == 0) + return; + else if (ret == 1) + goto vout_isr_err; + else if (ret == 2) + goto intlace; + } + break; #else case OMAP_DISPLAY_TYPE_VENC: - if (vout->first_int) { - vout->first_int = 0; - goto vout_isr_err; - } - if (irqstatus & DISPC_IRQ_EVSYNC_ODD) - fid = 1; - else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN) - fid = 0; - else - goto vout_isr_err; - fid = 1; - vout->field_id ^= 1; - if (fid != vout->field_id) { - if (0 == fid) - vout->field_id = fid; - - goto vout_isr_err; - } - if (0 == fid) { - if (vout->cur_frm == vout->next_frm) - goto vout_isr_err; - vout->cur_frm->ts = timevalue; - vout->cur_frm->state = VIDEOBUF_DONE; - wake_up_interruptible(&vout->cur_frm->done); - vout->cur_frm = vout->next_frm; + ret = interlace_display(vout, irqstatus, timevalue, flags); + if (ret == 0) + return; + else if (ret == 1) goto vout_isr_err; - } else if (1 == fid) { - if (list_empty(&vout->dma_queue) || - (vout->cur_frm != vout->next_frm)) { - goto vout_isr_err; - } - goto venc; - } + else if (ret == 2) + goto intlace; #endif default: goto vout_isr_err; @@ -1156,9 +1222,7 @@ wb: goto vout_isr_err; } -#ifndef CONFIG_OMAP2_DSS_HDMI -venc: -#endif +intlace: vout->next_frm = list_entry(vout->dma_queue.next, struct videobuf_buffer, queue); list_del(&vout->next_frm->queue); @@ -1813,6 +1877,10 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, struct omapvideo_info *ovid; struct omap_video_timings *timing; struct omap_vout_device *vout = fh; + u16 multiplier = 1; + u8 device_type = PROGRESSIVE; + /* default is progressive buffer and progressive display */ + enum device_n_buffer_type dev_buf_type = PBUF_PDEV; if (vout->streaming) return -EBUSY; @@ -1829,6 +1897,28 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, } timing = &ovl->manager->device->panel.timings; + /* validate the combination of input buffer & device type. + Code needs to be added for interlaced LCD display */ + if (ovl->manager->device->type == OMAP_DISPLAY_TYPE_HDMI) + device_type = nature_of_hdmi(); + + if (f->fmt.pix.field != V4L2_FIELD_NONE && + f->fmt.pix.field != V4L2_FIELD_SEQ_TB) + f->fmt.pix.field = V4L2_FIELD_NONE; + + if ((f->fmt.pix.field == V4L2_FIELD_NONE) && + (device_type == PROGRESSIVE)) + dev_buf_type = PBUF_PDEV; + else if ((f->fmt.pix.field == V4L2_FIELD_NONE) && + (device_type == INTERLACED)) + dev_buf_type = PBUF_IDEV; + else if ((f->fmt.pix.field == V4L2_FIELD_SEQ_TB) && + (device_type == INTERLACED)) + dev_buf_type = IBUF_IDEV; + else if ((f->fmt.pix.field == V4L2_FIELD_SEQ_TB) && + (device_type == PROGRESSIVE)) + dev_buf_type = IBUF_PDEV; + /* We dont support RGB24-packed mode if vrfb rotation * is enabled*/ if ((rotation_enabled(vout)) && @@ -1837,13 +1927,16 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, goto s_fmt_vid_out_exit; } - /* get the framebuffer parameters */ + /* y resolution to be doubled in case of interlaced HDMI */ + if ((ovl->info.field == IBUF_IDEV) || (ovl->info.field == PBUF_IDEV)) + multiplier = 2; + /* get the framebuffer parameters */ if (!cpu_is_omap44xx() && rotate_90_or_270(vout)) { vout->fbuf.fmt.height = timing->x_res; - vout->fbuf.fmt.width = timing->y_res; + vout->fbuf.fmt.width = timing->y_res * multiplier; } else { - vout->fbuf.fmt.height = timing->y_res; + vout->fbuf.fmt.height = timing->y_res * multiplier; vout->fbuf.fmt.width = timing->x_res; } @@ -1860,6 +1953,9 @@ static int vidioc_s_fmt_vid_out(struct file *file, void *fh, vout->bpp = bpp; vout->pix = f->fmt.pix; vout->vrfb_bpp = 1; + ovl->info.field = dev_buf_type; + ovl->info.pic_width = f->fmt.pix.width; + ovl->info.pic_height = f->fmt.pix.height; /* If YUYV then vrfb bpp is 2, for others its 1 */ if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat || @@ -2042,6 +2138,7 @@ static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *crop) static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) { int ret = -EINVAL; + int multiplier = 1; struct omap_vout_device *vout = fh; struct omapvideo_info *ovid; struct omap_overlay *ovl; @@ -2065,11 +2162,15 @@ static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop) /* get the display device attached to the overlay */ timing = &ovl->manager->device->panel.timings; + /* y resolution to be doubled in case of interlaced HDMI */ + if ((ovl->info.field == IBUF_IDEV) || (ovl->info.field == PBUF_IDEV)) + multiplier = 2; + if (rotate_90_or_270(vout)) { vout->fbuf.fmt.height = timing->x_res; - vout->fbuf.fmt.width = timing->y_res; + vout->fbuf.fmt.width = timing->y_res * multiplier; } else { - vout->fbuf.fmt.height = timing->y_res; + vout->fbuf.fmt.height = timing->y_res * multiplier ; vout->fbuf.fmt.width = timing->x_res; } @@ -2321,6 +2422,7 @@ static int vidioc_qbuf(struct file *file, void *fh, struct videobuf_queue *q = &vout->vbq; int ret = 0; u32 addr = 0, uv_addr = 0; + q->field = vout->pix.field; if ((V4L2_BUF_TYPE_VIDEO_OUTPUT != buffer->type) || (buffer->index >= vout->buffer_allocated) || diff --git a/drivers/media/video/omap/omap_voutlib.c b/drivers/media/video/omap/omap_voutlib.c index b941c761eef9..27d3c0896680 100644 --- a/drivers/media/video/omap/omap_voutlib.c +++ b/drivers/media/video/omap/omap_voutlib.c @@ -91,7 +91,6 @@ int omap_vout_try_window(struct v4l2_framebuffer *fbuf, /* We now have a valid preview window, so go with it */ new_win->w = try_win; - new_win->field = V4L2_FIELD_ANY; return 0; } EXPORT_SYMBOL_GPL(omap_vout_try_window); |