dss-lld: add to PDK
[processor-sdk/pdk.git] / packages / ti / drv / dss / src / drv / disp / dss_dispApi.c
1 /*
2  *  Copyright (c) Texas Instruments Incorporated 2018
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *    Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *    Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the
15  *    distribution.
16  *
17  *    Neither the name of Texas Instruments Incorporated nor the names of
18  *    its contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
34 /**
35  *  \file dss_dispApi.c
36  *
37  *  \brief File containing the DSS display driver implementation.
38  *
39  */
41 /* ========================================================================== */
42 /*                             Include Files                                  */
43 /* ========================================================================== */
45 #include <ti/drv/dss/dss.h>
46 #include <ti/drv/dss/src/drv/common/dss_evtMgr.h>
47 #include <ti/drv/dss/src/drv/disp/dss_dispDrv.h>
48 #include <ti/drv/dss/src/drv/disp/dss_dispPriv.h>
49 #include <dss_soc_priv.h>
51 /* ========================================================================== */
52 /*                           Macros & Typedefs                                */
53 /* ========================================================================== */
55 /* Number of lines for which time duration before VSYNC is considered to be too
56  * small for DSS operations to finish */
57 #define DSS_DISP_NUM_LINES_NEAR_VSYNC                  ((uint32_t) 5U)
59 /* ========================================================================== */
60 /*                         Structure Declarations                             */
61 /* ========================================================================== */
63 /* None */
65 /* ========================================================================== */
66 /*                          Function Declarations                             */
67 /* ========================================================================== */
69 /**
70  *  Below ifdef __cplusplus is added so that C++ build passes without
71  *  typecasting. This is because the prototype is build as C type
72  *  whereas this file is build as CPP file. Hence we get C++ build error.
73  *  Also if typecasting is used, then we get MisraC error Rule 11.1.
74  */
75 #ifdef __cplusplus
76 extern "C" {
77 #endif
79 /*
80  * Display APIs
81  */
82 static Fdrv_Handle Dss_dispDrvCreate(uint32_t drvId,
83                                      uint32_t instId,
84                                      void *createArgs,
85                                      void *createStatusArgs,
86                                      const Fvid2_DrvCbParams *fdmCbParams);
87 static int32_t Dss_dispDrvDelete(Fdrv_Handle handle, void *reserved);
88 static int32_t Dss_dispDrvQueue(Fdrv_Handle handle,
89                                 Fvid2_FrameList *frmList,
90                                 uint32_t streamId);
91 static int32_t Dss_dispDrvDequeue(Fdrv_Handle handle,
92                                   Fvid2_FrameList *frmList,
93                                   uint32_t streamId,
94                                   uint32_t timeout);
95 static int32_t Dss_dispDrvControl(Fdrv_Handle handle,
96                                   uint32_t cmd,
97                                   void *cmdArgs,
98                                   void *cmdStatusArgs);
100 #ifdef __cplusplus
102 #endif
104 /* ========================================================================== */
105 /*                            Global Variables                                */
106 /* ========================================================================== */
108 extern Dss_EvtMgrClientInfo gDss_DispEvtMgrClientInfo[DSS_DISP_EVT_MGR_MAX_CLIENTS];
110 /* ========================================================================== */
111 /*                  Internal/Private Function Declarations                    */
112 /* ========================================================================== */
114 /*
115  * Display IOCTLs
116  */
117 static void Dss_dispDrvClientCb(void *arg0);
118 static int32_t Dss_dispDrvStartIoctl(Dss_DispDrvInstObj *instObj);
119 static int32_t Dss_dispDrvStopIoctl(Dss_DispDrvInstObj *instObj);
120 static int32_t Dss_dispDrvSetDssParamsIoctl(Dss_DispDrvInstObj *instObj,
121                                             const Dss_DispParams *dispParams);
122 static int32_t Dss_dispDrvSetMflagParamsIoctl(
123                                     Dss_DispDrvInstObj *instObj,
124                                     const Dss_DispPipeMflagParams *mflagParams);
125 static int32_t Dss_dispDrvGetStatusIoctl(Dss_DispDrvInstObj *instObj,
126                                          Dss_DispCurrentStatus *dispStatus);
127 static int32_t Dss_dispDrvSetPipeSafetyParamsIoctl(
128                             Dss_DispDrvInstObj *instObj,
129                             const Dss_DispPipeSafetyChkParams *safetyChkParams);
130 static int32_t Dss_dispDrvSetPipeCscParamsIoctl(
131                             Dss_DispDrvInstObj *instObj,
132                             const CSL_DssCscCoeff *cscCoeff);
133 static int32_t Dss_dispDrvSetBufPrgmCbParamsIoctl(
134                             Dss_DispDrvInstObj *instObj,
135                             const Dss_DispBufPrgmCbParams *bufPrgmCbParams);
136 static int32_t Dss_dispDrvSetPipePrgmCbParamsIoctl(
137                             Dss_DispDrvInstObj *instObj,
138                             const Dss_DispPipePrgmCbParams *pipePrgmCbParams);
139 static int32_t Dss_dispDrvSetPipeUnderFlowCbParamsIoctl(
140                             Dss_DispDrvInstObj *instObj,
141                             const Dss_DispUnderFlowCbParams *underFlowCbParams);
142 static int32_t Dss_dispDrvValidateDssParams(const Dss_DispDrvInstObj *instObj,
143                                             const Dss_DispParams *dispParams);
144 static int32_t Dss_dispDrvValidateRtParams(const Dss_DispDrvInstObj *instObj,
145                                            const Dss_DispRtParams *rtParams);
146 static int32_t Dss_dispDrvApplyRtParams(Dss_DispDrvInstObj *instObj,
147                                         const Dss_DispRtParams *rtParams);
148 static void Dss_dispSafetyErrCbFxn(const uint32_t *event,
149                                    uint32_t numEvents,
150                                    void *arg);
151 static uint32_t Dss_dispIsFarFromVsync(const Dss_DispDrvInstObj *instObj);
153 /* ========================================================================== */
154 /*                          Function Definitions                              */
155 /* ========================================================================== */
157 int32_t Dss_dispDrvInit(uint32_t numInst,
158                         const Dss_DispDrvInitParams *initParams)
160     int32_t retVal = FVID2_SOK;
161     Dss_DispDrvCommonObj *pObj;
163     retVal = Dss_dispDrvPrivInit(numInst, initParams);
164     if(FVID2_SOK == retVal)
165     {
166         pObj = &gDss_DispDrvCommonObj;
167         GT_assert(DssTrace, (NULL != pObj));
169         /* Initialize Driver operations */
170         Fvid2DrvOps_init(&pObj->fvidDrvOps);
172         pObj->fvidDrvOps.drvId = DSS_DISP_DRV_ID;
173         pObj->fvidDrvOps.createFxn = &Dss_dispDrvCreate;
174         pObj->fvidDrvOps.deleteFxn = &Dss_dispDrvDelete;
175         pObj->fvidDrvOps.controlFxn = &Dss_dispDrvControl;
176         pObj->fvidDrvOps.queueFxn = &Dss_dispDrvQueue;
177         pObj->fvidDrvOps.dequeueFxn = &Dss_dispDrvDequeue;
179         retVal = Fvid2_registerDriver(&pObj->fvidDrvOps);
180         if(FVID2_SOK != retVal)
181         {
182             GT_0trace(DssTrace, GT_ERR,
183                       "Registering to FVID2 driver manager failed\r\n");
184             /* Un-initialize the internal objects if error occurs */
185             retVal += Dss_dispDrvPrivDeInit();
186         }
187         else
188         {
189             /* Init successful */
190             pObj->isRegistered = TRUE;
191             pObj->numInst = numInst;
192         }
193     }
195     return (retVal);
198 int32_t Dss_dispDrvDeInit(void)
200     int32_t retVal = FVID2_SOK;
201     Dss_DispDrvCommonObj *pObj;
203     pObj = &gDss_DispDrvCommonObj;
204     GT_assert(DssTrace, (NULL != pObj));
206     if(TRUE == pObj->isRegistered)
207     {
208         /* Unregister from driver manager */
209         retVal = Fvid2_unRegisterDriver(&pObj->fvidDrvOps);
210         if(FVID2_SOK != retVal)
211         {
212             GT_0trace(DssTrace, GT_ERR,
213                       "Unregistering from FVID2 driver manager failed\r\n");
214         }
215         pObj->isRegistered = FALSE;
216     }
218     retVal += Dss_dispDrvPrivDeInit();
220     return (retVal);
223 /* ========================================================================== */
224 /*                       Static Function Definitions                          */
225 /* ========================================================================== */
227 static Fdrv_Handle Dss_dispDrvCreate(uint32_t drvId,
228                                      uint32_t instId,
229                                      void *createArgs,
230                                      void *createStatusArgs,
231                                      const Fvid2_DrvCbParams *fdmCbParams)
233     int32_t retVal = FVID2_SOK, tempRetVal;
234     uint32_t instCreateFlag = FALSE, nodeId;
235     Fdrv_Handle drvHandle = NULL;
236     Dss_DispDrvInstObj *instObj = NULL;
237     Dss_DispCreateParams *createParams;
238     Dss_DispCreateStatus *createStatus;
239     Dss_DctrlDrvClientInfo clientInfo;
240     Dss_DctrlVpParams vpParams;
242     /* Check for NULL pointers and invalid arguments */
243     if((NULL == createArgs) ||
244        (NULL == createStatusArgs) ||
245        (NULL == fdmCbParams) ||
246        (DSS_DISP_DRV_ID != drvId))
247     {
248         GT_0trace(DssTrace, GT_ERR, "Invalid arguments\r\n");
249         retVal = FVID2_EBADARGS;
250     }
251     else
252     {
253         /* Get the instance object for this instance */
254         instObj = Dss_dispDrvGetInstObj(instId);
255         if(NULL == instObj)
256         {
257             GT_0trace(DssTrace, GT_ERR, "Invalid instance ID\r\n");
258             retVal = FVID2_EINVALID_PARAMS;
259         }
260     }
262     if(NULL != instObj)
263     {
264         /* Take the instance semaphore */
265         (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
267         /* Check if the instance is already opened */
268         if(TRUE == instObj->drvState.isOpened)
269         {
270             GT_0trace(DssTrace,
271                       GT_ERR,
272                       "Driver instance already created!!\r\n");
273             retVal = FVID2_EDEVICE_INUSE;
274         }
275     }
277     if(FVID2_SOK == retVal)
278     {
279         /* Check for valid create parameters and copy them */
280         createParams = (Dss_DispCreateParams *) createArgs;
281         Fvid2Utils_memcpy(&instObj->createParams,
282                           createParams,
283                           sizeof (Dss_DispCreateParams));
284     }
286     if(FVID2_SOK == retVal)
287     {
288         retVal = Dss_dispDrvCreateInstObj(instObj);
289         if(FVID2_SOK != retVal)
290         {
291             GT_0trace(DssTrace, GT_ERR,
292                       "Channel object create failed!!\r\n");
293         }
294         else
295         {
296             instCreateFlag = TRUE;
297         }
298     }
300     if(FVID2_SOK == retVal)
301     {
302         instObj->pipeId = instId;
303         retVal = Dss_convModuletoNode(&nodeId, instObj->pipeId,
304                                       DSS_DCTRL_NODE_TYPE_PIPE);
305         GT_assert(DssTrace,
306                   ((DSS_DCTRL_NODE_INVALID != nodeId) ||
307                    (FVID2_SOK == retVal)));
308         instObj->pipeNodeId = nodeId;
309     }
311     if(FVID2_SOK == retVal)
312     {
313         /* Initialize instance variables */
314         Fvid2Utils_memcpy(
315             &instObj->fdmCbParams,
316             fdmCbParams,
317             sizeof (Fvid2_DrvCbParams));
319         instObj->drvState.isOpened = TRUE;
320         instObj->isPrevBufRep = FALSE;
321         instObj->isInIsrContext = FALSE;
322         drvHandle = instObj;
323     }
325     if(FVID2_SOK == retVal)
326     {
327         clientInfo.cbFxn = &Dss_dispDrvClientCb;
328         clientInfo.arg = instObj;
329         instObj->dctrlHandle = Dss_dctrlDrvRegisterClient(instObj->pipeNodeId,
330                                                           &clientInfo);
331         if(NULL == instObj->dctrlHandle)
332         {
333             GT_0trace(DssTrace,
334                       GT_ERR,
335                       "Display Controller registration failed for DSS");
336             retVal = FVID2_EALLOC;
337         }
338         else
339         {
340             retVal = Dss_dctrlDrvGetVpParams(instObj->dctrlHandle, &vpParams);
341             if(FVID2_SOK != retVal)
342             {
343                 GT_0trace(DssTrace,
344                           GT_ERR,
345                           "Getting information from Display controller failed");
346             }
347             else
348             {
349                 instObj->standard = vpParams.lcdOpTimingCfg.mInfo.standard;
350                 instObj->dispWidth = vpParams.lcdOpTimingCfg.mInfo.width;
351                 instObj->dispHeight = vpParams.lcdOpTimingCfg.mInfo.height;
352                 instObj->dispScanFormat =
353                                     vpParams.lcdOpTimingCfg.mInfo.scanFormat;
354                 instObj->vpId = vpParams.vpId;
355             }
356         }
357     }
359     if(FVID2_SOK != retVal)
360     {
361         if((NULL != instObj) && (NULL != instObj->dctrlHandle))
362         {
363             retVal += Dss_dctrlDrvUnRegisterClient(instObj->dctrlHandle);
364         }
365     }
367     /* Return the status if possible */
368     if(NULL != createStatusArgs)
369     {
370         createStatus = (Dss_DispCreateStatus *) createStatusArgs;
371         createStatus->retVal = retVal;
372         if(NULL != instObj)
373         {
374             createStatus->standard = instObj->standard;
375             createStatus->dispWidth = instObj->dispWidth;
376             createStatus->dispHeight = instObj->dispHeight;
377             createStatus->minNumPrimeBuf = DSS_DISP_DRV_MIN_PRIME_BUFFERS;
378         }
379     }
381     if(NULL != instObj)
382     {
383         /* Deallocate if error occurs */
384         if(FVID2_SOK != retVal)
385         {
386             if(TRUE == instCreateFlag)
387             {
388                 tempRetVal = Dss_dispDrvDeleteInstObj(instObj);
389                 GT_assert(DssTrace, (FVID2_SOK == tempRetVal));
390             }
391         }
393         /* Post the instance semaphore */
394         (void) SemaphoreP_post(instObj->lockSem);
395     }
397     return (drvHandle);
400 static int32_t Dss_dispDrvDelete(Fdrv_Handle handle, void *reserved)
402     int32_t retVal = FVID2_SOK;
403     Dss_DispDrvInstObj *instObj = NULL;
405     /* Check for NULL pointers and invalid arguments */
406     if(NULL == handle)
407     {
408         GT_0trace(DssTrace, GT_ERR, "Invalid arguments\r\n");
409         retVal = FVID2_EBADARGS;
410     }
411     else
412     {
413         instObj = (Dss_DispDrvInstObj *) handle;
414     }
416     if(NULL != instObj)
417     {
418         /* Take the instance semaphore */
419         (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
421         /* Check if already opened. */
422         if(TRUE != instObj->drvState.isOpened)
423         {
424             GT_0trace(DssTrace, GT_ERR, "Driver not opened\r\n");
425             retVal = FVID2_EFAIL;
426         }
427     }
429     if(FVID2_SOK == retVal)
430     {
431         /* If already started, stop it. */
432         if(TRUE == instObj->drvState.isStarted)
433         {
434             retVal = Dss_dispDrvStopIoctl(instObj);
435             if(FVID2_SOK != retVal)
436             {
437                 GT_0trace(DssTrace, GT_ERR, "Stop display failed\r\n");
438             }
439         }
440     }
442     if(FVID2_SOK == retVal)
443     {
444         if(NULL != instObj->dctrlHandle)
445         {
446             retVal = Dss_dctrlDrvUnRegisterClient(instObj->dctrlHandle);
447         }
448         retVal += Dss_dispDrvDeleteInstObj(instObj);
449         GT_assert(DssTrace, (FVID2_SOK == retVal));
451         /* Reset other variables */
452         instObj->drvState.isOpened = FALSE;
453         instObj->drvState.isStarted = FALSE;
454         instObj->currStatus.queueCount = 0U;
455         instObj->currStatus.dequeueCount = 0U;
456         instObj->currStatus.dispFrmCount = 0U;
457         instObj->currStatus.repeatFrmCount = 0U;
459         instObj->fdmCbParams.fdmCbFxn = NULL;
460         instObj->fdmCbParams.fdmErrCbFxn = NULL;
461         instObj->fdmCbParams.handle = NULL;
462         instObj->fdmCbParams.errList = NULL;
463         instObj->fdmCbParams.fdmData = NULL;
464     }
466     if(NULL != instObj)
467     {
468         /* Post the instance semaphore */
469         (void) SemaphoreP_post(instObj->lockSem);
470     }
472     return (retVal);
475 static int32_t Dss_dispDrvQueue(Fdrv_Handle handle,
476                                 Fvid2_FrameList *frmList,
477                                 uint32_t streamId)
479     int32_t  retVal = FVID2_SOK;
480     uint32_t frmCnt, cookie;
481     uint32_t reqQCnt, isSafe;
482     uint32_t isBufAccepted = TRUE;
483     Fvid2_Frame *frm, *newFrm;
484     Dss_DispDrvInstObj *instObj;
485     Dss_DispDrvQueObj *qObj, *qObjTemp;
486     CSL_dss_pipeRegs *pipeRegs;
487     const Dss_SocInfo *socInfo;
488     Dss_DispRtParams *rtParams;
489     int32_t rtParamsRetVal = FVID2_SOK;
491     /* Check for NULL pointers */
492     if((NULL == handle) || (NULL == frmList))
493     {
494         GT_0trace(DssTrace, GT_ERR, "NULL pointer\r\n");
495         retVal = FVID2_EBADARGS;
496     }
498     if(FVID2_SOK == retVal)
499     {
500         instObj = (Dss_DispDrvInstObj *) handle;
502         /* Check frame list for error and NULL pointer check */
503         retVal = Fvid2_checkFrameList(frmList, (uint32_t) FVID2_MAX_FRAME_PTR);
504         if(FVID2_SOK != retVal)
505         {
506             GT_0trace(DssTrace, GT_ERR, "Check frame list error\r\n");
507         }
509         if(FALSE == instObj->drvState.isOpened)
510         {
511             /* If driver handle is not open then skip this frame queue */
512             GT_0trace(DssTrace,
513                       GT_ERR,
514                       "Can't queue to an un-opened instance!!\r\n");
515             retVal = FVID2_EFAIL;
516         }
517         /* Only one frame submit supported per instance */
518         if(frmList->numFrames > 1U)
519         {
520             GT_0trace(DssTrace,
521                       GT_ERR,
522                       "Only one frame submit supported in current design\r\n");
523             retVal = FVID2_EFAIL;
524         }
525     }
527     if(FVID2_SOK == retVal)
528     {
529         /* For all frames that need to be queued. The loop is dummy */
530         for(frmCnt=0U; frmCnt<frmList->numFrames; frmCnt++)
531         {
532             /* Get FVID2 frame pointer - NULL check is already done in
533              * check frame list function */
534             frm = frmList->frames[frmCnt];
535             GT_assert(DssTrace, (NULL != frm));
537             cookie = HwiP_disable();
539             /* Allocate a free queue object from the pool */
540             qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
541                                                         instObj->bmObj.freeQ);
542             if(NULL == qObj)
543             {
544                 HwiP_restore(cookie);
545                 GT_0trace(DssTrace,
546                           GT_ERR,
547                           "Q object allocation failed\r\n");
548                 retVal = FVID2_EALLOC;
549                 break;
550             }
552             /* Copy the frame to the driver's queue object */
553             qObj->frm = frm;
554             /* Initial credit count should be zero!! */
555             GT_assert(DssTrace, (0U == qObj->creditCnt));
557             /* Push mechanism */
558             /* 1.  Check if the new frame should be updated immediately in case
559              *     of frame repeat.
560              * 2.  Check if the previous frame was repeated
561              * 3.  Check if request queue is empty
562              * 4.  If request queue is not empty then put it in the request
563              *     queue and exit.
564              * 5.  If request queue is empty then push the buffer to hardware
565              * 6.  If hardware accepts then put the buffer in current queue and
566              *     update the credit count
567              * 7.  If hardware accepts the buffer then make the prevRepBuf as
568              *     false. This is required if two back to back buffers are
569              *     queued in same frame period. (The second buffer should not be
570              *     pushed if first once is accepted)
571              * 8.  If hardware doesn't accept the buffer then put it in the
572              *     request queue.
573              * 9.  In Vsync call back we set the prevBufRepeated flag
574              *     appropriately.
575              *     a. Set to true if no buffer is available in request queue
576              *     b. Set to false if buffer is given to hardware
577              * 10. Here we will overwrite the buffer present in the currQ with
578              *     the new one. Basically what needs to done is to revert what
579              *     is being done in Vsync callback function when the buffer
580              *     is repeated. So peak the current queue and decrement
581              *     the credit count. It will automatically moved to doneQ in
582              *     next Vsync Call back.
583              */
584             reqQCnt = Fvid2Utils_getNumQElem(instObj->bmObj.reqQ);
585             if((0U == reqQCnt) &&
586                (FALSE == instObj->createParams.progPipeVsyncEnable) &&
587                (TRUE == instObj->isPrevBufRep) &&
588                /* Don't program if queue is called from ISR callback context.
589                 * Just push to request queue */
590                (FALSE == instObj->isInIsrContext))
591             {
592                 /* Call the user buffer program callback */
593                 if(NULL != instObj->bufPrgmCbParams.bufPrgmCbFxn)
594                 {
595                     newFrm = instObj->bufPrgmCbParams.bufPrgmCbFxn(
596                                                     instObj->fdmCbParams.handle,
597                                                     qObj->frm,
598                                                     FALSE,
599                                                     qObj->creditCnt);
600                     if(NULL != newFrm)
601                     {
602                         /* Swap the current frame */
603                         qObj->frm = newFrm;
604                     }
605                 }
607                 /* Query display controller to check if it is safe to push */
608                 isSafe = Dss_dispIsFarFromVsync(instObj);
610                 if((retVal == FVID2_SOK) && (isSafe == TRUE))
611                 {
612                     instObj->progFrame = qObj->frm;
614                     /* Get video pipe registers */
615                     socInfo = Dss_getSocInfo();
616                     pipeRegs = socInfo->pipeRegs[instObj->pipeId];
617                     GT_assert(DssTrace, (NULL != pipeRegs));
619                     if(NULL != instObj->progFrame->perFrameCfg)
620                     {
621                         rtParams =
622                             (Dss_DispRtParams *)(instObj->progFrame->perFrameCfg);
623                         rtParamsRetVal = Dss_dispDrvValidateRtParams(instObj,
624                                                                      rtParams);
625                         if(FVID2_SOK == rtParamsRetVal)
626                         {
627                             Dss_dispDrvApplyRtParams(instObj, rtParams);
628                         }
629                     }
631                     CSL_dssVidPipeSetBuffAddr(pipeRegs,
632                                               FVID2_FID_TOP,
633                                               instObj->progFrame->addr[0U],
634                                               instObj->progFrame->addr[1U]);
636                     if(instObj->inScanFormat == FVID2_SF_INTERLACED)
637                     {
638                         CSL_dssVidPipeSetBuffAddr(pipeRegs,
639                                                   FVID2_FID_BOTTOM,
640                                                   instObj->progFrame->addr[3U],
641                                                   instObj->progFrame->addr[4U]);
642                     }
643                     if(NULL != instObj->pipePrgmCbParams.pipePrgmCbFxn)
644                     {
645                         /* Give callback to application that buffer has been
646                          * programmed
647                          */
648                         instObj->pipePrgmCbParams.pipePrgmCbFxn(
649                                                 instObj->progFrame,
650                                                 instObj->pipePrgmCbParams.appData);
651                     }
653                     retVal = Dss_dctrlDrvSetGoBit(instObj->dctrlHandle);
654                 }
656                 isBufAccepted = isSafe;
658                 if(TRUE == isBufAccepted)
659                 {
660                     /* Decrement the credit count of previously repeated buffer,
661                      * This is not a repeat now as we are overwriting the
662                      * buffer */
663                     qObjTemp = (Dss_DispDrvQueObj *) Fvid2Utils_peakTail(
664                         instObj->bmObj.currQ);
665                     /* This can't return NULL unless there is a bug in the
666                      * buffer management */
667                     GT_assert(DssTrace, (NULL != qObjTemp));
668                     qObjTemp->creditCnt--;
670                     Fvid2Utils_queue(instObj->bmObj.currQ, &qObj->qElem, qObj);
671                     qObj->creditCnt++;
672                     instObj->isPrevBufRep = FALSE;
673                     /* This is like a queue only, so increment the count*/
674                     instObj->currStatus.queueCount++;
675                 }
676                 else
677                 {
678                     /* Add the queue object in driver's request queue */
679                     Fvid2Utils_queue(instObj->bmObj.reqQ, &qObj->qElem, qObj);
680                     instObj->currStatus.queueCount++;
681                 }
682             }
683             else
684             {
685                 /* Add the queue object in driver's request queue */
686                 Fvid2Utils_queue(instObj->bmObj.reqQ, &qObj->qElem, qObj);
687                 instObj->currStatus.queueCount++;
688             }
690             HwiP_restore(cookie);
692             /* Mark frame in frmList as NULL */
693             frmList->frames[frmCnt] = NULL;
694         }
695     }
697     return (retVal);
700 static int32_t Dss_dispDrvDequeue(Fdrv_Handle handle,
701                                   Fvid2_FrameList *frmList,
702                                   uint32_t streamId,
703                                   uint32_t timeout)
705     int32_t retVal = FVID2_SOK;
706     uint32_t cookie;
707     Dss_DispDrvInstObj *instObj;
708     Dss_DispDrvQueObj *qObj;
709     Dss_DispDrvBufManObj *bmObj;
711     /* Check for NULL pointers */
712     if((NULL == handle) || (NULL == frmList) || (streamId > 0U))
713     {
714         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
715         retVal = FVID2_EBADARGS;
716     }
718     if(FVID2_SOK == retVal)
719     {
720         instObj = (Dss_DispDrvInstObj *) handle;
721         bmObj   = &instObj->bmObj;
723         if(FALSE == instObj->drvState.isOpened)
724         {
725             GT_0trace(
726                 DssTrace,
727                 GT_ERR,
728                 "Invalid Driver state: Can't dequeue to an un-opened instance!!\r\n");
729             retVal = FVID2_EFAIL;
730         }
731     }
733     if(FVID2_SOK == retVal)
734     {
735         /* Init frame list fields */
736         frmList->numFrames  = 0U;
737         frmList->perListCfg = NULL;
739         cookie = HwiP_disable();
741         /* Get a completed queue object from driver's done queue */
742         qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(bmObj->doneQ);
743         if(NULL == qObj)
744         {
745             /* When display is stopped, give back all the driver owned buffer
746              * including the current programmed and the buffers in request
747              * queue */
748             if(TRUE != instObj->drvState.isStarted)
749             {
750                 /* Give the buffers in current state */
751                 qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(bmObj->currQ);
752                 if(NULL == qObj)
753                 {
754                     /* At last give back the buffers in request queue as well */
755                     qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
756                                                                 bmObj->reqQ);
757                 }
759                 /* Check if all these operation has failed */
760                 if(NULL == qObj)
761                 {
762                     GT_0trace(DssTrace,
763                               GT_DEBUG,
764                               "NO_MORE_BUFFERS: No more buffers with driver\n");
765                     retVal = FVID2_ENO_MORE_BUFFERS;
766                 }
767             }
768             else
769             {
770                 GT_0trace(DssTrace,
771                           GT_DEBUG,
772                           "AGAIN: Out queue Empty. Try again\r\n");
773                 retVal = FVID2_EAGAIN;
774             }
775         }
777         HwiP_restore(cookie);
779         /* Copy the driver's frame list to application's frame list */
780         if(NULL != qObj)
781         {
782             cookie = HwiP_disable();
784             GT_assert(DssTrace, (NULL != qObj->frm));
785             frmList->frames[frmList->numFrames] = qObj->frm;
786             frmList->numFrames++;
788             /* Give back the queue object back to the free pool */
789             qObj->frm = NULL;
790             /* At time of dequeue, credit should be zero!! */
791             GT_assert(DssTrace, (0U == qObj->creditCnt));
792             Fvid2Utils_queue(bmObj->freeQ, &qObj->qElem, qObj);
793             instObj->currStatus.dequeueCount++;
795             HwiP_restore(cookie);
796         }
797     }
799     return (retVal);
802 static int32_t Dss_dispDrvControl(Fdrv_Handle handle,
803                                   uint32_t cmd,
804                                   void *cmdArgs,
805                                   void *cmdStatusArgs)
807     int32_t retVal = FVID2_SOK;
808     Dss_DispDrvInstObj *instObj;
810     /* Check for NULL pointers */
811     if(NULL == handle)
812     {
813         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
814         retVal = FVID2_EBADARGS;
815     }
817     if(FVID2_SOK == retVal)
818     {
819         instObj = (Dss_DispDrvInstObj *) handle;
820         switch (cmd)
821         {
822             case FVID2_START:
823                 retVal = Dss_dispDrvStartIoctl(instObj);
824                 break;
825             case FVID2_STOP:
826                 retVal = Dss_dispDrvStopIoctl(instObj);
827                 break;
828             case IOCTL_DSS_DISP_SET_DSS_PARAMS:
829                 retVal = Dss_dispDrvSetDssParamsIoctl(
830                                instObj,
831                                (const Dss_DispParams *) cmdArgs);
832                 break;
833             case IOCTL_DSS_DISP_SET_PIPE_MFLAG_PARAMS:
834                 retVal = Dss_dispDrvSetMflagParamsIoctl(
835                                instObj,
836                                (const Dss_DispPipeMflagParams *) cmdArgs);
837                 break;
838             case IOCTL_DSS_DISP_GET_CURRENT_STATUS:
839                 retVal = Dss_dispDrvGetStatusIoctl(
840                                instObj,
841                                (Dss_DispCurrentStatus *) cmdArgs);
842                 break;
843             case IOCTL_DSS_DISP_SET_PIPE_SAFETY_CHK_PARAMS:
844                 retVal = Dss_dispDrvSetPipeSafetyParamsIoctl(
845                                instObj,
846                                (const Dss_DispPipeSafetyChkParams *) cmdArgs);
847                 break;
848             case IOCTL_DSS_DISP_SET_PIPE_CSC_COEFF:
849                 retVal = Dss_dispDrvSetPipeCscParamsIoctl(
850                                 instObj,
851                                 (const CSL_DssCscCoeff *) cmdArgs);
852                 break;
853             case IOCTL_DSS_DISP_REGISTER_BUF_PRGM_CB:
854                 retVal = Dss_dispDrvSetBufPrgmCbParamsIoctl(
855                                 instObj,
856                                 (const Dss_DispBufPrgmCbParams *) cmdArgs);
857                 break;
858             case IOCTL_DSS_DISP_REGISTER_PIPE_PRGM_CB:
859                 retVal = Dss_dispDrvSetPipePrgmCbParamsIoctl(
860                                 instObj,
861                                 (const Dss_DispPipePrgmCbParams *) cmdArgs);
862                 break;
863             case IOCTL_DSS_DISP_REGISTER_PIPE_UNDERFLOW_CB:
864                 retVal = Dss_dispDrvSetPipeUnderFlowCbParamsIoctl(
865                                 instObj,
866                                 (const Dss_DispUnderFlowCbParams *) cmdArgs);
867                 break;
868             default:
869                 GT_0trace(DssTrace, GT_ERR,
870                           "UNSUPPORTED_CMD: IOCTL not supported\r\n");
871                 retVal = FVID2_EUNSUPPORTED_CMD;
872                 break;
873         }
874     }
876     return (retVal);
879 static void Dss_dispDrvClientCb(void *arg0)
881     Dss_DispDrvInstObj *instObj;
882     Dss_DispDrvQueObj *qObj, *qObjTemp;
883     uint32_t currQCnt, reqQCnt, cookie;
884     uint32_t frmQueuedToDoneQ = FALSE;
885     CSL_dss_pipeRegs *pipeRegs;
886     const Dss_SocInfo *socInfo;
887     Fvid2_Frame *newFrm;
888     Dss_DispRtParams *rtParams;
889     int32_t rtParamsRetVal = FVID2_SOK;
891     GT_assert(DssTrace, (NULL != arg0));
892     instObj = (Dss_DispDrvInstObj *)arg0;
894     if(TRUE == instObj->drvState.isStarted)
895     {
896         cookie = HwiP_disable();
898         if(NULL != instObj->currFrame)
899         {
900             /* Update channel statistics */
901             instObj->currStatus.dispFrmCount++;
902             /* Get current queue head */
903             qObj = (Dss_DispDrvQueObj *) Fvid2Utils_peakHead(instObj->bmObj.currQ);
904             GT_assert(DssTrace, (NULL != qObj));
906             /* Decrement credit count as frame display is complete - credit can't
907             * be zero */
908             GT_assert(DssTrace, (qObj->creditCnt > 0U));
909             qObj->creditCnt--;
910             if(qObj->creditCnt > 0U)
911             {
912                 instObj->currStatus.repeatFrmCount++;
913             }
915             /* Get the current queue counts */
916             currQCnt = Fvid2Utils_getNumQElem(instObj->bmObj.currQ);
917             reqQCnt = Fvid2Utils_getNumQElem(instObj->bmObj.reqQ);
919             if(0U == qObj->creditCnt)
920             {
921                 qObjTemp = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
922                                                             instObj->bmObj.currQ);
923                 /* Head node and qObj should match */
924                 GT_assert(DssTrace, (qObj == qObjTemp));
926                 /* In last frame repeat mode, we could return all the frames to
927                 * the application if credit becomes 0 and there are some more
928                 * request in the current or request queue. Current queue is
929                 * checked for 1 element as the current frame is still present
930                 * in the queue. */
931                 if((currQCnt > 1U) || (reqQCnt > 0U))
932                 {
933                     /* Return the frame to done queue */
934                     GT_assert(DssTrace, (NULL != qObj->frm));
935                     Fvid2Utils_queue(instObj->bmObj.doneQ, &qObj->qElem, qObj);
936                     frmQueuedToDoneQ = TRUE;
937                 }
938                 /* In last frame repeat mode, if credit becomes 0 and there are
939                 * no more request in the current and request queues, take this
940                 * request and queue it back to request queue so that when
941                 * the hardware asks for next buffer, we repeat the frame
942                 * automatically. This is needed because the user could
943                 * queue a request in between and this frame will end-up
944                 * in the current queue!!
945                 * Also increment the repeat frame counter here. */
946                 else if((currQCnt == 1U) && (reqQCnt == 0U))
947                 {
948                     instObj->currStatus.repeatFrmCount++;
949                     Fvid2Utils_queue(instObj->bmObj.reqQ, &qObj->qElem, qObj);
950                 }
951                 else
952                 {
953                     /* This can't happen as currQCnt can't be zero!! */
954                     GT_assert(DssTrace, FALSE);
955                 }
956             }
957         }
959         if(NULL != instObj->fdmCbParams.fdmCbFxn)
960         {
961             /* Give callback to application if periodic call back is enabled or
962              * if frame is put in done queue */
963             if((TRUE == instObj->createParams.periodicCbEnable) ||
964                (TRUE == frmQueuedToDoneQ))
965             {
966                 instObj->isInIsrContext = TRUE;
967                 instObj->fdmCbParams.fdmCbFxn(instObj->fdmCbParams.fdmData);
968                 instObj->isInIsrContext = FALSE;
969             }
970         }
972         instObj->currFrame = instObj->progFrame;
974         /* Get new frame from request queue or repeat frame */
975         qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(instObj->bmObj.reqQ);
976         if(NULL != qObj)
977         {
978             /*
979              * Buffer available in request queue
980              */
981             /* Increment credit */
982             qObj->creditCnt++;
983             Fvid2Utils_queue(instObj->bmObj.currQ, &qObj->qElem, qObj);
984             instObj->isPrevBufRep = FALSE;
985         }
986         else
987         {
988             /*
989              * No more buffers available in request queue.
990              * Repeat the last frame queued.
991              */
992             qObj = (Dss_DispDrvQueObj *) Fvid2Utils_peakTail(
993                                                         instObj->bmObj.currQ);
994             /* This can't return NULL unless there is a bug in the buffer
995              * management */
996             GT_assert(DssTrace, (NULL != qObj));
997             /* Increment credit */
998             qObj->creditCnt++;
999             /* Mark the buffer as repeated */
1000             instObj->isPrevBufRep = TRUE;
1001         }
1003         /* Call the user buffer program callback */
1004         if(NULL != instObj->bufPrgmCbParams.bufPrgmCbFxn)
1005         {
1006             newFrm = instObj->bufPrgmCbParams.bufPrgmCbFxn(
1007                                             instObj->fdmCbParams.handle,
1008                                             qObj->frm,
1009                                             instObj->isPrevBufRep,
1010                                             qObj->creditCnt);
1011             if(NULL != newFrm)
1012             {
1013                 /* Swap the current frame */
1014                 qObj->frm = newFrm;
1015             }
1016         }
1018         /* Set frame to be programmed */
1019         instObj->progFrame = qObj->frm;
1020         /* Driver should always give the buffers when requested */
1021         GT_assert(DssTrace, (instObj->progFrame != NULL));
1022         /* Get video pipe registers */
1023         socInfo = Dss_getSocInfo();
1024         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1025         GT_assert(DssTrace, (NULL != pipeRegs));
1027         if(NULL != instObj->progFrame->perFrameCfg)
1028         {
1029             rtParams = (Dss_DispRtParams *)(instObj->progFrame->perFrameCfg);
1030             rtParamsRetVal = Dss_dispDrvValidateRtParams(instObj, rtParams);
1031             if(FVID2_SOK == rtParamsRetVal)
1032             {
1033                 Dss_dispDrvApplyRtParams(instObj, rtParams);
1034             }
1035         }
1037         CSL_dssVidPipeSetBuffAddr(pipeRegs,
1038                                   FVID2_FID_TOP,
1039                                   instObj->progFrame->addr[0U],
1040                                   instObj->progFrame->addr[1U]);
1042         if(instObj->inScanFormat == FVID2_SF_INTERLACED)
1043         {
1044             CSL_dssVidPipeSetBuffAddr(pipeRegs,
1045                                       FVID2_FID_BOTTOM,
1046                                       instObj->progFrame->addr[3U],
1047                                       instObj->progFrame->addr[4U]);
1048         }
1050         if(NULL != instObj->pipePrgmCbParams.pipePrgmCbFxn)
1051         {
1052             /* Give callback to application that buffer has been programmed */
1053             instObj->pipePrgmCbParams.pipePrgmCbFxn(
1054                             instObj->progFrame,
1055                             instObj->pipePrgmCbParams.appData);
1056         }
1058         HwiP_restore(cookie);
1059     }
1060     else if(TRUE == instObj->drvState.isStarting)
1061     {
1062         cookie = HwiP_disable();
1064         /* Start display */
1065         instObj->drvState.isStarted = TRUE;
1066         qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(instObj->bmObj.reqQ);
1067         if(NULL != qObj)
1068         {
1069             /*
1070             * Buffer available in request queue
1071             */
1072             /* Increment credit */
1073             qObj->creditCnt++;
1074             Fvid2Utils_queue(instObj->bmObj.currQ, &qObj->qElem, qObj);
1075             instObj->isPrevBufRep = FALSE;
1076             instObj->progFrame = qObj->frm;
1077         }
1078         else
1079         {
1080             /* This can't return NULL unless application has made a mistake */
1081             GT_assert(DssTrace, (NULL != qObj));
1082         }
1084         /* Driver should always give the buffers when requested */
1085         GT_assert(DssTrace, (instObj->progFrame != NULL));
1087         /* Get video pipe registers */
1088         socInfo = Dss_getSocInfo();
1089         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1090         GT_assert(DssTrace, (NULL != pipeRegs));
1092         CSL_dssVidPipeSetBuffAddr(pipeRegs,
1093                                   FVID2_FID_TOP,
1094                                   instObj->progFrame->addr[0U],
1095                                   instObj->progFrame->addr[1U]);
1097         if(instObj->inScanFormat == FVID2_SF_INTERLACED)
1098         {
1099             CSL_dssVidPipeSetBuffAddr(pipeRegs,
1100                                       FVID2_FID_BOTTOM,
1101                                       instObj->progFrame->addr[3U],
1102                                       instObj->progFrame->addr[4U]);
1103         }
1105         CSL_dssVidPipeEnable(pipeRegs, TRUE);
1106         instObj->drvState.isStarting = FALSE;
1108         if(NULL != instObj->pipePrgmCbParams.pipePrgmCbFxn)
1109         {
1110             /* Give callback to application that buffer has been programmed */
1111             instObj->pipePrgmCbParams.pipePrgmCbFxn(
1112                             instObj->progFrame,
1113                             instObj->pipePrgmCbParams.appData);
1114         }
1116         HwiP_restore(cookie);
1117     }
1118     else if(TRUE == instObj->drvState.isStopping)
1119     {
1120         cookie = HwiP_disable();
1122         /* Get video pipe registers */
1123         socInfo = Dss_getSocInfo();
1124         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1125         GT_assert(DssTrace, (NULL != pipeRegs));
1127         /* Disable Video Pipe */
1128         CSL_dssVidPipeEnable(pipeRegs, FALSE);
1129         instObj->currFrame = NULL;
1130         instObj->progFrame = NULL;
1131         instObj->drvState.isStopping = FALSE;
1133         /* Take the buffers in current state and push them in to the request
1134          * queue so that the next start will use those buffers */
1135         qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(instObj->bmObj.currQ);
1136         while (NULL != qObj)
1137         {
1138             qObj->creditCnt = 0U;
1139             /* Push it to the request queue */
1140             Fvid2Utils_queueBack(instObj->bmObj.reqQ, &qObj->qElem, qObj);
1141             qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
1142                                                         instObj->bmObj.currQ);
1143         };
1145         if(NULL != instObj->pipePrgmCbParams.pipePrgmCbFxn)
1146         {
1147             /* Give callback to application that buffer has been programmed */
1148             instObj->pipePrgmCbParams.pipePrgmCbFxn(
1149                                         instObj->progFrame,
1150                                         instObj->pipePrgmCbParams.appData);
1151         }
1153         HwiP_restore(cookie);
1154     }
1155     else
1156     {
1157         /* Should never execute this */
1158         GT_assert(DssTrace, FALSE);
1159     }
1162 static int32_t Dss_dispDrvStartIoctl(Dss_DispDrvInstObj *instObj)
1164     int32_t retVal = FVID2_SOK;
1165     uint32_t numElemInReqQ, isSafe, dummyStart;
1166     Dss_DispDrvBufManObj *bmObj;
1167     Dss_DispDrvQueObj *qObj;
1168     uint32_t cookie;
1169     CSL_dss_pipeRegs *pipeRegs;
1170     const Dss_SocInfo *socInfo;
1172     /* Check for NULL pointers */
1173     GT_assert(DssTrace, (NULL != instObj));
1175     /* Take the instance semaphore */
1176     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1178     bmObj = &instObj->bmObj;
1180     /* Initialize instance variables that needs to be reset in stop/start
1181      * sequence */
1182     instObj->currStatus.dispFrmCount = 0U;
1183     instObj->currStatus.repeatFrmCount = 0U;
1184     bmObj->expectedFid = 0U;
1185     bmObj->curFid = 0U;
1187     /* Check if the number of elements in the queue is sufficient to prime */
1188     numElemInReqQ = Fvid2Utils_getNumQElem(instObj->bmObj.reqQ);
1189     if(numElemInReqQ < DSS_DISP_DRV_MIN_PRIME_BUFFERS)
1190     {
1191         GT_0trace(DssTrace, GT_ERR, "Insufficient buffers queued\r\n");
1192         retVal = FVID2_EFAIL;
1193     }
1195     if(FVID2_SOK == retVal)
1196     {
1197         if(FALSE == instObj->createParams.progPipeVsyncEnable)
1198         {
1199             /* Get video pipe registers */
1200             socInfo = Dss_getSocInfo();
1201             pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1202             GT_assert(DssTrace, (NULL != pipeRegs));
1204             cookie = HwiP_disable();
1205             /* Check if it is safe to start or start is too near to VSYNC */
1206             isSafe = Dss_dispIsFarFromVsync(instObj);
1207             if(TRUE == isSafe)
1208             {
1209                 qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
1210                                                         instObj->bmObj.reqQ);
1211                 if(NULL != qObj)
1212                 {
1213                     /*
1214                      * Buffer available in request queue
1215                      */
1216                     /* Increment credit */
1217                     qObj->creditCnt++;
1218                     Fvid2Utils_queue(instObj->bmObj.currQ, &qObj->qElem, qObj);
1219                     instObj->isPrevBufRep = FALSE;
1220                     instObj->progFrame = qObj->frm;
1221                 }
1222                 else
1223                 {
1224                     /*
1225                     * No more buffers available in request queue.
1226                     * Repeat the last frame queued.
1227                     */
1228                     qObj = (Dss_DispDrvQueObj *) Fvid2Utils_peakTail(
1229                                                         instObj->bmObj.currQ);
1230                     /* This can't return NULL unless there is a bug in the
1231                      * buffer management */
1232                     GT_assert(DssTrace, (NULL != qObj));
1233                     /* Increment credit */
1234                     qObj->creditCnt++;
1235                     /* Mark the buffer as repeated */
1236                     instObj->isPrevBufRep = TRUE;
1237                     instObj->progFrame = qObj->frm;
1238                 }
1240                 /* Driver should always give the buffers when requested */
1241                 GT_assert(DssTrace, (instObj->progFrame != NULL));
1243                 CSL_dssVidPipeSetBuffAddr(pipeRegs,
1244                                           FVID2_FID_TOP,
1245                                           instObj->progFrame->addr[0U],
1246                                           instObj->progFrame->addr[1U]);
1248                 if(instObj->inScanFormat == FVID2_SF_INTERLACED)
1249                 {
1250                     CSL_dssVidPipeSetBuffAddr(pipeRegs,
1251                                               FVID2_FID_BOTTOM,
1252                                               instObj->progFrame->addr[3U],
1253                                               instObj->progFrame->addr[4U]);
1254                 }
1256                 /* Start display */
1257                 instObj->drvState.isStarted = TRUE;
1258                 dummyStart = FALSE;
1259                 CSL_dssVidPipeEnable(pipeRegs, TRUE);
1260                 if(NULL != instObj->pipePrgmCbParams.pipePrgmCbFxn)
1261                 {
1262                     /* Give callback to application that buffer has been
1263                      * programmed */
1264                     instObj->pipePrgmCbParams.pipePrgmCbFxn(
1265                                             instObj->progFrame,
1266                                             instObj->pipePrgmCbParams.appData);
1267                 }
1268             }
1269             else
1270             {
1271                 instObj->drvState.isStarting = TRUE;
1272                 dummyStart = TRUE;
1273             }
1275             HwiP_restore(cookie);
1276             retVal = Dss_dctrlDrvStartClient(instObj->dctrlHandle, dummyStart);
1278             if(FVID2_SOK != retVal)
1279             {
1280                 instObj->drvState.isStarted = FALSE;
1281                 instObj->drvState.isStarting = FALSE;
1282                 CSL_dssVidPipeEnable(pipeRegs, FALSE);
1283                 Dss_dctrlDrvStopClient(instObj->dctrlHandle, dummyStart);
1284                 GT_0trace(DssTrace, GT_ERR, "Driver start failed!!\r\n");
1285             }
1286         }
1287         else
1288         {
1289             instObj->drvState.isStarting = TRUE;
1290             retVal = Dss_dctrlDrvStartClient(instObj->dctrlHandle, TRUE);
1291             if(FVID2_SOK != retVal)
1292             {
1293                 instObj->drvState.isStarting = FALSE;
1294                 Dss_dctrlDrvStopClient(instObj->dctrlHandle, TRUE);
1295                 GT_0trace(DssTrace, GT_ERR, "Driver start failed!!\r\n");
1296             }
1297         }
1298     }
1300     if(FVID2_SOK != retVal)
1301     {
1302         GT_0trace(DssTrace, GT_ERR, "Fvid2 start failed\r\n");
1303     }
1305     /* Post the instance semaphore */
1306     (void) SemaphoreP_post(instObj->lockSem);
1308     return (retVal);
1311 static int32_t Dss_dispDrvStopIoctl(Dss_DispDrvInstObj *instObj)
1313     int32_t  retVal = FVID2_SOK;
1314     uint32_t cookie;
1315     Dss_DispDrvQueObj *qObj;
1316     CSL_dss_pipeRegs *pipeRegs;
1317     const Dss_SocInfo *socInfo;
1319     /* Check for NULL pointers */
1320     GT_assert(DssTrace, (NULL != instObj));
1322     /* Take the instance semaphore */
1323     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1325     if(FALSE == instObj->createParams.progPipeVsyncEnable)
1326     {
1327         /* Get video pipe registers */
1328         socInfo = Dss_getSocInfo();
1329         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1330         GT_assert(DssTrace, (NULL != pipeRegs));
1332         /* Disable Video Pipe */
1333         CSL_dssVidPipeEnable(pipeRegs, FALSE);
1334         instObj->currFrame = NULL;
1335         instObj->progFrame = NULL;
1336         retVal = Dss_dctrlDrvStopClient(instObj->dctrlHandle, FALSE);
1338         if(FVID2_SOK == retVal)
1339         {
1340             cookie = HwiP_disable();
1342             instObj->drvState.isStarted = FALSE;
1344             /* Take the buffers in current state and push them in to the request
1345              * queue so that the next start will use those buffers */
1346             qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
1347                                                         instObj->bmObj.currQ);
1348             while (NULL != qObj)
1349             {
1350                 qObj->creditCnt = 0U;
1351                 /* Push it to the request queue */
1352                 Fvid2Utils_queueBack(instObj->bmObj.reqQ, &qObj->qElem, qObj);
1353                 qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
1354                                                         instObj->bmObj.currQ);
1355             };
1357             HwiP_restore(cookie);
1358         }
1359     }
1360     else
1361     {
1362         instObj->drvState.isStopping = TRUE;
1363         instObj->drvState.isStarted = FALSE;
1364         retVal = Dss_dctrlDrvStopClient(instObj->dctrlHandle, TRUE);
1365     }
1367     if(FVID2_SOK != retVal)
1368     {
1369         GT_0trace(DssTrace, GT_ERR, "Fvid2 stop failed\r\n");
1370     }
1372     /* Post the instance semaphore */
1373     (void) SemaphoreP_post(instObj->lockSem);
1375     return (retVal);
1378 static int32_t Dss_dispDrvSetDssParamsIoctl(Dss_DispDrvInstObj *instObj,
1379                                             const Dss_DispParams *dispParams)
1381     int32_t retVal = FVID2_SOK;
1382     uint32_t layerNum;
1383     CSL_DssOverlayPipePosCfg overlayPosCfg;
1384     CSL_dss_pipeRegs *pipeRegs;
1385     CSL_dss_overlayRegs *overlayRegs;
1386     const Dss_SocInfo *socInfo;
1387     Dss_DctrlDrvPipeInfo *pipeInfo;
1388     Dss_DispParams *pipeParams;
1390     GT_assert(DssTrace, (NULL != instObj));
1392     /* Check for wrong inputs */
1393     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == dispParams))
1394     {
1395         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1396         retVal = FVID2_EBADARGS;
1397     }
1399     /* Take the instance semaphore */
1400     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1402     if(FVID2_SOK == retVal)
1403     {
1404         pipeInfo = Dss_dctrlDrvGetPipeInfo(instObj->dctrlHandle);
1405         pipeParams = &instObj->pipeParams[instObj->pipeId];
1407         /* Get video pipe registers */
1408         socInfo = Dss_getSocInfo();
1409         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1410         GT_assert(DssTrace, (NULL != pipeRegs));
1412         /* Get overlay registers */
1413         overlayRegs = socInfo->overlayRegs[pipeInfo->overlayId];
1414         GT_assert(DssTrace, (NULL != overlayRegs));
1416         retVal = Dss_dispDrvValidateDssParams(
1417                                         (const Dss_DispDrvInstObj *)instObj,
1418                                         (const Dss_DispParams *)dispParams);
1419     }
1421     if(FVID2_SOK == retVal)
1422     {
1423         Fvid2Utils_memcpy(pipeParams, dispParams, sizeof(Dss_DispParams));
1424         retVal = CSL_dssVidPipeSetConfig(
1425                         pipeRegs,
1426                         (const CSL_DssVidPipeCfg *)(&dispParams->pipeCfg),
1427                         (const CSL_DssVidPipeVC1Cfg *)(&dispParams->vc1Cfg));
1428     }
1430     if(FVID2_SOK == retVal)
1431     {
1432         instObj->inScanFormat = dispParams->pipeCfg.inFmt.scanFormat;
1433         CSL_dssVidPipeSetDmaConfig(
1434                     pipeRegs,
1435                     (const CSL_DssVidPipeDmaCfg *)(&dispParams->dmaCfg));
1437         CSL_dssVidPipeSetAlphaConfig(
1438                     pipeRegs,
1439                     (const CSL_DssVidPipeAlphaCfg *)(&dispParams->alphaCfg));
1441 #if defined (SOC_J721E)
1442         CSL_dssVidPipeSetCropConfig(
1443                 pipeRegs,
1444                 (const Fvid2_EdgeCropConfig *)(&dispParams->cropParams.cropCfg),
1445                 dispParams->cropParams.cropEnable);
1446 #endif
1448         layerNum = CSL_dssOverlayGetEnabledPipeLayerNum(overlayRegs,
1449                                                         pipeInfo->pipeId);
1450         GT_assert(DssTrace, (layerNum < CSL_DSS_OVERLAY_LAYER_MAX));
1451         overlayPosCfg.layerPos.startX = dispParams->layerPos.startX;
1452         overlayPosCfg.layerPos.startY = dispParams->layerPos.startY;
1453         CSL_dssOverlaySetPipePosConfig(
1454                     overlayRegs,
1455                     (const CSL_DssOverlayPipePosCfg *)(&overlayPosCfg),
1456                     layerNum);
1457         pipeInfo->startX = dispParams->layerPos.startX;
1458         pipeInfo->startY = dispParams->layerPos.startY;
1459     }
1461     if(FVID2_SOK != retVal)
1462     {
1463         GT_0trace(DssTrace, GT_ERR, "Set DSS parameter IOCTL failed\r\n");
1464     }
1466     /* Post the instance semaphore */
1467     (void) SemaphoreP_post(instObj->lockSem);
1469     return (retVal);
1472 static int32_t Dss_dispDrvSetMflagParamsIoctl(
1473                                     Dss_DispDrvInstObj *instObj,
1474                                     const Dss_DispPipeMflagParams *mflagParams)
1476     int32_t retVal = FVID2_SOK;
1477     CSL_dss_pipeRegs *pipeRegs;
1478     const Dss_SocInfo *socInfo;
1480     GT_assert(DssTrace, (NULL != instObj));
1482     /* Check for wrong inputs */
1483     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == mflagParams))
1484     {
1485         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1486         retVal = FVID2_EBADARGS;
1487     }
1489     /* Take the instance semaphore */
1490     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1492     if(FVID2_SOK == retVal)
1493     {
1494         /* Get video pipe registers */
1495         socInfo = Dss_getSocInfo();
1496         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1497         GT_assert(DssTrace, (NULL != pipeRegs));
1499         if(TRUE == instObj->drvState.isStarted)
1500         {
1501             retVal = FVID2_EDEVICE_INUSE;
1502             GT_0trace(DssTrace,
1503                     GT_ERR,
1504                     "Cannot set MFLAG parameters while display is in use\r\n");
1505         }
1507         CSL_dssVidPipeSetMflagConfig(
1508                     pipeRegs,
1509                     (const CSL_DssVidPipeMFlagCfg *)(&mflagParams->mflagCfg));
1510     }
1512     if(FVID2_SOK != retVal)
1513     {
1514         GT_0trace(DssTrace, GT_ERR, "Set MFLAG parameters IOCTL failed\r\n");
1515     }
1517     /* Post the instance semaphore */
1518     (void) SemaphoreP_post(instObj->lockSem);
1520     return (retVal);
1523 static int32_t Dss_dispDrvGetStatusIoctl(Dss_DispDrvInstObj *instObj,
1524                                          Dss_DispCurrentStatus *dispStatus)
1526     int32_t retVal = FVID2_SOK;
1528     GT_assert(DssTrace, (NULL != instObj));
1530     /* Check for wrong inputs */
1531     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == dispStatus))
1532     {
1533         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1534         retVal = FVID2_EBADARGS;
1535     }
1537     /* Take the instance semaphore */
1538     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1540     if(FVID2_SOK == retVal)
1541     {
1542         Fvid2Utils_memcpy(dispStatus,
1543                           &instObj->currStatus,
1544                           sizeof(Dss_DispCurrentStatus));
1545     }
1547     if(FVID2_SOK != retVal)
1548     {
1549         GT_0trace(DssTrace, GT_ERR, "Get status IOCTL failed\r\n");
1550     }
1552     /* Post the instance semaphore */
1553     (void) SemaphoreP_post(instObj->lockSem);
1555     return (retVal);
1558 static int32_t Dss_dispDrvSetPipeSafetyParamsIoctl(
1559                             Dss_DispDrvInstObj *instObj,
1560                             const Dss_DispPipeSafetyChkParams *safetyChkParams)
1562     int32_t retVal = FVID2_SOK;
1563     uint32_t eventGroup, numHandle, evtMgrId, safetyEvt;
1564     CSL_dss_pipeRegs *pipeRegs;
1565     const Dss_SocInfo *socInfo;
1566     const CSL_DssSafetyChkCfg *safetyChkCfg;
1568     /* Check for NULL pointers */
1569     GT_assert(DssTrace, (NULL != instObj));
1570     /* Check for wrong inputs */
1571     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == safetyChkParams))
1572     {
1573         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1574         retVal = FVID2_EBADARGS;
1575     }
1577     /* Take the instance semaphore */
1578     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1580     if(FVID2_SOK == retVal)
1581     {
1582         /* Get video pipe registers */
1583         socInfo = Dss_getSocInfo();
1584         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1585         GT_assert(DssTrace, (NULL != pipeRegs));
1587         Fvid2Utils_memcpy(&instObj->safetyChkParams,
1588                           safetyChkParams,
1589                           sizeof (Dss_DispPipeSafetyChkParams));
1591         /* Register for Safety Error Events */
1592         Dss_convModuletoEventGroup(&eventGroup,
1593                                    instObj->drvInstId,
1594                                    DSS_EVENT_GROUP_TYPE_PIPE);
1595         GT_assert(DssTrace, (DSS_EVENT_GROUP_INVALID != eventGroup));
1596         safetyEvt = DSS_PIPE_EVENT_SAFETY_VIOLATION;
1597         numHandle = instObj->numRegEvtHandle;
1598         evtMgrId = Dss_getEvtMgrSafetyIntrId();
1599         instObj->evtGroupHandle[instObj->numRegEvtHandle] =
1600                             Dss_evtMgrRegister(
1601                                 evtMgrId,
1602                                 eventGroup,
1603                                 (const uint32_t *)&safetyEvt,
1604                                 1U,
1605                                 Dss_dispSafetyErrCbFxn,
1606                                 (void *)&gDss_DispEvtMgrClientInfo[numHandle]);
1607         instObj->numRegEvtHandle++;
1609         /* Call CSL APIs */
1610         if(0U != safetyChkParams->safetySignSeedVal)
1611         {
1612             CSL_dssVidPipeSetSafetySignSeedVal(
1613                                         pipeRegs,
1614                                         safetyChkParams->safetySignSeedVal);
1615         }
1616         if(CSL_DSS_SAFETY_CHK_DATA_INTEGRITY ==
1617                                     safetyChkParams->safetyChkCfg.safetyChkMode)
1618         {
1619             CSL_dssVidPipeSetSafetyReferenceSign(
1620                             pipeRegs,
1621                             safetyChkParams->referenceSign);
1622         }
1623         safetyChkCfg = &safetyChkParams->safetyChkCfg;
1624         CSL_dssVidPipeSetSafetyChkConfig(pipeRegs, safetyChkCfg);
1625     }
1627     if(FVID2_SOK != retVal)
1628     {
1629         GT_0trace(DssTrace,
1630                   GT_ERR,
1631                   "Register Safety Error Cb Params IOCTL failed\r\n");
1632     }
1634     /* Post the instance semaphore */
1635     (void) SemaphoreP_post(instObj->lockSem);
1637     return retVal;
1640 static int32_t Dss_dispDrvSetPipeCscParamsIoctl(
1641                             Dss_DispDrvInstObj *instObj,
1642                             const CSL_DssCscCoeff *cscCoeff)
1644     int32_t retVal = FVID2_SOK;
1645     CSL_dss_pipeRegs *pipeRegs;
1646     const Dss_SocInfo *socInfo;
1648     GT_assert(DssTrace, (NULL != instObj));
1650     /* Check for wrong inputs */
1651     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == cscCoeff))
1652     {
1653         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1654         retVal = FVID2_EBADARGS;
1655     }
1657     /* Take the instance semaphore */
1658     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1660     if(FVID2_SOK == retVal)
1661     {
1662         /* Get video pipe registers */
1663         socInfo = Dss_getSocInfo();
1664         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1665         GT_assert(DssTrace, (NULL != pipeRegs));
1667         CSL_dssVidPipeSetCSCCoeff(
1668                         pipeRegs,
1669                         (const CSL_DssCscCoeff *)(cscCoeff));
1670     }
1672     if(FVID2_SOK != retVal)
1673     {
1674         GT_0trace(DssTrace, GT_ERR, "Set CSC coefficients IOCTL failed\r\n");
1675     }
1677     /* Post the instance semaphore */
1678     (void) SemaphoreP_post(instObj->lockSem);
1680     return (retVal);
1683 static int32_t Dss_dispDrvSetBufPrgmCbParamsIoctl(
1684                             Dss_DispDrvInstObj *instObj,
1685                             const Dss_DispBufPrgmCbParams *bufPrgmCbParams)
1687     int32_t retVal = FVID2_SOK;
1689     /* Check for NULL pointers */
1690     GT_assert(DssTrace, (NULL != instObj));
1692     /* Check for wrong inputs */
1693     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == bufPrgmCbParams))
1694     {
1695         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1696         retVal = FVID2_EBADARGS;
1697     }
1699     /* Take the instance semaphore */
1700     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1702     if(FVID2_SOK == retVal)
1703     {
1704         /* IOCTL supported only when display is stopped */
1705         if(TRUE == instObj->drvState.isStarted)
1706         {
1707             GT_0trace(DssTrace, GT_ERR, "Display in progress!!\r\n");
1708             retVal = FVID2_EFAIL;
1709         }
1710     }
1712     if(FVID2_SOK == retVal)
1713     {
1714         instObj->bufPrgmCbParams.bufPrgmCbFxn = bufPrgmCbParams->bufPrgmCbFxn;
1715     }
1717     if(FVID2_SOK != retVal)
1718     {
1719         GT_0trace(DssTrace,
1720                   GT_ERR,
1721                   "Set buffer program callback IOCTL failed\r\n");
1722     }
1724     /* Post the instance semaphore */
1725     (void) SemaphoreP_post(instObj->lockSem);
1727     return (retVal);
1730 static int32_t Dss_dispDrvSetPipePrgmCbParamsIoctl(
1731                             Dss_DispDrvInstObj *instObj,
1732                             const Dss_DispPipePrgmCbParams *pipePrgmCbParams)
1734     int32_t retVal = FVID2_SOK;
1736     /* Check for NULL pointers */
1737     GT_assert(DssTrace, (NULL != instObj));
1739     /* Check for wrong inputs */
1740     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == pipePrgmCbParams))
1741     {
1742         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1743         retVal = FVID2_EBADARGS;
1744     }
1746     /* Take the instance semaphore */
1747     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1749     if(FVID2_SOK == retVal)
1750     {
1751         /* IOCTL supported only when display is stopped */
1752         if(TRUE == instObj->drvState.isStarted)
1753         {
1754             GT_0trace(DssTrace, GT_ERR, "Display in progress!!\r\n");
1755             retVal = FVID2_EFAIL;
1756         }
1757     }
1759     if(FVID2_SOK == retVal)
1760     {
1761         Fvid2Utils_memcpy(&instObj->pipePrgmCbParams,
1762                           pipePrgmCbParams,
1763                           sizeof (Dss_DispPipePrgmCbParams));
1764     }
1766     if(FVID2_SOK != retVal)
1767     {
1768         GT_0trace(DssTrace,
1769                   GT_ERR,
1770                   "Set pipe program callback IOCTL failed\r\n");
1771     }
1773     /* Post the instance semaphore */
1774     (void) SemaphoreP_post(instObj->lockSem);
1776     return (retVal);
1779 static int32_t Dss_dispDrvSetPipeUnderFlowCbParamsIoctl(
1780                             Dss_DispDrvInstObj *instObj,
1781                             const Dss_DispUnderFlowCbParams *underFlowCbParams)
1783     int32_t retVal = FVID2_SOK;
1785     /* Check for NULL pointers */
1786     GT_assert(DssTrace, (NULL != instObj));
1788     /* Check for wrong inputs */
1789     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == underFlowCbParams))
1790     {
1791         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1792         retVal = FVID2_EBADARGS;
1793     }
1795     /* Take the instance semaphore */
1796     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1798     if(FVID2_SOK == retVal)
1799     {
1800         /* IOCTL supported only when display is stopped */
1801         if(TRUE == instObj->drvState.isStarted)
1802         {
1803             GT_0trace(DssTrace, GT_ERR, "Display in progress!!\r\n");
1804             retVal = FVID2_EFAIL;
1805         }
1806     }
1808     if(FVID2_SOK == retVal)
1809     {
1810         Fvid2Utils_memcpy(&instObj->underFlowCbParams,
1811                           underFlowCbParams,
1812                           sizeof (Dss_DispUnderFlowCbParams));
1813     }
1815     if(FVID2_SOK != retVal)
1816     {
1817         GT_0trace(DssTrace,
1818                   GT_ERR,
1819                   "Set pipe underflow callback IOCTL failed\r\n");
1820     }
1822     /* Post the instance semaphore */
1823     (void) SemaphoreP_post(instObj->lockSem);
1825     return (retVal);
1828 static int32_t Dss_dispDrvValidateDssParams(const Dss_DispDrvInstObj *instObj,
1829                                             const Dss_DispParams *dispParams)
1831     int32_t retVal = FVID2_SOK;
1833     if((FALSE == Dss_dispIsVidInst(instObj->drvInstId)) &&
1834        (FALSE == Dss_dispIsVidLInst(instObj->drvInstId)))
1835     {
1836         GT_0trace(DssTrace,
1837                   GT_ERR,
1838                   "Invalid Driver Id\r\n");
1839         retVal = FVID2_EINVALID_PARAMS;
1840     }
1841     if(((dispParams->pipeCfg.outWidth + dispParams->layerPos.startX) >
1842                                                         instObj->dispWidth) ||
1843        ((dispParams->pipeCfg.outHeight + dispParams->layerPos.startY) >
1844                                                         instObj->dispHeight))
1845     {
1846         GT_0trace(DssTrace,
1847                   GT_ERR,
1848                   "Input width+startX/height+startY > display width/height\r\n");
1849         retVal = FVID2_EINVALID_PARAMS;
1850     }
1852     /* Interlaced to progressive or vice versa*/
1853     if(dispParams->pipeCfg.inFmt.scanFormat != instObj->dispScanFormat)
1854     {
1855         GT_0trace(DssTrace,
1856                   GT_ERR,
1857                   "Format(interlaced/progressive) conversion not supported\r\n");
1858         retVal = FVID2_EINVALID_PARAMS;
1859     }
1861     /* Scaling ratio check */
1862     if(((dispParams->pipeCfg.inFmt.height * 16U) <
1863                                         (dispParams->pipeCfg.outHeight)) ||
1864        ((dispParams->pipeCfg.inFmt.width * 16U) <
1865                                         (dispParams->pipeCfg.outWidth)))
1866     {
1867         GT_0trace(DssTrace,
1868                   GT_ERR,
1869                   "Upscaling ratio is more than 16x \r\n");
1870         retVal = FVID2_EINVALID_PARAMS;
1871     }
1872     if(((dispParams->pipeCfg.inFmt.height) >
1873                                     (dispParams->pipeCfg.outHeight * 4U)) ||
1874        ((dispParams->pipeCfg.inFmt.width) >
1875                                     (dispParams->pipeCfg.outWidth * 4U)))
1876     {
1877         GT_0trace(DssTrace,
1878                   GT_ERR,
1879                   "Downscaling ratio is more than 0.25x \r\n");
1880         retVal = FVID2_EINVALID_PARAMS;
1881     }
1883     if((dispParams->pipeCfg.inFmt.height != dispParams->pipeCfg.outHeight) ||
1884        (dispParams->pipeCfg.inFmt.width != dispParams->pipeCfg.outWidth))
1885     {
1886         if(TRUE == Dss_dispIsVidLInst(instObj->drvInstId))
1887         {
1888             GT_0trace(DssTrace,
1889                       GT_ERR,
1890                       "Scaling cant be enabled for video lite pipe \r\n");
1891             retVal = FVID2_EINVALID_PARAMS;
1892         }
1893         if(FALSE == dispParams->pipeCfg.scEnable)
1894         {
1895             GT_0trace(DssTrace,
1896                       GT_ERR,
1897                       "Scaling should be enabled \r\n");
1898             retVal = FVID2_EINVALID_PARAMS;
1899         }
1900     }
1902     if((dispParams->cropParams.cropCfg.cropTop >= 32U) ||
1903        (dispParams->cropParams.cropCfg.cropBottom >= 32U) ||
1904        (dispParams->cropParams.cropCfg.cropLeft >= 32U) ||
1905        (dispParams->cropParams.cropCfg.cropRight >= 32U))
1906     {
1907         GT_0trace(DssTrace,
1908                   GT_ERR,
1909                   "Crop Parameter(s) should be less than 32 \r\n");
1910         retVal = FVID2_EINVALID_PARAMS;
1911     }
1913     if(((dispParams->pipeCfg.flipType == FVID2_FLIP_TYPE_V) ||
1914         (dispParams->pipeCfg.flipType == FVID2_FLIP_TYPE_H)) &&
1915        ((dispParams->pipeCfg.inFmt.dataFormat == FVID2_DF_RGB24_888) ||
1916         (dispParams->pipeCfg.inFmt.dataFormat == FVID2_DF_BGR24_888)))
1917     {
1918         GT_0trace(DssTrace,
1919                   GT_ERR,
1920                   "Flip Parameter(s) should not be used for 24-bit RGB/BGR formats \r\n");
1921         retVal = FVID2_EINVALID_PARAMS;
1922     }
1924     /* There is a limitation with scaling in DSS, where maximum scaling ratio
1925      * supported is the ratio of the DSS functional clock and Pixel Clock.
1926      * Driver can't check this condition as it is unaware of Pixel Clock.
1927      * So it should be checked by the application.
1928      */
1929     return retVal;
1932 static int32_t Dss_dispDrvValidateRtParams(const Dss_DispDrvInstObj *instObj,
1933                                            const Dss_DispRtParams *rtParams)
1935     int32_t retVal = FVID2_SOK;
1936     const Dss_DispParams *pipeParams;
1937     const Dss_FrameRtParams *frameRtParams;
1939     if(NULL != rtParams->outFrmParams)
1940     {
1941         if(((rtParams->outFrmParams->width + rtParams->posCfg->startX) >
1942                                                         instObj->dispWidth) ||
1943            ((rtParams->outFrmParams->height + rtParams->posCfg->startY) >
1944                                                         instObj->dispHeight))
1945         {
1946             retVal = FVID2_EINVALID_PARAMS;
1947         }
1948     }
1950     if((NULL != rtParams->outFrmParams) && (NULL != rtParams->inFrmParams))
1951     {
1952         /* Scaling ratio check */
1953         if(((rtParams->inFrmParams->height * 16U) <
1954                                     (rtParams->outFrmParams->height)) ||
1955            ((rtParams->inFrmParams->width * 16U) <
1956                                     (rtParams->outFrmParams->width)))
1957         {
1958             retVal = FVID2_EINVALID_PARAMS;
1959         }
1960         if(((rtParams->inFrmParams->height) >
1961                                     (rtParams->outFrmParams->height * 4U)) ||
1962            ((rtParams->inFrmParams->width) >
1963                                     (rtParams->outFrmParams->width * 4U)))
1964         {
1965             retVal = FVID2_EINVALID_PARAMS;
1966         }
1967         if((rtParams->inFrmParams->height != rtParams->outFrmParams->height) ||
1968            (rtParams->inFrmParams->width != rtParams->outFrmParams->width))
1969         {
1970             if(TRUE == Dss_dispIsVidLInst(instObj->drvInstId))
1971             {
1972                 retVal = FVID2_EINVALID_PARAMS;
1973             }
1974         }
1975     }
1977     if(NULL != rtParams->inFrmParams)
1978     {
1979         pipeParams = &instObj->pipeParams[instObj->pipeId];
1980         frameRtParams = rtParams->inFrmParams;
1981         if(((pipeParams->pipeCfg.flipType == FVID2_FLIP_TYPE_V) ||
1982            (pipeParams->pipeCfg.flipType == FVID2_FLIP_TYPE_H)) &&
1983           ((frameRtParams->dataFormat == FVID2_DF_RGB24_888) ||
1984            (frameRtParams->dataFormat == FVID2_DF_BGR24_888)))
1985         {
1986             GT_0trace(DssTrace,
1987                       GT_ERR,
1988                       "Flip Parameter(s) should not be used for 24-bit RGB/BGR formats \r\n");
1989             retVal = FVID2_EINVALID_PARAMS;
1990         }
1991     }
1993     /* There is a limitation with scaling in DSS, where maximum scaling ratio
1994      * supported is the ratio of the DSS functional clock and Pixel Clock.
1995      * Driver can't check this condition as it is unaware of Pixel Clock.
1996      * So it should be checked by the application.
1997      */
1998     return retVal;
2001 static int32_t Dss_dispDrvApplyRtParams(Dss_DispDrvInstObj *instObj,
2002                                         const Dss_DispRtParams *rtParams)
2004     int32_t rtParamsRetVal = FVID2_SOK;
2005     uint32_t i, layerNum;
2006     CSL_dss_pipeRegs *pipeRegs;
2007     CSL_dss_overlayRegs *overlayRegs;
2008     const Dss_SocInfo *socInfo;
2009     uint32_t pipeRtUpdate = FALSE;
2010     Dss_DctrlDrvPipeInfo *pipeInfo;
2011     CSL_DssOverlayPipePosCfg overlayPosCfg;
2012     Dss_DispParams *pipeParams;
2014     /* Get video pipe registers */
2015     socInfo = Dss_getSocInfo();
2016     pipeRegs = socInfo->pipeRegs[instObj->pipeId];
2017     GT_assert(DssTrace, (NULL != pipeRegs));
2019     pipeParams = &instObj->pipeParams[instObj->pipeId];
2020     if(NULL != rtParams->scParams)
2021     {
2022         pipeRtUpdate = TRUE;
2023         pipeParams->pipeCfg.pixelInc = rtParams->scParams->pixelInc;
2024     }
2025     if(NULL != rtParams->inFrmParams)
2026     {
2027         pipeRtUpdate = TRUE;
2028         pipeParams->pipeCfg.inFmt.width  = rtParams->inFrmParams->width;
2029         pipeParams->pipeCfg.inFmt.height = rtParams->inFrmParams->height;
2030         pipeParams->pipeCfg.inFmt.dataFormat =
2031                                             rtParams->inFrmParams->dataFormat;
2032         for(i=0U; i<FVID2_MAX_PLANES; i++)
2033         {
2034             pipeParams->pipeCfg.inFmt.pitch[i] =
2035                                             rtParams->inFrmParams->pitch[i];
2036         }
2037     }
2038     if((NULL != rtParams->outFrmParams) &&
2039        (TRUE == Dss_dispIsVidInst(instObj->drvInstId)))
2040     {
2041         pipeRtUpdate = TRUE;
2042         pipeParams->pipeCfg.outWidth  = rtParams->outFrmParams->width;
2043         pipeParams->pipeCfg.outHeight = rtParams->outFrmParams->height;
2044     }
2045     if(TRUE == pipeRtUpdate)
2046     {
2047         rtParamsRetVal =
2048             CSL_dssVidPipeSetConfig(
2049                         pipeRegs,
2050                         (const CSL_DssVidPipeCfg *)(&pipeParams->pipeCfg),
2051                         (const CSL_DssVidPipeVC1Cfg *)(&pipeParams->vc1Cfg));
2052         GT_assert(DssTrace, (FVID2_SOK == rtParamsRetVal));
2053     }
2054     if(NULL != rtParams->posCfg)
2055     {
2056         pipeInfo = Dss_dctrlDrvGetPipeInfo(instObj->dctrlHandle);
2057         /* Get overlay registers */
2058         overlayRegs = socInfo->overlayRegs[pipeInfo->overlayId];
2059         GT_assert(DssTrace, (NULL != overlayRegs));
2060         layerNum = CSL_dssOverlayGetEnabledPipeLayerNum(overlayRegs,
2061                                                         pipeInfo->pipeId);
2062         GT_assert(DssTrace, (layerNum < CSL_DSS_OVERLAY_LAYER_MAX));
2063         overlayPosCfg.layerPos.startX = rtParams->posCfg->startX;
2064         overlayPosCfg.layerPos.startY = rtParams->posCfg->startY;
2065         CSL_dssOverlaySetPipePosConfig(
2066                             overlayRegs,
2067                             (const CSL_DssOverlayPipePosCfg *)(&overlayPosCfg),
2068                             layerNum);
2069         pipeInfo->startX = rtParams->posCfg->startX;
2070         pipeInfo->startY = rtParams->posCfg->startY;
2071     }
2072     return rtParamsRetVal;
2075 static void Dss_dispSafetyErrCbFxn(const uint32_t *event,
2076                                    uint32_t numEvents,
2077                                    void *arg)
2079     uint32_t  i, currEvent, pipeId = 0U;
2080     Dss_EvtMgrClientInfo *pClientObj = (Dss_EvtMgrClientInfo *)arg;
2081     uint32_t eventGroup = pClientObj->eventGroup;
2082     Dss_DispDrvInstObj *instObj;
2083     CSL_dss_pipeRegs *pipeRegs;
2084     const Dss_SocInfo *socInfo;
2086     /* Get pipe id */
2087     Dss_convEventGrouptoModule(eventGroup, &pipeId);
2088     GT_assert(DssTrace, (CSL_DSS_MODULE_INVALID != pipeId));
2089     instObj = Dss_dispDrvGetInstObj(pipeId);
2090     /* Instobj cannot be NULL */
2091     GT_assert(DssTrace, (NULL != instObj));
2092     /* Get video pipe registers */
2093     socInfo = Dss_getSocInfo();
2094     pipeRegs = socInfo->pipeRegs[pipeId];
2095     GT_assert(DssTrace, (NULL != pipeRegs));
2097     for(i=0U; i<numEvents; i++)
2098     {
2099         currEvent = event[i];
2100         if(DSS_PIPE_EVENT_SAFETY_VIOLATION == currEvent)
2101         {
2102             instObj->currStatus.safetyViolationCount++;
2103             if(CSL_DSS_SAFETY_CHK_DATA_INTEGRITY ==
2104                             instObj->safetyChkParams.safetyChkCfg.safetyChkMode)
2105             {
2106                 instObj->safetyChkParams.capturedSign =
2107                                         CSL_dssVidPipeGetSafetySign(pipeRegs);
2108             }
2109             if(NULL != instObj->safetyChkParams.safetyErrCbFxn)
2110             {
2111                 instObj->safetyChkParams.safetyErrCbFxn(
2112                                          instObj->safetyChkParams.capturedSign,
2113                                          instObj->safetyChkParams.appData);
2114             }
2115         }
2116         else
2117         {
2118             GT_assert(DssTrace, FALSE);
2119         }
2120     }
2122     return;
2125 static uint32_t Dss_dispIsFarFromVsync(const Dss_DispDrvInstObj *instObj)
2127     uint32_t isFarFromVsync = FALSE;
2129     isFarFromVsync = Dss_dctrlDrvIsSafeToPush(instObj->dctrlHandle);
2131     if(instObj->dispHeight <= DSS_DISP_NUM_LINES_NEAR_VSYNC)
2132     {
2133         isFarFromVsync = FALSE;
2134     }
2136     return isFarFromVsync;