Initialize Tizen 2.3
[adaptation/xorg/driver/xserver-xorg-video-emulfb.git] / src / xv / fbdev_video.c
1 /*
2  * xserver-xorg-video-emulfb
3  *
4  * Copyright 2004 Keith Packard
5  * Copyright 2005 Eric Anholt
6  * Copyright 2006 Nokia Corporation
7  * Copyright 2010 - 2011 Samsung Electronics co., Ltd. All Rights Reserved.
8  *
9  * Contact: Boram Park <boram1288.park@samsung.com>
10  *
11  * Permission to use, copy, modify, distribute and sell this software and its
12  * documentation for any purpose is hereby granted without fee, provided that
13  * the above copyright notice appear in all copies and that both that
14  * copyright notice and this permission notice appear in supporting
15  * documentation, and that the names of the authors and/or copyright holders
16  * not be used in advertising or publicity pertaining to distribution of the
17  * software without specific, written prior permission.  The authors and
18  * copyright holders make no representations about the suitability of this
19  * software for any purpose.  It is provided "as is" without any express
20  * or implied warranty.
21  *
22  * THE AUTHORS AND COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO
23  * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
24  * FITNESS, IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
25  * ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
26  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
27  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
28  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29  *
30  */
31
32 #ifdef HAVE_CONFIG_H
33 #include "config.h"
34 #endif
35 #include <unistd.h>
36 #include <string.h>
37 #include <errno.h>
38 #include <sys/time.h>
39 #include <sys/ioctl.h>
40
41 #include <pixman.h>
42 #include <X11/Xatom.h>
43 #include <X11/extensions/Xv.h>
44 #include <X11/extensions/Xvproto.h>
45 #include <X11/extensions/dpmsconst.h>
46 #include "fourcc.h"
47
48 #include "fb.h"
49 #include "fbdevhw.h"
50 #include "damage.h"
51
52 #include "xf86xv.h"
53
54 #include "fbdev.h"
55
56 #include "fbdev_dpms.h"
57 #include "fbdev_video.h"
58 #include "fbdev_util.h"
59 #include "fbdev_util.h"
60 #include "fbdev_pixman.h"
61 #include "fbdev_fb.h"
62 #include "fbdev_video_fourcc.h"
63 #include "fbdev_video_v4l2.h"
64 #include "fbdev_video_virtual.h"
65
66 #include "xv_types.h"
67
68 extern CallbackListPtr DPMSCallback;
69
70 static XF86VideoEncodingRec DummyEncoding[] =
71 {
72         { 0, "XV_IMAGE", -1, -1, { 1, 1 } },
73         { 1, "XV_IMAGE", 2560, 2560, { 1, 1 } },
74 };
75
76 static XF86VideoFormatRec Formats[] =
77 {
78         { 16, TrueColor },
79         { 24, TrueColor },
80         { 32, TrueColor },
81 };
82
83 static XF86AttributeRec Attributes[] =
84 {
85         { 0, -1, 270, "_USER_WM_PORT_ATTRIBUTE_ROTATION" },
86         { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_HFLIP" },
87         { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_VFLIP" },
88         { 0, -1, 1, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION" },
89         { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_DRAWING_MODE" },
90         { 0, 0, 1, "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF" },
91 };
92
93 typedef enum
94 {
95         PAA_MIN,
96         PAA_ROTATION,
97         PAA_HFLIP,
98         PAA_VFLIP,
99         PAA_PREEMPTION,
100         PAA_DRAWINGMODE,
101         PAA_STREAMOFF,
102         PAA_MAX
103 } FBDevPortAttrAtom;
104
105 enum
106 {
107         ON_NONE,
108         ON_FB,
109         ON_WINDOW,
110         ON_PIXMAP
111 };
112
113 static struct
114 {
115         FBDevPortAttrAtom  paa;
116         const char      *name;
117         Atom             atom;
118 } atom_list[] =
119 {
120         { PAA_ROTATION, "_USER_WM_PORT_ATTRIBUTE_ROTATION", None },
121         { PAA_HFLIP, "_USER_WM_PORT_ATTRIBUTE_HFLIP", None },
122         { PAA_VFLIP, "_USER_WM_PORT_ATTRIBUTE_VFLIP", None },
123         { PAA_PREEMPTION, "_USER_WM_PORT_ATTRIBUTE_PREEMPTION", None },
124         { PAA_DRAWINGMODE, "_USER_WM_PORT_ATTRIBUTE_DRAWING_MODE", None },
125         { PAA_STREAMOFF, "_USER_WM_PORT_ATTRIBUTE_STREAM_OFF", None },
126 };
127
128 static int registered_handler;
129 extern CallbackListPtr DPMSCallback;
130
131 #define FBDEV_MAX_PORT    16
132 #define REQ_BUF_NUM       3
133
134 #define NUM_FORMATS       (sizeof(Formats) / sizeof(Formats[0]))
135 #define NUM_ATTRIBUTES    (sizeof(Attributes) / sizeof(Attributes[0]))
136 #define NUM_ATOMS         (sizeof(atom_list) / sizeof(atom_list[0]))
137
138 static PixmapPtr
139 _fbdevVideoGetPixmap (DrawablePtr pDraw)
140 {
141     if (pDraw->type == DRAWABLE_WINDOW)
142         return pDraw->pScreen->GetWindowPixmap ((WindowPtr) pDraw);
143     else
144         return (PixmapPtr) pDraw;
145 }
146
147 static void
148 _fbdevVideoGetRotation (ScreenPtr      pScreen,
149                         FBDevPortPrivPtr pPortPriv,
150                         DrawablePtr    pDraw,
151                         int           *scn_rotate,
152                         int           *rotate,
153                         int           *hw_rotate)
154 {
155         ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
156         FBDevPtr pFBDev = FBDEVPTR (pScrnInfo);
157
158         *scn_rotate = 0;
159         *rotate = 0;
160         *hw_rotate = 0;
161
162 #ifdef RANDR
163         switch (pFBDev->rotate)
164         {
165         case RR_Rotate_90:
166                 *scn_rotate = 270;
167         break;
168         case RR_Rotate_180:
169                 *scn_rotate = 180;
170         break;
171         case RR_Rotate_270:
172                 *scn_rotate = 90;
173         break;
174         case RR_Rotate_0:
175                 break;
176         }
177 #endif
178
179         if (pPortPriv->rotate >= 0)
180                 *rotate = pPortPriv->rotate;
181
182         *hw_rotate = (*rotate + *scn_rotate + 360) % 360;
183 }
184
185 static void
186 _fbdevVideoCloseV4l2Handle (ScrnInfoPtr pScrnInfo, FBDevPortPrivPtr pPortPriv)
187 {
188         FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate;
189
190     if (pPortPriv->aligned_buffer)
191     {
192         free (pPortPriv->aligned_buffer);
193         pPortPriv->aligned_buffer = NULL;
194         pPortPriv->buffer_size = 0;
195         pPortPriv->aligned_width = 0;
196     }
197
198         if (!pPortPriv->v4l2_handle)
199                 return;
200
201         fbdevVideoV4l2CloseHandle (pPortPriv->v4l2_handle);
202
203         pFBDev->v4l2_owner[pPortPriv->v4l2_index] = NULL;
204
205         pPortPriv->v4l2_handle = NULL;
206         pPortPriv->v4l2_index = -1;
207 }
208
209 static Atom
210 _fbdevVideoGetPortAtom (FBDevPortAttrAtom paa)
211 {
212         int i;
213
214         return_val_if_fail (paa > PAA_MIN && paa < PAA_MAX, None);
215
216         for (i = 0; i < NUM_ATOMS; i++)
217         {
218                 if (paa == atom_list[i].paa)
219                 {
220                         if (atom_list[i].atom == None)
221                                 atom_list[i].atom = MakeAtom (atom_list[i].name, strlen (atom_list[i].name), TRUE);
222
223                         return atom_list[i].atom;
224                 }
225         }
226
227         ErrorF ("Error: Unknown Port Attribute Name!\n");
228
229         return None;
230 }
231
232 static int
233 _fbdevVideoInterfbdevtXRects (xRectangle *dest, xRectangle *src1, xRectangle *src2)
234 {
235         int dest_x, dest_y;
236         int dest_x2, dest_y2;
237         int return_val;
238
239         return_val_if_fail (src1 != NULL, FALSE);
240         return_val_if_fail (src2 != NULL, FALSE);
241
242         return_val = FALSE;
243
244         dest_x = MAX (src1->x, src2->x);
245         dest_y = MAX (src1->y, src2->y);
246         dest_x2 = MIN (src1->x + src1->width, src2->x + src2->width);
247         dest_y2 = MIN (src1->y + src1->height, src2->y + src2->height);
248
249         if (dest_x2 > dest_x && dest_y2 > dest_y)
250         {
251                 if (dest)
252                 {
253                         dest->x = dest_x;
254                         dest->y = dest_y;
255                         dest->width = dest_x2 - dest_x;
256                         dest->height = dest_y2 - dest_y;
257                 }
258                 return_val = TRUE;
259         }
260         else if (dest)
261         {
262                 dest->width = 0;
263                 dest->height = 0;
264         }
265
266         return return_val;
267 }
268
269 static int
270 _fbdevVideodrawingOn (FBDevPortPrivPtr pPortPriv, DrawablePtr pDraw)
271 {
272     if (pDraw->type == DRAWABLE_PIXMAP)
273         return ON_PIXMAP;
274     else if (pDraw->type == DRAWABLE_WINDOW)
275     {
276         PropertyPtr prop = fbdev_util_get_window_property ((WindowPtr)pDraw,
277                                                            "XV_ON_DRAWABLE");
278         if (prop && *(int*)prop->data > 0)
279             return ON_WINDOW;
280     }
281
282     return ON_FB;
283 }
284
285 static int
286 _fbdevVideoParseFormatBuffer (uchar *buf, uint *phy_addrs)
287 {
288         XV_PUTIMAGE_DATA_PTR data = (XV_PUTIMAGE_DATA_PTR) buf;
289
290         int valid = XV_PUTIMAGE_VALIDATE_DATA (data);
291         if (valid < 0)
292                 return valid;
293
294         phy_addrs[0] = data->YPhyAddr;
295         phy_addrs[1] = data->CbPhyAddr;
296         phy_addrs[2] = data->CrPhyAddr;
297
298         return 0;
299 }
300
301 static XF86ImageRec *
302 _fbdevVideoGetImageInfo (int id)
303 {
304         XF86ImagePtr pImages;
305         int i, count = 0;
306
307         pImages = fbdevVideoV4l2SupportImages (&count);
308
309         for (i = 0; i < count; i++)
310         {
311                 if (pImages[i].id == id)
312                         return &pImages[i];
313         }
314
315         return NULL;
316 };
317
318 static Bool
319 _fbdevVideoSetMode (ScrnInfoPtr pScrnInfo, FBDevPortPrivPtr pPortPriv, int *index)
320 {
321         FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate;
322         Bool full = TRUE;
323         int  i = 0;
324
325         *index = -1;
326
327         if (pPortPriv->preemption == -1)
328         {
329                 pPortPriv->mode = PORT_MODE_WAITING;
330                 return TRUE;
331         }
332
333         for (i = 0; i < pFBDev->v4l2_num; i++)
334                 if (!fbdevVideoV4l2HandleOpened (i))
335                 {
336                         full = FALSE;
337                         break;
338                 }
339
340         if (!full)
341         {
342                 *index = i;
343                 pPortPriv->mode = PORT_MODE_V4L2;
344                 return TRUE;
345         }
346
347         /* All handles are occupied. So we need to steal one of them. */
348
349         if (pPortPriv->preemption == 0)
350         {
351                 pPortPriv->mode = PORT_MODE_WAITING;
352                 return TRUE;
353         }
354
355         for (i = 0; i < pFBDev->v4l2_num; i++)
356         {
357                 FBDevPortPrivPtr pOwnerPort = (FBDevPortPrivPtr) pFBDev->v4l2_owner[i];
358
359                 if (pOwnerPort && pOwnerPort->preemption == 0)
360                 {
361                         _fbdevVideoCloseV4l2Handle (pScrnInfo, pOwnerPort);
362
363                         pOwnerPort->mode = PORT_MODE_WAITING;
364                         pPortPriv->mode = PORT_MODE_V4L2;
365                         *index = i;
366                         return TRUE;
367                 }
368         }
369
370         xf86DrvMsg (0, X_ERROR, "fbdev/put_image: Three or more preemptive ports were requested\n");
371
372         return FALSE;
373 }
374
375 static int
376 _fbdevVideoPutImageV4l2 (ScrnInfoPtr pScrnInfo,
377                          FBDevPortPrivPtr pPortPriv,
378                          xRectangle *img,
379                          xRectangle *src,
380                          xRectangle *dst,
381                          RegionPtr   clip_boxes,
382                          int scn_rotate,
383                          int rotate,
384                          int hw_rotate,
385                          XF86ImageRec *image_info,
386                          uchar *buf,
387                          FBDevPortMode modeBefore,
388                          int v4l2_index,
389                          DrawablePtr pDraw)
390 {
391         FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate;
392         uint phy_addrs[4] = {0,};
393         FBDevV4l2Memory memory;
394         uint pixelformat;
395         int fmt_type = 0;
396
397         if (!fbdevVideoV4l2GetFormatInfo (image_info->id, &fmt_type, &pixelformat, &memory))
398         {
399                 xf86DrvMsg (0, X_ERROR, "ID(%c%c%c%c) is not in 'format_infos'.\n",
400                             image_info->id & 0xFF, (image_info->id & 0xFF00) >> 8,
401                             (image_info->id & 0xFF0000) >> 16,  (image_info->id & 0xFF000000) >> 24);
402                 return BadRequest;
403         }
404
405         if (memory == V4L2_MEMORY_USERPTR)
406         {
407                 int ret;
408                 if ((ret = _fbdevVideoParseFormatBuffer (buf, phy_addrs)) < 0)
409                 {
410                         if (ret == XV_HEADER_ERROR)
411                                 xf86DrvMsg (0, X_ERROR, "XV_HEADER_ERROR\n");
412                         else if (ret == XV_VERSION_MISMATCH)
413                                 xf86DrvMsg (0, X_ERROR, "XV_VERSION_MISMATCH\n");
414
415                         return BadRequest;
416                 }
417
418                 /* Skip frame */
419                 if (phy_addrs[0] == 0)
420                         return Success;
421         }
422
423         if (!pPortPriv->v4l2_handle)
424         {
425                 pPortPriv->v4l2_handle = fbdevVideoV4l2OpenHandle (pScrnInfo->pScreen, v4l2_index, REQ_BUF_NUM);
426                 if (!pPortPriv->v4l2_handle)
427                 {
428                         int other_index = (v4l2_index == 0) ? 1 : 0;
429                         if (fbdevVideoV4l2HandleOpened (other_index))
430                         {
431                                 xf86DrvMsg (0, X_ERROR, "fbdevVideoV4l2OpenHandle failed. no empty.\n");
432                                 return BadRequest;
433                         }
434                         else
435                         {
436                                 pPortPriv->v4l2_handle = fbdevVideoV4l2OpenHandle (pScrnInfo->pScreen, other_index, REQ_BUF_NUM);
437                                 if (!pPortPriv->v4l2_handle)
438                                 {
439                                         xf86DrvMsg (0, X_ERROR, "fbdevVideoV4l2OpenHandle failed. fail open.\n");
440                                         return BadRequest;
441                                 }
442                         }
443
444                         v4l2_index = other_index;
445                 }
446
447                 pFBDev->v4l2_owner[v4l2_index] = (void*)pPortPriv;
448                 pPortPriv->v4l2_index = v4l2_index;
449         }
450
451         if (!fbdevVideoV4l2CheckSize (pPortPriv->v4l2_handle, pixelformat, img, src, dst, fmt_type, V4L2_MEMORY_MMAP))
452                 return BadRequest;
453
454         if (fbdevVideoV4l2SetFormat (pPortPriv->v4l2_handle, img, src, dst,
455                                      image_info->id, scn_rotate, hw_rotate,
456                                      pPortPriv->hflip, pPortPriv->vflip,
457                                      REQ_BUF_NUM, FALSE))
458         {
459                 fbdevVideoV4l2Draw (pPortPriv->v4l2_handle, buf, phy_addrs);
460
461                 if (modeBefore == PORT_MODE_WAITING)
462                         pScrnInfo->pScreen->WindowExposures ((WindowPtr) pDraw, clip_boxes, NULL);
463
464 #if ENABLE_ARM
465                 /* update cliplist */
466                 if (!REGION_EQUAL (pScrnInfo->pScreen, &pPortPriv->clip, clip_boxes))
467                 {
468                         /* setting transparency length to 8 */
469                         if (!pFBDev->bFbAlphaEnabled)
470                         {
471                                 fbdevFbScreenAlphaInit (fbdevHWGetFD (pScrnInfo));
472                                 pFBDev->bFbAlphaEnabled = TRUE;
473                         }
474                 }
475 #endif
476
477                 return Success;
478         }
479
480         _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv);
481
482         pPortPriv->mode = PORT_MODE_WAITING;
483
484         return Success;
485 }
486
487 static int
488 _fbdevVideoPutImageOnDrawable (ScrnInfoPtr pScrnInfo,
489                                FBDevPortPrivPtr pPortPriv,
490                                xRectangle *img,
491                                xRectangle *src,
492                                xRectangle *dst,
493                                RegionPtr   clip_boxes,
494                                int scn_rotate,
495                                int rotate,
496                                XF86ImageRec *image_info,
497                                uchar *buf,
498                                DrawablePtr pDraw)
499 {
500         pixman_format_code_t src_format, dst_format;
501         xRectangle pxm = {0,};
502
503         PixmapPtr pPixmap = _fbdevVideoGetPixmap (pDraw);
504
505         pxm.width = pPixmap->drawable.width;
506         pxm.height = pPixmap->drawable.height;
507
508         switch (image_info->id)
509         {
510         case FOURCC_I420:
511         case FOURCC_YV12:
512                 src_format = PIXMAN_yv12;
513                 break;
514         case FOURCC_YUY2:
515                 src_format = PIXMAN_yuy2;
516                 break;
517         case FOURCC_RGB565:
518                 src_format = PIXMAN_r5g6b5;
519                 break;
520         case FOURCC_RGB32:
521                 src_format = PIXMAN_a8r8g8b8;
522                 break;
523         default:
524                 return FALSE;
525         }
526
527         switch (image_info->id)
528         {
529         case FOURCC_I420:
530                 dst_format = PIXMAN_x8b8g8r8;
531                 break;
532         default:
533                 dst_format = PIXMAN_x8r8g8b8;
534                 break;
535         }
536
537     if (image_info->id == FOURCC_I420 && img->width % 16)
538     {
539         int src_p[3] = {0,}, src_o[3] = {0,}, src_l[3] = {0,};
540         int dst_p[3] = {0,}, dst_o[3] = {0,}, dst_l[3] = {0,};
541         unsigned short src_w, src_h, dst_w, dst_h;
542         int size;
543
544         src_w = img->width;
545         src_h = img->height;
546         fbdevVideoQueryImageAttributes (NULL, image_info->id, &src_w, &src_h,
547                                         src_p, src_o, src_l);
548
549         dst_w = (img->width + 15) & ~15;
550         dst_h = img->height;
551         size = fbdevVideoQueryImageAttributes (NULL, image_info->id, &dst_w, &dst_h,
552                                                dst_p, dst_o, dst_l);
553
554         if (!pPortPriv->aligned_buffer || pPortPriv->buffer_size != size)
555         {
556             if (pPortPriv->aligned_buffer)
557                 free (pPortPriv->aligned_buffer);
558
559             pPortPriv->aligned_buffer = malloc (size);
560             if (!pPortPriv->aligned_buffer)
561                 return FALSE;
562             pPortPriv->buffer_size = size;
563         }
564
565         fbdev_util_copy_image (src_w, src_h,
566                                (char*)buf, src_w, src_h,
567                                src_p, src_o, src_l,
568                                (char*)pPortPriv->aligned_buffer, dst_w, dst_h,
569                                dst_p, dst_o, dst_l,
570                                3, 2, 2);
571
572         pPortPriv->aligned_width = dst_w;
573         img->width = dst_w;
574         buf = pPortPriv->aligned_buffer;
575     }
576
577         /* support only RGB  */
578         fbdev_pixman_convert_image (PIXMAN_OP_SRC,
579                                     buf, pPixmap->devPrivate.ptr,
580                                     src_format, dst_format,
581                                     img, &pxm, src, dst,
582                                     NULL, rotate,
583                                     pPortPriv->hflip, pPortPriv->vflip);
584
585     DamageDamageRegion (pDraw, clip_boxes);
586
587         return Success;
588 }
589
590 static Bool
591 _fbdevVideoSetHWPortsProperty (ScreenPtr pScreen, int nums)
592 {
593         WindowPtr pWin = pScreen->root;
594         Atom atom_hw_ports;
595
596         if (!pWin || !serverClient)
597                 return FALSE;
598
599         atom_hw_ports = MakeAtom ("X_HW_PORTS", strlen ("X_HW_PORTS"), TRUE);
600
601         dixChangeWindowProperty (serverClient,
602                                  pWin, atom_hw_ports, XA_CARDINAL, 32,
603                                  PropModeReplace, 1, (unsigned int*)&nums, FALSE);
604
605         return TRUE;
606 }
607
608 static void
609 _fbdevVideoDPMSHandler(CallbackListPtr *list, pointer closure, pointer calldata)
610 {
611         FBDevDPMSPtr pDPMSInfo = (FBDevDPMSPtr) calldata;
612
613         if(!pDPMSInfo || !pDPMSInfo->pScrn)
614         {
615                 xf86DrvMsg (0, X_ERROR, "[%s] DPMS info or screen info is invalid !\n", __FUNCTION__);
616                 return;
617         }
618
619         switch(DPMSPowerLevel)
620         {
621         case DPMSModeOn:
622                 break;
623
624         case DPMSModeSuspend:
625                 break;
626
627         case DPMSModeStandby://LCD on
628         {
629                 ScrnInfoPtr pScrnInfo = pDPMSInfo->pScrn;
630                 FBDevPtr pFBDev = FBDEVPTR (pScrnInfo);
631                 XF86VideoAdaptorPtr pAdaptor = pFBDev->pAdaptor[0];
632                 int i;
633
634                 DRVLOG ("%s : DPMSModeStandby \n", __FUNCTION__);
635
636                 for (i = 0; i < FBDEV_MAX_PORT; i++)
637                 {
638                         FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
639                         if (!pPortPriv->v4l2_handle || !pPortPriv->need_streamon)
640                                 continue;
641
642                         if (!fbdevVideoV4l2StreamOn (pPortPriv->v4l2_handle))
643                         {
644                                 /* will re-open if failed */
645                                 _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv);
646                                 pPortPriv->v4l2_handle = NULL;
647                         }
648                         pPortPriv->need_streamon = FALSE;
649                 }
650                 break;
651         }
652         case DPMSModeOff://LCD off
653         {
654                 ScrnInfoPtr pScrnInfo = pDPMSInfo->pScrn;
655                 FBDevPtr pFBDev = FBDEVPTR (pScrnInfo);
656                 XF86VideoAdaptorPtr pAdaptor = pFBDev->pAdaptor[0];
657                 int i;
658
659                 DRVLOG ("%s : DPMSModeOff \n", __FUNCTION__);
660
661                 for (i = 0; i < FBDEV_MAX_PORT; i++)
662                 {
663                         FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
664                         if (!pPortPriv->v4l2_handle || pPortPriv->need_streamon)
665                                 continue;
666
667                         fbdevVideoV4l2StreamOff (pPortPriv->v4l2_handle);
668                         pPortPriv->need_streamon = TRUE;
669                 }
670
671                 break;
672         }
673         default:
674                 return;
675         }
676 }
677
678 static void
679 _fbdevVideoBlockHandler (pointer data, OSTimePtr pTimeout, pointer pRead)
680 {
681         ScrnInfoPtr pScrnInfo = (ScrnInfoPtr)data;
682         FBDevPtr pFBDev = FBDEVPTR (pScrnInfo);
683         ScreenPtr pScreen = pScrnInfo->pScreen;
684
685         if(registered_handler && _fbdevVideoSetHWPortsProperty (pScreen, pFBDev->v4l2_num))
686         {
687                 RemoveBlockAndWakeupHandlers(_fbdevVideoBlockHandler, (WakeupHandlerProcPtr)NoopDDA, data);
688                 registered_handler = FALSE;
689         }
690 }
691
692 static int
693 FBDevVideoGetPortAttribute (ScrnInfoPtr pScrnInfo,
694                             Atom        attribute,
695                             INT32      *value,
696                             pointer     data)
697 {
698         DRVLOG ("[GetPortAttribute] \n");
699
700         FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) data;
701
702         if (attribute == _fbdevVideoGetPortAtom (PAA_ROTATION))
703         {
704                 *value = pPortPriv->rotate;
705                 return Success;
706         }
707         else if (attribute == _fbdevVideoGetPortAtom (PAA_HFLIP))
708         {
709                 *value = pPortPriv->hflip;
710                 return Success;
711         }
712         else if (attribute == _fbdevVideoGetPortAtom (PAA_VFLIP))
713         {
714                 *value = pPortPriv->vflip;
715                 return Success;
716         }
717         else if (attribute == _fbdevVideoGetPortAtom (PAA_PREEMPTION))
718         {
719                 *value = pPortPriv->preemption;
720                 return Success;
721         }
722         else if (attribute == _fbdevVideoGetPortAtom (PAA_DRAWINGMODE))
723         {
724                 *value = (pPortPriv->mode == PORT_MODE_WAITING);
725                 return Success;
726         }
727         return BadMatch;
728 }
729
730 static int
731 FBDevVideoSetPortAttribute (ScrnInfoPtr pScrnInfo,
732                             Atom        attribute,
733                             INT32       value,
734                             pointer     data)
735 {
736         FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) data;
737
738         if (attribute == _fbdevVideoGetPortAtom (PAA_ROTATION))
739         {
740                 pPortPriv->rotate = value;
741                 DRVLOG ("[SetPortAttribute] rotate(%d) \n", value);
742                 return Success;
743         }
744         else if (attribute == _fbdevVideoGetPortAtom (PAA_HFLIP))
745         {
746                 pPortPriv->hflip = value;
747                 DRVLOG ("[SetPortAttribute] hflip(%d) \n", value);
748                 return Success;
749         }
750         else if (attribute == _fbdevVideoGetPortAtom (PAA_VFLIP))
751         {
752                 pPortPriv->vflip = value;
753                 DRVLOG ("[SetPortAttribute] vflip(%d) \n", value);
754                 return Success;
755         }
756         else if (attribute == _fbdevVideoGetPortAtom (PAA_PREEMPTION))
757         {
758                 pPortPriv->preemption = value;
759                 DRVLOG ("[SetPortAttribute] preemption(%d) \n", value);
760                 return Success;
761         }
762         else if (attribute == _fbdevVideoGetPortAtom (PAA_STREAMOFF))
763         {
764                 DRVLOG ("[SetPortAttribute] STREAMOFF \n");
765                 _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv);
766                 return Success;
767         }
768         return BadMatch;
769 }
770
771 static void
772 FBDevVideoQueryBestSize (ScrnInfoPtr pScrnInfo,
773                          Bool motion,
774                          short vid_w, short vid_h,
775                          short dst_w, short dst_h,
776                          uint *p_w, uint *p_h,
777                          pointer data)
778 {
779         DRVLOG ("%s (%s:%d)\n", __FUNCTION__, __FILE__, __LINE__);
780
781         *p_w = dst_w;
782         *p_h = dst_h;
783 }
784
785 static void
786 FBDevVideoStop (ScrnInfoPtr pScrnInfo, pointer data, Bool exit)
787 {
788         DRVLOG ("%s (%s:%d) exit(%d)\n", __FUNCTION__, __FILE__, __LINE__, exit);
789
790         FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) data;
791
792         if (pPortPriv->mode == PORT_MODE_V4L2)
793         {
794                 _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv);
795
796 #if ENABLE_ARM
797                 FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate;
798
799                 if (pFBDev->bFbAlphaEnabled)
800                 {
801                         fbdevFbScreenAlphaDeinit (fbdevHWGetFD (pScrnInfo));
802                         pFBDev->bFbAlphaEnabled = FALSE;
803                 }
804 #endif
805         }
806
807     if (pPortPriv->aligned_buffer)
808     {
809         free (pPortPriv->aligned_buffer);
810         pPortPriv->aligned_buffer = NULL;
811         pPortPriv->buffer_size = 0;
812         pPortPriv->aligned_width = 0;
813     }
814
815         pPortPriv->mode = PORT_MODE_INIT;
816         pPortPriv->preemption = 0;
817         pPortPriv->rotate = -1;
818         pPortPriv->need_streamon = FALSE;
819
820         if (exit)
821                 REGION_EMPTY (pScrnInfo, &pPortPriv->clip);
822 }
823
824 static int
825 FBDevVideoReputImage (ScrnInfoPtr pScrn, short src_x, short src_y,
826                                   short drw_x, short drw_y, short src_w,
827                                   short src_h, short drw_w, short drw_h,
828                                   RegionPtr clipBoxes, pointer data,
829                                   DrawablePtr pDraw)
830
831 {
832         return Success;
833 }
834
835 int
836 fbdevVideoQueryImageAttributes (ScrnInfoPtr    pScrnInfo,
837                                 int            id,
838                                 unsigned short *w,
839                                 unsigned short *h,
840                                 int            *pitches,
841                                 int            *offsets,
842                                 int            *lengths)
843 {
844         int size = 0, tmp = 0;
845
846         *w = (*w + 1) & ~1;
847         if (offsets)
848                 offsets[0] = 0;
849
850         switch (id)
851         {
852         case FOURCC_RGB565:
853                 size += (*w << 1);
854                 if (pitches)
855                         pitches[0] = size;
856                 size *= *h;
857         if (lengths)
858             lengths[0] = size;
859                 break;
860         case FOURCC_RGB24:
861                 size += (*w << 1) + *w;
862                 if (pitches)
863                         pitches[0] = size;
864                 size *= *h;
865         if (lengths)
866             lengths[0] = size;
867                 break;
868         case FOURCC_RGB32:
869                 size += (*w << 2);
870                 if (pitches)
871                         pitches[0] = size;
872                 size *= *h;
873         if (lengths)
874             lengths[0] = size;
875                 break;
876         case FOURCC_I420:
877         case FOURCC_S420:
878         case FOURCC_YV12:
879                 *h = (*h + 1) & ~1;
880                 size = (*w + 3) & ~3;
881                 if (pitches)
882                         pitches[0] = size;
883
884                 size *= *h;
885                 if (offsets)
886                         offsets[1] = size;
887         if (lengths)
888             lengths[0] = size;
889
890                 tmp = ((*w >> 1) + 3) & ~3;
891                 if (pitches)
892                         pitches[1] = pitches[2] = tmp;
893
894                 tmp *= (*h >> 1);
895                 size += tmp;
896                 if (offsets)
897                         offsets[2] = size;
898         if (lengths)
899             lengths[1] = tmp;
900
901                 size += tmp;
902         if (lengths)
903             lengths[2] = tmp;
904
905                 break;
906         case FOURCC_UYVY:
907         case FOURCC_SUYV:
908         case FOURCC_YUY2:
909         case FOURCC_ST12:
910         case FOURCC_SN12:
911                 size = *w << 1;
912                 if (pitches)
913                         pitches[0] = size;
914
915                 size *= *h;
916                 break;
917         case FOURCC_NV12:
918                 size = *w;
919                 if (pitches)
920                         pitches[0] = size;
921
922                 size *= *h;
923                 if (offsets)
924                         offsets[1] = size;
925
926                 tmp = *w;
927                 if (pitches)
928                         pitches[1] = tmp;
929
930                 tmp *= (*h >> 1);
931                 size += tmp;
932                 break;
933         default:
934                 return BadIDChoice;
935         }
936
937         return size;
938 }
939
940 static int
941 FBDEVVideoQueryImageAttributes (ScrnInfoPtr    pScrnInfo,
942                                 int            id,
943                                 unsigned short *w,
944                                 unsigned short *h,
945                                 int            *pitches,
946                                 int            *offsets)
947 {
948     return fbdevVideoQueryImageAttributes (pScrnInfo, id, w, h, pitches, offsets, NULL);
949 }
950
951 static int
952 FBDevVideoPutImage (ScrnInfoPtr pScrnInfo,
953                     short src_x, short src_y, short dst_x, short dst_y,
954                     short src_w, short src_h, short dst_w, short dst_h,
955                     int id,
956                     uchar *buf,
957                     short width, short height,
958                     Bool sync,
959                     RegionPtr clip_boxes,
960                     pointer data,
961                     DrawablePtr pDraw)
962 {
963         ScreenPtr pScreen = pScrnInfo->pScreen;
964         FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) data;
965         XF86ImageRec *image_info;
966         FBDevPortMode modeBefore = pPortPriv->mode;
967         xRectangle img = {0, 0, width, height};
968         xRectangle src = {src_x, src_y, src_w, src_h};
969         xRectangle dst = {dst_x, dst_y, dst_w, dst_h};
970         int scn_rotate, rotate, hw_rotate;
971         int v4l2_index = 0;
972         FBDevPtr pFBDev = FBDEVPTR (pScrnInfo);
973         int drawing;
974
975         if (pFBDev->isLcdOff)
976                 return Success;
977
978         pPortPriv->pDraw = pDraw;
979         drawing = _fbdevVideodrawingOn (pPortPriv, pDraw);
980
981         image_info = _fbdevVideoGetImageInfo (id);
982         if (!image_info)
983         {
984                 xf86DrvMsg (0, X_ERROR, "ID(%c%c%c%c) not supported.\n",
985                             id & 0xFF, (id & 0xFF00) >> 8,
986                             (id & 0xFF0000) >> 16,  (id & 0xFF000000) >> 24);
987                 return BadRequest;
988         }
989
990         _fbdevVideoGetRotation (pScreen, pPortPriv, pDraw, &scn_rotate, &rotate, &hw_rotate);
991
992         DRVLOG ("[PutImage] buf(%p) ID(%c%c%c%c) mode(%s) preem(%d) handle(%p) rot(%d+%d=%d) res(%dx%d) drawing(%d)\n",
993                 buf, id & 0xFF, (id & 0xFF00) >> 8, (id & 0xFF0000) >> 16,  (id & 0xFF000000) >> 24,
994                 pPortPriv->mode == PORT_MODE_WAITING ? "waiting" : "V4L2",
995                 pPortPriv->preemption,
996                 pPortPriv->v4l2_handle,
997                 scn_rotate, rotate, hw_rotate,
998                 pScreen->width, pScreen->height, drawing);
999
1000         DRVLOG ("[PutImage] \t   img(%d,%d %dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d) \n",
1001                 img.x, img.y, img.width, img.height,
1002                 src.x, src.y, src.width, src.height,
1003                 dst.x, dst.y, dst.width, dst.height);
1004
1005         _fbdevVideoInterfbdevtXRects (&src, &src, &img);
1006
1007         DRVLOG ("[PutImage] \t=> img(%d,%d %dx%d) src(%d,%d %dx%d) dst(%d,%d %dx%d) \n",
1008                 img.x, img.y, img.width, img.height,
1009                 src.x, src.y, src.width, src.height,
1010                 dst.x, dst.y, dst.width, dst.height);
1011
1012         if (drawing == ON_PIXMAP || drawing == ON_WINDOW)
1013                 return _fbdevVideoPutImageOnDrawable (pScrnInfo, pPortPriv, &img, &src, &dst, clip_boxes,
1014                                                       scn_rotate, hw_rotate, image_info, buf, pDraw);
1015
1016         if (pPortPriv->need_streamon && pPortPriv->v4l2_handle)
1017         {
1018                 _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv);
1019                 pPortPriv->need_streamon = FALSE;
1020                 pPortPriv->v4l2_handle = NULL;
1021         }
1022
1023         if (!pPortPriv->v4l2_handle)
1024                 if (!_fbdevVideoSetMode (pScrnInfo, pPortPriv, &v4l2_index))
1025                         return BadRequest;
1026
1027         if (pPortPriv->mode != PORT_MODE_V4L2)
1028                 return Success;
1029
1030         return _fbdevVideoPutImageV4l2 (pScrnInfo, pPortPriv, &img, &src, &dst, clip_boxes,
1031                                         scn_rotate, rotate, hw_rotate,
1032                                         image_info, buf, modeBefore, v4l2_index, pDraw);
1033 }
1034
1035 /**
1036  * Set up all our internal structures.
1037  */
1038 static XF86VideoAdaptorPtr
1039 fbdevVideoSetupImageVideo (ScreenPtr pScreen)
1040 {
1041         DRVLOG ("%s (%s:%d)\n", __FUNCTION__, __FILE__, __LINE__);
1042
1043         XF86VideoAdaptorPtr pAdaptor;
1044         FBDevPortPrivPtr pPortPriv;
1045         XF86ImagePtr pImages;
1046         int i, count = 0;
1047
1048         pAdaptor = calloc (1, sizeof (XF86VideoAdaptorRec) +
1049                            (sizeof (DevUnion) + sizeof (FBDevPortPriv)) * FBDEV_MAX_PORT);
1050         if (pAdaptor == NULL)
1051                 return NULL;
1052
1053         DummyEncoding[0].width = pScreen->width;
1054         DummyEncoding[0].height = pScreen->height;
1055
1056         pAdaptor->type = XvWindowMask | XvPixmapMask | XvInputMask | XvImageMask;
1057         pAdaptor->flags = (VIDEO_CLIP_TO_VIEWPORT | VIDEO_OVERLAID_IMAGES);
1058         pAdaptor->name = "FBDEV supporting Software Video Conversions";
1059         pAdaptor->nEncodings = sizeof (DummyEncoding) / sizeof (XF86VideoEncodingRec);
1060         pAdaptor->pEncodings = DummyEncoding;
1061         pAdaptor->nFormats = NUM_FORMATS;
1062         pAdaptor->pFormats = Formats;
1063         pAdaptor->nPorts = FBDEV_MAX_PORT;
1064         pAdaptor->pPortPrivates = (DevUnion*)(&pAdaptor[1]);
1065
1066         pPortPriv =
1067             (FBDevPortPrivPtr) (&pAdaptor->pPortPrivates[FBDEV_MAX_PORT]);
1068
1069         for (i=0; i<FBDEV_MAX_PORT; i++)
1070         {
1071                 pAdaptor->pPortPrivates[i].ptr = &pPortPriv[i];
1072
1073                 pPortPriv[i].index = i;
1074                 pPortPriv[i].rotate = -1;
1075                 pPortPriv[i].v4l2_index = -1;
1076
1077                 REGION_INIT (pScreen, &pPortPriv[i].clipBoxes, NullBox, 0);
1078         }
1079
1080         pImages = fbdevVideoV4l2SupportImages (&count);
1081
1082         pAdaptor->nAttributes = NUM_ATTRIBUTES;
1083         pAdaptor->pAttributes = Attributes;
1084         pAdaptor->nImages = count;
1085         pAdaptor->pImages = pImages;
1086
1087         pAdaptor->PutImage             = FBDevVideoPutImage;
1088         pAdaptor->ReputImage           = FBDevVideoReputImage;
1089         pAdaptor->StopVideo            = FBDevVideoStop;
1090         pAdaptor->GetPortAttribute     = FBDevVideoGetPortAttribute;
1091         pAdaptor->SetPortAttribute     = FBDevVideoSetPortAttribute;
1092         pAdaptor->QueryBestSize        = FBDevVideoQueryBestSize;
1093         pAdaptor->QueryImageAttributes = FBDEVVideoQueryImageAttributes;
1094
1095         return pAdaptor;
1096 }
1097
1098 #ifdef XV
1099 /**
1100  * Set up everything we need for Xv.
1101  */
1102 Bool fbdevVideoInit (ScreenPtr pScreen)
1103 {
1104         DRVLOG ("%s (%s:%d)\n", __FUNCTION__, __FILE__, __LINE__);
1105
1106         ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
1107         FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate;
1108
1109         pFBDev->pAdaptor[0] = fbdevVideoSetupImageVideo (pScreen);
1110         if (!pFBDev->pAdaptor[0])
1111                 return FALSE;
1112
1113         pFBDev->pAdaptor[1] = fbdevVideoSetupVirtualVideo (pScreen);
1114         if (!pFBDev->pAdaptor[1])
1115         {
1116                 free (pFBDev->pAdaptor[0]);
1117                 return FALSE;
1118         }
1119
1120         xf86XVScreenInit (pScreen, pFBDev->pAdaptor, ADAPTOR_NUM);
1121
1122         pFBDev->v4l2_num   = fbdevVideoV4l2GetHandleNums ();
1123         pFBDev->v4l2_owner = (void**)calloc (sizeof (void*), pFBDev->v4l2_num);
1124
1125         if(registered_handler == FALSE)
1126         {
1127                 RegisterBlockAndWakeupHandlers(_fbdevVideoBlockHandler, (WakeupHandlerProcPtr)NoopDDA, pScrnInfo);
1128                 registered_handler = TRUE;
1129         }
1130
1131         if (AddCallback (&DPMSCallback, _fbdevVideoDPMSHandler, NULL) != TRUE)
1132         {
1133                 xf86DrvMsg (pScrnInfo->scrnIndex, X_ERROR, "Failed to register _fbdevVideoDPMSHandler. \n");
1134                 return FALSE;
1135         }
1136
1137         return TRUE;
1138 }
1139
1140 /**
1141  * Shut down Xv, used on regeneration.
1142  */
1143 void fbdevVideoFini (ScreenPtr pScreen)
1144 {
1145         DRVLOG ("%s (%s:%d)\n", __FUNCTION__, __FILE__, __LINE__);
1146
1147         ScrnInfoPtr pScrnInfo = xf86Screens[pScreen->myNum];
1148         FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate;
1149
1150         XF86VideoAdaptorPtr pAdaptor = pFBDev->pAdaptor[0];
1151         int i;
1152
1153         if (!pAdaptor)
1154                 return;
1155
1156         DeleteCallback (&DPMSCallback, _fbdevVideoDPMSHandler, NULL);
1157
1158         for (i = 0; i < FBDEV_MAX_PORT; i++)
1159         {
1160                 FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pAdaptor->pPortPrivates[i].ptr;
1161
1162                 REGION_UNINIT (pScreen, &pPortPriv->clipBoxes);
1163
1164                 _fbdevVideoCloseV4l2Handle (pScrnInfo, pPortPriv);
1165         }
1166
1167         free (pFBDev->pAdaptor[0]);
1168         pFBDev->pAdaptor[0] = NULL;
1169
1170         free (pFBDev->pAdaptor[1]);
1171         pFBDev->pAdaptor[1] = NULL;
1172
1173         if (pFBDev->v4l2_owner)
1174         {
1175                 free (pFBDev->v4l2_owner);
1176                 pFBDev->v4l2_owner = NULL;
1177                 pFBDev->v4l2_num = 0;
1178         }
1179 }
1180
1181 #endif
1182
1183 void
1184 fbdevVideoSetOffset (ScrnInfoPtr pScrnInfo, int x, int y)
1185 {
1186         FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate;
1187         int i;
1188         for (i = 0; i < pFBDev->v4l2_num; i++)
1189         {
1190                 FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pFBDev->v4l2_owner[i];
1191
1192                 if (pPortPriv)
1193                 {
1194                         if (!pPortPriv->v4l2_handle)
1195                                 continue;
1196
1197                         fbdevVideoV4l2VideoOffset (pPortPriv->v4l2_handle, x , y);
1198                 }
1199         }
1200 }
1201
1202 void
1203 fbdevVideoGetV4l2Handles (ScrnInfoPtr pScrnInfo, void ***handles, int *cnt)
1204 {
1205         FBDevPtr pFBDev = (FBDevPtr) pScrnInfo->driverPrivate;
1206         void **ret;
1207         int i, j;
1208
1209         *cnt = 0;
1210
1211         for (i = 0; i < pFBDev->v4l2_num; i++)
1212         {
1213                 FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pFBDev->v4l2_owner[i];
1214                 if (pPortPriv && pPortPriv->v4l2_handle)
1215                         (*cnt)++;
1216         }
1217
1218         if (*cnt == 0)
1219         {
1220                 *handles = NULL;
1221                 return;
1222         }
1223
1224         ret = (void**)calloc (*cnt, sizeof (void*));
1225         *handles = ret;
1226
1227         j = 0;
1228
1229         for (i = 0; i < pFBDev->v4l2_num; i++)
1230         {
1231                 FBDevPortPrivPtr pPortPriv = (FBDevPortPrivPtr) pFBDev->v4l2_owner[i];
1232                 if (pPortPriv && pPortPriv->v4l2_handle)
1233                 {
1234                         ret[j] = pPortPriv->v4l2_handle;
1235                         j++;
1236                 }
1237         }
1238 }