[DSS DRV][Bug Fix][PDK-5040]Display stops working if two pipelines are started back...
[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 extern SemaphoreP_Handle gDssStartSyncSem;
111 /* ========================================================================== */
112 /*                  Internal/Private Function Declarations                    */
113 /* ========================================================================== */
115 /*
116  * Display IOCTLs
117  */
118 static void Dss_dispDrvClientCb(void *arg0);
119 static int32_t Dss_dispDrvStartIoctl(Dss_DispDrvInstObj *instObj);
120 static int32_t Dss_dispDrvStopIoctl(Dss_DispDrvInstObj *instObj);
121 static int32_t Dss_dispDrvSetDssParamsIoctl(Dss_DispDrvInstObj *instObj,
122                                             const Dss_DispParams *dispParams);
123 static int32_t Dss_dispDrvSetMflagParamsIoctl(
124                                     Dss_DispDrvInstObj *instObj,
125                                     const Dss_DispPipeMflagParams *mflagParams);
126 static int32_t Dss_dispDrvGetStatusIoctl(Dss_DispDrvInstObj *instObj,
127                                          Dss_DispCurrentStatus *dispStatus);
128 static int32_t Dss_dispDrvSetPipeSafetyParamsIoctl(
129                             Dss_DispDrvInstObj *instObj,
130                             const Dss_DispPipeSafetyChkParams *safetyChkParams);
131 static int32_t Dss_dispDrvSetPipeCscParamsIoctl(
132                             Dss_DispDrvInstObj *instObj,
133                             const CSL_DssCscCoeff *cscCoeff);
134 static int32_t Dss_dispDrvSetBufPrgmCbParamsIoctl(
135                             Dss_DispDrvInstObj *instObj,
136                             const Dss_DispBufPrgmCbParams *bufPrgmCbParams);
137 static int32_t Dss_dispDrvSetPipePrgmCbParamsIoctl(
138                             Dss_DispDrvInstObj *instObj,
139                             const Dss_DispPipePrgmCbParams *pipePrgmCbParams);
140 static int32_t Dss_dispDrvSetPipeUnderFlowCbParamsIoctl(
141                             Dss_DispDrvInstObj *instObj,
142                             const Dss_DispUnderFlowCbParams *underFlowCbParams);
143 static int32_t Dss_dispDrvValidateDssParams(const Dss_DispDrvInstObj *instObj,
144                                             const Dss_DispParams *dispParams);
145 static int32_t Dss_dispDrvValidateRtParams(const Dss_DispDrvInstObj *instObj,
146                                            const Dss_DispRtParams *rtParams);
147 static int32_t Dss_dispDrvApplyRtParams(Dss_DispDrvInstObj *instObj,
148                                         const Dss_DispRtParams *rtParams);
149 static void Dss_dispSafetyErrCbFxn(const uint32_t *event,
150                                    uint32_t numEvents,
151                                    void *arg);
152 static uint32_t Dss_dispIsFarFromVsync(const Dss_DispDrvInstObj *instObj);
154 /* ========================================================================== */
155 /*                          Function Definitions                              */
156 /* ========================================================================== */
158 int32_t Dss_dispDrvInit(uint32_t numInst,
159                         const Dss_DispDrvInitParams *initParams)
161     int32_t retVal = FVID2_SOK;
162     Dss_DispDrvCommonObj *pObj;
164     retVal = Dss_dispDrvPrivInit(numInst, initParams);
165     if(FVID2_SOK == retVal)
166     {
167         pObj = &gDss_DispDrvCommonObj;
168         GT_assert(DssTrace, (NULL != pObj));
170         /* Initialize Driver operations */
171         Fvid2DrvOps_init(&pObj->fvidDrvOps);
173         pObj->fvidDrvOps.drvId = DSS_DISP_DRV_ID;
174         pObj->fvidDrvOps.createFxn = &Dss_dispDrvCreate;
175         pObj->fvidDrvOps.deleteFxn = &Dss_dispDrvDelete;
176         pObj->fvidDrvOps.controlFxn = &Dss_dispDrvControl;
177         pObj->fvidDrvOps.queueFxn = &Dss_dispDrvQueue;
178         pObj->fvidDrvOps.dequeueFxn = &Dss_dispDrvDequeue;
180         retVal = Fvid2_registerDriver(&pObj->fvidDrvOps);
181         if(FVID2_SOK != retVal)
182         {
183             GT_0trace(DssTrace, GT_ERR,
184                       "Registering to FVID2 driver manager failed\r\n");
185             /* Un-initialize the internal objects if error occurs */
186             retVal += Dss_dispDrvPrivDeInit();
187         }
188         else
189         {
190             /* Init successful */
191             pObj->isRegistered = TRUE;
192             pObj->numInst = numInst;
193         }
194     }
196     return (retVal);
199 int32_t Dss_dispDrvDeInit(void)
201     int32_t retVal = FVID2_SOK;
202     Dss_DispDrvCommonObj *pObj;
204     pObj = &gDss_DispDrvCommonObj;
205     GT_assert(DssTrace, (NULL != pObj));
207     if(TRUE == pObj->isRegistered)
208     {
209         /* Unregister from driver manager */
210         retVal = Fvid2_unRegisterDriver(&pObj->fvidDrvOps);
211         if(FVID2_SOK != retVal)
212         {
213             GT_0trace(DssTrace, GT_ERR,
214                       "Unregistering from FVID2 driver manager failed\r\n");
215         }
216         pObj->isRegistered = FALSE;
217     }
219     retVal += Dss_dispDrvPrivDeInit();
221     return (retVal);
224 /* ========================================================================== */
225 /*                       Static Function Definitions                          */
226 /* ========================================================================== */
228 static Fdrv_Handle Dss_dispDrvCreate(uint32_t drvId,
229                                      uint32_t instId,
230                                      void *createArgs,
231                                      void *createStatusArgs,
232                                      const Fvid2_DrvCbParams *fdmCbParams)
234     int32_t retVal = FVID2_SOK, tempRetVal;
235     uint32_t instCreateFlag = FALSE, nodeId;
236     Fdrv_Handle drvHandle = NULL;
237     Dss_DispDrvInstObj *instObj = NULL;
238     Dss_DispCreateParams *createParams;
239     Dss_DispCreateStatus *createStatus;
240     Dss_DctrlDrvClientInfo clientInfo;
241     Dss_DctrlVpParams vpParams;
243     /* Check for NULL pointers and invalid arguments */
244     if((NULL == createArgs) ||
245        (NULL == createStatusArgs) ||
246        (NULL == fdmCbParams) ||
247        (DSS_DISP_DRV_ID != drvId))
248     {
249         GT_0trace(DssTrace, GT_ERR, "Invalid arguments\r\n");
250         retVal = FVID2_EBADARGS;
251     }
252     else
253     {
254         /* Get the instance object for this instance */
255         instObj = Dss_dispDrvGetInstObj(instId);
256         if(NULL == instObj)
257         {
258             GT_0trace(DssTrace, GT_ERR, "Invalid instance ID\r\n");
259             retVal = FVID2_EINVALID_PARAMS;
260         }
261     }
263     if(NULL != instObj)
264     {
265         /* Take the instance semaphore */
266         (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
268         /* Check if the instance is already opened */
269         if(TRUE == instObj->drvState.isOpened)
270         {
271             GT_0trace(DssTrace,
272                       GT_ERR,
273                       "Driver instance already created!!\r\n");
274             retVal = FVID2_EDEVICE_INUSE;
275         }
276     }
278     if(FVID2_SOK == retVal)
279     {
280         /* Check for valid create parameters and copy them */
281         createParams = (Dss_DispCreateParams *) createArgs;
282         Fvid2Utils_memcpy(&instObj->createParams,
283                           createParams,
284                           sizeof (Dss_DispCreateParams));
285     }
287     if(FVID2_SOK == retVal)
288     {
289         retVal = Dss_dispDrvCreateInstObj(instObj);
290         if(FVID2_SOK != retVal)
291         {
292             GT_0trace(DssTrace, GT_ERR,
293                       "Channel object create failed!!\r\n");
294         }
295         else
296         {
297             instCreateFlag = TRUE;
298         }
299     }
301     if(FVID2_SOK == retVal)
302     {
303         instObj->pipeId = instId;
304         retVal = Dss_convModuletoNode(&nodeId, instObj->pipeId,
305                                       DSS_DCTRL_NODE_TYPE_PIPE);
306         GT_assert(DssTrace,
307                   ((DSS_DCTRL_NODE_INVALID != nodeId) ||
308                    (FVID2_SOK == retVal)));
309         instObj->pipeNodeId = nodeId;
310     }
312     if(FVID2_SOK == retVal)
313     {
314         /* Initialize instance variables */
315         Fvid2Utils_memcpy(
316             &instObj->fdmCbParams,
317             fdmCbParams,
318             sizeof (Fvid2_DrvCbParams));
320         instObj->drvState.isOpened = TRUE;
321         instObj->isPrevBufRep = FALSE;
322         instObj->isInIsrContext = FALSE;
323         drvHandle = instObj;
324     }
326     if(FVID2_SOK == retVal)
327     {
328         clientInfo.cbFxn = &Dss_dispDrvClientCb;
329         clientInfo.arg = instObj;
330         instObj->dctrlHandle = Dss_dctrlDrvRegisterClient(instObj->pipeNodeId,
331                                                           &clientInfo);
332         if(NULL == instObj->dctrlHandle)
333         {
334             GT_0trace(DssTrace,
335                       GT_ERR,
336                       "Display Controller registration failed for DSS");
337             retVal = FVID2_EALLOC;
338         }
339         else
340         {
341             retVal = Dss_dctrlDrvGetVpParams(instObj->dctrlHandle, &vpParams);
342             if(FVID2_SOK != retVal)
343             {
344                 GT_0trace(DssTrace,
345                           GT_ERR,
346                           "Getting information from Display controller failed");
347             }
348             else
349             {
350                 instObj->standard = vpParams.lcdOpTimingCfg.mInfo.standard;
351                 instObj->dispWidth = vpParams.lcdOpTimingCfg.mInfo.width;
352                 instObj->dispHeight = vpParams.lcdOpTimingCfg.mInfo.height;
353                 instObj->dispScanFormat =
354                                     vpParams.lcdOpTimingCfg.mInfo.scanFormat;
355                 instObj->vpId = vpParams.vpId;
356             }
357         }
358     }
360     if(FVID2_SOK != retVal)
361     {
362         if((NULL != instObj) && (NULL != instObj->dctrlHandle))
363         {
364             retVal += Dss_dctrlDrvUnRegisterClient(instObj->dctrlHandle);
365         }
366     }
368     /* Return the status if possible */
369     if(NULL != createStatusArgs)
370     {
371         createStatus = (Dss_DispCreateStatus *) createStatusArgs;
372         createStatus->retVal = retVal;
373         if(NULL != instObj)
374         {
375             createStatus->standard = instObj->standard;
376             createStatus->dispWidth = instObj->dispWidth;
377             createStatus->dispHeight = instObj->dispHeight;
378             createStatus->minNumPrimeBuf = DSS_DISP_DRV_MIN_PRIME_BUFFERS;
379         }
380     }
382     if(NULL != instObj)
383     {
384         /* Deallocate if error occurs */
385         if(FVID2_SOK != retVal)
386         {
387             if(TRUE == instCreateFlag)
388             {
389                 tempRetVal = Dss_dispDrvDeleteInstObj(instObj);
390                 GT_assert(DssTrace, (FVID2_SOK == tempRetVal));
391             }
392         }
394         /* Post the instance semaphore */
395         (void) SemaphoreP_post(instObj->lockSem);
396     }
398     return (drvHandle);
401 static int32_t Dss_dispDrvDelete(Fdrv_Handle handle, void *reserved)
403     int32_t retVal = FVID2_SOK;
404     Dss_DispDrvInstObj *instObj = NULL;
406     /* Check for NULL pointers and invalid arguments */
407     if(NULL == handle)
408     {
409         GT_0trace(DssTrace, GT_ERR, "Invalid arguments\r\n");
410         retVal = FVID2_EBADARGS;
411     }
412     else
413     {
414         instObj = (Dss_DispDrvInstObj *) handle;
415     }
417     if(NULL != instObj)
418     {
419         /* Take the instance semaphore */
420         (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
422         /* Check if already opened. */
423         if(TRUE != instObj->drvState.isOpened)
424         {
425             GT_0trace(DssTrace, GT_ERR, "Driver not opened\r\n");
426             retVal = FVID2_EFAIL;
427         }
428     }
430     if(FVID2_SOK == retVal)
431     {
432         /* If already started, stop it. */
433         if(TRUE == instObj->drvState.isStarted)
434         {
435             retVal = Dss_dispDrvStopIoctl(instObj);
436             if(FVID2_SOK != retVal)
437             {
438                 GT_0trace(DssTrace, GT_ERR, "Stop display failed\r\n");
439             }
440         }
441     }
443     if(FVID2_SOK == retVal)
444     {
445         if(NULL != instObj->dctrlHandle)
446         {
447             retVal = Dss_dctrlDrvUnRegisterClient(instObj->dctrlHandle);
448         }
449         retVal += Dss_dispDrvDeleteInstObj(instObj);
450         GT_assert(DssTrace, (FVID2_SOK == retVal));
452         /* Reset other variables */
453         instObj->drvState.isOpened = FALSE;
454         instObj->drvState.isStarted = FALSE;
455         instObj->currStatus.queueCount = 0U;
456         instObj->currStatus.dequeueCount = 0U;
457         instObj->currStatus.dispFrmCount = 0U;
458         instObj->currStatus.repeatFrmCount = 0U;
460         instObj->fdmCbParams.fdmCbFxn = NULL;
461         instObj->fdmCbParams.fdmErrCbFxn = NULL;
462         instObj->fdmCbParams.handle = NULL;
463         instObj->fdmCbParams.errList = NULL;
464         instObj->fdmCbParams.fdmData = NULL;
465     }
467     if(NULL != instObj)
468     {
469         /* Post the instance semaphore */
470         (void) SemaphoreP_post(instObj->lockSem);
471     }
473     return (retVal);
476 static int32_t Dss_dispDrvQueue(Fdrv_Handle handle,
477                                 Fvid2_FrameList *frmList,
478                                 uint32_t streamId)
480     int32_t  retVal = FVID2_SOK;
481     uint32_t frmCnt, cookie;
482     uint32_t reqQCnt, isSafe;
483     uint32_t isBufAccepted = TRUE;
484     Fvid2_Frame *frm, *newFrm;
485     Dss_DispDrvInstObj *instObj;
486     Dss_DispDrvQueObj *qObj, *qObjTemp;
487     CSL_dss_pipeRegs *pipeRegs;
488     const Dss_SocInfo *socInfo;
489     Dss_DispRtParams *rtParams;
490     int32_t rtParamsRetVal = FVID2_SOK;
492     /* Check for NULL pointers */
493     if((NULL == handle) || (NULL == frmList))
494     {
495         GT_0trace(DssTrace, GT_ERR, "NULL pointer\r\n");
496         retVal = FVID2_EBADARGS;
497     }
499     if(FVID2_SOK == retVal)
500     {
501         instObj = (Dss_DispDrvInstObj *) handle;
503         /* Check frame list for error and NULL pointer check */
504         retVal = Fvid2_checkFrameList(frmList, (uint32_t) FVID2_MAX_FRAME_PTR);
505         if(FVID2_SOK != retVal)
506         {
507             GT_0trace(DssTrace, GT_ERR, "Check frame list error\r\n");
508         }
510         if(FALSE == instObj->drvState.isOpened)
511         {
512             /* If driver handle is not open then skip this frame queue */
513             GT_0trace(DssTrace,
514                       GT_ERR,
515                       "Can't queue to an un-opened instance!!\r\n");
516             retVal = FVID2_EFAIL;
517         }
518         /* Only one frame submit supported per instance */
519         if(frmList->numFrames > 1U)
520         {
521             GT_0trace(DssTrace,
522                       GT_ERR,
523                       "Only one frame submit supported in current design\r\n");
524             retVal = FVID2_EFAIL;
525         }
526     }
528     if(FVID2_SOK == retVal)
529     {
530         /* For all frames that need to be queued. The loop is dummy */
531         for(frmCnt=0U; frmCnt<frmList->numFrames; frmCnt++)
532         {
533             /* Get FVID2 frame pointer - NULL check is already done in
534              * check frame list function */
535             frm = frmList->frames[frmCnt];
536             GT_assert(DssTrace, (NULL != frm));
538             cookie = HwiP_disable();
540             /* Allocate a free queue object from the pool */
541             qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
542                                                         instObj->bmObj.freeQ);
543             if(NULL == qObj)
544             {
545                 HwiP_restore(cookie);
546                 GT_0trace(DssTrace,
547                           GT_ERR,
548                           "Q object allocation failed\r\n");
549                 retVal = FVID2_EALLOC;
550                 break;
551             }
553             /* Copy the frame to the driver's queue object */
554             qObj->frm = frm;
555             /* Initial credit count should be zero!! */
556             GT_assert(DssTrace, (0U == qObj->creditCnt));
558             /* Push mechanism */
559             /* 1.  Check if the new frame should be updated immediately in case
560              *     of frame repeat.
561              * 2.  Check if the previous frame was repeated
562              * 3.  Check if request queue is empty
563              * 4.  If request queue is not empty then put it in the request
564              *     queue and exit.
565              * 5.  If request queue is empty then push the buffer to hardware
566              * 6.  If hardware accepts then put the buffer in current queue and
567              *     update the credit count
568              * 7.  If hardware accepts the buffer then make the prevRepBuf as
569              *     false. This is required if two back to back buffers are
570              *     queued in same frame period. (The second buffer should not be
571              *     pushed if first once is accepted)
572              * 8.  If hardware doesn't accept the buffer then put it in the
573              *     request queue.
574              * 9.  In Vsync call back we set the prevBufRepeated flag
575              *     appropriately.
576              *     a. Set to true if no buffer is available in request queue
577              *     b. Set to false if buffer is given to hardware
578              * 10. Here we will overwrite the buffer present in the currQ with
579              *     the new one. Basically what needs to done is to revert what
580              *     is being done in Vsync callback function when the buffer
581              *     is repeated. So peak the current queue and decrement
582              *     the credit count. It will automatically moved to doneQ in
583              *     next Vsync Call back.
584              */
585             reqQCnt = Fvid2Utils_getNumQElem(instObj->bmObj.reqQ);
586             if((0U == reqQCnt) &&
587                (FALSE == instObj->createParams.progPipeVsyncEnable) &&
588                (TRUE == instObj->isPrevBufRep) &&
589                /* Don't program if queue is called from ISR callback context.
590                 * Just push to request queue */
591                (FALSE == instObj->isInIsrContext))
592             {
593                 /* Call the user buffer program callback */
594                 if(NULL != instObj->bufPrgmCbParams.bufPrgmCbFxn)
595                 {
596                     newFrm = instObj->bufPrgmCbParams.bufPrgmCbFxn(
597                                                     instObj->fdmCbParams.handle,
598                                                     qObj->frm,
599                                                     FALSE,
600                                                     qObj->creditCnt);
601                     if(NULL != newFrm)
602                     {
603                         /* Swap the current frame */
604                         qObj->frm = newFrm;
605                     }
606                 }
608                 /* Query display controller to check if it is safe to push */
609                 isSafe = Dss_dispIsFarFromVsync(instObj);
611                 if((retVal == FVID2_SOK) && (isSafe == TRUE))
612                 {
613                     instObj->progFrame = qObj->frm;
615                     /* Get video pipe registers */
616                     socInfo = Dss_getSocInfo();
617                     pipeRegs = socInfo->pipeRegs[instObj->pipeId];
618                     GT_assert(DssTrace, (NULL != pipeRegs));
620                     if(NULL != instObj->progFrame->perFrameCfg)
621                     {
622                         rtParams =
623                             (Dss_DispRtParams *)(instObj->progFrame->perFrameCfg);
624                         rtParamsRetVal = Dss_dispDrvValidateRtParams(instObj,
625                                                                      rtParams);
626                         if(FVID2_SOK == rtParamsRetVal)
627                         {
628                             Dss_dispDrvApplyRtParams(instObj, rtParams);
629                         }
630                     }
632                     CSL_dssVidPipeSetBuffAddr(pipeRegs,
633                                               FVID2_FID_TOP,
634                                               instObj->progFrame->addr[0U],
635                                               instObj->progFrame->addr[1U]);
637                     if(instObj->inScanFormat == FVID2_SF_INTERLACED)
638                     {
639                         CSL_dssVidPipeSetBuffAddr(pipeRegs,
640                                                   FVID2_FID_BOTTOM,
641                                                   instObj->progFrame->addr[3U],
642                                                   instObj->progFrame->addr[4U]);
643                     }
644                     if(NULL != instObj->pipePrgmCbParams.pipePrgmCbFxn)
645                     {
646                         /* Give callback to application that buffer has been
647                          * programmed
648                          */
649                         instObj->pipePrgmCbParams.pipePrgmCbFxn(
650                                                 instObj->progFrame,
651                                                 instObj->pipePrgmCbParams.appData);
652                     }
654                     retVal = Dss_dctrlDrvSetGoBit(instObj->dctrlHandle);
655                 }
657                 isBufAccepted = isSafe;
659                 if(TRUE == isBufAccepted)
660                 {
661                     /* Decrement the credit count of previously repeated buffer,
662                      * This is not a repeat now as we are overwriting the
663                      * buffer */
664                     qObjTemp = (Dss_DispDrvQueObj *) Fvid2Utils_peakTail(
665                         instObj->bmObj.currQ);
666                     /* This can't return NULL unless there is a bug in the
667                      * buffer management */
668                     GT_assert(DssTrace, (NULL != qObjTemp));
669                     qObjTemp->creditCnt--;
671                     Fvid2Utils_queue(instObj->bmObj.currQ, &qObj->qElem, qObj);
672                     qObj->creditCnt++;
673                     instObj->isPrevBufRep = FALSE;
674                     /* This is like a queue only, so increment the count*/
675                     instObj->currStatus.queueCount++;
676                 }
677                 else
678                 {
679                     /* Add the queue object in driver's request queue */
680                     Fvid2Utils_queue(instObj->bmObj.reqQ, &qObj->qElem, qObj);
681                     instObj->currStatus.queueCount++;
682                 }
683             }
684             else
685             {
686                 /* Add the queue object in driver's request queue */
687                 Fvid2Utils_queue(instObj->bmObj.reqQ, &qObj->qElem, qObj);
688                 instObj->currStatus.queueCount++;
689             }
691             HwiP_restore(cookie);
693             /* Mark frame in frmList as NULL */
694             frmList->frames[frmCnt] = NULL;
695         }
696     }
698     return (retVal);
701 static int32_t Dss_dispDrvDequeue(Fdrv_Handle handle,
702                                   Fvid2_FrameList *frmList,
703                                   uint32_t streamId,
704                                   uint32_t timeout)
706     int32_t retVal = FVID2_SOK;
707     uint32_t cookie;
708     Dss_DispDrvInstObj *instObj;
709     Dss_DispDrvQueObj *qObj;
710     Dss_DispDrvBufManObj *bmObj;
712     /* Check for NULL pointers */
713     if((NULL == handle) || (NULL == frmList) || (streamId > 0U))
714     {
715         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
716         retVal = FVID2_EBADARGS;
717     }
719     if(FVID2_SOK == retVal)
720     {
721         instObj = (Dss_DispDrvInstObj *) handle;
722         bmObj   = &instObj->bmObj;
724         if(FALSE == instObj->drvState.isOpened)
725         {
726             GT_0trace(
727                 DssTrace,
728                 GT_ERR,
729                 "Invalid Driver state: Can't dequeue to an un-opened instance!!\r\n");
730             retVal = FVID2_EFAIL;
731         }
732     }
734     if(FVID2_SOK == retVal)
735     {
736         /* Init frame list fields */
737         frmList->numFrames  = 0U;
738         frmList->perListCfg = NULL;
740         cookie = HwiP_disable();
742         /* Get a completed queue object from driver's done queue */
743         qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(bmObj->doneQ);
744         if(NULL == qObj)
745         {
746             /* When display is stopped, give back all the driver owned buffer
747              * including the current programmed and the buffers in request
748              * queue */
749             if(TRUE != instObj->drvState.isStarted)
750             {
751                 /* Give the buffers in current state */
752                 qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(bmObj->currQ);
753                 if(NULL == qObj)
754                 {
755                     /* At last give back the buffers in request queue as well */
756                     qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
757                                                                 bmObj->reqQ);
758                 }
760                 /* Check if all these operation has failed */
761                 if(NULL == qObj)
762                 {
763                     GT_0trace(DssTrace,
764                               GT_DEBUG,
765                               "NO_MORE_BUFFERS: No more buffers with driver\n");
766                     retVal = FVID2_ENO_MORE_BUFFERS;
767                 }
768             }
769             else
770             {
771                 GT_0trace(DssTrace,
772                           GT_DEBUG,
773                           "AGAIN: Out queue Empty. Try again\r\n");
774                 retVal = FVID2_EAGAIN;
775             }
776         }
778         HwiP_restore(cookie);
780         /* Copy the driver's frame list to application's frame list */
781         if(NULL != qObj)
782         {
783             cookie = HwiP_disable();
785             GT_assert(DssTrace, (NULL != qObj->frm));
786             frmList->frames[frmList->numFrames] = qObj->frm;
787             frmList->numFrames++;
789             /* Give back the queue object back to the free pool */
790             qObj->frm = NULL;
791             /* At time of dequeue, credit should be zero!! */
792             GT_assert(DssTrace, (0U == qObj->creditCnt));
793             Fvid2Utils_queue(bmObj->freeQ, &qObj->qElem, qObj);
794             instObj->currStatus.dequeueCount++;
796             HwiP_restore(cookie);
797         }
798     }
800     return (retVal);
803 static int32_t Dss_dispDrvControl(Fdrv_Handle handle,
804                                   uint32_t cmd,
805                                   void *cmdArgs,
806                                   void *cmdStatusArgs)
808     int32_t retVal = FVID2_SOK;
809     Dss_DispDrvInstObj *instObj;
811     /* Check for NULL pointers */
812     if(NULL == handle)
813     {
814         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
815         retVal = FVID2_EBADARGS;
816     }
818     if(FVID2_SOK == retVal)
819     {
820         instObj = (Dss_DispDrvInstObj *) handle;
821         switch (cmd)
822         {
823             case FVID2_START:
824                 retVal = Dss_dispDrvStartIoctl(instObj);
825                 break;
826             case FVID2_STOP:
827                 retVal = Dss_dispDrvStopIoctl(instObj);
828                 break;
829             case IOCTL_DSS_DISP_SET_DSS_PARAMS:
830                 retVal = Dss_dispDrvSetDssParamsIoctl(
831                                instObj,
832                                (const Dss_DispParams *) cmdArgs);
833                 break;
834             case IOCTL_DSS_DISP_SET_PIPE_MFLAG_PARAMS:
835                 retVal = Dss_dispDrvSetMflagParamsIoctl(
836                                instObj,
837                                (const Dss_DispPipeMflagParams *) cmdArgs);
838                 break;
839             case IOCTL_DSS_DISP_GET_CURRENT_STATUS:
840                 retVal = Dss_dispDrvGetStatusIoctl(
841                                instObj,
842                                (Dss_DispCurrentStatus *) cmdArgs);
843                 break;
844             case IOCTL_DSS_DISP_SET_PIPE_SAFETY_CHK_PARAMS:
845                 retVal = Dss_dispDrvSetPipeSafetyParamsIoctl(
846                                instObj,
847                                (const Dss_DispPipeSafetyChkParams *) cmdArgs);
848                 break;
849             case IOCTL_DSS_DISP_SET_PIPE_CSC_COEFF:
850                 retVal = Dss_dispDrvSetPipeCscParamsIoctl(
851                                 instObj,
852                                 (const CSL_DssCscCoeff *) cmdArgs);
853                 break;
854             case IOCTL_DSS_DISP_REGISTER_BUF_PRGM_CB:
855                 retVal = Dss_dispDrvSetBufPrgmCbParamsIoctl(
856                                 instObj,
857                                 (const Dss_DispBufPrgmCbParams *) cmdArgs);
858                 break;
859             case IOCTL_DSS_DISP_REGISTER_PIPE_PRGM_CB:
860                 retVal = Dss_dispDrvSetPipePrgmCbParamsIoctl(
861                                 instObj,
862                                 (const Dss_DispPipePrgmCbParams *) cmdArgs);
863                 break;
864             case IOCTL_DSS_DISP_REGISTER_PIPE_UNDERFLOW_CB:
865                 retVal = Dss_dispDrvSetPipeUnderFlowCbParamsIoctl(
866                                 instObj,
867                                 (const Dss_DispUnderFlowCbParams *) cmdArgs);
868                 break;
869             default:
870                 GT_0trace(DssTrace, GT_ERR,
871                           "UNSUPPORTED_CMD: IOCTL not supported\r\n");
872                 retVal = FVID2_EUNSUPPORTED_CMD;
873                 break;
874         }
875     }
877     return (retVal);
880 static void Dss_dispDrvClientCb(void *arg0)
882     Dss_DispDrvInstObj *instObj;
883     Dss_DispDrvQueObj *qObj, *qObjTemp;
884     uint32_t currQCnt, reqQCnt, cookie;
885     uint32_t frmQueuedToDoneQ = FALSE;
886     CSL_dss_pipeRegs *pipeRegs;
887     const Dss_SocInfo *socInfo;
888     Fvid2_Frame *newFrm;
889     Dss_DispRtParams *rtParams;
890     int32_t rtParamsRetVal = FVID2_SOK;
892     GT_assert(DssTrace, (NULL != arg0));
893     instObj = (Dss_DispDrvInstObj *)arg0;
895     if(TRUE == instObj->drvState.isStarted)
896     {
897         cookie = HwiP_disable();
899         if(NULL != instObj->currFrame)
900         {
901             /* Update channel statistics */
902             instObj->currStatus.dispFrmCount++;
903             /* Get current queue head */
904             qObj = (Dss_DispDrvQueObj *) Fvid2Utils_peakHead(instObj->bmObj.currQ);
905             GT_assert(DssTrace, (NULL != qObj));
907             /* Decrement credit count as frame display is complete - credit can't
908             * be zero */
909             GT_assert(DssTrace, (qObj->creditCnt > 0U));
910             qObj->creditCnt--;
911             if(qObj->creditCnt > 0U)
912             {
913                 instObj->currStatus.repeatFrmCount++;
914             }
916             /* Get the current queue counts */
917             currQCnt = Fvid2Utils_getNumQElem(instObj->bmObj.currQ);
918             reqQCnt = Fvid2Utils_getNumQElem(instObj->bmObj.reqQ);
920             if(0U == qObj->creditCnt)
921             {
922                 qObjTemp = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
923                                                             instObj->bmObj.currQ);
924                 /* Head node and qObj should match */
925                 GT_assert(DssTrace, (qObj == qObjTemp));
927                 /* In last frame repeat mode, we could return all the frames to
928                 * the application if credit becomes 0 and there are some more
929                 * request in the current or request queue. Current queue is
930                 * checked for 1 element as the current frame is still present
931                 * in the queue. */
932                 if((currQCnt > 1U) || (reqQCnt > 0U))
933                 {
934                     /* Return the frame to done queue */
935                     GT_assert(DssTrace, (NULL != qObj->frm));
936                     Fvid2Utils_queue(instObj->bmObj.doneQ, &qObj->qElem, qObj);
937                     frmQueuedToDoneQ = TRUE;
938                 }
939                 /* In last frame repeat mode, if credit becomes 0 and there are
940                 * no more request in the current and request queues, take this
941                 * request and queue it back to request queue so that when
942                 * the hardware asks for next buffer, we repeat the frame
943                 * automatically. This is needed because the user could
944                 * queue a request in between and this frame will end-up
945                 * in the current queue!!
946                 * Also increment the repeat frame counter here. */
947                 else if((currQCnt == 1U) && (reqQCnt == 0U))
948                 {
949                     instObj->currStatus.repeatFrmCount++;
950                     Fvid2Utils_queue(instObj->bmObj.reqQ, &qObj->qElem, qObj);
951                 }
952                 else
953                 {
954                     /* This can't happen as currQCnt can't be zero!! */
955                     GT_assert(DssTrace, FALSE);
956                 }
957             }
958         }
960         if(NULL != instObj->fdmCbParams.fdmCbFxn)
961         {
962             /* Give callback to application if periodic call back is enabled or
963              * if frame is put in done queue */
964             if((TRUE == instObj->createParams.periodicCbEnable) ||
965                (TRUE == frmQueuedToDoneQ))
966             {
967                 instObj->isInIsrContext = TRUE;
968                 instObj->fdmCbParams.fdmCbFxn(instObj->fdmCbParams.fdmData);
969                 instObj->isInIsrContext = FALSE;
970             }
971         }
973         instObj->currFrame = instObj->progFrame;
975         /* Get new frame from request queue or repeat frame */
976         qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(instObj->bmObj.reqQ);
977         if(NULL != qObj)
978         {
979             /*
980              * Buffer available in request queue
981              */
982             /* Increment credit */
983             qObj->creditCnt++;
984             Fvid2Utils_queue(instObj->bmObj.currQ, &qObj->qElem, qObj);
985             instObj->isPrevBufRep = FALSE;
986         }
987         else
988         {
989             /*
990              * No more buffers available in request queue.
991              * Repeat the last frame queued.
992              */
993             qObj = (Dss_DispDrvQueObj *) Fvid2Utils_peakTail(
994                                                         instObj->bmObj.currQ);
995             /* This can't return NULL unless there is a bug in the buffer
996              * management */
997             GT_assert(DssTrace, (NULL != qObj));
998             /* Increment credit */
999             qObj->creditCnt++;
1000             /* Mark the buffer as repeated */
1001             instObj->isPrevBufRep = TRUE;
1002         }
1004         /* Call the user buffer program callback */
1005         if(NULL != instObj->bufPrgmCbParams.bufPrgmCbFxn)
1006         {
1007             newFrm = instObj->bufPrgmCbParams.bufPrgmCbFxn(
1008                                             instObj->fdmCbParams.handle,
1009                                             qObj->frm,
1010                                             instObj->isPrevBufRep,
1011                                             qObj->creditCnt);
1012             if(NULL != newFrm)
1013             {
1014                 /* Swap the current frame */
1015                 qObj->frm = newFrm;
1016             }
1017         }
1019         /* Set frame to be programmed */
1020         instObj->progFrame = qObj->frm;
1021         /* Driver should always give the buffers when requested */
1022         GT_assert(DssTrace, (instObj->progFrame != NULL));
1023         /* Get video pipe registers */
1024         socInfo = Dss_getSocInfo();
1025         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1026         GT_assert(DssTrace, (NULL != pipeRegs));
1028         if(NULL != instObj->progFrame->perFrameCfg)
1029         {
1030             rtParams = (Dss_DispRtParams *)(instObj->progFrame->perFrameCfg);
1031             rtParamsRetVal = Dss_dispDrvValidateRtParams(instObj, rtParams);
1032             if(FVID2_SOK == rtParamsRetVal)
1033             {
1034                 Dss_dispDrvApplyRtParams(instObj, rtParams);
1035             }
1036         }
1038         CSL_dssVidPipeSetBuffAddr(pipeRegs,
1039                                   FVID2_FID_TOP,
1040                                   instObj->progFrame->addr[0U],
1041                                   instObj->progFrame->addr[1U]);
1043         if(instObj->inScanFormat == FVID2_SF_INTERLACED)
1044         {
1045             CSL_dssVidPipeSetBuffAddr(pipeRegs,
1046                                       FVID2_FID_BOTTOM,
1047                                       instObj->progFrame->addr[3U],
1048                                       instObj->progFrame->addr[4U]);
1049         }
1051         if(NULL != instObj->pipePrgmCbParams.pipePrgmCbFxn)
1052         {
1053             /* Give callback to application that buffer has been programmed */
1054             instObj->pipePrgmCbParams.pipePrgmCbFxn(
1055                             instObj->progFrame,
1056                             instObj->pipePrgmCbParams.appData);
1057         }
1059         HwiP_restore(cookie);
1060     }
1061     else if(TRUE == instObj->drvState.isStarting)
1062     {
1063         cookie = HwiP_disable();
1065         /* Start display */
1066         instObj->drvState.isStarted = TRUE;
1067         qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(instObj->bmObj.reqQ);
1068         if(NULL != qObj)
1069         {
1070             /*
1071             * Buffer available in request queue
1072             */
1073             /* Increment credit */
1074             qObj->creditCnt++;
1075             Fvid2Utils_queue(instObj->bmObj.currQ, &qObj->qElem, qObj);
1076             instObj->isPrevBufRep = FALSE;
1077             instObj->progFrame = qObj->frm;
1078         }
1079         else
1080         {
1081             /* This can't return NULL unless application has made a mistake */
1082             GT_assert(DssTrace, (NULL != qObj));
1083         }
1085         /* Driver should always give the buffers when requested */
1086         GT_assert(DssTrace, (instObj->progFrame != NULL));
1088         /* Get video pipe registers */
1089         socInfo = Dss_getSocInfo();
1090         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1091         GT_assert(DssTrace, (NULL != pipeRegs));
1093         CSL_dssVidPipeSetBuffAddr(pipeRegs,
1094                                   FVID2_FID_TOP,
1095                                   instObj->progFrame->addr[0U],
1096                                   instObj->progFrame->addr[1U]);
1098         if(instObj->inScanFormat == FVID2_SF_INTERLACED)
1099         {
1100             CSL_dssVidPipeSetBuffAddr(pipeRegs,
1101                                       FVID2_FID_BOTTOM,
1102                                       instObj->progFrame->addr[3U],
1103                                       instObj->progFrame->addr[4U]);
1104         }
1106         CSL_dssVidPipeEnable(pipeRegs, TRUE);
1107         instObj->drvState.isStarting = FALSE;
1109         if(NULL != instObj->pipePrgmCbParams.pipePrgmCbFxn)
1110         {
1111             /* Give callback to application that buffer has been programmed */
1112             instObj->pipePrgmCbParams.pipePrgmCbFxn(
1113                             instObj->progFrame,
1114                             instObj->pipePrgmCbParams.appData);
1115         }
1117         HwiP_restore(cookie);
1118     }
1119     else if(TRUE == instObj->drvState.isStopping)
1120     {
1121         cookie = HwiP_disable();
1123         /* Get video pipe registers */
1124         socInfo = Dss_getSocInfo();
1125         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1126         GT_assert(DssTrace, (NULL != pipeRegs));
1128         /* Disable Video Pipe */
1129         CSL_dssVidPipeEnable(pipeRegs, FALSE);
1130         instObj->currFrame = NULL;
1131         instObj->progFrame = NULL;
1132         instObj->drvState.isStopping = FALSE;
1134         /* Take the buffers in current state and push them in to the request
1135          * queue so that the next start will use those buffers */
1136         qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(instObj->bmObj.currQ);
1137         while (NULL != qObj)
1138         {
1139             qObj->creditCnt = 0U;
1140             /* Push it to the request queue */
1141             Fvid2Utils_queueBack(instObj->bmObj.reqQ, &qObj->qElem, qObj);
1142             qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
1143                                                         instObj->bmObj.currQ);
1144         };
1146         if(NULL != instObj->pipePrgmCbParams.pipePrgmCbFxn)
1147         {
1148             /* Give callback to application that buffer has been programmed */
1149             instObj->pipePrgmCbParams.pipePrgmCbFxn(
1150                                         instObj->progFrame,
1151                                         instObj->pipePrgmCbParams.appData);
1152         }
1154         HwiP_restore(cookie);
1155     }
1156     else
1157     {
1158         /* Should never execute this */
1159         GT_assert(DssTrace, FALSE);
1160     }
1163 static int32_t Dss_dispDrvStartIoctl(Dss_DispDrvInstObj *instObj)
1165     int32_t retVal = FVID2_SOK;
1166     uint32_t numElemInReqQ, isSafe, dummyStart;
1167     Dss_DispDrvBufManObj *bmObj;
1168     Dss_DispDrvQueObj *qObj;
1169     uint32_t cookie;
1170     CSL_dss_pipeRegs *pipeRegs;
1171     const Dss_SocInfo *socInfo;
1173     /* Check for NULL pointers */
1174     GT_assert(DssTrace, (NULL != instObj));
1176     /* wait for start sync semaphore */
1177     if(NULL != gDssStartSyncSem)
1178     {
1179         /* Take the instance semaphore */
1180         (void) SemaphoreP_pend(gDssStartSyncSem, SemaphoreP_WAIT_FOREVER);
1181     }
1183     /* Take the instance semaphore */
1184     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1186     bmObj = &instObj->bmObj;
1188     /* Initialize instance variables that needs to be reset in stop/start
1189      * sequence */
1190     instObj->currStatus.dispFrmCount = 0U;
1191     instObj->currStatus.repeatFrmCount = 0U;
1192     bmObj->expectedFid = 0U;
1193     bmObj->curFid = 0U;
1195     /* Check if the number of elements in the queue is sufficient to prime */
1196     numElemInReqQ = Fvid2Utils_getNumQElem(instObj->bmObj.reqQ);
1197     if(numElemInReqQ < DSS_DISP_DRV_MIN_PRIME_BUFFERS)
1198     {
1199         GT_0trace(DssTrace, GT_ERR, "Insufficient buffers queued\r\n");
1200         retVal = FVID2_EFAIL;
1201     }
1203     if(FVID2_SOK == retVal)
1204     {
1205         if(FALSE == instObj->createParams.progPipeVsyncEnable)
1206         {
1207             /* Get video pipe registers */
1208             socInfo = Dss_getSocInfo();
1209             pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1210             GT_assert(DssTrace, (NULL != pipeRegs));
1212             cookie = HwiP_disable();
1213             /* Check if it is safe to start or start is too near to VSYNC */
1214             isSafe = Dss_dispIsFarFromVsync(instObj);
1215             if(TRUE == isSafe)
1216             {
1217                 qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
1218                                                         instObj->bmObj.reqQ);
1219                 if(NULL != qObj)
1220                 {
1221                     /*
1222                      * Buffer available in request queue
1223                      */
1224                     /* Increment credit */
1225                     qObj->creditCnt++;
1226                     Fvid2Utils_queue(instObj->bmObj.currQ, &qObj->qElem, qObj);
1227                     instObj->isPrevBufRep = FALSE;
1228                     instObj->progFrame = qObj->frm;
1229                 }
1230                 else
1231                 {
1232                     /*
1233                     * No more buffers available in request queue.
1234                     * Repeat the last frame queued.
1235                     */
1236                     qObj = (Dss_DispDrvQueObj *) Fvid2Utils_peakTail(
1237                                                         instObj->bmObj.currQ);
1238                     /* This can't return NULL unless there is a bug in the
1239                      * buffer management */
1240                     GT_assert(DssTrace, (NULL != qObj));
1241                     /* Increment credit */
1242                     qObj->creditCnt++;
1243                     /* Mark the buffer as repeated */
1244                     instObj->isPrevBufRep = TRUE;
1245                     instObj->progFrame = qObj->frm;
1246                 }
1248                 /* Driver should always give the buffers when requested */
1249                 GT_assert(DssTrace, (instObj->progFrame != NULL));
1251                 CSL_dssVidPipeSetBuffAddr(pipeRegs,
1252                                           FVID2_FID_TOP,
1253                                           instObj->progFrame->addr[0U],
1254                                           instObj->progFrame->addr[1U]);
1256                 if(instObj->inScanFormat == FVID2_SF_INTERLACED)
1257                 {
1258                     CSL_dssVidPipeSetBuffAddr(pipeRegs,
1259                                               FVID2_FID_BOTTOM,
1260                                               instObj->progFrame->addr[3U],
1261                                               instObj->progFrame->addr[4U]);
1262                 }
1264                 /* Start display */
1265                 instObj->drvState.isStarted = TRUE;
1266                 dummyStart = FALSE;
1267                 CSL_dssVidPipeEnable(pipeRegs, TRUE);
1268                 if(NULL != instObj->pipePrgmCbParams.pipePrgmCbFxn)
1269                 {
1270                     /* Give callback to application that buffer has been
1271                      * programmed */
1272                     instObj->pipePrgmCbParams.pipePrgmCbFxn(
1273                                             instObj->progFrame,
1274                                             instObj->pipePrgmCbParams.appData);
1275                 }
1276             }
1277             else
1278             {
1279                 instObj->drvState.isStarting = TRUE;
1280                 dummyStart = TRUE;
1281             }
1283             HwiP_restore(cookie);
1284             retVal = Dss_dctrlDrvStartClient(instObj->dctrlHandle, dummyStart);
1286             if(FVID2_SOK != retVal)
1287             {
1288                 instObj->drvState.isStarted = FALSE;
1289                 instObj->drvState.isStarting = FALSE;
1290                 CSL_dssVidPipeEnable(pipeRegs, FALSE);
1291                 Dss_dctrlDrvStopClient(instObj->dctrlHandle, dummyStart);
1292                 GT_0trace(DssTrace, GT_ERR, "Driver start failed!!\r\n");
1293             }
1294         }
1295         else
1296         {
1297             instObj->drvState.isStarting = TRUE;
1298             retVal = Dss_dctrlDrvStartClient(instObj->dctrlHandle, TRUE);
1299             if(FVID2_SOK != retVal)
1300             {
1301                 instObj->drvState.isStarting = FALSE;
1302                 Dss_dctrlDrvStopClient(instObj->dctrlHandle, TRUE);
1303                 GT_0trace(DssTrace, GT_ERR, "Driver start failed!!\r\n");
1304             }
1305         }
1306     }
1308     if(FVID2_SOK != retVal)
1309     {
1310         GT_0trace(DssTrace, GT_ERR, "Fvid2 start failed\r\n");
1311     }
1313     /* Post the instance semaphore */
1314     (void) SemaphoreP_post(instObj->lockSem);
1316     return (retVal);
1319 static int32_t Dss_dispDrvStopIoctl(Dss_DispDrvInstObj *instObj)
1321     int32_t  retVal = FVID2_SOK;
1322     uint32_t cookie;
1323     Dss_DispDrvQueObj *qObj;
1324     CSL_dss_pipeRegs *pipeRegs;
1325     const Dss_SocInfo *socInfo;
1327     /* Check for NULL pointers */
1328     GT_assert(DssTrace, (NULL != instObj));
1330     /* Take the instance semaphore */
1331     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1333     if(FALSE == instObj->createParams.progPipeVsyncEnable)
1334     {
1335         /* Get video pipe registers */
1336         socInfo = Dss_getSocInfo();
1337         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1338         GT_assert(DssTrace, (NULL != pipeRegs));
1340         /* Disable Video Pipe */
1341         CSL_dssVidPipeEnable(pipeRegs, FALSE);
1342         instObj->currFrame = NULL;
1343         instObj->progFrame = NULL;
1344         retVal = Dss_dctrlDrvStopClient(instObj->dctrlHandle, FALSE);
1346         if(FVID2_SOK == retVal)
1347         {
1348             cookie = HwiP_disable();
1350             instObj->drvState.isStarted = FALSE;
1352             /* Take the buffers in current state and push them in to the request
1353              * queue so that the next start will use those buffers */
1354             qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
1355                                                         instObj->bmObj.currQ);
1356             while (NULL != qObj)
1357             {
1358                 qObj->creditCnt = 0U;
1359                 /* Push it to the request queue */
1360                 Fvid2Utils_queueBack(instObj->bmObj.reqQ, &qObj->qElem, qObj);
1361                 qObj = (Dss_DispDrvQueObj *) Fvid2Utils_dequeue(
1362                                                         instObj->bmObj.currQ);
1363             };
1365             HwiP_restore(cookie);
1366         }
1367     }
1368     else
1369     {
1370         instObj->drvState.isStopping = TRUE;
1371         instObj->drvState.isStarted = FALSE;
1372         retVal = Dss_dctrlDrvStopClient(instObj->dctrlHandle, TRUE);
1373     }
1375     if(FVID2_SOK != retVal)
1376     {
1377         GT_0trace(DssTrace, GT_ERR, "Fvid2 stop failed\r\n");
1378     }
1380     /* Post the instance semaphore */
1381     (void) SemaphoreP_post(instObj->lockSem);
1383     return (retVal);
1386 static int32_t Dss_dispDrvSetDssParamsIoctl(Dss_DispDrvInstObj *instObj,
1387                                             const Dss_DispParams *dispParams)
1389     int32_t retVal = FVID2_SOK;
1390     uint32_t layerNum;
1391     CSL_DssOverlayPipePosCfg overlayPosCfg;
1392     CSL_dss_pipeRegs *pipeRegs;
1393     CSL_dss_overlayRegs *overlayRegs;
1394     const Dss_SocInfo *socInfo;
1395     Dss_DctrlDrvPipeInfo *pipeInfo;
1396     Dss_DispParams *pipeParams;
1398     GT_assert(DssTrace, (NULL != instObj));
1400     /* Check for wrong inputs */
1401     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == dispParams))
1402     {
1403         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1404         retVal = FVID2_EBADARGS;
1405     }
1407     /* Take the instance semaphore */
1408     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1410     if(FVID2_SOK == retVal)
1411     {
1412         pipeInfo = Dss_dctrlDrvGetPipeInfo(instObj->dctrlHandle);
1413         pipeParams = &instObj->pipeParams[instObj->pipeId];
1415         /* Get video pipe registers */
1416         socInfo = Dss_getSocInfo();
1417         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1418         GT_assert(DssTrace, (NULL != pipeRegs));
1420         /* Get overlay registers */
1421         overlayRegs = socInfo->overlayRegs[pipeInfo->overlayId];
1422         GT_assert(DssTrace, (NULL != overlayRegs));
1424         retVal = Dss_dispDrvValidateDssParams(
1425                                         (const Dss_DispDrvInstObj *)instObj,
1426                                         (const Dss_DispParams *)dispParams);
1427     }
1429     if(FVID2_SOK == retVal)
1430     {
1431         Fvid2Utils_memcpy(pipeParams, dispParams, sizeof(Dss_DispParams));
1432         retVal = CSL_dssVidPipeSetConfig(
1433                         pipeRegs,
1434                         (const CSL_DssVidPipeCfg *)(&dispParams->pipeCfg),
1435                         (const CSL_DssVidPipeVC1Cfg *)(&dispParams->vc1Cfg));
1436     }
1438     if(FVID2_SOK == retVal)
1439     {
1440         instObj->inScanFormat = dispParams->pipeCfg.inFmt.scanFormat;
1441         CSL_dssVidPipeSetDmaConfig(
1442                     pipeRegs,
1443                     (const CSL_DssVidPipeDmaCfg *)(&dispParams->dmaCfg));
1445         CSL_dssVidPipeSetAlphaConfig(
1446                     pipeRegs,
1447                     (const CSL_DssVidPipeAlphaCfg *)(&dispParams->alphaCfg));
1449 #if defined (SOC_J721E)
1450         CSL_dssVidPipeSetCropConfig(
1451                 pipeRegs,
1452                 (const Fvid2_EdgeCropConfig *)(&dispParams->cropParams.cropCfg),
1453                 dispParams->cropParams.cropEnable);
1454 #endif
1456         layerNum = CSL_dssOverlayGetEnabledPipeLayerNum(overlayRegs,
1457                                                         pipeInfo->pipeId);
1458         GT_assert(DssTrace, (layerNum < CSL_DSS_OVERLAY_LAYER_MAX));
1459         overlayPosCfg.layerPos.startX = dispParams->layerPos.startX;
1460         overlayPosCfg.layerPos.startY = dispParams->layerPos.startY;
1461         CSL_dssOverlaySetPipePosConfig(
1462                     overlayRegs,
1463                     (const CSL_DssOverlayPipePosCfg *)(&overlayPosCfg),
1464                     layerNum);
1465         pipeInfo->startX = dispParams->layerPos.startX;
1466         pipeInfo->startY = dispParams->layerPos.startY;
1467     }
1469     if(FVID2_SOK != retVal)
1470     {
1471         GT_0trace(DssTrace, GT_ERR, "Set DSS parameter IOCTL failed\r\n");
1472     }
1474     /* Post the instance semaphore */
1475     (void) SemaphoreP_post(instObj->lockSem);
1477     return (retVal);
1480 static int32_t Dss_dispDrvSetMflagParamsIoctl(
1481                                     Dss_DispDrvInstObj *instObj,
1482                                     const Dss_DispPipeMflagParams *mflagParams)
1484     int32_t retVal = FVID2_SOK;
1485     CSL_dss_pipeRegs *pipeRegs;
1486     const Dss_SocInfo *socInfo;
1488     GT_assert(DssTrace, (NULL != instObj));
1490     /* Check for wrong inputs */
1491     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == mflagParams))
1492     {
1493         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1494         retVal = FVID2_EBADARGS;
1495     }
1497     /* Take the instance semaphore */
1498     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1500     if(FVID2_SOK == retVal)
1501     {
1502         /* Get video pipe registers */
1503         socInfo = Dss_getSocInfo();
1504         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1505         GT_assert(DssTrace, (NULL != pipeRegs));
1507         if(TRUE == instObj->drvState.isStarted)
1508         {
1509             retVal = FVID2_EDEVICE_INUSE;
1510             GT_0trace(DssTrace,
1511                     GT_ERR,
1512                     "Cannot set MFLAG parameters while display is in use\r\n");
1513         }
1515         CSL_dssVidPipeSetMflagConfig(
1516                     pipeRegs,
1517                     (const CSL_DssVidPipeMFlagCfg *)(&mflagParams->mflagCfg));
1518     }
1520     if(FVID2_SOK != retVal)
1521     {
1522         GT_0trace(DssTrace, GT_ERR, "Set MFLAG parameters IOCTL failed\r\n");
1523     }
1525     /* Post the instance semaphore */
1526     (void) SemaphoreP_post(instObj->lockSem);
1528     return (retVal);
1531 static int32_t Dss_dispDrvGetStatusIoctl(Dss_DispDrvInstObj *instObj,
1532                                          Dss_DispCurrentStatus *dispStatus)
1534     int32_t retVal = FVID2_SOK;
1536     GT_assert(DssTrace, (NULL != instObj));
1538     /* Check for wrong inputs */
1539     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == dispStatus))
1540     {
1541         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1542         retVal = FVID2_EBADARGS;
1543     }
1545     /* Take the instance semaphore */
1546     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1548     if(FVID2_SOK == retVal)
1549     {
1550         Fvid2Utils_memcpy(dispStatus,
1551                           &instObj->currStatus,
1552                           sizeof(Dss_DispCurrentStatus));
1553     }
1555     if(FVID2_SOK != retVal)
1556     {
1557         GT_0trace(DssTrace, GT_ERR, "Get status IOCTL failed\r\n");
1558     }
1560     /* Post the instance semaphore */
1561     (void) SemaphoreP_post(instObj->lockSem);
1563     return (retVal);
1566 static int32_t Dss_dispDrvSetPipeSafetyParamsIoctl(
1567                             Dss_DispDrvInstObj *instObj,
1568                             const Dss_DispPipeSafetyChkParams *safetyChkParams)
1570     int32_t retVal = FVID2_SOK;
1571     uint32_t eventGroup, numHandle, evtMgrId, safetyEvt;
1572     CSL_dss_pipeRegs *pipeRegs;
1573     const Dss_SocInfo *socInfo;
1574     const CSL_DssSafetyChkCfg *safetyChkCfg;
1576     /* Check for NULL pointers */
1577     GT_assert(DssTrace, (NULL != instObj));
1578     /* Check for wrong inputs */
1579     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == safetyChkParams))
1580     {
1581         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1582         retVal = FVID2_EBADARGS;
1583     }
1585     /* Take the instance semaphore */
1586     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1588     if(FVID2_SOK == retVal)
1589     {
1590         /* Get video pipe registers */
1591         socInfo = Dss_getSocInfo();
1592         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1593         GT_assert(DssTrace, (NULL != pipeRegs));
1595         Fvid2Utils_memcpy(&instObj->safetyChkParams,
1596                           safetyChkParams,
1597                           sizeof (Dss_DispPipeSafetyChkParams));
1599         /* Register for Safety Error Events */
1600         Dss_convModuletoEventGroup(&eventGroup,
1601                                    instObj->drvInstId,
1602                                    DSS_EVENT_GROUP_TYPE_PIPE);
1603         GT_assert(DssTrace, (DSS_EVENT_GROUP_INVALID != eventGroup));
1604         safetyEvt = DSS_PIPE_EVENT_SAFETY_VIOLATION;
1605         numHandle = instObj->numRegEvtHandle;
1606         evtMgrId = Dss_getEvtMgrSafetyIntrId();
1607         instObj->evtGroupHandle[instObj->numRegEvtHandle] =
1608                             Dss_evtMgrRegister(
1609                                 evtMgrId,
1610                                 eventGroup,
1611                                 (const uint32_t *)&safetyEvt,
1612                                 1U,
1613                                 Dss_dispSafetyErrCbFxn,
1614                                 (void *)&gDss_DispEvtMgrClientInfo[numHandle]);
1615         instObj->numRegEvtHandle++;
1617         /* Call CSL APIs */
1618         if(0U != safetyChkParams->safetySignSeedVal)
1619         {
1620             CSL_dssVidPipeSetSafetySignSeedVal(
1621                                         pipeRegs,
1622                                         safetyChkParams->safetySignSeedVal);
1623         }
1624         if(CSL_DSS_SAFETY_CHK_DATA_INTEGRITY ==
1625                                     safetyChkParams->safetyChkCfg.safetyChkMode)
1626         {
1627             CSL_dssVidPipeSetSafetyReferenceSign(
1628                             pipeRegs,
1629                             safetyChkParams->referenceSign);
1630         }
1631         safetyChkCfg = &safetyChkParams->safetyChkCfg;
1632         CSL_dssVidPipeSetSafetyChkConfig(pipeRegs, safetyChkCfg);
1633     }
1635     if(FVID2_SOK != retVal)
1636     {
1637         GT_0trace(DssTrace,
1638                   GT_ERR,
1639                   "Register Safety Error Cb Params IOCTL failed\r\n");
1640     }
1642     /* Post the instance semaphore */
1643     (void) SemaphoreP_post(instObj->lockSem);
1645     return retVal;
1648 static int32_t Dss_dispDrvSetPipeCscParamsIoctl(
1649                             Dss_DispDrvInstObj *instObj,
1650                             const CSL_DssCscCoeff *cscCoeff)
1652     int32_t retVal = FVID2_SOK;
1653     CSL_dss_pipeRegs *pipeRegs;
1654     const Dss_SocInfo *socInfo;
1656     GT_assert(DssTrace, (NULL != instObj));
1658     /* Check for wrong inputs */
1659     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == cscCoeff))
1660     {
1661         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1662         retVal = FVID2_EBADARGS;
1663     }
1665     /* Take the instance semaphore */
1666     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1668     if(FVID2_SOK == retVal)
1669     {
1670         /* Get video pipe registers */
1671         socInfo = Dss_getSocInfo();
1672         pipeRegs = socInfo->pipeRegs[instObj->pipeId];
1673         GT_assert(DssTrace, (NULL != pipeRegs));
1675         CSL_dssVidPipeSetCSCCoeff(
1676                         pipeRegs,
1677                         (const CSL_DssCscCoeff *)(cscCoeff));
1678     }
1680     if(FVID2_SOK != retVal)
1681     {
1682         GT_0trace(DssTrace, GT_ERR, "Set CSC coefficients IOCTL failed\r\n");
1683     }
1685     /* Post the instance semaphore */
1686     (void) SemaphoreP_post(instObj->lockSem);
1688     return (retVal);
1691 static int32_t Dss_dispDrvSetBufPrgmCbParamsIoctl(
1692                             Dss_DispDrvInstObj *instObj,
1693                             const Dss_DispBufPrgmCbParams *bufPrgmCbParams)
1695     int32_t retVal = FVID2_SOK;
1697     /* Check for NULL pointers */
1698     GT_assert(DssTrace, (NULL != instObj));
1700     /* Check for wrong inputs */
1701     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == bufPrgmCbParams))
1702     {
1703         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1704         retVal = FVID2_EBADARGS;
1705     }
1707     /* Take the instance semaphore */
1708     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1710     if(FVID2_SOK == retVal)
1711     {
1712         /* IOCTL supported only when display is stopped */
1713         if(TRUE == instObj->drvState.isStarted)
1714         {
1715             GT_0trace(DssTrace, GT_ERR, "Display in progress!!\r\n");
1716             retVal = FVID2_EFAIL;
1717         }
1718     }
1720     if(FVID2_SOK == retVal)
1721     {
1722         instObj->bufPrgmCbParams.bufPrgmCbFxn = bufPrgmCbParams->bufPrgmCbFxn;
1723     }
1725     if(FVID2_SOK != retVal)
1726     {
1727         GT_0trace(DssTrace,
1728                   GT_ERR,
1729                   "Set buffer program callback IOCTL failed\r\n");
1730     }
1732     /* Post the instance semaphore */
1733     (void) SemaphoreP_post(instObj->lockSem);
1735     return (retVal);
1738 static int32_t Dss_dispDrvSetPipePrgmCbParamsIoctl(
1739                             Dss_DispDrvInstObj *instObj,
1740                             const Dss_DispPipePrgmCbParams *pipePrgmCbParams)
1742     int32_t retVal = FVID2_SOK;
1744     /* Check for NULL pointers */
1745     GT_assert(DssTrace, (NULL != instObj));
1747     /* Check for wrong inputs */
1748     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == pipePrgmCbParams))
1749     {
1750         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1751         retVal = FVID2_EBADARGS;
1752     }
1754     /* Take the instance semaphore */
1755     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1757     if(FVID2_SOK == retVal)
1758     {
1759         /* IOCTL supported only when display is stopped */
1760         if(TRUE == instObj->drvState.isStarted)
1761         {
1762             GT_0trace(DssTrace, GT_ERR, "Display in progress!!\r\n");
1763             retVal = FVID2_EFAIL;
1764         }
1765     }
1767     if(FVID2_SOK == retVal)
1768     {
1769         Fvid2Utils_memcpy(&instObj->pipePrgmCbParams,
1770                           pipePrgmCbParams,
1771                           sizeof (Dss_DispPipePrgmCbParams));
1772     }
1774     if(FVID2_SOK != retVal)
1775     {
1776         GT_0trace(DssTrace,
1777                   GT_ERR,
1778                   "Set pipe program callback IOCTL failed\r\n");
1779     }
1781     /* Post the instance semaphore */
1782     (void) SemaphoreP_post(instObj->lockSem);
1784     return (retVal);
1787 static int32_t Dss_dispDrvSetPipeUnderFlowCbParamsIoctl(
1788                             Dss_DispDrvInstObj *instObj,
1789                             const Dss_DispUnderFlowCbParams *underFlowCbParams)
1791     int32_t retVal = FVID2_SOK;
1793     /* Check for NULL pointers */
1794     GT_assert(DssTrace, (NULL != instObj));
1796     /* Check for wrong inputs */
1797     if((instObj->drvInstId >= DSS_DISP_INST_MAX) || (NULL == underFlowCbParams))
1798     {
1799         GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
1800         retVal = FVID2_EBADARGS;
1801     }
1803     /* Take the instance semaphore */
1804     (void) SemaphoreP_pend(instObj->lockSem, SemaphoreP_WAIT_FOREVER);
1806     if(FVID2_SOK == retVal)
1807     {
1808         /* IOCTL supported only when display is stopped */
1809         if(TRUE == instObj->drvState.isStarted)
1810         {
1811             GT_0trace(DssTrace, GT_ERR, "Display in progress!!\r\n");
1812             retVal = FVID2_EFAIL;
1813         }
1814     }
1816     if(FVID2_SOK == retVal)
1817     {
1818         Fvid2Utils_memcpy(&instObj->underFlowCbParams,
1819                           underFlowCbParams,
1820                           sizeof (Dss_DispUnderFlowCbParams));
1821     }
1823     if(FVID2_SOK != retVal)
1824     {
1825         GT_0trace(DssTrace,
1826                   GT_ERR,
1827                   "Set pipe underflow callback IOCTL failed\r\n");
1828     }
1830     /* Post the instance semaphore */
1831     (void) SemaphoreP_post(instObj->lockSem);
1833     return (retVal);
1836 static int32_t Dss_dispDrvValidateDssParams(const Dss_DispDrvInstObj *instObj,
1837                                             const Dss_DispParams *dispParams)
1839     int32_t retVal = FVID2_SOK;
1841     if((FALSE == Dss_dispIsVidInst(instObj->drvInstId)) &&
1842        (FALSE == Dss_dispIsVidLInst(instObj->drvInstId)))
1843     {
1844         GT_0trace(DssTrace,
1845                   GT_ERR,
1846                   "Invalid Driver Id\r\n");
1847         retVal = FVID2_EINVALID_PARAMS;
1848     }
1849     if(((dispParams->pipeCfg.outWidth + dispParams->layerPos.startX) >
1850                                                         instObj->dispWidth) ||
1851        ((dispParams->pipeCfg.outHeight + dispParams->layerPos.startY) >
1852                                                         instObj->dispHeight))
1853     {
1854         GT_0trace(DssTrace,
1855                   GT_ERR,
1856                   "Input width+startX/height+startY > display width/height\r\n");
1857         retVal = FVID2_EINVALID_PARAMS;
1858     }
1860     /* Interlaced to progressive or vice versa*/
1861     if(dispParams->pipeCfg.inFmt.scanFormat != instObj->dispScanFormat)
1862     {
1863         GT_0trace(DssTrace,
1864                   GT_ERR,
1865                   "Format(interlaced/progressive) conversion not supported\r\n");
1866         retVal = FVID2_EINVALID_PARAMS;
1867     }
1869     /* Scaling ratio check */
1870     if(((dispParams->pipeCfg.inFmt.height * 16U) <
1871                                         (dispParams->pipeCfg.outHeight)) ||
1872        ((dispParams->pipeCfg.inFmt.width * 16U) <
1873                                         (dispParams->pipeCfg.outWidth)))
1874     {
1875         GT_0trace(DssTrace,
1876                   GT_ERR,
1877                   "Upscaling ratio is more than 16x \r\n");
1878         retVal = FVID2_EINVALID_PARAMS;
1879     }
1880     if(((dispParams->pipeCfg.inFmt.height) >
1881                                     (dispParams->pipeCfg.outHeight * 4U)) ||
1882        ((dispParams->pipeCfg.inFmt.width) >
1883                                     (dispParams->pipeCfg.outWidth * 4U)))
1884     {
1885         GT_0trace(DssTrace,
1886                   GT_ERR,
1887                   "Downscaling ratio is more than 0.25x \r\n");
1888         retVal = FVID2_EINVALID_PARAMS;
1889     }
1891     if((dispParams->pipeCfg.inFmt.height != dispParams->pipeCfg.outHeight) ||
1892        (dispParams->pipeCfg.inFmt.width != dispParams->pipeCfg.outWidth))
1893     {
1894         if(TRUE == Dss_dispIsVidLInst(instObj->drvInstId))
1895         {
1896             GT_0trace(DssTrace,
1897                       GT_ERR,
1898                       "Scaling cant be enabled for video lite pipe \r\n");
1899             retVal = FVID2_EINVALID_PARAMS;
1900         }
1901         if(FALSE == dispParams->pipeCfg.scEnable)
1902         {
1903             GT_0trace(DssTrace,
1904                       GT_ERR,
1905                       "Scaling should be enabled \r\n");
1906             retVal = FVID2_EINVALID_PARAMS;
1907         }
1908     }
1910     if((dispParams->cropParams.cropCfg.cropTop >= 32U) ||
1911        (dispParams->cropParams.cropCfg.cropBottom >= 32U) ||
1912        (dispParams->cropParams.cropCfg.cropLeft >= 32U) ||
1913        (dispParams->cropParams.cropCfg.cropRight >= 32U))
1914     {
1915         GT_0trace(DssTrace,
1916                   GT_ERR,
1917                   "Crop Parameter(s) should be less than 32 \r\n");
1918         retVal = FVID2_EINVALID_PARAMS;
1919     }
1921     if(((dispParams->pipeCfg.flipType == FVID2_FLIP_TYPE_V) ||
1922         (dispParams->pipeCfg.flipType == FVID2_FLIP_TYPE_H)) &&
1923        ((dispParams->pipeCfg.inFmt.dataFormat == FVID2_DF_RGB24_888) ||
1924         (dispParams->pipeCfg.inFmt.dataFormat == FVID2_DF_BGR24_888)))
1925     {
1926         GT_0trace(DssTrace,
1927                   GT_ERR,
1928                   "Flip Parameter(s) should not be used for 24-bit RGB/BGR formats \r\n");
1929         retVal = FVID2_EINVALID_PARAMS;
1930     }
1932     /* There is a limitation with scaling in DSS, where maximum scaling ratio
1933      * supported is the ratio of the DSS functional clock and Pixel Clock.
1934      * Driver can't check this condition as it is unaware of Pixel Clock.
1935      * So it should be checked by the application.
1936      */
1937     return retVal;
1940 static int32_t Dss_dispDrvValidateRtParams(const Dss_DispDrvInstObj *instObj,
1941                                            const Dss_DispRtParams *rtParams)
1943     int32_t retVal = FVID2_SOK;
1944     const Dss_DispParams *pipeParams;
1945     const Dss_FrameRtParams *frameRtParams;
1947     if(NULL != rtParams->outFrmParams)
1948     {
1949         if(((rtParams->outFrmParams->width + rtParams->posCfg->startX) >
1950                                                         instObj->dispWidth) ||
1951            ((rtParams->outFrmParams->height + rtParams->posCfg->startY) >
1952                                                         instObj->dispHeight))
1953         {
1954             retVal = FVID2_EINVALID_PARAMS;
1955         }
1956     }
1958     if((NULL != rtParams->outFrmParams) && (NULL != rtParams->inFrmParams))
1959     {
1960         /* Scaling ratio check */
1961         if(((rtParams->inFrmParams->height * 16U) <
1962                                     (rtParams->outFrmParams->height)) ||
1963            ((rtParams->inFrmParams->width * 16U) <
1964                                     (rtParams->outFrmParams->width)))
1965         {
1966             retVal = FVID2_EINVALID_PARAMS;
1967         }
1968         if(((rtParams->inFrmParams->height) >
1969                                     (rtParams->outFrmParams->height * 4U)) ||
1970            ((rtParams->inFrmParams->width) >
1971                                     (rtParams->outFrmParams->width * 4U)))
1972         {
1973             retVal = FVID2_EINVALID_PARAMS;
1974         }
1975         if((rtParams->inFrmParams->height != rtParams->outFrmParams->height) ||
1976            (rtParams->inFrmParams->width != rtParams->outFrmParams->width))
1977         {
1978             if(TRUE == Dss_dispIsVidLInst(instObj->drvInstId))
1979             {
1980                 retVal = FVID2_EINVALID_PARAMS;
1981             }
1982         }
1983     }
1985     if(NULL != rtParams->inFrmParams)
1986     {
1987         pipeParams = &instObj->pipeParams[instObj->pipeId];
1988         frameRtParams = rtParams->inFrmParams;
1989         if(((pipeParams->pipeCfg.flipType == FVID2_FLIP_TYPE_V) ||
1990            (pipeParams->pipeCfg.flipType == FVID2_FLIP_TYPE_H)) &&
1991           ((frameRtParams->dataFormat == FVID2_DF_RGB24_888) ||
1992            (frameRtParams->dataFormat == FVID2_DF_BGR24_888)))
1993         {
1994             GT_0trace(DssTrace,
1995                       GT_ERR,
1996                       "Flip Parameter(s) should not be used for 24-bit RGB/BGR formats \r\n");
1997             retVal = FVID2_EINVALID_PARAMS;
1998         }
1999     }
2001     /* There is a limitation with scaling in DSS, where maximum scaling ratio
2002      * supported is the ratio of the DSS functional clock and Pixel Clock.
2003      * Driver can't check this condition as it is unaware of Pixel Clock.
2004      * So it should be checked by the application.
2005      */
2006     return retVal;
2009 static int32_t Dss_dispDrvApplyRtParams(Dss_DispDrvInstObj *instObj,
2010                                         const Dss_DispRtParams *rtParams)
2012     int32_t rtParamsRetVal = FVID2_SOK;
2013     uint32_t i, layerNum;
2014     CSL_dss_pipeRegs *pipeRegs;
2015     CSL_dss_overlayRegs *overlayRegs;
2016     const Dss_SocInfo *socInfo;
2017     uint32_t pipeRtUpdate = FALSE;
2018     Dss_DctrlDrvPipeInfo *pipeInfo;
2019     CSL_DssOverlayPipePosCfg overlayPosCfg;
2020     Dss_DispParams *pipeParams;
2022     /* Get video pipe registers */
2023     socInfo = Dss_getSocInfo();
2024     pipeRegs = socInfo->pipeRegs[instObj->pipeId];
2025     GT_assert(DssTrace, (NULL != pipeRegs));
2027     pipeParams = &instObj->pipeParams[instObj->pipeId];
2028     if(NULL != rtParams->scParams)
2029     {
2030         pipeRtUpdate = TRUE;
2031         pipeParams->pipeCfg.pixelInc = rtParams->scParams->pixelInc;
2032     }
2033     if(NULL != rtParams->inFrmParams)
2034     {
2035         pipeRtUpdate = TRUE;
2036         pipeParams->pipeCfg.inFmt.width  = rtParams->inFrmParams->width;
2037         pipeParams->pipeCfg.inFmt.height = rtParams->inFrmParams->height;
2038         pipeParams->pipeCfg.inFmt.dataFormat =
2039                                             rtParams->inFrmParams->dataFormat;
2040         for(i=0U; i<FVID2_MAX_PLANES; i++)
2041         {
2042             pipeParams->pipeCfg.inFmt.pitch[i] =
2043                                             rtParams->inFrmParams->pitch[i];
2044         }
2045     }
2046     if((NULL != rtParams->outFrmParams) &&
2047        (TRUE == Dss_dispIsVidInst(instObj->drvInstId)))
2048     {
2049         pipeRtUpdate = TRUE;
2050         pipeParams->pipeCfg.outWidth  = rtParams->outFrmParams->width;
2051         pipeParams->pipeCfg.outHeight = rtParams->outFrmParams->height;
2052     }
2053     if(TRUE == pipeRtUpdate)
2054     {
2055         rtParamsRetVal =
2056             CSL_dssVidPipeSetConfig(
2057                         pipeRegs,
2058                         (const CSL_DssVidPipeCfg *)(&pipeParams->pipeCfg),
2059                         (const CSL_DssVidPipeVC1Cfg *)(&pipeParams->vc1Cfg));
2060         GT_assert(DssTrace, (FVID2_SOK == rtParamsRetVal));
2061     }
2062     if(NULL != rtParams->posCfg)
2063     {
2064         pipeInfo = Dss_dctrlDrvGetPipeInfo(instObj->dctrlHandle);
2065         /* Get overlay registers */
2066         overlayRegs = socInfo->overlayRegs[pipeInfo->overlayId];
2067         GT_assert(DssTrace, (NULL != overlayRegs));
2068         layerNum = CSL_dssOverlayGetEnabledPipeLayerNum(overlayRegs,
2069                                                         pipeInfo->pipeId);
2070         GT_assert(DssTrace, (layerNum < CSL_DSS_OVERLAY_LAYER_MAX));
2071         overlayPosCfg.layerPos.startX = rtParams->posCfg->startX;
2072         overlayPosCfg.layerPos.startY = rtParams->posCfg->startY;
2073         CSL_dssOverlaySetPipePosConfig(
2074                             overlayRegs,
2075                             (const CSL_DssOverlayPipePosCfg *)(&overlayPosCfg),
2076                             layerNum);
2077         pipeInfo->startX = rtParams->posCfg->startX;
2078         pipeInfo->startY = rtParams->posCfg->startY;
2079     }
2080     return rtParamsRetVal;
2083 static void Dss_dispSafetyErrCbFxn(const uint32_t *event,
2084                                    uint32_t numEvents,
2085                                    void *arg)
2087     uint32_t  i, currEvent, pipeId = 0U;
2088     Dss_EvtMgrClientInfo *pClientObj = (Dss_EvtMgrClientInfo *)arg;
2089     uint32_t eventGroup = pClientObj->eventGroup;
2090     Dss_DispDrvInstObj *instObj;
2091     CSL_dss_pipeRegs *pipeRegs;
2092     const Dss_SocInfo *socInfo;
2094     /* Get pipe id */
2095     Dss_convEventGrouptoModule(eventGroup, &pipeId);
2096     GT_assert(DssTrace, (CSL_DSS_MODULE_INVALID != pipeId));
2097     instObj = Dss_dispDrvGetInstObj(pipeId);
2098     /* Instobj cannot be NULL */
2099     GT_assert(DssTrace, (NULL != instObj));
2100     /* Get video pipe registers */
2101     socInfo = Dss_getSocInfo();
2102     pipeRegs = socInfo->pipeRegs[pipeId];
2103     GT_assert(DssTrace, (NULL != pipeRegs));
2105     for(i=0U; i<numEvents; i++)
2106     {
2107         currEvent = event[i];
2108         if(DSS_PIPE_EVENT_SAFETY_VIOLATION == currEvent)
2109         {
2110             instObj->currStatus.safetyViolationCount++;
2111             if(CSL_DSS_SAFETY_CHK_DATA_INTEGRITY ==
2112                             instObj->safetyChkParams.safetyChkCfg.safetyChkMode)
2113             {
2114                 instObj->safetyChkParams.capturedSign =
2115                                         CSL_dssVidPipeGetSafetySign(pipeRegs);
2116             }
2117             if(NULL != instObj->safetyChkParams.safetyErrCbFxn)
2118             {
2119                 instObj->safetyChkParams.safetyErrCbFxn(
2120                                          instObj->safetyChkParams.capturedSign,
2121                                          instObj->safetyChkParams.appData);
2122             }
2123         }
2124         else
2125         {
2126             GT_assert(DssTrace, FALSE);
2127         }
2128     }
2130     return;
2133 static uint32_t Dss_dispIsFarFromVsync(const Dss_DispDrvInstObj *instObj)
2135     uint32_t isFarFromVsync = FALSE;
2137     isFarFromVsync = Dss_dctrlDrvIsSafeToPush(instObj->dctrlHandle);
2139     if(instObj->dispHeight <= DSS_DISP_NUM_LINES_NEAR_VSYNC)
2140     {
2141         isFarFromVsync = FALSE;
2142     }
2144     return isFarFromVsync;