33 #include <linux/module.h>
35 #include <linux/sched.h>
36 #include <linux/types.h>
39 #include <linux/videodev2.h>
41 #include <linux/slab.h>
61 #define VOUT_NAME "omap_vout"
70 static u32 video1_numbuffers = 3;
71 static u32 video2_numbuffers = 3;
74 static bool vid1_static_vrfb_alloc;
75 static bool vid2_static_vrfb_alloc;
81 "Number of buffers to be allocated at init time for Video1 device.");
85 "Number of buffers to be allocated at init time for Video2 device.");
89 "Size of the buffer to be allocated for video1 device");
93 "Size of the buffer to be allocated for video2 device");
97 "Static allocation of the VRFB buffer for video1 device");
101 "Static allocation of the VRFB buffer for video2 device");
119 .description =
"RGB565, le",
126 .description =
"RGB32, le",
134 .description =
"RGB24, le",
138 .description =
"YUYV (YUV 4:2:2), packed",
142 .description =
"UYVY, packed",
147 #define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
165 if (ifmt == NUM_OUTPUT_FORMATS)
204 static u32 omap_vout_uservirt_to_phys(
u32 virtp)
206 unsigned long physp = 0;
220 int res, nr_pages = 1;
228 if (res == nr_pages) {
233 "get_user_pages failed\n");
249 numbuffers = (vout->
vid) ? video2_numbuffers : video1_numbuffers;
250 vout->
buffer_size = (vout->
vid) ? video2_bufsize : video1_bufsize;
252 for (i = 0; i < numbuffers; i++) {
265 static int v4l2_rot_to_dss_rot(
int v4l2_rotation,
270 switch (v4l2_rotation) {
295 int ps = 2, line_length = 0;
314 *cropped_offset = (line_length *
ps) *
374 int cropheight, cropwidth, pixheight, pixwidth;
377 (outw != vout->
pix.width || outh != vout->
pix.height)) {
382 vout->
dss_mode = video_mode_to_dss_mode(vout);
391 if (is_rotation_90_or_270(vout)) {
392 cropheight = vout->
crop.width;
393 cropwidth = vout->
crop.height;
394 pixheight = vout->
pix.width;
395 pixwidth = vout->
pix.height;
397 cropheight = vout->
crop.height;
398 cropwidth = vout->
crop.width;
399 pixheight = vout->
pix.height;
400 pixwidth = vout->
pix.width;
405 info.width = cropwidth;
406 info.height = cropheight;
412 info.out_height = outh;
413 info.global_alpha = vout->
win.global_alpha;
414 if (!is_rotation_enabled(vout)) {
417 info.screen_width = pixwidth;
421 info.screen_width = 2048;
425 "%s enable=%d addr=%x width=%d\n height=%d color_mode=%d\n"
426 "rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
427 "out_height=%d rotation_type=%d screen_width=%d\n",
466 timing = &dssdev->
panel.timings;
469 outh = win->
w.height;
478 posy = (timing->
y_res - win->
w.width) - win->
w.left;
483 posx = (timing->
x_res - win->
w.width) - win->
w.left;
484 posy = (timing->
y_res - win->
w.height) - win->
w.top;
492 posx = (timing->
x_res - win->
w.height) - win->
w.top;
501 ret = omapvid_setup_overlay(vout, ovl, posx, posy,
504 goto omapvid_init_err;
536 unsigned int irqstatus,
struct timeval timevalue)
556 }
else if (0 == fid) {
575 static void omap_vout_isr(
void *
arg,
unsigned int irqstatus)
602 switch (cur_display->
type) {
612 if (!(irqstatus & irq))
616 fid = omapvid_handle_interlace_display(vout, irqstatus,
622 if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN))
650 ret = omapvid_init(vout, addr);
653 "failed to set overlay info\n");
655 ret = omapvid_apply_changes(vout);
674 int startindex = 0,
i,
j;
675 u32 phy_addr = 0, virt_addr = 0;
678 int vid_max_buf_size;
690 video1_numbuffers : video2_numbuffers;
705 video1_numbuffers : video2_numbuffers;
708 if (*size > vid_max_buf_size) {
710 "buffer allocation mismatch [%u] [%u]\n",
715 for (i = startindex; i < *
count; i++) {
724 if (!is_rotation_enabled(vout))
727 for (j = i; j < *
count; j++) {
750 int num_buffers = 0,
i;
753 video1_numbuffers : video2_numbuffers;
795 omap_vout_uservirt_to_phys(vb->
baddr);
801 size = (
unsigned long) vb->
size;
852 static unsigned int omap_vout_poll(
struct file *
file,
879 static struct vm_operations_struct omap_vout_vm_ops = {
880 .open = omap_vout_vm_open,
881 .close = omap_vout_vm_close,
894 " %s pgoff=0x%lx, start=0x%lx, end=0x%lx\n", __func__,
907 if (VIDEO_MAX_FRAME == i) {
909 "offset invalid [offset=0x%lx]\n",
916 "insufficient memory [%lu] [%u]\n",
923 vma->
vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
925 vma->
vm_ops = &omap_vout_vm_ops;
944 static int omap_vout_release(
struct file *file)
967 ret = omapvid_apply_changes(vout);
970 "Unable to apply changes\n");
973 omap_vout_free_extra_buffers(vout);
1011 static int omap_vout_open(
struct file *file)
1016 vout = video_drvdata(file);
1032 video_vbq_ops.buf_setup = omap_vout_buffer_setup;
1033 video_vbq_ops.buf_prepare = omap_vout_buffer_prepare;
1034 video_vbq_ops.buf_release = omap_vout_buffer_release;
1035 video_vbq_ops.buf_queue = omap_vout_buffer_queue;
1049 static int vidioc_querycap(
struct file *file,
void *fh,
1063 static int vidioc_enum_fmt_vid_out(
struct file *file,
void *fh,
1079 static int vidioc_g_fmt_vid_out(
struct file *file,
void *fh,
1089 static int vidioc_try_fmt_vid_out(
struct file *file,
void *fh,
1106 timing = &dssdev->
panel.timings;
1111 omap_vout_try_format(&f->
fmt.
pix);
1115 static int vidioc_s_fmt_vid_out(
struct file *file,
void *fh,
1137 goto s_fmt_vid_out_exit;
1139 timing = &dssdev->
panel.timings;
1143 if ((is_rotation_enabled(vout)) &&
1146 goto s_fmt_vid_out_exit;
1151 if (is_rotation_90_or_270(vout)) {
1161 bpp = omap_vout_try_format(&f->
fmt.
pix);
1178 ret = omapvid_init(vout, 0);
1181 goto s_fmt_vid_out_exit;
1191 static int vidioc_try_fmt_vid_overlay(
struct file *file,
void *fh,
1215 static int vidioc_s_fmt_vid_overlay(
struct file *file,
void *fh,
1232 vout->
win.global_alpha = 255;
1234 vout->
win.global_alpha = f->
fmt.
win.global_alpha;
1236 vout->
win.chromakey = f->
fmt.
win.chromakey;
1242 static int vidioc_enum_fmt_vid_overlay(
struct file *file,
void *fh,
1245 int index = fmt->
index;
1257 static int vidioc_g_fmt_vid_overlay(
struct file *file,
void *fh,
1270 win->
w = vout->
win.w;
1276 key_value =
info.trans_key;
1282 static int vidioc_cropcap(
struct file *file,
void *fh,
1301 static int vidioc_g_crop(
struct file *file,
void *fh,
struct v4l2_crop *crop)
1307 crop->
c = vout->
crop;
1311 static int vidioc_s_crop(
struct file *file,
void *fh,
const struct v4l2_crop *crop)
1334 timing = &dssdev->
panel.timings;
1336 if (is_rotation_90_or_270(vout)) {
1346 &vout->
fbuf, &crop->
c);
1353 static int vidioc_queryctrl(
struct file *file,
void *fh,
1369 ctrl->
name[0] =
'\0';
1375 static int vidioc_g_ctrl(
struct file *file,
void *fh,
struct v4l2_control *ctrl)
1408 static int vidioc_s_ctrl(
struct file *file,
void *fh,
struct v4l2_control *
a)
1417 int rotation = a->
value;
1434 if (v4l2_rot_to_dss_rot(rotation, &vout->
rotation,
1441 vout->
control[0].value = rotation;
1454 if (!ovl->manager || !ovl->manager->get_manager_info) {
1460 ovl->manager->get_manager_info(ovl->manager, &
info);
1462 if (ovl->manager->set_manager_info(ovl->manager, &
info)) {
1476 unsigned int mirror = a->
value;
1494 vout->
control[2].value = mirror;
1504 static int vidioc_reqbufs(
struct file *file,
void *fh,
1508 unsigned int i, num_buffers = 0;
1534 video1_numbuffers : video2_numbuffers;
1571 static int vidioc_querybuf(
struct file *file,
void *fh,
1579 static int vidioc_qbuf(
struct file *file,
void *fh,
1591 if ((buffer->
length < vout->
pix.sizeimage) ||
1597 if ((is_rotation_enabled(vout)) &&
1600 "DMA Channel not allocated for Rotation\n");
1607 static int vidioc_dqbuf(
struct file *file,
void *fh,
struct v4l2_buffer *
b)
1630 size = (
unsigned long) vb->
size;
1636 static int vidioc_streamon(
struct file *file,
void *fh,
enum v4l2_buf_type i)
1675 if (omap_vout_calculate_offset(vout)) {
1702 ret = omapvid_init(vout, addr);
1705 "failed to set overlay info\n");
1707 ret = omapvid_apply_changes(vout);
1732 static int vidioc_streamoff(
struct file *file,
void *fh,
enum v4l2_buf_type i)
1757 ret = omapvid_apply_changes(vout);
1810 ovl->
manager->set_manager_info) {
1814 info.trans_key_type = key_type;
1815 info.trans_key = vout->
win.chromakey;
1828 ovl->
manager->set_manager_info) {
1849 ovl = ovid->overlays[0];
1866 if (
info.partial_alpha_enabled)
1901 .poll = omap_vout_poll,
1903 .mmap = omap_vout_mmap,
1904 .open = omap_vout_open,
1905 .release = omap_vout_release,
1934 vout->
fbuf.fmt.width = display->
panel.timings.x_res;
1935 vout->
fbuf.fmt.height = display->
panel.timings.y_res;
1938 vout->
win.global_alpha = 255;
1939 vout->
fbuf.flags = 0;
1942 vout->
win.chromakey = 0;
1950 control[0].
value = 0;
1959 control[1].
value = 0;
1966 " video device struct\n");
1974 vfd->
fops = &omap_vout_fops;
1992 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
1996 vout = vid_dev->
vouts[vid_num];
1999 numbuffers = (vid_num == 0) ? video1_numbuffers : video2_numbuffers;
2000 vout->
buffer_size = (vid_num == 0) ? video1_bufsize : video2_bufsize;
2003 for (i = 0; i < numbuffers; i++) {
2017 int static_vrfb_allocation = (vid_num == 0) ?
2018 vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
2020 static_vrfb_allocation);
2026 for (i = 0; i < numbuffers; i++) {
2042 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
2050 dev_err(&pdev->
dev,
": could not allocate memory\n");
2055 vid_dev->
vouts[
k] = vout;
2072 if (omap_vout_setup_video_data(vout) != 0) {
2080 if (omap_vout_setup_video_bufs(pdev,
k) != 0) {
2090 "Video for Linux device\n");
2095 video_set_drvdata(vfd, vout);
2098 ret = omapvid_init(vid_dev->
vouts[
k], 0);
2113 dev_info(&pdev->
dev,
": registered and initialized"
2114 " video device %d\n", vfd->
minor);
2133 if (!video_is_registered(vfd)) {
2163 struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
2169 omap_vout_cleanup_device(vid_dev->
vouts[k]);
2190 dev_err(&pdev->
dev,
"probed for an unknown device\n");
2195 if (vid_dev ==
NULL)
2203 dev_warn(&pdev->
dev,
"no driver for display: %s\n",
2242 ret = dssdrv->
enable(def_display);
2249 "'%s' Display already enabled\n",
2256 dev_err(&pdev->
dev,
"v4l2_device_register failed\n");
2261 ret = omap_vout_create_video_devices(pdev);
2268 if (display->
driver->update)
2269 display->
driver->update(display, 0, 0,
2270 display->
panel.timings.x_res,
2271 display->
panel.timings.y_res);
2286 if (def_display && def_display->
driver)
2287 def_display->
driver->disable(def_display);
2298 .remove = omap_vout_remove,
2301 static int __init omap_vout_init(
void)
2310 static void omap_vout_cleanup(
void)