Merge branch 'devel/dri3' into devel/tizen
[platform/adaptation/samsung_exynos/xf86-video-exynos.git] / src / crtcconfig / sec_display.c
1 /*
2  * Copyright © 2007 Red Hat, Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *
23  * Authors:
24  *    Dave Airlie <airlied@redhat.com>
25  *
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include <stdint.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <fcntl.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <poll.h>
39 #include <dirent.h>
40
41 #include <X11/extensions/dpmsconst.h>
42 #include <xorgVersion.h>
43 #include <X11/Xatom.h>
44 #include <xf86Crtc.h>
45 #include <xf86DDC.h>
46 #include <xf86cmap.h>
47 #include <sec.h>
48
49 #include "sec_crtc.h"
50 #include "sec_output.h"
51 #include "sec_plane.h"
52 #include "sec_display.h"
53 #include "sec_video_fourcc.h"
54 #include "sec_wb.h"
55 #include "sec_converter.h"
56 #include "sec_util.h"
57 #include "sec_xberc.h"
58 #include <xf86RandR12.h>
59 #include "common.h"
60 #include "sec_dummy.h"
61
62 static Bool SECCrtcConfigResize(ScrnInfoPtr pScrn, int width, int height);
63 static void SECModeVblankHandler(int fd, unsigned int frame, unsigned int tv_sec,
64                                  unsigned int tv_usec, void *event);
65 static void SECModePageFlipHandler(int fd, unsigned int frame, unsigned int tv_sec,
66                                    unsigned int tv_usec, void *event_data);
67 static void SECModeG2dHandler(int fd, unsigned int cmdlist_no, unsigned int tv_sec,
68                               unsigned int tv_usec, void *event_data);
69 static void SECModeIppHandler(int fd, unsigned int prop_id, unsigned int *buf_idx, unsigned int tv_sec,
70                               unsigned int tv_usec, void *event_data);
71
72 static const xf86CrtcConfigFuncsRec sec_xf86crtc_config_funcs =
73 {
74     SECCrtcConfigResize
75 };
76
77 static void
78 _secDisplaySetDrmEventCtx(SECModePtr pSecMode)
79 {
80     pSecMode->event_context.vblank_handler = SECModeVblankHandler;
81     pSecMode->event_context.page_flip_handler = SECModePageFlipHandler;
82     pSecMode->event_context.g2d_handler = SECModeG2dHandler;
83     pSecMode->event_context.ipp_handler = SECModeIppHandler;
84 }
85
86 static int
87 _secSetMainMode (ScrnInfoPtr pScrn, SECModePtr pSecMode)
88 {
89     xf86CrtcConfigPtr pXf86CrtcConfig;
90     pXf86CrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
91     int i;
92
93     for (i = 0; i < pXf86CrtcConfig->num_output; i++)
94     {
95         xf86OutputPtr pOutput = pXf86CrtcConfig->output[i];
96         SECOutputPrivPtr pOutputPriv = pOutput->driver_private;
97         if (!pOutputPriv)
98             continue;
99         if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_LVDS ||
100             pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown)
101         {
102             memcpy (&pSecMode->main_lcd_mode, pOutputPriv->mode_output->modes, sizeof(drmModeModeInfo));
103             return 1;
104         }
105     }
106     if (pSecMode->main_lcd_mode.hdisplay == 0 ||
107         pSecMode->main_lcd_mode.vdisplay == 0)
108     {
109         pSecMode->main_lcd_mode.hdisplay = 640;
110         pSecMode->main_lcd_mode.vdisplay = 480;
111         return 1;
112     }
113     return -1;
114 }
115
116 static void
117 _secDisplayRemoveFlipPixmaps (ScrnInfoPtr pScrn)
118 {
119     xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
120     int c;
121
122     for (c = 0; c < pCrtcConfig->num_crtc; c++)
123     {
124         xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c];
125         int conn_type = secCrtcGetConnectType (pCrtc);
126         if (conn_type == DRM_MODE_CONNECTOR_Unknown)
127             secCrtcRemoveFlipPixmap (pCrtc);
128     }
129 }
130
131 static void
132 _saveFrameBuffer (ScrnInfoPtr pScrn, tbm_bo bo, int w, int h)
133 {
134     SECPtr pSec = SECPTR(pScrn);
135     char file[128];
136     SECFbBoDataPtr bo_data;
137
138     if (!pSec->dump_info)
139         return;
140
141     tbm_bo_get_user_data (bo, TBM_BO_DATA_FB, (void * *)&bo_data);
142     XDBG_RETURN_IF_FAIL(bo_data != NULL);
143
144     snprintf (file, sizeof(file), "%03d_fb_%d.bmp", pSec->flip_cnt, bo_data->fb_id);
145     secUtilDoDumpBmps (pSec->dump_info, bo, w, h, NULL, file);
146     pSec->flip_cnt++;
147 }
148
149 static int
150 secHandleEvent (int fd, secDrmEventContextPtr evctx)
151 {
152 #define MAX_BUF_SIZE    1024
153
154     char buffer[MAX_BUF_SIZE];
155     unsigned int len, i;
156     struct drm_event *e;
157
158     /* The DRM read semantics guarantees that we always get only
159      * complete events. */
160     len = read (fd, buffer, sizeof buffer);
161     if (len == 0)
162     {
163         XDBG_WARNING (MDISP, "warning: the size of the drm_event is 0.\n");
164         return 0;
165     }
166     if (len < sizeof *e)
167     {
168         XDBG_WARNING (MDISP, "warning: the size of the drm_event is less than drm_event structure.\n");
169         return -1;
170     }
171     if (len > MAX_BUF_SIZE - sizeof (struct drm_exynos_ipp_event))
172     {
173         XDBG_WARNING (MDISP, "warning: the size of the drm_event can be over the maximum size.\n");
174         return -1;
175     }
176
177     i = 0;
178     while (i < len)
179     {
180         e = (struct drm_event *) &buffer[i];
181         switch (e->type)
182         {
183             case DRM_EVENT_VBLANK:
184                 {
185                     struct drm_event_vblank *vblank;
186
187                     if (evctx->vblank_handler == NULL)
188                         break;
189
190                     vblank = (struct drm_event_vblank *) e;
191                     evctx->vblank_handler (fd,
192                             vblank->sequence,
193                             vblank->tv_sec,
194                             vblank->tv_usec,
195                             (void *)((unsigned long)vblank->user_data));
196                 }
197                 break;
198             case DRM_EVENT_FLIP_COMPLETE:
199                 {
200                     struct drm_event_vblank *vblank;
201
202                     if (evctx->page_flip_handler == NULL)
203                         break;
204
205                     vblank = (struct drm_event_vblank *) e;
206                     evctx->page_flip_handler (fd,
207                             vblank->sequence,
208                             vblank->tv_sec,
209                             vblank->tv_usec,
210                             (void *)((unsigned long)vblank->user_data));
211                 }
212                 break;
213             case DRM_EXYNOS_G2D_EVENT:
214                 {
215                     struct drm_exynos_g2d_event *g2d;
216
217                     if (evctx->g2d_handler == NULL)
218                         break;
219
220                     g2d = (struct drm_exynos_g2d_event *) e;
221                     evctx->g2d_handler (fd,
222                             g2d->cmdlist_no,
223                             g2d->tv_sec,
224                             g2d->tv_usec,
225                             (void *)((unsigned long)g2d->user_data));
226                 }
227                 break;
228             case DRM_EXYNOS_IPP_EVENT:
229                 {
230                     struct drm_exynos_ipp_event *ipp;
231
232                     if (evctx->ipp_handler == NULL)
233                         break;
234
235                     ipp = (struct drm_exynos_ipp_event *) e;
236                     evctx->ipp_handler (fd,
237                             ipp->prop_id,
238                             ipp->buf_id,
239                             ipp->tv_sec,
240                             ipp->tv_usec,
241                             (void *)((unsigned long)ipp->user_data));
242                 }
243                 break;
244             default:
245                 break;
246         }
247         i += e->length;
248     }
249
250     return 0;
251 }
252
253 static Bool
254 SECCrtcConfigResize(ScrnInfoPtr pScrn, int width, int height)
255 {
256     ScreenPtr pScreen = pScrn->pScreen;
257     SECPtr pSec = SECPTR (pScrn);
258
259     XDBG_DEBUG(MDISP, "Resize cur(%dx%d) new(%d,%d)\n",
260                pScrn->virtualX,
261                pScrn->virtualY,
262                width, height);
263 #ifdef NO_CRTC_MODE
264     pSec->isCrtcOn = secCrtcCheckInUseAll(pScrn);
265 #endif
266     if (pScrn->virtualX == width &&
267         pScrn->virtualY == height)
268     {
269         return TRUE;
270     }
271     secFbResize(pSec->pFb, width, height);
272
273     /* set  the new size of pScrn */
274     pScrn->virtualX = width;
275     pScrn->virtualY = height;
276     pScrn->displayWidth = width;
277     secExaScreenSetScrnPixmap (pScreen);
278
279     secOutputDrmUpdate (pScrn);
280
281     _secDisplayRemoveFlipPixmaps (pScrn);
282
283     return TRUE;
284 }
285
286 static void
287 SECModeVblankHandler(int fd, unsigned int frame, unsigned int tv_sec,
288                      unsigned int tv_usec, void *event)
289 {
290     SECVBlankInfoPtr pVblankInfo = event;
291     SECVBlankInfoType vblank_type;
292     void *data;
293
294     XDBG_RETURN_IF_FAIL (pVblankInfo != NULL);
295
296     vblank_type = pVblankInfo->type;
297     data = pVblankInfo->data;
298
299 #if DBG_DRM_EVENT
300     xDbgLogDrmEventRemoveVblank (pVblankInfo->xdbg_log_vblank);
301 #endif
302
303     if (vblank_type == VBLANK_INFO_SWAP)
304     {
305         XDBG_TRACE (MDISP, "vblank handler (%p, %ld, %ld)\n",
306                     pVblankInfo, pVblankInfo->time, GetTimeInMillis () - pVblankInfo->time);
307         secDri2FrameEventHandler (frame, tv_sec, tv_usec, data);
308     }
309     else if (vblank_type == VBLANK_INFO_PLANE)
310         secLayerVBlankEventHandler (frame, tv_sec, tv_usec, data);
311     else if (vblank_type == VBLANK_INFO_PRESENT)
312     {
313         XDBG_TRACE (MDISP, "vblank handler (%p, %ld, %ld)\n",
314                     pVblankInfo, pVblankInfo->time, GetTimeInMillis () - pVblankInfo->time);
315         secPresentVblankHandler(frame, tv_sec, tv_usec, data);
316     }
317     else
318         XDBG_ERROR (MDISP, "unknown the vblank type\n");
319
320     free (pVblankInfo);
321     pVblankInfo = NULL;
322 }
323
324 static void
325 SECModePageFlipHandler(int fd, unsigned int frame, unsigned int tv_sec,
326                        unsigned int tv_usec, void *event_data)
327 {
328     SECPageFlipPtr flip = event_data;
329     xf86CrtcPtr pCrtc;
330     SECCrtcPrivPtr pCrtcPriv;
331
332     if (!flip)
333     {
334         XDBG_ERROR (MDISP, "flip is null\n");
335         return;
336     }
337
338     XDBG_TRACE (MDISP, "pageflip handler (%p, %ld, %ld)\n",
339                 flip, flip->time, GetTimeInMillis () - flip->time);
340
341    #if DBG_DRM_EVENT
342     if( flip->xdbg_log_pageflip != NULL )
343         xDbgLogDrmEventRemovePageflip (flip->xdbg_log_pageflip);
344    #endif
345
346     pCrtc = flip->pCrtc;
347     pCrtcPriv = pCrtc->driver_private;
348     pCrtcPriv->is_flipping = FALSE;
349     pCrtcPriv->is_fb_blit_flipping = FALSE;
350     pCrtcPriv->flip_count--; /* check flipping completed */
351
352     /* Is this the event whose info shall be delivered to higher level? */
353     /* Yes: Cache msc, ust for later delivery. */
354     pCrtcPriv->fe_frame = frame;
355     pCrtcPriv->fe_tv_sec = tv_sec;
356     pCrtcPriv->fe_tv_usec = tv_usec;
357
358     if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0)
359         if (pCrtcPriv->accessibility_front_bo && pCrtcPriv->accessibility_back_bo)
360         {
361             tbm_bo temp;
362             temp = pCrtcPriv->accessibility_front_bo;
363             pCrtcPriv->accessibility_front_bo = pCrtcPriv->accessibility_back_bo;
364             pCrtcPriv->accessibility_back_bo = temp;
365         }
366
367     /* accessibility */
368     if (flip->accessibility_back_bo)
369     {
370         secRenderBoUnref(flip->accessibility_back_bo);
371         flip->accessibility_back_bo = NULL;
372     }
373
374     /* if accessibility is diabled, remove the accessibility_bo
375        when the pageflip is occurred once after the accessibility is disabled */
376     if (!pCrtcPriv->bAccessibility && pCrtcPriv->screen_rotate_degree == 0)
377     {
378         if (pCrtcPriv->accessibility_front_bo)
379         {
380             secRenderBoUnref (pCrtcPriv->accessibility_front_bo);
381             pCrtcPriv->accessibility_front_bo = NULL;
382         }
383         if (pCrtcPriv->accessibility_back_bo)
384         {
385             secRenderBoUnref (pCrtcPriv->accessibility_back_bo);
386             pCrtcPriv->accessibility_back_bo = NULL;
387         }
388     }
389
390     /* Release back framebuffer */
391     if (flip->back_bo)
392     {
393         secRenderBoUnref(flip->back_bo);
394         flip->back_bo = NULL;
395     }
396
397     if (pCrtcPriv->flip_info == NULL)
398     {
399         /**
400         *  If pCrtcPriv->flip_info is failed and secCrtcGetFirstPendingFlip (pCrtc) has data,
401         *  ModePageFlipHandler is triggered by secDisplayUpdateRequest(). - Maybe FB_BLIT or FB is updated by CPU.
402         *  In this case we should call _secDri2ProcessPending().
403         */
404         DRI2FrameEventPtr pending_flip;
405         pending_flip = secCrtcGetFirstPendingFlip (pCrtc);
406         if( pending_flip != NULL )
407         {
408             XDBG_DEBUG (MDISP, "FB_BLIT or FB is updated by CPU. But there's secCrtcGetFirstPendingFlip(). So trigger it manually\n");
409             flip->dispatch_me = TRUE;
410             pCrtcPriv->flip_info = pending_flip;
411         }
412         else
413             goto fail;
414     }
415
416     XDBG_DEBUG(MDISP, "ModePageFlipHandler ctrc_id:%d dispatch_me:%d, frame:%d, flip_count=%d is_pending=%p\n",
417                secCrtcID(pCrtcPriv), flip->dispatch_me, frame, pCrtcPriv->flip_count, secCrtcGetFirstPendingFlip (pCrtc));
418
419     /* Last crtc completed flip? */
420     if (flip->dispatch_me)
421     {
422         secCrtcCountFps(pCrtc);
423
424         /* Deliver cached msc, ust from reference crtc to flip event handler */
425         if (flip->handler)
426                 flip->handler(pCrtcPriv->fe_frame, pCrtcPriv->fe_tv_sec,
427                           pCrtcPriv->fe_tv_usec, pCrtcPriv->flip_info, flip->flip_failed);
428     }
429
430     free (flip);
431     return;
432 fail:
433     if (flip->accessibility_back_bo)
434     {
435         secRenderBoUnref(flip->accessibility_back_bo);
436         flip->accessibility_back_bo = NULL;
437     }
438
439     if (flip->back_bo)
440     {
441         secRenderBoUnref(flip->back_bo);
442         flip->back_bo = NULL;
443     }
444
445     free (flip);
446 }
447
448 static void
449 SECModeG2dHandler(int fd, unsigned int cmdlist_no, unsigned int tv_sec,
450                   unsigned int tv_usec, void *event_data)
451 {
452 }
453
454 static void
455 SECModeIppHandler(int fd, unsigned int prop_id, unsigned int *buf_idx,
456                   unsigned int tv_sec, unsigned int tv_usec, void *event_data)
457 {
458     XDBG_DEBUG (MDRM, "wb_prop_id(%d) prop_id(%d), buf_idx(%d, %d) \n",
459                 secWbGetPropID(), prop_id, buf_idx[0], buf_idx[1]);
460
461     if (secWbGetPropID () == prop_id)
462         secWbHandleIppEvent (fd, buf_idx, event_data);
463     else
464         secCvtHandleIppEvent (fd, buf_idx, event_data, FALSE);
465 }
466
467 static void
468 SECModeWakeupHanlder(pointer data, int err, pointer p)
469 {
470     SECModePtr pSecMode;
471     fd_set *read_mask;
472
473     if (data == NULL || err < 0)
474         return;
475
476     pSecMode = data;
477     read_mask = p;
478     if (FD_ISSET (pSecMode->fd, read_mask))
479         secHandleEvent (pSecMode->fd, &pSecMode->event_context);
480 }
481
482 Bool
483 secModePreInit (ScrnInfoPtr pScrn, int drm_fd)
484 {
485     SECPtr pSec = SECPTR (pScrn);
486     SECModePtr pSecMode;
487     unsigned int i;
488     int cpp;
489
490 //    secLogSetLevel(MDISP, 0);
491
492     pSecMode = calloc (1, sizeof *pSecMode);
493     if (!pSecMode)
494         return FALSE;
495
496     pSecMode->fd = drm_fd;
497     xorg_list_init (&pSecMode->crtcs);
498     xorg_list_init (&pSecMode->outputs);
499     xorg_list_init (&pSecMode->planes);
500
501     xf86CrtcConfigInit (pScrn, &sec_xf86crtc_config_funcs);
502
503     cpp = pScrn->bitsPerPixel /8;
504
505     pSecMode->cpp = cpp;
506     pSecMode->mode_res = drmModeGetResources (pSecMode->fd);
507     if (!pSecMode->mode_res)
508     {
509         xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
510                     "failed to get resources: %s\n", strerror (errno));
511         free (pSecMode);
512         return FALSE;
513     }
514
515     pSecMode->plane_res = drmModeGetPlaneResources (pSecMode->fd);
516     if (!pSecMode->plane_res)
517     {
518         xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
519                     "failed to get plane resources: %s\n", strerror (errno));
520         drmModeFreeResources (pSecMode->mode_res);
521         free (pSecMode);
522         return FALSE;
523     }
524
525     xf86CrtcSetSizeRange (pScrn, 320, 200, pSecMode->mode_res->max_width,
526                           pSecMode->mode_res->max_height);
527 #if 1
528     for (i = 0; i < pSecMode->mode_res->count_crtcs; i++)
529         secCrtcInit (pScrn, pSecMode, i);
530
531     for (i = 0; i < pSecMode->mode_res->count_connectors; i++)
532         secOutputInit (pScrn, pSecMode, i);
533 #endif
534     for (i = 0; i < pSecMode->plane_res->count_planes; i++)
535         secPlaneInit (pScrn, pSecMode, i);
536 #if 0
537     secDummyOutputInit(pScrn, pSecMode, FALSE);
538 #endif //NO_CRTC_MODE
539     _secSetMainMode (pScrn, pSecMode);
540
541     /* virtaul x and virtual y of the screen is ones from main lcd mode */
542     pScrn->virtualX = pSecMode->main_lcd_mode.hdisplay;
543     pScrn->virtualY = pSecMode->main_lcd_mode.vdisplay;
544     xf86InitialConfiguration (pScrn, TRUE);
545
546     /* soolim::
547      * we assume that kernel always support the pageflipping
548      * and the drm vblank
549      */
550     /* set the drm event context */
551     _secDisplaySetDrmEventCtx(pSecMode);
552
553     pSec->pSecMode = pSecMode;
554
555     /* virtaul x and virtual y of the screen is ones from main lcd mode */
556     pScrn->virtualX = pSecMode->main_lcd_mode.hdisplay;
557     pScrn->virtualY = pSecMode->main_lcd_mode.vdisplay;
558
559 #if DBG_DRM_EVENT
560     xDbgLogDrmEventInit();
561 #endif
562
563     return TRUE;
564 }
565
566 void
567 secModeInit (ScrnInfoPtr pScrn)
568 {
569     SECPtr pSec = SECPTR (pScrn);
570     SECModePtr pSecMode = pSec->pSecMode;
571
572     /* We need to re-register the mode->fd for the synchronisation
573      * feedback on every server generation, so perform the
574      * registration within ScreenInit and not PreInit.
575      */
576     //pSecMode->flip_count = 0;
577     AddGeneralSocket(pSecMode->fd);
578     RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
579                                    SECModeWakeupHanlder, pSecMode);
580
581 }
582
583 void
584 secModeDeinit (ScrnInfoPtr pScrn)
585 {
586     SECPtr pSec = SECPTR (pScrn);
587     SECModePtr pSecMode = (SECModePtr) pSec->pSecMode;
588     xf86CrtcPtr pCrtc = NULL;
589     xf86OutputPtr pOutput = NULL;
590
591     secDisplayDeinitDispMode (pScrn);
592
593     SECCrtcPrivPtr crtc_ref=NULL, crtc_next=NULL;
594     xorg_list_for_each_entry_safe (crtc_ref, crtc_next, &pSecMode->crtcs, link)
595     {
596         pCrtc = crtc_ref->pCrtc;
597         xf86CrtcDestroy (pCrtc);
598     }
599
600     SECOutputPrivPtr output_ref, output_next;
601     xorg_list_for_each_entry_safe (output_ref, output_next, &pSecMode->outputs, link)
602     {
603         pOutput = output_ref->pOutput;
604         xf86OutputDestroy (pOutput);
605     }
606
607     SECPlanePrivPtr plane_ref, plane_next;
608     xorg_list_for_each_entry_safe (plane_ref, plane_next, &pSecMode->planes, link)
609     {
610         secPlaneDeinit (pScrn, plane_ref);
611     }
612
613     if (pSecMode->mode_res)
614         drmModeFreeResources (pSecMode->mode_res);
615
616     if (pSecMode->plane_res)
617         drmModeFreePlaneResources (pSecMode->plane_res);
618
619     /* mode->rotate_fb_id should have been destroyed already */
620
621 #ifdef NO_CRTC_MODE
622     if (pSecMode->num_dummy_output > 0)
623     {
624         xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
625         int i;
626         for (i = 0; i < xf86_config->num_crtc; i++)
627         {
628             xf86CrtcPtr pCrtc = xf86_config->crtc[i];
629             xf86CrtcDestroy (pCrtc);
630         }
631
632         for (i = 0; i < xf86_config->num_output; i++)
633         {
634             xf86OutputPtr pOutput = xf86_config->output[i];
635             xf86OutputDestroy(pOutput);
636         }
637     }
638 #endif //NO_CRTC_MODE
639
640     free (pSecMode);
641     pSec->pSecMode = NULL;
642 }
643
644 /*
645   * Return the crtc covering 'box'. If two crtcs cover a portion of
646   * 'box', then prefer 'desired'. If 'desired' is NULL, then prefer the crtc
647   * with greater coverage
648   */
649 xf86CrtcPtr
650 secModeCoveringCrtc (ScrnInfoPtr pScrn, BoxPtr pBox, xf86CrtcPtr pDesiredCrtc, BoxPtr pBoxCrtc)
651 {
652     xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
653     xf86CrtcPtr pCrtc, pBestCrtc;
654     int coverage, best_coverage;
655     int c;
656     BoxRec crtc_box, cover_box;
657
658     XDBG_RETURN_VAL_IF_FAIL (pBox != NULL, NULL);
659
660     pBestCrtc = NULL;
661     best_coverage = 0;
662
663     if (pBoxCrtc)
664     {
665         pBoxCrtc->x1 = 0;
666         pBoxCrtc->y1 = 0;
667         pBoxCrtc->x2 = 0;
668         pBoxCrtc->y2 = 0;
669     }
670
671     for (c = 0; c < pCrtcConfig->num_crtc; c++)
672     {
673         pCrtc = pCrtcConfig->crtc[c];
674
675         /* If the CRTC is off, treat it as not covering */
676         if(!secCrtcOn(pCrtc))
677             continue;
678
679         crtc_box.x1 = pCrtc->x;
680         crtc_box.x2 = pCrtc->x + xf86ModeWidth (&pCrtc->mode, pCrtc->rotation);
681         crtc_box.y1 = pCrtc->y;
682         crtc_box.y2 = pCrtc->y + xf86ModeHeight (&pCrtc->mode, pCrtc->rotation);
683
684         secUtilBoxIntersect(&cover_box, &crtc_box, pBox);
685         coverage = secUtilBoxArea(&cover_box);
686
687         if (coverage && pCrtc == pDesiredCrtc)
688         {
689             if (pBoxCrtc)
690                 *pBoxCrtc = crtc_box;
691             return pCrtc;
692         }
693
694         if (coverage > best_coverage)
695         {
696             if (pBoxCrtc)
697                 *pBoxCrtc = crtc_box;
698             pBestCrtc = pCrtc;
699             best_coverage = coverage;
700         }
701     }
702
703     return pBestCrtc;
704 }
705
706 int secModeGetCrtcPipe (xf86CrtcPtr pCrtc)
707 {
708     SECCrtcPrivPtr pCrtcPriv = pCrtc->driver_private;
709     if (pCrtcPriv == NULL)
710         return -1;
711     return pCrtcPriv->pipe;
712 }
713
714 Bool
715 secModePageFlip (ScrnInfoPtr pScrn, xf86CrtcPtr pCrtc, void* flip_info, int pipe, tbm_bo back_bo,
716                                  RegionPtr pFlipRegion, unsigned int client_idx, XID drawable_id,
717                                  SECFlipEventHandler handler)
718 {
719     SECPageFlipPtr pPageFlip = NULL;
720     SECFbBoDataPtr bo_data;
721     SECCrtcPrivPtr pCrtcPriv;
722     SECModePtr pSecMode;
723     xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
724     xf86CrtcPtr pCurCrtc;
725     SECPtr pSec = SECPTR(pScrn);
726     int ret;
727     int fb_id = 0;
728
729     BoxRec b1;
730     int retBox, found=0;
731     int i;
732
733     tbm_bo_get_user_data (back_bo, TBM_BO_DATA_FB, (void * *)&bo_data);
734     XDBG_RETURN_VAL_IF_FAIL(bo_data != NULL, FALSE);
735
736     for (i = 0; i < pCrtcConfig->num_crtc; i++)
737     {
738         pCurCrtc = pCrtcConfig->crtc[i];
739         if (!pCurCrtc->enabled)
740             continue;
741         pCrtcPriv =  pCurCrtc->driver_private;
742         pSecMode =  pCrtcPriv->pSecMode;
743
744         b1.x1 = pCurCrtc->x;
745         b1.y1 = pCurCrtc->y;
746         b1.x2 = pCurCrtc->x + pCurCrtc->mode.HDisplay;
747         b1.y2 = pCurCrtc->y + pCurCrtc->mode.VDisplay;
748
749         retBox = secUtilBoxInBox(&bo_data->pos, &b1);
750         if(retBox == rgnSAME || retBox == rgnIN)
751         {
752             pPageFlip = calloc (1, sizeof (SECPageFlipRec));
753             if (pPageFlip == NULL)
754             {
755                 xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "Page flip alloc failed\n");
756                 return FALSE;
757             }
758
759             /* Only the reference crtc will finally deliver its page flip
760              * completion event. All other crtc's events will be discarded.
761              */
762             pPageFlip->dispatch_me = 0;
763             pPageFlip->pCrtc = pCurCrtc;
764             pPageFlip->clone = TRUE;
765             pPageFlip->back_bo = secRenderBoRef (back_bo);
766             pPageFlip->data = flip_info;
767             pPageFlip->flip_failed = FALSE;
768             pPageFlip->handler = handler;
769
770             /* accessilitity */
771             if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0)
772             {
773                 tbm_bo accessibility_bo = pCrtcPriv->accessibility_back_bo;
774                 SECFbBoDataPtr accessibility_bo_data;
775
776                 tbm_bo_get_user_data (accessibility_bo, TBM_BO_DATA_FB, (void * *)&accessibility_bo_data);
777                 XDBG_GOTO_IF_FAIL (accessibility_bo_data != NULL, fail);
778
779                 fb_id = accessibility_bo_data->fb_id;
780
781                 /*Buffer is already changed by bo_swap*/
782                 if (!secCrtcExecAccessibility (pCurCrtc, back_bo, accessibility_bo))
783                     goto fail;
784
785                 pPageFlip->accessibility_back_bo = secRenderBoRef(accessibility_bo);
786             }
787             else
788             {
789                 fb_id = bo_data->fb_id;
790
791                 tbm_bo_map(pPageFlip->back_bo, TBM_DEVICE_2D, TBM_OPTION_READ);
792                 tbm_bo_unmap(pPageFlip->back_bo);
793             }
794
795             pCrtcPriv->is_flipping = TRUE;
796
797             if (!pCrtcPriv->onoff && !pCrtcPriv->onoff_always)
798                 secCrtcTurn (pCrtcPriv->pCrtc, TRUE, FALSE, FALSE);
799
800 #if DBG_DRM_EVENT
801             pPageFlip->xdbg_log_pageflip = xDbgLogDrmEventAddPageflip (pipe, client_idx, drawable_id);
802 #endif
803
804             XDBG_DEBUG (MSEC, "dump_mode(%x)\n", pSec->dump_mode);
805
806             if (pSec->dump_mode & XBERC_DUMP_MODE_FB)
807                 _saveFrameBuffer (pScrn, back_bo,
808                                   bo_data->pos.x2 - bo_data->pos.x1,
809                                   bo_data->pos.y2 - bo_data->pos.y1);
810
811             pPageFlip->time = GetTimeInMillis ();
812
813             /*Set DirtyFB*/
814             if(pSec->use_partial_update && pFlipRegion)
815             {
816                 int nBox;
817                 BoxPtr pBox;
818                 RegionRec new_region;
819                 RegionPtr pRegion = pFlipRegion;
820
821                 for (nBox = RegionNumRects(pRegion),
822                      pBox = RegionRects(pRegion); nBox--; pBox++)
823                 {
824                     XDBG_DEBUG (MDISP, "dirtfb region(%d): (%d,%d %dx%d)\n", nBox,
825                                 pBox->x1, pBox->y1, pBox->x2-pBox->x1, pBox->y2-pBox->y1);
826                 }
827
828                 if (pCrtcPriv->screen_rotate_degree > 0)
829                 {
830                     RegionCopy (&new_region, pFlipRegion);
831                     secUtilRotateRegion (pCrtc->mode.HDisplay, pCrtc->mode.VDisplay,
832                                          &new_region, pCrtcPriv->screen_rotate_degree);
833                     pRegion = &new_region;
834
835                     for (nBox = RegionNumRects(pRegion),
836                          pBox = RegionRects(pRegion); nBox--; pBox++)
837                     {
838                         XDBG_DEBUG (MDISP, "(R)dirtfb region(%d): (%d,%d %dx%d)\n", nBox,
839                                     pBox->x1, pBox->y1, pBox->x2-pBox->x1, pBox->y2-pBox->y1);
840                     }
841                 }
842
843                 drmModeDirtyFB (pSec->drm_fd, fb_id,
844                                 (drmModeClipPtr)RegionRects (pRegion),
845                                 (uint32_t)RegionNumRects (pRegion));
846             }
847
848
849             /* DRM Page Flip */
850             ret  = drmModePageFlip (pSec->drm_fd, secCrtcID(pCrtcPriv), fb_id,
851                     DRM_MODE_PAGE_FLIP_EVENT, pPageFlip);
852             if (ret)
853             {
854                 xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", strerror (errno));
855                 goto fail;
856             }
857
858             XDBG_TRACE (MDISP, "pageflip do (%p, %ld)\n", pPageFlip, pPageFlip->time);
859
860             pCrtcPriv->flip_count++; /* check flipping completed */
861             pCrtcPriv->flip_info = (DRI2FrameEventPtr)flip_info;
862
863             found++;
864             XDBG_DEBUG(MDISP, "ModePageFlip crtc_id:%d, fb_id:%d, back_fb_id:%d, back_name:%d, accessibility:%d\n",
865                        secCrtcID(pCrtcPriv), fb_id, bo_data->fb_id,
866                        tbm_bo_export (back_bo), pCrtcPriv->bAccessibility);
867         }
868     }
869
870     if(found==0)
871     {
872         XDBG_WARNING(MDISP, "Cannot find CRTC in (%d,%d)-(%d,%d)\n",
873                      bo_data->pos.x1, bo_data->pos.y1, bo_data->pos.x2, bo_data->pos.y2);
874         return FALSE;
875     }
876
877     /* Set dispatch_me to last pageflip */
878     pPageFlip->dispatch_me = 1;
879
880     return TRUE;
881
882 fail:
883     pCrtcPriv->flip_count++; /* check flipping completed */
884     pCrtcPriv->flip_info = (DRI2FrameEventPtr)flip_info;
885     pPageFlip->dispatch_me = 1;
886     pPageFlip->flip_failed = TRUE;
887
888     SECModePageFlipHandler(pSecMode->fd, 0, 0, 0, pPageFlip);
889
890     XDBG_ERROR(MDISP, "drmModePageFlip error(crtc:%d, fb_id:%d, back_fb_id:%d, back_name:%d, accessibility:%d)\n",
891                secCrtcID(pCrtcPriv), fb_id, bo_data->fb_id, tbm_bo_export (back_bo), pCrtcPriv->bAccessibility);
892
893     return FALSE;
894 }
895
896 /* load palette per a crtc */
897 void
898 secModeLoadPalette (ScrnInfoPtr pScrn, int numColors, int* indices,
899                     LOCO* colors, VisualPtr pVisual)
900 {
901     xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
902     int i, j, index;
903     int p;
904     uint16_t lut_r[256], lut_g[256], lut_b[256];
905
906     for (p = 0; p < pCrtcConfig->num_crtc; p++)
907     {
908         xf86CrtcPtr pCrtc = pCrtcConfig->crtc[p];
909
910         switch (pScrn->depth)
911         {
912         case 16:
913             for (i = 0; i < numColors; i++)
914             {
915                 index = indices[i];
916                 if (index <= 31)
917                 {
918                     for (j = 0; j < 8; j++)
919                     {
920                         lut_r[index * 8 + j] = colors[index].red << 8;
921                         lut_b[index * 8 + j] = colors[index].blue << 8;
922                     }
923                 }
924                 for (j = 0; j < 4; j++)
925                 {
926                     lut_g[index * 4 + j] = colors[index].green << 8;
927                 }
928             }
929             break;
930         default:
931             for (i = 0; i < numColors; i++)
932             {
933                 index = indices[i];
934                 lut_r[index] = colors[index].red << 8;
935                 lut_g[index] = colors[index].green << 8;
936                 lut_b[index] = colors[index].blue << 8;
937
938             }
939             break;
940         }
941
942         /* make the change through RandR */
943         RRCrtcGammaSet (pCrtc->randr_crtc, lut_r, lut_g, lut_b);
944     }
945 }
946
947 void
948 secDisplaySwapModeFromKmode(ScrnInfoPtr pScrn,
949                             drmModeModeInfoPtr kmode,
950                             DisplayModePtr      pMode)
951 {
952     char fake_name[32] = "fake_mode";
953
954     memset (pMode, 0, sizeof (DisplayModeRec));
955     pMode->status = MODE_OK;
956
957     pMode->Clock = kmode->clock;
958
959     pMode->HDisplay = kmode->vdisplay;
960     pMode->HSyncStart = kmode->vsync_start;
961     pMode->HSyncEnd = kmode->vsync_end;
962     pMode->HTotal = kmode->vtotal;
963     pMode->HSkew = kmode->vscan;
964
965     pMode->VDisplay = kmode->hdisplay;
966     pMode->VSyncStart = kmode->hsync_start;
967     pMode->VSyncEnd = kmode->hsync_end;
968     pMode->VTotal = kmode->htotal;
969     pMode->VScan = kmode->hskew;
970
971     pMode->Flags = kmode->flags; //& FLAG_BITS;
972     pMode->name = strdup (fake_name);
973
974     if (kmode->type & DRM_MODE_TYPE_DRIVER)
975         pMode->type = M_T_DRIVER;
976     if (kmode->type & DRM_MODE_TYPE_PREFERRED)
977         pMode->type |= M_T_PREFERRED;
978
979     xf86SetModeCrtc (pMode, pScrn->adjustFlags);
980 }
981
982
983
984
985 void
986 secDisplayModeFromKmode(ScrnInfoPtr pScrn,
987                         drmModeModeInfoPtr kmode,
988                         DisplayModePtr  pMode)
989 {
990     memset (pMode, 0, sizeof (DisplayModeRec));
991     pMode->status = MODE_OK;
992
993     pMode->Clock = kmode->clock;
994
995     pMode->HDisplay = kmode->hdisplay;
996     pMode->HSyncStart = kmode->hsync_start;
997     pMode->HSyncEnd = kmode->hsync_end;
998     pMode->HTotal = kmode->htotal;
999     pMode->HSkew = kmode->hskew;
1000
1001     pMode->VDisplay = kmode->vdisplay;
1002     pMode->VSyncStart = kmode->vsync_start;
1003     pMode->VSyncEnd = kmode->vsync_end;
1004     pMode->VTotal = kmode->vtotal;
1005     pMode->VScan = kmode->vscan;
1006
1007     pMode->Flags = kmode->flags; //& FLAG_BITS;
1008     pMode->name = strdup (kmode->name);
1009     pMode->VRefresh = kmode->vrefresh;
1010
1011     if (kmode->type & DRM_MODE_TYPE_DRIVER)
1012         pMode->type = M_T_DRIVER;
1013     if (kmode->type & DRM_MODE_TYPE_PREFERRED)
1014         pMode->type |= M_T_PREFERRED;
1015
1016     xf86SetModeCrtc (pMode, pScrn->adjustFlags);
1017 }
1018
1019
1020 void
1021 secDisplaySwapModeToKmode(ScrnInfoPtr pScrn,
1022                           drmModeModeInfoPtr kmode,
1023                           DisplayModePtr pMode)
1024 {
1025     memset (kmode, 0, sizeof (*kmode));
1026
1027     kmode->clock = pMode->Clock;
1028     kmode->hdisplay = pMode->VDisplay;
1029     kmode->hsync_start = pMode->VSyncStart;
1030     kmode->hsync_end = pMode->VSyncEnd;
1031     kmode->htotal = pMode->VTotal;
1032     kmode->hskew = pMode->VScan;
1033
1034     kmode->vdisplay = pMode->HDisplay;
1035     kmode->vsync_start = pMode->HSyncStart;
1036     kmode->vsync_end = pMode->HSyncEnd;
1037     kmode->vtotal = pMode->HTotal;
1038     kmode->vscan = pMode->HSkew;
1039     kmode->vrefresh = xf86ModeVRefresh (pMode);
1040
1041     kmode->flags = pMode->Flags; //& FLAG_BITS;
1042     if (pMode->name)
1043         strncpy (kmode->name, pMode->name, DRM_DISPLAY_MODE_LEN);
1044     kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1045 }
1046
1047
1048 void
1049 secDisplayModeToKmode(ScrnInfoPtr pScrn,
1050                       drmModeModeInfoPtr kmode,
1051                       DisplayModePtr pMode)
1052 {
1053     memset (kmode, 0, sizeof (*kmode));
1054
1055     kmode->clock = pMode->Clock;
1056     kmode->hdisplay = pMode->HDisplay;
1057     kmode->hsync_start = pMode->HSyncStart;
1058     kmode->hsync_end = pMode->HSyncEnd;
1059     kmode->htotal = pMode->HTotal;
1060     kmode->hskew = pMode->HSkew;
1061
1062     kmode->vdisplay = pMode->VDisplay;
1063     kmode->vsync_start = pMode->VSyncStart;
1064     kmode->vsync_end = pMode->VSyncEnd;
1065     kmode->vtotal = pMode->VTotal;
1066     kmode->vscan = pMode->VScan;
1067     kmode->vrefresh = xf86ModeVRefresh (pMode);
1068
1069     kmode->flags = pMode->Flags; //& FLAG_BITS;
1070     if (pMode->name)
1071         strncpy (kmode->name, pMode->name, DRM_DISPLAY_MODE_LEN);
1072
1073     kmode->name[DRM_DISPLAY_MODE_LEN-1] = 0;
1074 }
1075
1076
1077 static uint32_t crtc_id;
1078 static tbm_bo hdmi_bo;
1079
1080 static Bool connect_crtc;
1081
1082 static int
1083 _secDisplayGetAvailableCrtcID (ScrnInfoPtr pScrn)
1084 {
1085     SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
1086     int i;
1087     int crtc_id = 0;
1088
1089     for (i = 0; i < pSecMode->mode_res->count_crtcs; i++)
1090     {
1091         drmModeCrtcPtr kcrtc = NULL;
1092         kcrtc = drmModeGetCrtc (pSecMode->fd, pSecMode->mode_res->crtcs[i]);
1093         if (!kcrtc)
1094         {
1095             XDBG_ERROR (MSEC, "fail to get kcrtc. \n");
1096             return 0;
1097         }
1098
1099         if (kcrtc->buffer_id > 0)
1100         {
1101             drmModeFreeCrtc (kcrtc);
1102             continue;
1103         }
1104
1105         crtc_id = kcrtc->crtc_id;
1106         drmModeFreeCrtc (kcrtc);
1107
1108         return crtc_id;
1109     }
1110
1111     return 0;
1112 }
1113
1114 static void
1115 _secDisplayWbCloseFunc (SECWb *wb, SECWbNotify noti, void *noti_data, void *user_data)
1116 {
1117     ScrnInfoPtr pScrn = (ScrnInfoPtr)user_data;
1118     SECPtr pSec;
1119
1120     if (!pScrn)
1121         return;
1122
1123     pSec = SECPTR (pScrn);
1124
1125     pSec->wb_clone = NULL;
1126 }
1127
1128 Bool
1129 secDisplayInitDispMode (ScrnInfoPtr pScrn, SECDisplayConnMode conn_mode)
1130 {
1131     SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
1132     Bool ret = FALSE;
1133     uint32_t *output_ids = NULL;
1134     int output_cnt = 1;
1135     uint32_t fb_id;
1136     drmModeModeInfoPtr pKmode = NULL;
1137     drmModeCrtcPtr kcrtc = NULL;
1138     SECFbBoDataPtr bo_data = NULL;
1139     SECOutputPrivPtr pOutputPriv=NULL, pNext=NULL;
1140     int connector_type = -1;
1141     int width, height;
1142
1143     if (connect_crtc)
1144         return TRUE;
1145
1146     /* get output ids */
1147     output_ids = calloc (output_cnt, sizeof (uint32_t));
1148     XDBG_RETURN_VAL_IF_FAIL (output_ids != NULL, FALSE);
1149
1150     xorg_list_for_each_entry_safe (pOutputPriv, pNext, &pSecMode->outputs, link)
1151     {
1152         if (conn_mode == DISPLAY_CONN_MODE_HDMI)
1153         {
1154             if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIA ||
1155                 pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_HDMIB)
1156             {
1157                 output_ids[0] = pOutputPriv->mode_output->connector_id;
1158                 pKmode = &pSecMode->ext_connector_mode;
1159                 connector_type = pOutputPriv->mode_output->connector_type;
1160                 break;
1161             }
1162         }
1163         else if (conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
1164         {
1165             if (pOutputPriv->mode_output->connector_type == DRM_MODE_CONNECTOR_VIRTUAL)
1166             {
1167                 output_ids[0] = pOutputPriv->mode_output->connector_id;
1168                 pKmode = &pSecMode->ext_connector_mode;
1169                 connector_type = pOutputPriv->mode_output->connector_type;
1170                 break;
1171             }
1172
1173         }
1174         else
1175         {
1176             XDBG_NEVER_GET_HERE (MTVO);
1177             goto fail_to_init;
1178         }
1179     }
1180     XDBG_GOTO_IF_FAIL (output_ids[0] > 0, fail_to_init);
1181     XDBG_GOTO_IF_FAIL (pKmode != NULL, fail_to_init);
1182
1183     width = pKmode->hdisplay;
1184     height = pKmode->vdisplay;
1185
1186     pOutputPriv = secOutputGetPrivateForConnType (pScrn, connector_type);
1187     if (pOutputPriv && pOutputPriv->mode_encoder)
1188         XDBG_GOTO_IF_FAIL (pOutputPriv->mode_encoder->crtc_id == 0, fail_to_init);
1189
1190     crtc_id = _secDisplayGetAvailableCrtcID (pScrn);
1191     XDBG_GOTO_IF_FAIL (crtc_id > 0, fail_to_init);
1192
1193     /* get crtc_id */
1194     kcrtc = drmModeGetCrtc (pSecMode->fd, crtc_id);
1195     XDBG_GOTO_IF_FAIL (kcrtc != NULL, fail_to_init);
1196
1197     if (kcrtc->buffer_id > 0)
1198     {
1199         XDBG_ERROR (MTVO, "crtc(%d) already has buffer(%d) \n",
1200                     crtc_id, kcrtc->buffer_id);
1201         goto fail_to_init;
1202     }
1203
1204     /* get fb_id */
1205     hdmi_bo = secRenderBoCreate (pScrn, width, height);
1206     XDBG_GOTO_IF_FAIL (hdmi_bo != NULL, fail_to_init);
1207
1208     tbm_bo_get_user_data(hdmi_bo, TBM_BO_DATA_FB, (void * *)&bo_data);
1209     XDBG_GOTO_IF_FAIL (bo_data != NULL, fail_to_init);
1210
1211     fb_id = bo_data->fb_id;
1212
1213     /* set crtc */
1214     if (drmModeSetCrtc (pSecMode->fd, crtc_id, fb_id, 0, 0, output_ids, output_cnt, pKmode))
1215     {
1216         XDBG_ERRNO (MTVO, "drmModeSetCrtc failed. \n");
1217         goto fail_to_init;
1218     }
1219     else
1220     {
1221         ret = TRUE;
1222     }
1223
1224     secUtilSetDrmProperty (pSecMode, crtc_id, DRM_MODE_OBJECT_CRTC, "mode", 1);
1225
1226     secOutputDrmUpdate (pScrn);
1227
1228     XDBG_INFO (MDISP, "** ModeSet : (%dx%d) %dHz !!\n", pKmode->hdisplay, pKmode->vdisplay, pKmode->vrefresh);
1229
1230     connect_crtc = TRUE;
1231
1232 fail_to_init:
1233     free (output_ids);
1234     if (kcrtc)
1235         drmModeFreeCrtc (kcrtc);
1236
1237     return ret;
1238 }
1239
1240 void
1241 secDisplayDeinitDispMode (ScrnInfoPtr pScrn)
1242 {
1243     SECModePtr pSecMode = (SECModePtr) SECPTR (pScrn)->pSecMode;
1244
1245     if (!connect_crtc)
1246         return;
1247
1248     XDBG_INFO (MDISP, "** ModeUnset. !!\n");
1249
1250     secUtilSetDrmProperty (pSecMode, crtc_id, DRM_MODE_OBJECT_CRTC, "mode", 0);
1251
1252     if (hdmi_bo)
1253     {
1254         secRenderBoUnref (hdmi_bo);
1255         hdmi_bo = NULL;
1256     }
1257
1258     secOutputDrmUpdate (pScrn);
1259
1260     crtc_id = 0;
1261     connect_crtc = FALSE;
1262 }
1263
1264 Bool
1265 secDisplaySetDispSetMode  (ScrnInfoPtr pScrn, SECDisplaySetMode set_mode)
1266 {
1267     SECPtr pSec = SECPTR (pScrn);
1268     SECModePtr pSecMode = pSec->pSecMode;
1269 #ifdef NO_CRTC_MODE
1270     return TRUE;
1271 #endif
1272     if (pSecMode->set_mode == set_mode)
1273     {
1274         XDBG_INFO (MDISP, "set_mode(%d) is already set\n", set_mode);
1275         return TRUE;
1276     }
1277
1278     if (pSecMode->conn_mode == DISPLAY_CONN_MODE_NONE)
1279     {
1280         XDBG_WARNING (MDISP, "set_mode(%d) is failed : output is not connected yet\n", set_mode);
1281         return FALSE;
1282     }
1283
1284     switch (set_mode)
1285     {
1286     case DISPLAY_SET_MODE_OFF:
1287         if (secWbIsOpened ())
1288         {
1289             SECWb *wb = secWbGet ();
1290             secWbClose (wb);
1291         }
1292         secDisplayDeinitDispMode (pScrn);
1293         break;
1294     case DISPLAY_SET_MODE_CLONE:
1295         /* In case of DISPLAY_CONN_MODE_VIRTUAL, we will open writeback
1296          * on GetStill.
1297          */
1298         if (pSecMode->conn_mode != DISPLAY_CONN_MODE_VIRTUAL)
1299         {
1300             int wb_hz;
1301
1302             if (pSec->wb_clone)
1303             {
1304                 XDBG_ERROR (MWB, "Fail : wb_clone(%p) already exists.\n", pSec->wb_clone);
1305                 break;
1306             }
1307
1308             if (secWbIsOpened ())
1309             {
1310                 XDBG_ERROR (MWB, "Fail : wb(%p) already opened.\n", secWbGet ());
1311                 break;
1312             }
1313
1314             wb_hz = (pSec->wb_hz > 0)? pSec->wb_hz : pSecMode->ext_connector_mode.vrefresh;
1315
1316             XDBG_TRACE (MWB, "wb_hz(%d) vrefresh(%d)\n", pSec->wb_hz, pSecMode->ext_connector_mode.vrefresh);
1317
1318             pSec->wb_clone = secWbOpen (pScrn, FOURCC_SN12, 0, 0, (pSec->scanout)?TRUE:FALSE, wb_hz, TRUE);
1319             if (pSec->wb_clone)
1320             {
1321                 secWbAddNotifyFunc (pSec->wb_clone, WB_NOTI_CLOSED,
1322                                     _secDisplayWbCloseFunc, pScrn);
1323                 secWbSetRotate (pSec->wb_clone, pSecMode->rotate);
1324                 secWbSetTvout (pSec->wb_clone, TRUE);
1325                 if (!secWbStart (pSec->wb_clone))
1326                 {
1327                     secWbClose (pSec->wb_clone);
1328                     return FALSE;
1329                 }
1330             }
1331        }
1332        break;
1333     case DISPLAY_SET_MODE_EXT:
1334         if (secWbIsOpened ())
1335         {
1336             SECWb *wb = secWbGet ();
1337             secWbClose (wb);
1338         }
1339         secDisplayDeinitDispMode (pScrn);
1340        break;
1341     default:
1342        break;
1343     }
1344
1345     pSecMode->set_mode = set_mode;
1346
1347     return TRUE;
1348 }
1349
1350 SECDisplaySetMode
1351 secDisplayGetDispSetMode  (ScrnInfoPtr pScrn)
1352 {
1353     SECDisplaySetMode set_mode;
1354     SECPtr pSec = SECPTR (pScrn);
1355     SECModePtr pSecMode = pSec->pSecMode;
1356
1357     set_mode = pSecMode->set_mode;
1358
1359     return set_mode;
1360 }
1361
1362 Bool
1363 secDisplaySetDispRotate   (ScrnInfoPtr pScrn, int rotate)
1364 {
1365     SECPtr pSec = SECPTR (pScrn);
1366     SECModePtr pSecMode = pSec->pSecMode;
1367
1368     if (pSecMode->rotate == rotate)
1369         return TRUE;
1370
1371     pSecMode->rotate = rotate;
1372
1373     if (pSec->wb_clone)
1374         secWbSetRotate (pSec->wb_clone, rotate);
1375
1376     return TRUE;
1377 }
1378
1379 int
1380 secDisplayGetDispRotate   (ScrnInfoPtr pScrn)
1381 {
1382     int rotate;
1383     SECPtr pSec = SECPTR (pScrn);
1384     SECModePtr pSecMode = pSec->pSecMode;
1385
1386     rotate = pSecMode->rotate;
1387
1388     return rotate;
1389 }
1390
1391 Bool
1392 secDisplaySetDispConnMode (ScrnInfoPtr pScrn, SECDisplayConnMode conn_mode)
1393 {
1394     SECPtr pSec = SECPTR (pScrn);
1395     SECModePtr pSecMode = pSec->pSecMode;
1396
1397     if (pSecMode->conn_mode == conn_mode)
1398     {
1399         XDBG_DEBUG (MDISP, "conn_mode(%d) is already set\n", conn_mode);
1400         return TRUE;
1401     }
1402
1403     switch (conn_mode)
1404     {
1405     case DISPLAY_CONN_MODE_NONE:
1406        break;
1407     case DISPLAY_CONN_MODE_HDMI:
1408        break;
1409     case DISPLAY_CONN_MODE_VIRTUAL:
1410        break;
1411     default:
1412        break;
1413     }
1414
1415     pSecMode->conn_mode = conn_mode;
1416
1417     return TRUE;
1418 }
1419
1420 SECDisplayConnMode
1421 secDisplayGetDispConnMode (ScrnInfoPtr pScrn)
1422 {
1423     SECDisplayConnMode conn_mode;
1424
1425     SECPtr pSec = SECPTR (pScrn);
1426     SECModePtr pSecMode = pSec->pSecMode;
1427
1428     conn_mode = pSecMode->conn_mode;
1429
1430     return conn_mode;
1431 }
1432
1433 Bool
1434 secDisplayGetCurMSC (ScrnInfoPtr pScrn, int pipe, CARD64 *ust, CARD64 *msc)
1435 {
1436     drmVBlank vbl;
1437     int ret;
1438     SECPtr pSec = SECPTR (pScrn);
1439     SECModePtr pSecMode = pSec->pSecMode;
1440
1441     /* if lcd is off, return true with msc = 0 */
1442 #ifdef NO_CRTC_MODE
1443     if (pSec->isCrtcOn == FALSE)
1444     {
1445         *ust = 0;
1446         *msc = 0;
1447         return TRUE;
1448     }
1449 #endif //NO_CRTC_MODE
1450     if (pSec->isLcdOff)
1451     {
1452         *ust = 0;
1453         *msc = 0;
1454         return TRUE;
1455     }
1456
1457
1458     /* if pipe is -1, return the current msc of the main crtc */
1459     if (pipe == -1)
1460         pipe = 0;
1461
1462     vbl.request.type = DRM_VBLANK_RELATIVE;
1463
1464     if (pipe > 0)
1465     {
1466         if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
1467             vbl.request.type |= _DRM_VBLANK_EXYNOS_VIDI;
1468         else
1469             vbl.request.type |= DRM_VBLANK_SECONDARY;
1470     }
1471
1472     vbl.request.sequence = 0;
1473     ret = drmWaitVBlank (pSec->drm_fd, &vbl);
1474     if (ret)
1475     {
1476         *ust = 0;
1477         *msc = 0;
1478         xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
1479                     "first get vblank counter failed: %s\n",
1480                     strerror (errno));
1481         return FALSE;
1482     }
1483
1484     *ust = ((CARD64) vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
1485     *msc = vbl.reply.sequence;
1486
1487     return TRUE;
1488 }
1489
1490 Bool
1491 secDisplayVBlank (ScrnInfoPtr pScrn, int pipe, CARD64 *target_msc, int flip,
1492                         SECVBlankInfoType type, void *vblank_info)
1493 {
1494     drmVBlank vbl;
1495     int ret;
1496     SECPtr pSec = SECPTR (pScrn);
1497     SECVBlankInfoPtr pVblankInfo = NULL;
1498     SECModePtr pSecMode = pSec->pSecMode;
1499
1500     pVblankInfo = calloc (1, sizeof (SECVBlankInfoRec));
1501     if (pVblankInfo == NULL)
1502     {
1503         xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "vblank_info alloc failed\n");
1504         return FALSE;
1505     }
1506
1507     pVblankInfo->type = type;
1508     pVblankInfo->data = vblank_info;
1509     pVblankInfo->time = GetTimeInMillis ();
1510
1511     vbl.request.type =  DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
1512
1513     if (pipe > 0)
1514     {
1515         if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL)
1516             vbl.request.type |= _DRM_VBLANK_EXYNOS_VIDI;
1517         else
1518             vbl.request.type |= DRM_VBLANK_SECONDARY;
1519     }
1520
1521     /* If non-pageflipping, but blitting/exchanging, we need to use
1522      * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later
1523      * on.
1524      */
1525     if (flip == 0)
1526      {
1527          if (pSecMode->conn_mode == DISPLAY_CONN_MODE_VIRTUAL && pipe > 0)
1528                ; /* do not set the DRM_VBLANK_NEXTMISS */
1529          else
1530              vbl.request.type |= DRM_VBLANK_NEXTONMISS;
1531      }
1532
1533     vbl.request.sequence = *target_msc;
1534     vbl.request.signal = (unsigned long) pVblankInfo;
1535
1536 #if DBG_DRM_EVENT
1537     DRI2FrameEventPtr pEvent = (DRI2FrameEventPtr) vblank_info;
1538     if (type == VBLANK_INFO_SWAP)
1539         pVblankInfo->xdbg_log_vblank = xDbgLogDrmEventAddVblank (pipe, pEvent->client_idx, pEvent->drawable_id, type);
1540     else
1541         pVblankInfo->xdbg_log_vblank = xDbgLogDrmEventAddVblank (pipe, 0, 0, type);
1542 #endif
1543     ret = drmWaitVBlank (pSec->drm_fd, &vbl);
1544     if (ret)
1545     {
1546 #if DBG_DRM_EVENT
1547         xDbgLogDrmEventRemoveVblank (pVblankInfo->xdbg_log_vblank);
1548 #endif
1549         if (pVblankInfo)
1550         {
1551             free(pVblankInfo);
1552             pVblankInfo = NULL;
1553         }
1554         xf86DrvMsg (pScrn->scrnIndex, X_WARNING,
1555                 "divisor 0 get vblank counter failed: %s\n",
1556                 strerror (errno));
1557         return FALSE;
1558     }
1559
1560     XDBG_TRACE (MDISP, "vblank do (%p, %ld)\n", pVblankInfo, pVblankInfo->time);
1561
1562     /* Adjust returned value for 1 fame pageflip offset of flip > 0 */
1563     *target_msc = vbl.reply.sequence + flip;
1564
1565     return TRUE;
1566 }
1567
1568 int
1569 secDisplayDrawablePipe (DrawablePtr pDraw)
1570 {
1571     ScreenPtr pScreen = pDraw->pScreen;
1572     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1573     BoxRec box, crtc_box;
1574     xf86CrtcPtr pCrtc;
1575     int pipe = -1;
1576
1577     box.x1 = pDraw->x;
1578     box.y1 = pDraw->y;
1579     box.x2 = box.x1 + pDraw->width;
1580     box.y2 = box.y1 + pDraw->height;
1581
1582     pCrtc = secModeCoveringCrtc (pScrn, &box, NULL, &crtc_box);
1583
1584     if (pCrtc != NULL && !pCrtc->rotatedData)
1585         pipe = secModeGetCrtcPipe (pCrtc);
1586
1587     return pipe;
1588 }
1589
1590 int
1591 secDisplayCrtcPipe (ScrnInfoPtr pScrn, int crtc_id)
1592 {
1593     xf86CrtcConfigPtr pCrtcConfig = XF86_CRTC_CONFIG_PTR (pScrn);
1594     int c;
1595
1596     for (c = 0; c < pCrtcConfig->num_crtc; c++)
1597     {
1598         xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c];
1599         SECCrtcPrivPtr pCrtcPriv =  pCrtc->driver_private;
1600         if (pCrtcPriv->mode_crtc->crtc_id == crtc_id)
1601             return pCrtcPriv->pipe;
1602     }
1603
1604     XDBG_ERROR (MDISP, "%s(%d): crtc(%d) not found.\n", __func__, __LINE__, crtc_id);
1605
1606     for (c = 0; c < pCrtcConfig->num_crtc; c++)
1607     {
1608         xf86CrtcPtr pCrtc = pCrtcConfig->crtc[c];
1609         SECCrtcPrivPtr pCrtcPriv =  pCrtc->driver_private;
1610         XDBG_ERROR (MDISP, "%s(%d) : crtc(%d) != crtc(%d)\n", __func__, __LINE__,
1611                     pCrtcPriv->mode_crtc->crtc_id, crtc_id);
1612     }
1613
1614     return 0;
1615 }
1616
1617 Bool secDisplayUpdateRequest(ScrnInfoPtr pScrn)
1618 {
1619     XDBG_RETURN_VAL_IF_FAIL (pScrn != NULL, FALSE);
1620
1621     SECPtr pSec = SECPTR(pScrn);
1622     xf86CrtcPtr pCrtc = xf86CompatCrtc (pScrn);
1623     SECCrtcPrivPtr pCrtcPriv;
1624     tbm_bo bo;
1625     Bool ret = FALSE;
1626     SECPageFlipPtr pPageFlip = NULL;
1627
1628 #ifdef NO_CRTC_MODE
1629     if (pCrtc == NULL)
1630         return FALSE;
1631 #else
1632     XDBG_RETURN_VAL_IF_FAIL (pCrtc != NULL, FALSE);
1633 #endif
1634     pCrtcPriv =  pCrtc->driver_private;
1635 #ifdef NO_CRTC_MODE
1636     if (pCrtcPriv == NULL)
1637         return TRUE;
1638 #else
1639     XDBG_RETURN_VAL_IF_FAIL (pCrtcPriv != NULL, FALSE);
1640 #endif
1641
1642     bo = pCrtcPriv->front_bo;
1643
1644     if( pCrtcPriv->is_fb_blit_flipping || pCrtcPriv->is_flipping || secCrtcGetFirstPendingFlip (pCrtc) )
1645     {
1646         XDBG_DEBUG (MDISP, "drmModePageFlip is already requested!\n");
1647     }
1648     else
1649     {
1650         // Without buffer swap, we need to request drmModePageFlip().
1651         if( bo != NULL )
1652         {
1653             SECFbBoDataPtr bo_data;
1654             int fb_id = 0;
1655
1656             tbm_bo_get_user_data (bo, TBM_BO_DATA_FB, (void * *)&bo_data);
1657             XDBG_RETURN_VAL_IF_FAIL(bo_data != NULL, FALSE);
1658
1659             fb_id = bo_data->fb_id;
1660
1661             pPageFlip = calloc (1, sizeof (SECPageFlipRec));
1662             if (pPageFlip == NULL)
1663             {
1664                 xf86DrvMsg (pScrn->scrnIndex, X_WARNING, "Page flip alloc failed\n");
1665                 return FALSE;
1666             }
1667
1668             /* Only the reference crtc will finally deliver its page flip
1669              * completion event. All other crtc's events will be discarded.
1670              */
1671             pPageFlip->dispatch_me = 0;
1672             pPageFlip->pCrtc = pCrtc;
1673             pPageFlip->clone = TRUE;
1674             pPageFlip->back_bo = secRenderBoRef (bo);
1675             pPageFlip->data = NULL;
1676             pPageFlip->flip_failed = FALSE;
1677             pPageFlip->xdbg_log_pageflip = NULL;
1678             pPageFlip->time = GetTimeInMillis ();
1679             pPageFlip->handler = secDri2FlipEventHandler;
1680
1681             /* accessilitity */
1682             if (pCrtcPriv->bAccessibility || pCrtcPriv->screen_rotate_degree > 0)
1683             {
1684                 tbm_bo accessibility_bo = pCrtcPriv->accessibility_back_bo;
1685                 SECFbBoDataPtr accessibility_bo_data;
1686
1687                 tbm_bo_get_user_data (accessibility_bo, TBM_BO_DATA_FB, (void * *)&accessibility_bo_data);
1688                 XDBG_GOTO_IF_FAIL (accessibility_bo_data != NULL, fail);
1689
1690                 fb_id = accessibility_bo_data->fb_id;
1691
1692                 /*Buffer is already changed by bo_swap*/
1693                 if (!secCrtcExecAccessibility (pCrtc, bo, accessibility_bo))
1694                     goto fail;
1695
1696                 pPageFlip->accessibility_back_bo = secRenderBoRef(accessibility_bo);
1697             }
1698
1699             /*
1700             * DRM Page Flip
1701             * If pPageFlip->dispatch_me is NULL, then in SECModePageFlipHandler, nothing to happen.
1702             * That means only LCD buffer is updated.
1703             * Frame buffer is not swapped. Because these request is only for FB_BLIT case!
1704             */
1705             ret = drmModePageFlip (pSec->drm_fd, secCrtcID(pCrtcPriv), fb_id,
1706                     DRM_MODE_PAGE_FLIP_EVENT, pPageFlip);
1707             if (ret)
1708             {
1709                 XDBG_ERRNO (MDISP, "Page flip failed: %s\n", strerror (errno));
1710                 goto fail;
1711             }
1712
1713             pCrtcPriv->flip_info = NULL;
1714             pCrtcPriv->flip_count++;
1715             pCrtcPriv->is_fb_blit_flipping = TRUE;
1716         }
1717         else
1718         {
1719             XDBG_DEBUG (MDISP, "pCrtcPriv->front_bo is NULL!\n");
1720         }
1721     }
1722
1723     ret = TRUE;
1724
1725     return ret;
1726
1727 fail :
1728
1729     if( pPageFlip != NULL )
1730     {
1731         if (pPageFlip->accessibility_back_bo)
1732         {
1733             secRenderBoUnref(pPageFlip->accessibility_back_bo);
1734             pPageFlip->accessibility_back_bo = NULL;
1735         }
1736
1737         if (pPageFlip->back_bo)
1738         {
1739             secRenderBoUnref(pPageFlip->back_bo);
1740             pPageFlip->back_bo = NULL;
1741         }
1742
1743         free(pPageFlip);
1744     }
1745
1746     return ret;
1747 }
1748
1749 #ifdef NO_CRTC_MODE
1750 Bool
1751 secDisplayChangeMode (ScrnInfoPtr pScrn)
1752 {
1753     SECPtr pSec = SECPTR(pScrn);
1754     SECModePtr pSecMode = pSec->pSecMode;
1755     xf86CrtcPtr pCrtc = NULL;
1756     xf86OutputPtr pOutput = NULL;
1757     int temp = 99, i = 0;
1758     xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1759     for (i = 0; i < config->num_crtc; i++)
1760     {
1761         if (config->crtc[i]->active == TRUE)
1762         {
1763             /* Nothing to do */
1764             return TRUE;
1765         }
1766     }
1767     SECOutputPrivPtr output_ref, output_next;
1768 /* Priority LVDS > HDMI > Virtual */
1769     xorg_list_for_each_entry_safe (output_ref, output_next, &pSecMode->outputs, link)
1770     {
1771         if (output_ref->pOutput->crtc == NULL)
1772             continue;
1773         if (output_ref->mode_output == NULL)
1774             continue;
1775         if (output_ref->mode_output->connector_type == DRM_MODE_CONNECTOR_Unknown)
1776             continue;
1777         if (output_ref->mode_output->connector_type < temp)
1778         {
1779             pOutput = output_ref->pOutput;
1780             pCrtc = output_ref->pOutput->crtc;
1781             temp = (int) output_ref->mode_output->connector_type;
1782         }
1783     }
1784
1785     if (pCrtc != NULL && pOutput != NULL && pCrtc->active == FALSE)
1786     {
1787         DisplayModePtr max_mode = xf86CVTMode( 4096, 4096, 60, 0, 0);
1788         DisplayModePtr mode =
1789                 xf86OutputFindClosestMode(pOutput, max_mode);
1790         if (mode == NULL)
1791         {
1792             XDBG_ERROR(MDISP,
1793                        "Can't find display mode for output: %s\n", pOutput->name);
1794             if (max_mode)
1795                 free(max_mode);
1796             return FALSE;
1797         }
1798         if (!RRScreenSizeSet(pScrn->pScreen,
1799                              mode->HDisplay, mode->VDisplay,
1800                              pOutput->mm_width, pOutput->mm_height))
1801         {
1802             XDBG_ERROR(MDISP,
1803                        "Can't setup screen size H:%d V:%d for output: %s\n", mode->HDisplay, mode->VDisplay);
1804             if (max_mode)
1805                 free(max_mode);
1806             return FALSE;
1807         }
1808         if (!xf86CrtcSetModeTransform(pCrtc, mode, RR_Rotate_0, NULL, 0, 0))
1809         {
1810             XDBG_ERROR(MDISP,
1811                        "Can't transform Crtc to mode: %s\n", pCrtc, mode->name);
1812             if (max_mode)
1813                 free(max_mode);
1814             RRScreenSizeSet(pScrn->pScreen, 640, 480, 0, 0);
1815             return FALSE;
1816         }
1817         if (max_mode)
1818             free(max_mode);
1819         pSec->enableCursor = TRUE;
1820         secCrtcCursorEnable (pScrn, TRUE);
1821 //        xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1822 //        for (temp = 0; temp < config->num_output; temp++)
1823 //        {
1824 //            if (config->output[temp] == pOutput)
1825 //            {
1826 //                config->compat_output = temp;
1827 //                break;
1828 //            }
1829 //        }
1830         xf86SetScrnInfoModes(pScrn);
1831         xf86RandR12TellChanged(pScrn->pScreen);
1832     }
1833
1834     if (pSec->isCrtcOn == FALSE)
1835     {
1836         pSec->enableCursor = FALSE;
1837         secCrtcCursorEnable (pScrn, FALSE);
1838     }
1839
1840     if (pCrtc == NULL)
1841     {
1842         RRScreenSizeSet(pScrn->pScreen, 640, 480, 0, 0);
1843         xf86SetScrnInfoModes(pScrn);
1844         xf86RandR12TellChanged(pScrn->pScreen);
1845     }
1846
1847     return TRUE;
1848 }
1849 #endif