提交 5c7ab634 编写于 作者: V Vaibhav Hiremath 提交者: Mauro Carvalho Chehab

V4L/DVB: V4L2: Add support for OMAP2/3 V4L2 display driver on top of DSS2

Features Supported -
	1. Provides V4L2 user interface for the video pipelines of DSS
	2. Basic streaming working on LCD, DVI and TV.
	3. Works on latest DSS2 library from Tomi
	4. Support for various pixel formats like YUV, UYVY, RGB32, RGB24,
	   RGB565
	5. Supports Alpha blending.
	6. Supports Color keying both source and destination.
	7. Supports rotation.
	8. Supports cropping.
	9. Supports Background color setting.
	10. Allocated buffers to only needed size
Signed-off-by: NVaibhav Hiremath <hvaibhav@ti.com>
Reviewed-by: NHans Verkuil <hverkuil@xs4all.nl>
Reviewed-by: NMuralidharan Karicheri <mkaricheri@gmail.com>
Signed-off-by: NMurailidharan Karicheri <mkaricheri@gmail.com>
Signed-off-by: NMauro Carvalho Chehab <mchehab@redhat.com>
上级 0e1de38d
......@@ -631,6 +631,8 @@ config VIDEO_ISIF
To compile this driver as a module, choose M here: the
module will be called vpfe.
source "drivers/media/video/omap/Kconfig"
source "drivers/media/video/bt8xx/Kconfig"
config VIDEO_PMS
......
......@@ -179,6 +179,8 @@ obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
obj-$(CONFIG_ARCH_DAVINCI) += davinci/
obj-$(CONFIG_ARCH_OMAP) += omap/
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
EXTRA_CFLAGS += -Idrivers/media/dvb/frontends
EXTRA_CFLAGS += -Idrivers/media/common/tuners
config VIDEO_OMAP2_VOUT
tristate "OMAP2/OMAP3 V4L2-Display driver"
depends on ARCH_OMAP24XX || ARCH_OMAP34XX
select VIDEOBUF_GEN
select VIDEOBUF_DMA_SG
select OMAP2_DSS
select OMAP2_VRAM
select OMAP2_VRFB
default n
---help---
V4L2 Display driver support for OMAP2/3 based boards.
#
# Makefile for the omap video device drivers.
#
# OMAP2/3 Display driver
omap-vout-mod-objs := omap_vout.o omap_voutlib.o
obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout-mod.o
此差异已折叠。
/*
* omap_voutdef.h
*
* Copyright (C) 2010 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
#ifndef OMAP_VOUTDEF_H
#define OMAP_VOUTDEF_H
#include <plat/display.h>
#define YUYV_BPP 2
#define RGB565_BPP 2
#define RGB24_BPP 3
#define RGB32_BPP 4
#define TILE_SIZE 32
#define YUYV_VRFB_BPP 2
#define RGB_VRFB_BPP 1
#define MAX_CID 3
#define MAC_VRFB_CTXS 4
#define MAX_VOUT_DEV 2
#define MAX_OVLS 3
#define MAX_DISPLAYS 3
#define MAX_MANAGERS 3
/* Enum for Rotation
* DSS understands rotation in 0, 1, 2, 3 context
* while V4L2 driver understands it as 0, 90, 180, 270
*/
enum dss_rotation {
dss_rotation_0_degree = 0,
dss_rotation_90_degree = 1,
dss_rotation_180_degree = 2,
dss_rotation_270_degree = 3,
};
/*
* This structure is used to store the DMA transfer parameters
* for VRFB hidden buffer
*/
struct vid_vrfb_dma {
int dev_id;
int dma_ch;
int req_status;
int tx_status;
wait_queue_head_t wait;
};
struct omapvideo_info {
int id;
int num_overlays;
struct omap_overlay *overlays[MAX_OVLS];
};
struct omap2video_device {
struct mutex mtx;
int state;
struct v4l2_device v4l2_dev;
struct omap_vout_device *vouts[MAX_VOUT_DEV];
int num_displays;
struct omap_dss_device *displays[MAX_DISPLAYS];
int num_overlays;
struct omap_overlay *overlays[MAX_OVLS];
int num_managers;
struct omap_overlay_manager *managers[MAX_MANAGERS];
};
/* per-device data structure */
struct omap_vout_device {
struct omapvideo_info vid_info;
struct video_device *vfd;
struct omap2video_device *vid_dev;
int vid;
int opened;
/* we don't allow to change image fmt/size once buffer has
* been allocated
*/
int buffer_allocated;
/* allow to reuse previously allocated buffer which is big enough */
int buffer_size;
/* keep buffer info across opens */
unsigned long buf_virt_addr[VIDEO_MAX_FRAME];
unsigned long buf_phy_addr[VIDEO_MAX_FRAME];
enum omap_color_mode dss_mode;
/* we don't allow to request new buffer when old buffers are
* still mmaped
*/
int mmap_count;
spinlock_t vbq_lock; /* spinlock for videobuf queues */
unsigned long field_count; /* field counter for videobuf_buffer */
/* non-NULL means streaming is in progress. */
bool streaming;
struct v4l2_pix_format pix;
struct v4l2_rect crop;
struct v4l2_window win;
struct v4l2_framebuffer fbuf;
/* Lock to protect the shared data structures in ioctl */
struct mutex lock;
/* V4L2 control structure for different control id */
struct v4l2_control control[MAX_CID];
enum dss_rotation rotation;
bool mirror;
int flicker_filter;
/* V4L2 control structure for different control id */
int bpp; /* bytes per pixel */
int vrfb_bpp; /* bytes per pixel with respect to VRFB */
struct vid_vrfb_dma vrfb_dma_tx;
unsigned int smsshado_phy_addr[MAC_VRFB_CTXS];
unsigned int smsshado_virt_addr[MAC_VRFB_CTXS];
struct vrfb vrfb_context[MAC_VRFB_CTXS];
bool vrfb_static_allocation;
unsigned int smsshado_size;
unsigned char pos;
int ps, vr_ps, line_length, first_int, field_id;
enum v4l2_memory memory;
struct videobuf_buffer *cur_frm, *next_frm;
struct list_head dma_queue;
u8 *queued_buf_addr[VIDEO_MAX_FRAME];
u32 cropped_offset;
s32 tv_field1_offset;
void *isr_handle;
/* Buffer queue variables */
struct omap_vout_device *vout;
enum v4l2_buf_type type;
struct videobuf_queue vbq;
int io_allowed;
};
#endif /* ifndef OMAP_VOUTDEF_H */
/*
* omap_voutlib.c
*
* Copyright (C) 2005-2010 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
* Based on the OMAP2 camera driver
* Video-for-Linux (Version 2) camera capture driver for
* the OMAP24xx camera controller.
*
* Author: Andy Lowe (source@mvista.com)
*
* Copyright (C) 2004 MontaVista Software, Inc.
* Copyright (C) 2010 Texas Instruments.
*
*/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/videodev2.h>
#include <plat/cpu.h>
MODULE_AUTHOR("Texas Instruments");
MODULE_DESCRIPTION("OMAP Video library");
MODULE_LICENSE("GPL");
/* Return the default overlay cropping rectangle in crop given the image
* size in pix and the video display size in fbuf. The default
* cropping rectangle is the largest rectangle no larger than the capture size
* that will fit on the display. The default cropping rectangle is centered in
* the image. All dimensions and offsets are rounded down to even numbers.
*/
void omap_vout_default_crop(struct v4l2_pix_format *pix,
struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop)
{
crop->width = (pix->width < fbuf->fmt.width) ?
pix->width : fbuf->fmt.width;
crop->height = (pix->height < fbuf->fmt.height) ?
pix->height : fbuf->fmt.height;
crop->width &= ~1;
crop->height &= ~1;
crop->left = ((pix->width - crop->width) >> 1) & ~1;
crop->top = ((pix->height - crop->height) >> 1) & ~1;
}
EXPORT_SYMBOL_GPL(omap_vout_default_crop);
/* Given a new render window in new_win, adjust the window to the
* nearest supported configuration. The adjusted window parameters are
* returned in new_win.
* Returns zero if succesful, or -EINVAL if the requested window is
* impossible and cannot reasonably be adjusted.
*/
int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
struct v4l2_window *new_win)
{
struct v4l2_rect try_win;
/* make a working copy of the new_win rectangle */
try_win = new_win->w;
/* adjust the preview window so it fits on the display by clipping any
* offscreen areas
*/
if (try_win.left < 0) {
try_win.width += try_win.left;
try_win.left = 0;
}
if (try_win.top < 0) {
try_win.height += try_win.top;
try_win.top = 0;
}
try_win.width = (try_win.width < fbuf->fmt.width) ?
try_win.width : fbuf->fmt.width;
try_win.height = (try_win.height < fbuf->fmt.height) ?
try_win.height : fbuf->fmt.height;
if (try_win.left + try_win.width > fbuf->fmt.width)
try_win.width = fbuf->fmt.width - try_win.left;
if (try_win.top + try_win.height > fbuf->fmt.height)
try_win.height = fbuf->fmt.height - try_win.top;
try_win.width &= ~1;
try_win.height &= ~1;
if (try_win.width <= 0 || try_win.height <= 0)
return -EINVAL;
/* 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);
/* Given a new render window in new_win, adjust the window to the
* nearest supported configuration. The image cropping window in crop
* will also be adjusted if necessary. Preference is given to keeping the
* the window as close to the requested configuration as possible. If
* successful, new_win, vout->win, and crop are updated.
* Returns zero if succesful, or -EINVAL if the requested preview window is
* impossible and cannot reasonably be adjusted.
*/
int omap_vout_new_window(struct v4l2_rect *crop,
struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
struct v4l2_window *new_win)
{
int err;
err = omap_vout_try_window(fbuf, new_win);
if (err)
return err;
/* update our preview window */
win->w = new_win->w;
win->field = new_win->field;
win->chromakey = new_win->chromakey;
/* Adjust the cropping window to allow for resizing limitation */
if (cpu_is_omap24xx()) {
/* For 24xx limit is 8x to 1/2x scaling. */
if ((crop->height/win->w.height) >= 2)
crop->height = win->w.height * 2;
if ((crop->width/win->w.width) >= 2)
crop->width = win->w.width * 2;
if (crop->width > 768) {
/* The OMAP2420 vertical resizing line buffer is 768
* pixels wide. If the cropped image is wider than
* 768 pixels then it cannot be vertically resized.
*/
if (crop->height != win->w.height)
crop->width = 768;
}
} else if (cpu_is_omap34xx()) {
/* For 34xx limit is 8x to 1/4x scaling. */
if ((crop->height/win->w.height) >= 4)
crop->height = win->w.height * 4;
if ((crop->width/win->w.width) >= 4)
crop->width = win->w.width * 4;
}
return 0;
}
EXPORT_SYMBOL_GPL(omap_vout_new_window);
/* Given a new cropping rectangle in new_crop, adjust the cropping rectangle to
* the nearest supported configuration. The image render window in win will
* also be adjusted if necessary. The preview window is adjusted such that the
* horizontal and vertical rescaling ratios stay constant. If the render
* window would fall outside the display boundaries, the cropping rectangle
* will also be adjusted to maintain the rescaling ratios. If successful, crop
* and win are updated.
* Returns zero if succesful, or -EINVAL if the requested cropping rectangle is
* impossible and cannot reasonably be adjusted.
*/
int omap_vout_new_crop(struct v4l2_pix_format *pix,
struct v4l2_rect *crop, struct v4l2_window *win,
struct v4l2_framebuffer *fbuf, const struct v4l2_rect *new_crop)
{
struct v4l2_rect try_crop;
unsigned long vresize, hresize;
/* make a working copy of the new_crop rectangle */
try_crop = *new_crop;
/* adjust the cropping rectangle so it fits in the image */
if (try_crop.left < 0) {
try_crop.width += try_crop.left;
try_crop.left = 0;
}
if (try_crop.top < 0) {
try_crop.height += try_crop.top;
try_crop.top = 0;
}
try_crop.width = (try_crop.width < pix->width) ?
try_crop.width : pix->width;
try_crop.height = (try_crop.height < pix->height) ?
try_crop.height : pix->height;
if (try_crop.left + try_crop.width > pix->width)
try_crop.width = pix->width - try_crop.left;
if (try_crop.top + try_crop.height > pix->height)
try_crop.height = pix->height - try_crop.top;
try_crop.width &= ~1;
try_crop.height &= ~1;
if (try_crop.width <= 0 || try_crop.height <= 0)
return -EINVAL;
if (cpu_is_omap24xx()) {
if (crop->height != win->w.height) {
/* If we're resizing vertically, we can't support a
* crop width wider than 768 pixels.
*/
if (try_crop.width > 768)
try_crop.width = 768;
}
}
/* vertical resizing */
vresize = (1024 * crop->height) / win->w.height;
if (cpu_is_omap24xx() && (vresize > 2048))
vresize = 2048;
else if (cpu_is_omap34xx() && (vresize > 4096))
vresize = 4096;
win->w.height = ((1024 * try_crop.height) / vresize) & ~1;
if (win->w.height == 0)
win->w.height = 2;
if (win->w.height + win->w.top > fbuf->fmt.height) {
/* We made the preview window extend below the bottom of the
* display, so clip it to the display boundary and resize the
* cropping height to maintain the vertical resizing ratio.
*/
win->w.height = (fbuf->fmt.height - win->w.top) & ~1;
if (try_crop.height == 0)
try_crop.height = 2;
}
/* horizontal resizing */
hresize = (1024 * crop->width) / win->w.width;
if (cpu_is_omap24xx() && (hresize > 2048))
hresize = 2048;
else if (cpu_is_omap34xx() && (hresize > 4096))
hresize = 4096;
win->w.width = ((1024 * try_crop.width) / hresize) & ~1;
if (win->w.width == 0)
win->w.width = 2;
if (win->w.width + win->w.left > fbuf->fmt.width) {
/* We made the preview window extend past the right side of the
* display, so clip it to the display boundary and resize the
* cropping width to maintain the horizontal resizing ratio.
*/
win->w.width = (fbuf->fmt.width - win->w.left) & ~1;
if (try_crop.width == 0)
try_crop.width = 2;
}
if (cpu_is_omap24xx()) {
if ((try_crop.height/win->w.height) >= 2)
try_crop.height = win->w.height * 2;
if ((try_crop.width/win->w.width) >= 2)
try_crop.width = win->w.width * 2;
if (try_crop.width > 768) {
/* The OMAP2420 vertical resizing line buffer is
* 768 pixels wide. If the cropped image is wider
* than 768 pixels then it cannot be vertically resized.
*/
if (try_crop.height != win->w.height)
try_crop.width = 768;
}
} else if (cpu_is_omap34xx()) {
if ((try_crop.height/win->w.height) >= 4)
try_crop.height = win->w.height * 4;
if ((try_crop.width/win->w.width) >= 4)
try_crop.width = win->w.width * 4;
}
/* update our cropping rectangle and we're done */
*crop = try_crop;
return 0;
}
EXPORT_SYMBOL_GPL(omap_vout_new_crop);
/* Given a new format in pix and fbuf, crop and win
* structures are initialized to default values. crop
* is initialized to the largest window size that will fit on the display. The
* crop window is centered in the image. win is initialized to
* the same size as crop and is centered on the display.
* All sizes and offsets are constrained to be even numbers.
*/
void omap_vout_new_format(struct v4l2_pix_format *pix,
struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
struct v4l2_window *win)
{
/* crop defines the preview source window in the image capture
* buffer
*/
omap_vout_default_crop(pix, fbuf, crop);
/* win defines the preview target window on the display */
win->w.width = crop->width;
win->w.height = crop->height;
win->w.left = ((fbuf->fmt.width - win->w.width) >> 1) & ~1;
win->w.top = ((fbuf->fmt.height - win->w.height) >> 1) & ~1;
}
EXPORT_SYMBOL_GPL(omap_vout_new_format);
/*
* omap_voutlib.h
*
* Copyright (C) 2010 Texas Instruments.
*
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*
*/
#ifndef OMAP_VOUTLIB_H
#define OMAP_VOUTLIB_H
extern void omap_vout_default_crop(struct v4l2_pix_format *pix,
struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop);
extern int omap_vout_new_crop(struct v4l2_pix_format *pix,
struct v4l2_rect *crop, struct v4l2_window *win,
struct v4l2_framebuffer *fbuf,
const struct v4l2_rect *new_crop);
extern int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
struct v4l2_window *new_win);
extern int omap_vout_new_window(struct v4l2_rect *crop,
struct v4l2_window *win, struct v4l2_framebuffer *fbuf,
struct v4l2_window *new_win);
extern void omap_vout_new_format(struct v4l2_pix_format *pix,
struct v4l2_framebuffer *fbuf, struct v4l2_rect *crop,
struct v4l2_window *win);
#endif /* #ifndef OMAP_VOUTLIB_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册