Initialize Tizen 2.3
[adaptation/xorg/driver/xserver-xorg-video-emulfb.git] / src / xv / arm / fbdev_video_v4l2.c
1 /**************************************************************************
2
3 xserver-xorg-video-emulfb
4
5 Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
6
7 Contact: Boram Park <boram1288.park@samsung.com>
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sub license, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
16
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial portions
19 of the Software.
20
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
24 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
25 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
26 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
27 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29 **************************************************************************/
30
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #include <errno.h>
35 #include <sys/types.h>
36 #include <sys/mman.h>
37 #include <fcntl.h>
38 #include <unistd.h>
39 #include <X11/extensions/Xv.h>
40 #include <X11/extensions/Xvproto.h>
41
42 #include "fbdev_util.h"
43 #include "fbdev_video_v4l2.h"
44
45 #include "fbdev.h"
46 #include "fbdev_fb.h"
47 #include "fbdev_util.h"
48 #include "fbdev_video.h"
49 #include "fbdev_video_fourcc.h"
50
51 typedef struct _DeviceInfo
52 {
53         char *video;     /* video */
54         char *fb;        /* output frame buffer */
55         int   type;
56         int   bOpened;
57 } DeviceInfo;
58
59 typedef struct _FormatInfo
60 {
61         int           id;
62         int           type;
63         uint          pixelformat;
64         FBDevV4l2Memory memory;
65 } FormatInfo;
66
67 typedef struct
68 {
69         int index;
70
71         ScreenPtr pScreen;
72
73         int       video_fd;
74
75         int       fb_fd;
76         char     *fb_base_phy;
77         char     *fb_base_vir;
78         Bool      fb_shown;
79
80         struct fb_fix_screeninfo fix;
81
82         struct
83         {
84                 int init;
85                 xRectangle img;
86                 xRectangle crop;
87                 xRectangle pxm;
88                 xRectangle dst;
89                 int id;
90                 int hw_rotate;
91                 int scn_rotate;
92                 int hflip;
93                 int vflip;
94                 int requestbuffer;
95                 int streamon;
96                 int cur_idx;
97
98                 void* last_buffer;
99                 int   queued_index;
100
101                 void* backup;
102                 Bool  sync;
103         } status;
104
105         int size;
106         unsigned int pixfmt;
107         FBDevV4l2FimcBuffer fimcbuf;
108         FBDevV4l2SrcBuffer *src_buf;
109         FBDevV4l2Memory     memory;
110
111         int initial_dequeued_buf;
112         int re_setting;
113 } FBDevDispHandle;
114
115 enum
116 {
117         TYPE_RGB,
118         TYPE_YUV444,
119         TYPE_YUV422,
120         TYPE_YUV420,
121 };
122
123 static FormatInfo format_infos [] =
124 {
125         { FOURCC_RGB565,    TYPE_RGB,       V4L2_PIX_FMT_RGB565,    V4L2_MEMORY_MMAP },
126         { FOURCC_RGB32,     TYPE_RGB,       V4L2_PIX_FMT_RGB32,     V4L2_MEMORY_MMAP },
127         { FOURCC_I420,      TYPE_YUV420,    V4L2_PIX_FMT_YUV420,    V4L2_MEMORY_MMAP },
128         { FOURCC_S420,      TYPE_YUV420,    V4L2_PIX_FMT_YUV420,    V4L2_MEMORY_USERPTR },
129         { FOURCC_ST12,      TYPE_YUV420,    V4L2_PIX_FMT_NV12T,     V4L2_MEMORY_USERPTR },
130         { FOURCC_NV12,      TYPE_YUV420,    V4L2_PIX_FMT_NV12,      V4L2_MEMORY_MMAP },
131         { FOURCC_SN12,      TYPE_YUV420,    V4L2_PIX_FMT_NV12,      V4L2_MEMORY_USERPTR },
132         { FOURCC_YUY2,      TYPE_YUV422,    V4L2_PIX_FMT_YUYV,      V4L2_MEMORY_MMAP },
133         { FOURCC_SUYV,      TYPE_YUV422,    V4L2_PIX_FMT_YUYV,      V4L2_MEMORY_USERPTR },
134 };
135
136 static XF86ImageRec Images[] =
137 {
138         XVIMAGE_YUY2,
139         XVIMAGE_SUYV,
140         XVIMAGE_I420,
141         XVIMAGE_S420,
142         XVIMAGE_ST12,
143         XVIMAGE_NV12,
144         XVIMAGE_SN12,
145         XVIMAGE_RGB32,
146         XVIMAGE_RGB565,
147 };
148
149 static DeviceInfo device_infos[] =
150 {
151         { "/dev/video2", "/dev/fb1", OUTPUT_PATH_DMA, FALSE },
152         { "/dev/video3", "/dev/fb2", OUTPUT_PATH_DMA, FALSE },
153 };
154
155 #define NUM_IMAGES        (sizeof(Images) / sizeof(XF86ImageRec))
156 #define DEVICE_NUMS (sizeof (device_infos) / sizeof (DeviceInfo))
157
158 static Bool
159 _fbdevVideoV4l2SetSrc (int         fd,
160                        xRectangle *src_rect,
161                        xRectangle *crop_rect,
162                        uint        pixelformat)
163 {
164         struct v4l2_format      format = {0,};
165         struct v4l2_crop        crop = {0,};
166         int capabilities;
167
168         return_val_if_fail (fd >= 0, FALSE);
169
170         DRVLOG ("[SetSrc] src_r(%d,%d %dx%d) crop_r(%d,%d %dx%d) pixfmt(0x%08x) \n",
171                 src_rect->x, src_rect->y, src_rect->width, src_rect->height,
172                 crop_rect->x, crop_rect->y, crop_rect->width, crop_rect->height,
173                 pixelformat);
174
175         /* check if capabilities is valid */
176         capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OVERLAY;
177         if (!fbdev_v4l2_querycap (fd, capabilities))
178                 return FALSE;
179
180         /* set format */
181         CLEAR (format);
182         format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
183         if (!fbdev_v4l2_g_fmt (fd, &format))
184                 return FALSE;
185
186         format.fmt.pix.width       = src_rect->width;
187         format.fmt.pix.height      = src_rect->height;
188         format.fmt.pix.pixelformat = pixelformat;
189         format.fmt.pix.field       = V4L2_FIELD_NONE;
190         if (!fbdev_v4l2_s_fmt (fd, &format))
191                 return FALSE;
192
193         /* set crop_rect */
194         CLEAR (crop);
195         crop.type     = V4L2_BUF_TYPE_VIDEO_OUTPUT;
196         crop.c.left   = crop_rect->x;
197         crop.c.top    = crop_rect->y;
198         crop.c.width  = crop_rect->width;
199         crop.c.height = crop_rect->height;
200         if (!fbdev_v4l2_cropcap (fd, crop.type, &crop.c))
201                 return FALSE;
202
203         if (!fbdev_v4l2_s_crop (fd, &crop))
204                 return FALSE;
205
206         return TRUE;
207 }
208
209 static Bool
210 _fbdevVideoV4l2SetDst (int          fd,
211                        xRectangle  *dst_rect,
212                        xRectangle  *win_rect,
213                        int          rotation,
214                        int          hflip,
215                        int          vflip,
216                        int          path,
217                        uint         addr)
218 {
219         struct v4l2_format              format = {0,};
220         struct v4l2_control             ctrl = {0,};
221         struct v4l2_framebuffer fbuf = {0,};
222
223         return_val_if_fail (fd >= 0, FALSE);
224
225         DRVLOG ("[SetDst] dst_r(%d,%d %dx%d) win_r(%d,%d %dx%d) rot(%d) flip(%d,%d) path(%d) addr(%p) \n",
226                 dst_rect->x, dst_rect->y, dst_rect->width, dst_rect->height,
227                 win_rect->x, win_rect->y, win_rect->width, win_rect->height,
228                 rotation, hflip, vflip, path, (void*)addr);
229
230         /* set rotation */
231         CLEAR (ctrl);
232         ctrl.id    = V4L2_CID_ROTATION;
233         ctrl.value = rotation;
234         if (!fbdev_v4l2_s_ctrl (fd, &ctrl))
235                 return FALSE;
236
237         CLEAR (ctrl);
238         ctrl.id    = V4L2_CID_HFLIP;
239         ctrl.value = hflip;
240         if (!fbdev_v4l2_s_ctrl (fd, &ctrl))
241                 return FALSE;
242
243         CLEAR (ctrl);
244         ctrl.id    = V4L2_CID_VFLIP;
245         ctrl.value = vflip;
246         if (!fbdev_v4l2_s_ctrl (fd, &ctrl))
247                 return FALSE;
248
249         ctrl.id    = V4L2_CID_OVLY_MODE;
250         ctrl.value = 0x4;  //single buffer
251         if (!fbdev_v4l2_s_ctrl (fd, &ctrl))
252                 return FALSE;
253
254         /* set framebuffer */
255         CLEAR (fbuf);
256         if (!fbdev_v4l2_g_fbuf (fd, &fbuf))
257                 return FALSE;
258
259         if (path == OUTPUT_PATH_DMA)
260                 fbuf.base = (void*)addr;
261
262         fbuf.fmt.width  = dst_rect->width;
263         fbuf.fmt.height = dst_rect->height;
264         fbuf.fmt.pixelformat = V4L2_PIX_FMT_RGB32;
265         if (!fbdev_v4l2_s_fbuf (fd, &fbuf))
266                 return FALSE;
267
268         /* set format */
269         CLEAR (format);
270         format.type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
271         if (!fbdev_v4l2_g_fmt (fd, &format))
272                 return FALSE;
273
274         format.fmt.win.w.left   = win_rect->x;
275         format.fmt.win.w.top    = win_rect->y;
276         format.fmt.win.w.width  = win_rect->width;
277         format.fmt.win.w.height = win_rect->height;
278         if (!fbdev_v4l2_s_fmt (fd, &format))
279                 return FALSE;
280
281         return TRUE;
282 }
283
284 static Bool
285 _fbdevVideoV4l2SetBuffer (int fd,
286                           FBDevV4l2BufType type,
287                           FBDevV4l2Memory memory,
288                           int num_buf,
289                           FBDevV4l2SrcBuffer **mem_buf)
290 {
291         struct v4l2_requestbuffers      req = {0,};
292
293         return_val_if_fail (fd >= 0, FALSE);
294
295         DRVLOG ("[SetBuffer] num_buf(%d) mem_buf(%p) memory(%d)\n",
296                 num_buf, mem_buf, memory);
297
298         CLEAR (req);
299         req.count  = num_buf;
300         req.type   = type;
301         req.memory = memory;
302         if (!fbdev_v4l2_reqbuf (fd, &req))
303                 return FALSE;
304
305         if (memory == V4L2_MEMORY_MMAP)
306         {
307                 FBDevV4l2SrcBuffer *out_buf;
308                 int i;
309
310                 return_val_if_fail (mem_buf != NULL, FALSE);
311
312                 out_buf = calloc (req.count, sizeof (FBDevV4l2SrcBuffer));
313                 return_val_if_fail (out_buf != NULL, FALSE);
314
315                 for (i = 0; i < num_buf; i++)
316                 {
317                         struct v4l2_buffer buffer = {0,};
318
319                         CLEAR (buffer);
320                         buffer.index  = i;
321                         buffer.type   = type;
322                         buffer.memory = V4L2_MEMORY_MMAP;
323                         if (!fbdev_v4l2_querybuf (fd, &buffer))
324                         {
325                                 free (out_buf);
326                                 return FALSE;
327                         }
328
329                         out_buf[i].index  = buffer.index;
330                         out_buf[i].size   = buffer.length;
331                         out_buf[i].buf    = mmap (NULL, buffer.length,
332                                                   PROT_READ | PROT_WRITE , \
333                                                   MAP_SHARED , fd, buffer.m.offset);
334                         if (out_buf[i].buf == MAP_FAILED)
335                         {
336                                 xf86DrvMsg (0, X_ERROR, "[SetBuffer] mmap failed. index(%d)\n", i);
337                                 free (out_buf);
338                                 return FALSE;
339                         }
340                 }
341
342                 *mem_buf = out_buf;
343         }
344
345         return TRUE;
346 }
347
348 static Bool
349 _fbdevVideoV4l2ClearBuffer (int fd,
350                             FBDevV4l2BufType type,
351                             FBDevV4l2Memory memory,
352                             int num_buf,
353                             FBDevV4l2SrcBuffer *mem_buf)
354 {
355         struct v4l2_requestbuffers req = {0,};
356
357         return_val_if_fail (fd >= 0, FALSE);
358
359         DRVLOG ("[ClearBuffer] memory(%d) num_buf(%d) mem_buf(%p)\n",
360                 num_buf, mem_buf, memory);
361
362         if (memory == V4L2_MEMORY_MMAP && mem_buf)
363         {
364                 int i;
365
366                 for (i = 0; i < num_buf; i++)
367                         if (mem_buf[i].buf)
368                                 if (munmap (mem_buf[i].buf, mem_buf[i].size) == -1)
369                                         xf86DrvMsg (0, X_WARNING, "[ClearBuffer] Failed to unmap v4l2 buffer at index %d\n", i);
370
371                 free (mem_buf);
372         }
373
374         CLEAR (req);
375         req.count  = 0;
376         req.type   = type;
377         req.memory = memory;
378         if (!fbdev_v4l2_reqbuf (fd, &req))
379                 return FALSE;
380
381         return TRUE;
382 }
383
384 static Bool
385 _fbdevVideoV4l2StreamOn (int fd, FBDevV4l2BufType type)
386 {
387         return_val_if_fail (fd >= 0, FALSE);
388
389         DRVLOG ("[StreamOn] type(%d) \n", type);
390
391         if (!fbdev_v4l2_streamon (fd, type))
392                 return FALSE;
393
394         return TRUE;
395 }
396
397
398 static Bool
399 _fbdevVideoV4l2StreamOff (int fd, FBDevV4l2BufType type)
400 {
401         return_val_if_fail (fd >= 0, FALSE);
402
403         DRVLOG ("[StreamOff] type(%d) \n", type);
404
405         if (!fbdev_v4l2_streamoff (fd, type))
406                 return FALSE;
407
408         return TRUE;
409 }
410
411 static int
412 _fbdevVideoV4l2Dequeue (int fd, FBDevV4l2BufType type, FBDevV4l2Memory memory)
413 {
414         struct v4l2_buffer buf = {0,};
415
416         return_val_if_fail (fd >= 0, -1);
417
418         CLEAR (buf);
419         buf.type   = type;
420         buf.memory = memory;
421
422         if (!fbdev_v4l2_dequeue (fd, &buf))
423                 return FALSE;
424
425         DRVLOG ("[Dequeue] index(%d) type(%d) memory(%d)\n",
426                 buf.index, type, memory);
427
428         return buf.index;
429 }
430
431 static int
432 _fbdevVideoV4l2Queue (int fd, FBDevV4l2BufType type, FBDevV4l2Memory memory, int index, FBDevV4l2FimcBuffer *fimc_buf)
433 {
434         struct v4l2_buffer buf = {0,};
435
436         return_val_if_fail (fd >= 0, -1);
437
438         CLEAR (buf);
439         buf.index  = index;
440         buf.type   = type;
441         buf.memory = memory;
442
443         if (memory == V4L2_MEMORY_USERPTR)
444                 buf.m.userptr   = (unsigned long) fimc_buf;
445
446         if (!fbdev_v4l2_queue (fd, &buf))
447                 return FALSE;
448
449         DRVLOG ("[Queue] index(%d) type(%d) memory(%d)\n",
450                 index, type, memory);
451
452         return index;
453 }
454
455 static int
456 _open_device (char *device)
457 {
458         int fd;
459
460         return_val_if_fail (device != NULL, -1);
461
462         fd = open (device, O_RDWR);
463         if (fd < 0)
464         {
465                 xf86DrvMsg (0, X_ERROR, "Cannot open '%s'. fd(%d)\n", device, fd);
466                 return -1;
467         }
468
469         DRVLOG ("'%s' opened. fd(%d) \n", device, fd);
470
471         return fd;
472 }
473
474 static void
475 _close_device (int fd)
476 {
477         int ret;
478
479         return_if_fail (fd >= 0);
480
481         ret = close (fd);
482         if (ret < 0)
483         {
484                 xf86DrvMsg (0, X_ERROR, "Cannot close fd(%d)\n", fd);
485                 return;
486         }
487
488         DRVLOG ("fd(%d) closed. \n", fd);
489 }
490
491 static Bool
492 _move_resize_fb (FBDevDispHandle *hdisp, int x, int y, int width, int height)
493 {
494         struct fb_var_screeninfo var;
495
496         return_val_if_fail (hdisp->fb_fd >= 0, FALSE);
497
498         DRVLOG ("[MoveResize] '%s' to (%d,%d %dx%d) \n",
499                 device_infos[hdisp->index].fb, x, y, width, height);
500
501         if (!fbdevFbGetVarScreenInfo (hdisp->fb_fd, &var))
502                 return FALSE;
503
504         var.xres = var.xres_virtual = width;
505         var.yres = var.yres_virtual = height;
506         var.transp.length = 0;
507         var.activate = FB_ACTIVATE_FORCE;
508         if (!fbdevFbSetVarScreenInfo (hdisp->fb_fd, &var))
509                 return FALSE;
510
511         if (!fbdevFbGetFixScreenInfo (hdisp->fb_fd, &hdisp->fix))
512                 return FALSE;
513
514         if (hdisp->fix.smem_len == 0)
515                 return FALSE;
516
517         hdisp->fb_base_phy = (void*)hdisp->fix.smem_start;  /* Physical address */
518         if (!hdisp->fb_base_phy)
519                 return FALSE;
520
521         hdisp->fb_base_vir = mmap (NULL, hdisp->fix.smem_len,
522                                    PROT_READ | PROT_WRITE, MAP_SHARED, hdisp->fb_fd, 0);
523         if (!hdisp->fb_base_vir)
524                 return FALSE;
525
526         if (!fbdevFbSetWinPosition (hdisp->fb_fd, x, y)) /* 1 : auto */
527         {
528                 munmap ((void*)hdisp->fb_base_vir, hdisp->fix.smem_len);
529                 return FALSE;
530         }
531
532         return TRUE;
533 }
534
535 static Bool
536 _fbdevVideoV4l2EnsureStreamOff (FBDevDispHandle *hdisp)
537 {
538         if (!hdisp->status.streamon)
539                 return TRUE;
540
541         if (!_fbdevVideoV4l2StreamOff (hdisp->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT))
542                 return FALSE;
543
544         hdisp->status.streamon = FALSE;
545
546         return TRUE;
547 }
548
549 static Bool
550 _fbdevVideoV4l2OpenDevice (FBDevDispHandle *hdisp, int index, int requestbuffer)
551 {
552         if (device_infos[index].bOpened)
553         {
554                 DRVLOG ("[OpenDevice, %p] Already opened : %s\n", hdisp, device_infos[index].video);
555                 return FALSE;
556         }
557
558         hdisp->video_fd = _open_device (device_infos[index].video);
559         if (hdisp->video_fd < 0)
560                 return FALSE;
561
562         if (device_infos[index].type == OUTPUT_PATH_DMA)
563         {
564                 hdisp->fb_fd = _open_device (device_infos[index].fb);
565                 if (hdisp->fb_fd < 0)
566                 {
567                         _close_device (hdisp->video_fd);
568                         hdisp->video_fd = -1;
569                         return FALSE;
570                 }
571         }
572
573         device_infos[index].bOpened = TRUE;
574
575         return TRUE;
576 }
577
578 /* This function never failed.
579  * If failed, it means kernel has some problems.
580  * Then a device should be rebooted.
581  */
582 static void
583 _fbdevVideoV4l2CloseDevice (FBDevDispHandle *hdisp)
584 {
585         if (!_fbdevVideoV4l2EnsureStreamOff (hdisp)) // We will consider this as a LCD Off case.
586                 xf86DrvMsg (0, X_WARNING, "[CloseDevice, %p] Warning : Cannot stream off!! \n", hdisp);
587
588         if (hdisp->status.requestbuffer > 0)
589         {
590                 if (hdisp->video_fd >= 0)
591                         if (!_fbdevVideoV4l2ClearBuffer (hdisp->video_fd,
592                                                          V4L2_BUF_TYPE_VIDEO_OUTPUT,
593                                                          hdisp->memory,
594                                                          hdisp->status.requestbuffer,
595                                                          hdisp->src_buf))
596                                 xf86DrvMsg (0, X_WARNING, "[CloseDevice, %p] Warning : Cannot clear buffer!! \n", hdisp);
597
598                 hdisp->status.requestbuffer = 0;
599                 hdisp->src_buf = NULL;
600         }
601
602         if (hdisp->video_fd >= 0)
603         {
604                 _close_device (hdisp->video_fd);
605                 hdisp->video_fd = -1;
606         }
607
608         if (hdisp->fb_fd >= 0)
609         {
610                 fbdevFbDeActivate (hdisp->fb_fd);
611                 if (hdisp->fb_base_vir)
612                 {
613                         munmap ((void*)hdisp->fb_base_vir, hdisp->fix.smem_len);
614                         hdisp->fb_base_vir = NULL;
615                 }
616
617                 _close_device (hdisp->fb_fd);
618                 hdisp->fb_fd = -1;
619                 hdisp->fb_base_phy = NULL;
620                 hdisp->fb_shown = FALSE;
621         }
622
623         device_infos[hdisp->index].bOpened = FALSE;
624 }
625
626 int
627 fbdevVideoV4l2GetHandleNums (void)
628 {
629         return DEVICE_NUMS;
630 }
631
632 Bool
633 fbdevVideoV4l2HandleOpened (int index)
634 {
635         return_val_if_fail (index < DEVICE_NUMS, FALSE);
636
637         return device_infos[index].bOpened;
638 }
639
640 void *
641 fbdevVideoV4l2OpenHandle (ScreenPtr pScreen, int index, int requestbuffer)
642 {
643         FBDevDispHandle *handle;
644
645         return_val_if_fail (pScreen != NULL, NULL);
646         return_val_if_fail (index < DEVICE_NUMS, NULL);
647
648         handle = (FBDevDispHandle*)calloc (sizeof (FBDevDispHandle), 1);
649
650         return_val_if_fail (handle != NULL, NULL);
651
652         handle->pScreen = pScreen;
653         handle->index = index;
654         handle->status.hw_rotate = -1;
655         handle->status.id     = 0;
656         handle->status.cur_idx = -1;
657         handle->status.init = 0;
658         handle->memory = V4L2_MEMORY_MMAP;
659         handle->initial_dequeued_buf = requestbuffer;
660         handle->video_fd = -1;
661         handle->fb_fd = -1;
662
663         if (!_fbdevVideoV4l2OpenDevice (handle, index, requestbuffer))
664         {
665                 free (handle);
666                 return NULL;
667         }
668
669         DRVLOG ("[OpenHandle, %p] Handle(%d) opened. \n", handle, index);
670
671         return handle;
672 }
673
674 void
675 fbdevVideoV4l2CloseHandle (void *handle)
676 {
677         FBDevDispHandle *hdisp = (FBDevDispHandle*)handle;
678
679         return_if_fail (handle != NULL);
680
681         _fbdevVideoV4l2CloseDevice ((FBDevDispHandle*)handle);
682
683         if (hdisp->status.backup)
684         {
685                 free (hdisp->status.backup);
686                 hdisp->status.backup = NULL;
687         }
688
689         DRVLOG ("[CloseHandle, %p] Handle(%d) closed. \n", hdisp, hdisp->index);
690
691         free (handle);
692 }
693
694 Bool
695 fbdevVideoV4l2StreamOn (void *handle)
696 {
697         FBDevDispHandle *hdisp = (FBDevDispHandle*)handle;
698         uint phy_addrs[3];
699
700         return_val_if_fail (hdisp != NULL, FALSE);
701
702         hdisp->re_setting = TRUE;
703
704         if (!_fbdevVideoV4l2OpenDevice (hdisp, hdisp->index, hdisp->status.requestbuffer))
705                 return FALSE;
706
707         fbdevVideoV4l2SetFormat (handle,
708                                  &hdisp->status.img,
709                                  &hdisp->status.crop,
710                                  &hdisp->status.dst,
711                                  hdisp->status.id,
712                                  hdisp->status.scn_rotate,
713                                  hdisp->status.hw_rotate,
714                                  hdisp->status.hflip,
715                                  hdisp->status.vflip,
716                                  hdisp->status.requestbuffer,
717                                  hdisp->status.sync);
718
719         phy_addrs[0] = hdisp->fimcbuf.base[0];
720         phy_addrs[1] = hdisp->fimcbuf.base[1];
721         phy_addrs[2] = hdisp->fimcbuf.base[2];
722
723         fbdevVideoV4l2Draw (handle, hdisp->status.backup, phy_addrs);
724
725         if (hdisp->status.backup)
726         {
727                 free (hdisp->status.backup);
728                 hdisp->status.backup = NULL;
729         }
730
731         hdisp->re_setting = FALSE;
732
733         DRVLOG ("%s \n", __FUNCTION__);
734
735         return TRUE;
736 }
737
738 void
739 fbdevVideoV4l2StreamOff (void *handle)
740 {
741         FBDevDispHandle *hdisp = (FBDevDispHandle*)handle;
742         int requestbuffer;
743
744         return_if_fail (hdisp != NULL);
745
746         if (hdisp->memory == V4L2_MEMORY_MMAP)
747         {
748                 int size;
749
750                 if (hdisp->status.backup)
751                 {
752                         free (hdisp->status.backup);
753                         hdisp->status.backup = NULL;
754                 }
755
756                 size = fbdevVideoQueryImageAttributes (NULL, hdisp->status.id,
757                                                        (unsigned short*)&hdisp->status.img.width,
758                                                        (unsigned short*)&hdisp->status.img.height,
759                                                        NULL, NULL, NULL);
760
761                 if (size > 0)
762                         hdisp->status.backup = malloc (size);
763
764                 if (hdisp->status.backup &&
765                         hdisp->src_buf &&
766                         hdisp->src_buf[hdisp->status.queued_index].buf)
767                         memcpy (hdisp->status.backup,
768                                 hdisp->src_buf[hdisp->status.queued_index].buf,
769                                 size);
770         }
771
772         requestbuffer = hdisp->status.requestbuffer;
773
774         _fbdevVideoV4l2CloseDevice (hdisp);
775
776         hdisp->status.requestbuffer = requestbuffer;
777
778         DRVLOG ("%s \n", __FUNCTION__);
779 }
780
781 /* img->x, img->y : not used. */
782 Bool
783 fbdevVideoV4l2SetFormat (void *handle,
784                          xRectangle *img, xRectangle *crop, xRectangle *dst,
785                          uint id,
786                          int  scn_rotate,
787                          int  hw_rotate,
788                          int  hflip,
789                          int  vflip,
790                          int  requestbuffer,
791                          Bool sync)
792 {
793         FBDevDispHandle *hdisp = (FBDevDispHandle*)handle;
794         Bool src_changed = FALSE;
795         Bool dst_changed = FALSE;
796         Bool buf_changed = FALSE;
797
798         return_val_if_fail (handle != NULL, FALSE);
799         return_val_if_fail (img != NULL, FALSE);
800         return_val_if_fail (crop != NULL, FALSE);
801         return_val_if_fail (dst != NULL, FALSE);
802
803         DRVLOG ("[SetFormat, %p] try to set : img(%d,%d %dx%d) crop(%d,%d %dx%d) dst(%d,%d %dx%d) id(%x), rot(%d), flip(%d,%d) req(%d)\n", hdisp,
804                 img->x, img->y, img->width, img->height,
805                 crop->x, crop->y, crop->width, crop->height,
806                 dst->x, dst->y, dst->width, dst->height,
807                 id, hw_rotate, hflip, vflip, requestbuffer);
808
809         if (memcmp (&hdisp->status.img, img, sizeof (xRectangle)) ||
810                 memcmp (&hdisp->status.crop, crop, sizeof (xRectangle)) ||
811                 hdisp->status.id != id)
812                 src_changed = TRUE;
813
814         if (memcmp (&hdisp->status.dst, dst, sizeof (xRectangle)) ||
815                 hdisp->status.hw_rotate != hw_rotate ||
816                 hdisp->status.hflip != hflip ||
817                 hdisp->status.vflip != vflip)
818                 dst_changed = TRUE;
819
820         if (hdisp->status.requestbuffer != requestbuffer)
821                 buf_changed = TRUE;
822
823         if (hdisp->status.init && (src_changed || dst_changed || buf_changed))
824         {
825                 _fbdevVideoV4l2CloseDevice (hdisp);
826                 _fbdevVideoV4l2OpenDevice (hdisp, hdisp->index, requestbuffer);
827
828                 DRVLOG ("[SetFormat, %p] changed : img(%d) dst(%d) buf(%d) \n", hdisp,
829                         src_changed, dst_changed, buf_changed);
830
831                 /* After close device, below all steps should be done. */
832                 src_changed = dst_changed = buf_changed = TRUE;
833                 hdisp->status.init = 0;
834         }
835
836         if (hdisp->re_setting)
837                 src_changed = dst_changed = buf_changed = TRUE;
838
839         if (src_changed)
840         {
841                 fbdevVideoV4l2GetFormatInfo (id, NULL, &hdisp->pixfmt, &hdisp->memory);
842
843                 DRVLOG ("[SetFormat, %p] id(%c%c%c%c) => pixfmt(%d) memory(%d) \n", hdisp,
844                         id & 0xFF, (id & 0xFF00) >> 8, (id & 0xFF0000) >> 16,  (id & 0xFF000000) >> 24,
845                         hdisp->pixfmt, hdisp->memory);
846
847                 if (img->width % 16)
848                         xf86DrvMsg (0, X_WARNING, "img->width(%d) is not multiple of 16!!!\n", img->width);
849
850                 if (!_fbdevVideoV4l2SetSrc (hdisp->video_fd, img, crop, hdisp->pixfmt))
851                 {
852                         xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _fbdevVideoV4l2SetSrc is failed. \n", hdisp);
853                         return FALSE;
854                 }
855
856                 hdisp->status.img  = *img;
857                 hdisp->status.crop = *crop;
858                 hdisp->status.id   = id;
859                 hdisp->status.sync = sync;
860
861                 hdisp->status.requestbuffer = 0;
862                 hdisp->status.init = 1;
863         }
864
865         if (dst_changed)
866         {
867                 hdisp->status.cur_idx = 0;
868                 hdisp->status.hw_rotate = hw_rotate;
869                 hdisp->status.scn_rotate = scn_rotate;
870                 hdisp->status.hflip = hflip;
871                 hdisp->status.vflip = vflip;
872                 hdisp->status.dst = *dst;
873
874                 if (hdisp->fb_fd >= 0)
875                 {
876                         xRectangle fb_rect = *dst;
877                         if (!_move_resize_fb (hdisp, fb_rect.x, fb_rect.y, fb_rect.width, fb_rect.height))
878                         {
879                                 xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _move_resize_fb is failed. \n", hdisp);
880                                 return FALSE;
881                         }
882                 }
883
884                 fbdev_util_rotate_rect ((int)hdisp->pScreen->width,
885                                         (int)hdisp->pScreen->height,
886                                         0, (hw_rotate + (360 - scn_rotate)) % 360, dst);
887                 if (hdisp->fb_base_phy)
888                 {
889                         xRectangle win_rect = {0, 0, dst->width, dst->height};
890
891                         if (!_fbdevVideoV4l2SetDst (hdisp->video_fd, dst, &win_rect, hw_rotate, hflip, vflip, OUTPUT_PATH_DMA, (uint)hdisp->fb_base_phy))
892                         {
893                                 xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _fbdevVideoV4l2SetDst is failed. \n", hdisp);
894                                 return FALSE;
895                         }
896                 }
897                 else
898                 {
899                         if (!_fbdevVideoV4l2SetDst (hdisp->video_fd, dst, dst, hw_rotate, hflip, vflip, OUTPUT_PATH_FIMD, 0))
900                         {
901                                 xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _fbdevVideoV4l2SetDst is failed. \n", hdisp);
902                                 return FALSE;
903                         }
904                 }
905         }
906
907         if (buf_changed)
908         {
909                 if (!_fbdevVideoV4l2SetBuffer (hdisp->video_fd,
910                                                V4L2_BUF_TYPE_VIDEO_OUTPUT,
911                                                hdisp->memory,
912                                                requestbuffer,
913                                                &hdisp->src_buf))
914                 {
915                         xf86DrvMsg (0, X_ERROR, "[SetFormat, %p] _fbdevVideoV4l2SetBuffer is failed. \n", hdisp);
916                         return FALSE;
917                 }
918
919                 hdisp->status.cur_idx = 0;
920                 hdisp->status.requestbuffer = requestbuffer;
921                 hdisp->initial_dequeued_buf = requestbuffer;
922         }
923
924         if (!hdisp->status.streamon)
925         {
926                 _fbdevVideoV4l2StreamOn (hdisp->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT);
927                 hdisp->status.streamon = TRUE;
928         }
929
930         return TRUE;
931 }
932
933 XF86ImagePtr
934 fbdevVideoV4l2SupportImages (int *count)
935 {
936         if (count)
937                 *count = NUM_IMAGES;
938
939         return Images;
940 }
941
942 int
943 fbdevVideoV4l2Draw (void *handle, uchar *buf, uint *phy_addrs)
944 {
945         FBDevDispHandle *hdisp = (FBDevDispHandle*)handle;
946         int idx;
947
948         return_val_if_fail (handle != NULL, FALSE);
949 //      return_val_if_fail (phy_addrs != NULL, FALSE);
950
951         if (!hdisp->status.sync)
952         {
953                 if (hdisp->initial_dequeued_buf > 0)
954                 {
955                         idx = hdisp->status.requestbuffer - hdisp->initial_dequeued_buf;
956                         hdisp->initial_dequeued_buf--;
957                 }
958                 else
959                 {
960                         if ((idx = _fbdevVideoV4l2Dequeue (hdisp->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, hdisp->memory)) < 0)
961                         {
962                                 xf86DrvMsg (0, X_ERROR, "[Draw, %p] _fbdevVideoV4l2Dequeue is failed. \n", hdisp);
963                                 return FALSE;
964                         }
965                 }
966         }
967         else
968                 idx = hdisp->status.queued_index;
969
970         if (hdisp->memory == V4L2_MEMORY_MMAP)
971         {
972                 uchar *destbuf = hdisp->src_buf[idx].buf;
973                 int size;
974
975                 return_val_if_fail (buf != NULL, FALSE);
976
977                 hdisp->status.last_buffer = destbuf;
978
979                 size = fbdevVideoQueryImageAttributes (NULL, hdisp->status.id,
980                                                        (unsigned short*)&hdisp->status.img.width,
981                                                        (unsigned short*)&hdisp->status.img.height,
982                                                        NULL, NULL, NULL);
983                 memcpy (destbuf, buf, size);
984         }
985
986         hdisp->fimcbuf.base[0] = phy_addrs[0];
987         hdisp->fimcbuf.base[1] = phy_addrs[1];
988         hdisp->fimcbuf.base[2] = phy_addrs[2];
989         hdisp->fimcbuf.length[0] = hdisp->status.img.width * hdisp->status.img.height;
990         hdisp->fimcbuf.length[1] = hdisp->fimcbuf.length[0] >> 1;
991         hdisp->fimcbuf.length[2] = hdisp->fimcbuf.base[1] + hdisp->fimcbuf.length[1];
992
993         if ((idx = _fbdevVideoV4l2Queue (hdisp->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT,
994                                          hdisp->memory, idx, &hdisp->fimcbuf)) < 0)
995         {
996                 xf86DrvMsg (0, X_ERROR, "[Draw, %p] _fbdevVideoV4l2Queue is failed. \n", hdisp);
997                 return FALSE;
998         }
999
1000         if (hdisp->status.sync)
1001         {
1002                 if ((idx = _fbdevVideoV4l2Dequeue (hdisp->video_fd, V4L2_BUF_TYPE_VIDEO_OUTPUT, hdisp->memory)) < 0)
1003                 {
1004                         xf86DrvMsg (0, X_ERROR, "[Draw, %p] _fbdevVideoV4l2Dequeue is failed. \n", hdisp);
1005                         return FALSE;
1006                 }
1007         }
1008
1009         if (hdisp->fb_fd >= 0 && !hdisp->fb_shown)
1010         {
1011                 if (!fbdevFbActivate (hdisp->fb_fd))
1012                 {
1013                         xf86DrvMsg (0, X_ERROR, "[%s, %p] %d failed. \n", __FUNCTION__, hdisp, __LINE__);
1014                         return FALSE;
1015                 }
1016
1017                 hdisp->fb_shown = TRUE;
1018         }
1019
1020         hdisp->status.queued_index = idx + 1;
1021         if (hdisp->status.queued_index > hdisp->status.requestbuffer - 1)
1022                 hdisp->status.queued_index = 0;
1023
1024         return TRUE;
1025 }
1026
1027 Bool
1028 fbdevVideoV4l2GetFormatInfo (int id, int *type, uint *pixelformat, FBDevV4l2Memory *memory)
1029 {
1030         int i;
1031
1032         for (i = 0; i < sizeof (format_infos) / sizeof (FormatInfo); i++)
1033                 if (format_infos[i].id == id)
1034                 {
1035                         if (type)
1036                                 *type = format_infos[i].type;
1037                         if (pixelformat)
1038                                 *pixelformat = format_infos[i].pixelformat;
1039                         if (memory)
1040                                 *memory = format_infos[i].memory;
1041                         return TRUE;
1042                 }
1043
1044         return FALSE;
1045 }
1046
1047 /*  img : original src size
1048  *  src : real src size (cropped area inside img)
1049  *  dst : real dst size
1050  *        original dst size (in case that image is drawn on opened framebuffer)
1051  */
1052 Bool
1053 fbdevVideoV4l2CheckSize (void *handle, uint pixelformat,
1054                          xRectangle *img, xRectangle *src, xRectangle *dst,
1055                          int type, int memory)
1056 {
1057         /* img */
1058         if (img)
1059         {
1060                 if (img->width % 16)
1061                         xf86DrvMsg (0, X_WARNING, "img's width(%d) is not multiple of 16!!!\n", img->width);
1062
1063                 if (type == TYPE_YUV420 && img->height % 2)
1064                         xf86DrvMsg (0, X_WARNING, "img's height(%d) is not multiple of 2!!!\n", img->height);
1065
1066                 return_val_if_fail (img->width >= 16, FALSE);
1067                 return_val_if_fail (img->height >= 16, FALSE);
1068         }
1069
1070         /* src */
1071         if (src)
1072         {
1073                 if (type == TYPE_YUV420 || type == TYPE_YUV422)
1074                 {
1075                         src->x = src->x & (~0x1);
1076                         src->width = src->width & (~0x1);
1077                 }
1078
1079                 if (type == TYPE_YUV420)
1080                         src->height = src->height & (~0x1);
1081
1082                 return_val_if_fail (src->width >= 16, FALSE);
1083                 return_val_if_fail (src->height >= 16, FALSE);
1084         }
1085
1086         /* dst */
1087         if (dst)
1088         {
1089                 dst->width = dst->width & (~0x1);
1090                 dst->height = dst->height & (~0x1);
1091
1092                 return_val_if_fail (dst->width >= 8, FALSE);
1093                 return_val_if_fail (dst->height >= 8, FALSE);
1094         }
1095
1096         return TRUE;
1097 }
1098
1099 void
1100 fbdevVideoGetFBInfo (void *handle, void **base, xRectangle *pos)
1101 {
1102         FBDevDispHandle *hdisp = (FBDevDispHandle*)handle;
1103
1104         if (!hdisp)
1105                 return;
1106
1107         if (pos)
1108                 *pos = hdisp->status.dst;
1109         if (base)
1110                 *base = hdisp->fb_base_vir;
1111 }