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 <ti/drv/dss/src/drv/dctrl/dss_dctrlDrv.h>
50 #include <ti/drv/dss/src/drv/dctrl/dss_dctrlPriv.h>
51 #include <ti/drv/dss/src/drv/m2m/dss_m2mDrv.h>
52 #include <dss_soc_priv.h>
54 /* ========================================================================== */
55 /* Macros & Typedefs */
56 /* ========================================================================== */
58 /* ========================================================================== */
59 /* Structure Declarations */
60 /* ========================================================================== */
62 /* None */
64 /* ========================================================================== */
65 /* Function Declarations */
66 /* ========================================================================== */
67 /**
68 * Below ifdef __cplusplus is added so that C++ build passes without
69 * typecasting. This is because the prototype is build as C type
70 * whereas this file is build as CPP file. Hence we get C++ build error.
71 * Also if typecasting is used, then we get MisraC error Rule 11.1.
72 */
73 #ifdef __cplusplus
74 extern "C" {
75 #endif
78 #ifdef __cplusplus
79 }
80 #endif
82 /* ========================================================================== */
83 /* Global Variables */
84 /* ========================================================================== */
85 DssM2MDrv_CommonObj gDssM2mCommonObj;
87 Dss_EvtMgrClientInfo gDss_M2MEvtMgrClientInfo[DSS_DISP_EVT_MGR_MAX_CLIENTS];
88 /* ========================================================================== */
89 /* Internal/Private Function Declarations */
90 /* ========================================================================== */
91 static int32_t Dss_m2mDrvCreateInstQueues(DssM2MDrv_VirtContext *context);
93 static int32_t Dss_m2mDrvDeleteInstQueues(DssM2MDrv_VirtContext *context);
95 /* Returns TRUE if instance and channel/context configurations matches,
96 returns FALSE otherwise */
97 static uint32_t Dss_m2mDrvWbPipeCfgChk(const Dss_WbPipeCfgParams *instCfg,
98 const Dss_WbPipeCfgParams *progCfg);
100 /* Returns TRUE if instance and channel/context configurations matches,
101 returns FALSE otherwise */
102 static uint32_t Dss_m2mDrvWbDmaCfgChk(const CSL_DssWbPipeDmaCfg *instCfg,
103 const CSL_DssWbPipeDmaCfg *progCfg);
105 /* Returns TRUE if instance and channel/context configurations matches,
106 returns FALSE otherwise */
107 static uint32_t Dss_m2mDrvWbMFlagCfgChk(const Dss_WbPipeMflagParams *instCfg,
108 const Dss_WbPipeMflagParams *progCfg);
110 /* Returns TRUE if instance and channel/context configurations matches,
111 returns FALSE otherwise */
112 static uint32_t Dss_m2mDrvWbCscCfgChk(const CSL_DssCscCoeff *instCfg,
113 const CSL_DssCscCoeff *progCfg);
115 static int32_t Dss_m2mDrvPrgramWbPipe(DssM2MDrv_VirtContext *context);
116 /*
117 * Display IOCTLs
118 */
119 static int32_t Dss_m2mDrvIoctlStart(DssM2MDrv_VirtContext *context);
121 static int32_t Dss_m2mDrvIoctlStop(DssM2MDrv_VirtContext *context);
123 static int32_t Dss_m2mDrvIoctlSetWbPipeParams(DssM2MDrv_VirtContext *context,
124 const Dss_WbPipeCfgParams *pipeCfg);
126 static int32_t Dss_m2mDrvIoctlSetmFlagParams(DssM2MDrv_VirtContext *context,
127 const Dss_WbPipeMflagParams *mFlagParams);
129 static int32_t Dss_m2mDrvIoctlGetCurrentStatus(DssM2MDrv_VirtContext *context,
130 Dss_WbStatus *status);
132 static int32_t Dss_m2mDrvIoctlSetWbPipeCsc(DssM2MDrv_VirtContext *context,
133 const CSL_DssCscCoeff *csc);
135 static int32_t Dss_m2mDrvIoctlSetDmaCfg(DssM2MDrv_VirtContext *context,
136 const CSL_DssWbPipeDmaCfg *dmaCfg);
138 static void Dss_wbPipeCbFxn(const uint32_t *event,
139 uint32_t numEvents,
140 void *arg);
142 static void Dss_wbPipeDmaCompletionCbFxn(DssM2MDrv_InstObj *instObj);
143 /* ========================================================================== */
144 /* Function Definitions */
145 /* ========================================================================== */
146 /* FVID2 independent functions: Init and deinit*/
147 int32_t Dss_m2mDrvInit(const Dss_InitParams *initParams)
148 {
149 int32_t retVal = FVID2_SOK;
150 DssM2MDrv_CommonObj *m2mObj;
151 uint32_t loopCnt = 0U, contextCnt = 0U, eventGroup, pipeIdx = 0U;
152 uint32_t numEvents, evtMgrId, numHandle;
153 DssM2MDrv_VirtContext *virtContext;
154 DssM2MDrv_InstObj *instObj;
155 SemaphoreP_Params semParams;
156 const Dss_SocInfo *socInfo;
157 Dss_EvtMgrClientInfo *pClientInfo;
158 uint32_t enabledEvents[DSS_EVT_MGR_MAX_CLIENT_EVENTS];
160 m2mObj = &gDssM2mCommonObj;
161 GT_assert(DssTrace, (NULL != m2mObj));
163 /* Reset full driver object to '0' and set only required parameters */
164 Fvid2Utils_memset(m2mObj, 0U, sizeof(DssM2MDrv_CommonObj));
165 socInfo = Dss_getSocInfo();
166 Fvid2Utils_memcpy(&m2mObj->socInfo,
167 socInfo,
168 sizeof(Dss_SocInfo));
169 for(loopCnt = 0U ; loopCnt < DSS_DISP_EVT_MGR_MAX_CLIENTS ; loopCnt++)
170 {
171 pClientInfo = &gDss_M2MEvtMgrClientInfo[loopCnt];
172 Fvid2Utils_memset(pClientInfo, 0U, sizeof (Dss_EvtMgrClientInfo));
173 }
175 m2mObj->getTimeStamp = NULL;
176 m2mObj->isRegistered = (uint32_t)FALSE;
178 /* Allocate instance semaphore */
179 SemaphoreP_Params_init(&semParams);
180 semParams.mode = SemaphoreP_Mode_BINARY;
181 m2mObj->lockSem = SemaphoreP_create(1U, &semParams);
182 if (m2mObj->lockSem == NULL)
183 {
184 GT_0trace(DssTrace, GT_ERR, "Instance semaphore create failed!!\r\n");
185 retVal = FVID2_EALLOC;
186 }
188 for (loopCnt = 0U ; loopCnt < DSSM2M_NUM_WB_PIPELINE ; loopCnt++)
189 {
190 m2mObj->numVirtContUsed[loopCnt] = 0U;
191 instObj = &m2mObj->instObj[loopCnt];
192 instObj->drvInstId = loopCnt;
193 instObj->inUse = DSSM2M_DRV_USAGE_STATUS_NOT_USED;
194 instObj->commonObjRef = m2mObj;
195 instObj->wbRegs = socInfo->wbRegs[loopCnt];
196 instObj->commRegs = NULL;
197 instObj->numPipe = 0U;
198 for (pipeIdx = 0U ;
199 pipeIdx < DSSM2M_NUM_PIPELINE_TO_USE_IN_M2M_MODE ;
200 pipeIdx++)
201 {
202 instObj->pipeRegs[pipeIdx] = NULL;
203 instObj->pipeId[pipeIdx] = CSL_DSS_VID_PIPE_ID_MAX;
204 }
205 instObj->ovrRegs = NULL;
206 instObj->overlayId = CSL_DSS_OVERLAY_ID_MAX;
207 instObj->pathCfgDone = (uint32_t) FALSE;
208 for (contextCnt = 0U ;
209 contextCnt < DSSM2M_NUM_VIRTUAL_CONTEXT ;
210 contextCnt++)
211 {
212 virtContext = &m2mObj->virtContext[loopCnt][contextCnt];
213 for (pipeIdx = 0U ;
214 pipeIdx < DSSM2M_NUM_PIPELINE_TO_USE_IN_M2M_MODE ;
215 pipeIdx++)
216 {
217 virtContext->pipeId[pipeIdx] = CSL_DSS_VID_PIPE_ID_MAX;
218 }
219 virtContext->numPipe = 0U;
220 virtContext->overlayId = CSL_DSS_OVERLAY_ID_MAX;
221 virtContext->contextId = contextCnt;
222 virtContext->state = DSSM2M_DRV_STATE_IDLE;
223 virtContext->inUse = DSSM2M_DRV_USAGE_STATUS_NOT_USED;
224 virtContext->instObj = instObj;
225 }
226 /* Register WB Pipeline Events */
227 Dss_convModuletoEventGroup(&eventGroup,
228 instObj->drvInstId,
229 DSS_EVENT_GROUP_TYPE_WB_PIPE);
230 GT_assert(DssTrace, (DSS_EVENT_GROUP_INVALID != eventGroup));
232 Dss_getEnabledWbPipeFuncEvents(&enabledEvents[0U], &numEvents);
233 evtMgrId = Dss_getEvtMgrFuncIntrId();
234 numHandle = instObj->numRegEvtHandle;
235 instObj->evtGroupHandle[instObj->numRegEvtHandle] =
236 Dss_evtMgrRegister(
237 evtMgrId,
238 eventGroup,
239 (const uint32_t *)&enabledEvents[0U],
240 numEvents,
241 Dss_wbPipeCbFxn,
242 (void *)&gDss_M2MEvtMgrClientInfo[numHandle]);
243 /* Enable Events */
244 retVal = Dss_evtMgrEnable(instObj->evtGroupHandle[instObj->numRegEvtHandle]);
245 instObj->numRegEvtHandle++;
246 if (FVID2_SOK != retVal)
247 {
248 GT_0trace(DssTrace, GT_ERR,
249 "Registering/Enabling to DSS Event manager failed\r\n");
250 }
251 }
253 if (FVID2_SOK == retVal)
254 {
255 /* Initialize Driver operations */
256 Fvid2DrvOps_init(&m2mObj->fvidDrvOps);
257 m2mObj->fvidDrvOps.drvId = DSS_M2M_DRV_ID;
258 m2mObj->fvidDrvOps.createFxn = &Dss_m2mCreate;
259 m2mObj->fvidDrvOps.deleteFxn = &Dss_m2mDelete;
260 m2mObj->fvidDrvOps.controlFxn = &Dss_m2mControl;
261 m2mObj->fvidDrvOps.processRequestFxn = &Dss_m2mProcessRequest;
262 m2mObj->fvidDrvOps.getProcessedRequestFxn = &Dss_m2mGetProcessedRequest;
264 retVal = Fvid2_registerDriver(&m2mObj->fvidDrvOps);
265 if (FVID2_SOK != retVal)
266 {
267 GT_0trace(DssTrace, GT_ERR,
268 "Registering to FVID2 driver manager failed\r\n");
269 /* Un-initialize the internal objects if error occurs: deInit() */
270 }
271 else
272 {
273 /* Init successful */
274 m2mObj->isRegistered = (uint32_t) TRUE;
275 }
276 }
279 return (retVal);
280 }
282 int32_t Dss_m2mDrvDeInit(void)
283 {
284 int32_t retVal = FVID2_SOK;
285 DssM2MDrv_CommonObj *m2mObj;
286 uint32_t loopCnt = 0U, contextCnt = 0U, eventIdx = 0U, pipeIdx = 0U;
287 DssM2MDrv_VirtContext *virtContext;
288 DssM2MDrv_InstObj *instObj;
290 m2mObj = &gDssM2mCommonObj;
291 GT_assert(DssTrace, (NULL != m2mObj));
293 if (m2mObj->lockSem != NULL)
294 {
295 /* Delete semaphore */
296 (void)SemaphoreP_delete(m2mObj->lockSem);
297 }
298 for (loopCnt = 0U ; loopCnt < DSSM2M_NUM_WB_PIPELINE ; loopCnt++)
299 {
300 instObj = &m2mObj->instObj[loopCnt];
301 instObj->inUse = DSSM2M_DRV_USAGE_STATUS_NOT_USED;
302 instObj->commonObjRef = NULL;
303 instObj->commRegs = NULL;
304 for (pipeIdx = 0U ;
305 pipeIdx < DSSM2M_NUM_PIPELINE_TO_USE_IN_M2M_MODE ;
306 pipeIdx++)
307 {
308 instObj->pipeRegs[pipeIdx] = NULL;
309 instObj->pipeId[pipeIdx] = CSL_DSS_VID_PIPE_ID_MAX;
310 }
311 instObj->numPipe = 0U;
312 instObj->ovrRegs = NULL;
313 instObj->wbRegs = NULL;
314 instObj->pathCfgDone = (uint32_t) FALSE;
315 for (contextCnt = 0U ;
316 contextCnt < DSSM2M_NUM_VIRTUAL_CONTEXT ;
317 contextCnt++)
318 {
319 virtContext = &m2mObj->virtContext[loopCnt][contextCnt];
320 virtContext->numPipe = 0U;
321 virtContext->state = DSSM2M_DRV_STATE_UNINIT;
322 virtContext->inUse = DSSM2M_DRV_USAGE_STATUS_NOT_USED;
323 virtContext->instObj = NULL;
324 }
325 /* Unregister event groups and delete object */
326 for(eventIdx = 0U ; eventIdx < instObj->numRegEvtHandle ; eventIdx++)
327 {
328 retVal += Dss_evtMgrUnRegister(instObj->evtGroupHandle[eventIdx]);
329 instObj->numRegEvtHandle--;
330 }
331 }
333 /* unregister driver */
334 retVal = Fvid2_unRegisterDriver(&m2mObj->fvidDrvOps);
335 if (retVal != FVID2_SOK)
336 {
337 GT_0trace(DssTrace, GT_ERR,
338 "Unregistering from FVID2 driver manager failed\r\n");
339 }
341 return (retVal);
342 }
344 /* FVID2 Functions */
345 Fdrv_Handle Dss_m2mCreate(uint32_t drvId,
346 uint32_t instId,
347 void *createArgs,
348 void *createStatusArgs,
349 const Fvid2_DrvCbParams *fdmCbParams)
350 {
351 Fdrv_Handle drvHandle = NULL;
352 int32_t retVal = FVID2_SOK;
353 DssM2MDrv_CommonObj *m2mObj;
354 Dss_WbCreateParams *createParams;
355 Dss_WbCreateStatus *createStatus;
356 DssM2MDrv_VirtContext *virtContext;
357 DssM2MDrv_InstObj *instObj;
358 uint32_t loopCnt = 0U;
360 m2mObj = &gDssM2mCommonObj;
361 GT_assert(DssTrace, (NULL != m2mObj));
363 /* Check for NULL pointers and invalid arguments */
364 if ((NULL == createStatusArgs) ||
365 (NULL == fdmCbParams) ||
366 (DSS_M2M_DRV_ID != drvId) ||
367 (DSS_M2M_WB_PIPELINE_ID_MAX <= instId))
368 {
369 GT_0trace(DssTrace, GT_ERR, "Invalid arguments\r\n");
370 retVal = FVID2_EBADARGS;
371 }
372 else
373 {
374 createParams = (Dss_WbCreateParams *)createArgs;
375 createStatus = (Dss_WbCreateStatus *)createStatusArgs;
376 /* Get free Virtual Context */
377 for (loopCnt = 0U ; loopCnt < DSSM2M_NUM_VIRTUAL_CONTEXT ; loopCnt++)
378 {
379 if (m2mObj->virtContext[instId][loopCnt].inUse ==
380 DSSM2M_DRV_USAGE_STATUS_NOT_USED)
381 {
382 break;
383 }
384 }
385 if (DSSM2M_NUM_VIRTUAL_CONTEXT <= loopCnt)
386 {
387 retVal = FVID2_EALLOC;
388 GT_0trace(DssTrace, GT_ERR, "No more instances to allocate...\r\n");
389 }
390 else
391 {
392 virtContext = &m2mObj->virtContext[instId][loopCnt];
393 instObj = virtContext->instObj;
394 GT_assert(DssTrace, (NULL != instObj->commonObjRef));
396 if(NULL != instObj->commonObjRef->lockSem)
397 {
398 /* Take the instance semaphore */
399 (void) SemaphoreP_pend(instObj->commonObjRef->lockSem,
400 SemaphoreP_WAIT_FOREVER);
401 }
403 for (loopCnt = 0U ;
404 loopCnt < createParams->numPipe ;
405 loopCnt++)
406 {
407 if (((instObj->pipeId[loopCnt] != CSL_DSS_VID_PIPE_ID_MAX) &&
408 (instObj->pipeId[loopCnt] != createParams->pipeId[loopCnt])) ||
409 (createParams->pipeId[loopCnt] == CSL_DSS_VID_PIPE_ID_MAX))
410 {
411 break;
412 }
413 }
414 if (loopCnt < createParams->numPipe)
415 {
416 retVal = FVID2_EBADARGS;
417 GT_0trace(DssTrace, GT_ERR, "Wrong Pipe instance used!!!\r\n");
418 }
420 /* Check if same DSS Pipe and Overlay is provided within
421 different Create calls */
422 if (((instObj->overlayId != CSL_DSS_OVERLAY_ID_MAX) &&
423 (instObj->overlayId != createParams->overlayId)) ||
424 (createParams->overlayId == CSL_DSS_OVERLAY_ID_MAX))
425 {
426 retVal = FVID2_EBADARGS;
427 GT_0trace(DssTrace, GT_ERR, "Wrong Overlay instance used!!!\r\n");
428 }
430 if (FVID2_SOK == retVal)
431 {
432 /* Update app provided configurations in the instance object */
433 /* Copy create and Call-back parameters */
434 Fvid2Utils_memcpy(&virtContext->createParams,
435 createParams,
436 sizeof(Dss_WbCreateParams));
437 Fvid2Utils_memcpy(&virtContext->fdmCbParams,
438 fdmCbParams,
439 sizeof(Fvid2_DrvCbParams));
440 /* Set status to '0' */
441 Fvid2Utils_memset(&virtContext->wbStatus, 0U, sizeof(Dss_WbStatus));
442 /* Clear instance configurations,
443 these will be later set by IOCTLs */
444 Fvid2Utils_memset(&virtContext->instCfg,
445 0U,
446 sizeof(DssM2MDrv_moduleCfg));
447 for (loopCnt = 0U ;
448 loopCnt < createParams->numPipe ;
449 loopCnt++)
450 {
451 virtContext->pipeId[loopCnt] = createParams->pipeId[loopCnt];
452 }
453 virtContext->numPipe = createParams->numPipe;
454 virtContext->overlayId = createParams->overlayId;
455 }
457 if (FVID2_SOK == retVal)
458 {
459 virtContext->doneQ = NULL;
460 retVal = Fvid2Utils_constructQ(&virtContext->doneLlObj);
461 GT_assert(DssTrace, (retVal == FVID2_SOK));
462 virtContext->doneQ = &virtContext->doneLlObj;
463 }
465 if (FVID2_SOK == retVal)
466 {
467 if ((0U == m2mObj->numVirtContUsed[instId]) &&
468 (DSSM2M_DRV_USAGE_STATUS_NOT_USED == instObj->inUse))
469 {
470 for (loopCnt = 0U ;
471 loopCnt < createParams->numPipe ;
472 loopCnt++)
473 {
474 instObj->pipeId[loopCnt] = virtContext->pipeId[loopCnt];
475 }
476 instObj->overlayId = virtContext->overlayId;
477 instObj->numPipe = virtContext->numPipe;
478 /* Set instance status */
479 Fvid2Utils_memset(&instObj->status,
480 0U,
481 sizeof(Dss_WbStatus));
482 /* Create Queues for Buffer Management - Do this for
483 only first create call*/
484 retVal = Dss_m2mDrvCreateInstQueues(virtContext);
485 }
487 if (FVID2_SOK == retVal)
488 {
489 /* Set states of driver object and instance object */
490 virtContext->numBufQed = 0U;
491 instObj->commRegs =
492 instObj->commonObjRef->socInfo.commRegs[CSL_DSS_COMM_REG_ID_0];
493 instObj->ovrRegs =
494 instObj->commonObjRef->socInfo.overlayRegs[createParams->overlayId];
495 for (loopCnt = 0U ;
496 loopCnt < DSSM2M_NUM_PIPELINE_TO_USE_IN_M2M_MODE ;
497 loopCnt++)
498 {
499 instObj->pipeRegs[createParams->pipeId[loopCnt]] =
500 instObj->commonObjRef->socInfo.pipeRegs[createParams->pipeId[loopCnt]];
501 }
502 virtContext->inUse = DSSM2M_DRV_USAGE_STATUS_IN_USE;
503 virtContext->state = DSSM2M_DRV_STATE_CREATED;
504 instObj->inUse = DSSM2M_DRV_USAGE_STATUS_IN_USE;
505 m2mObj->numVirtContUsed[instId]++;
506 drvHandle = (Fdrv_Handle)virtContext;
507 }
508 }
509 /* Configure WB pipeline input connection */
510 if (FVID2_SOK == retVal)
511 {
512 switch (createParams->overlayId)
513 {
514 case CSL_DSS_OVERLAY_ID_1:
515 CSL_dssSetWbInputCh(instObj->commRegs,
516 CSL_DSS_WB_INPUT_OVERLAY1);
517 break;
518 case CSL_DSS_OVERLAY_ID_2:
519 CSL_dssSetWbInputCh(instObj->commRegs,
520 CSL_DSS_WB_INPUT_OVERLAY2);
521 break;
522 case CSL_DSS_OVERLAY_ID_3:
523 CSL_dssSetWbInputCh(instObj->commRegs,
524 CSL_DSS_WB_INPUT_OVERLAY3);
525 break;
526 case CSL_DSS_OVERLAY_ID_4:
527 CSL_dssSetWbInputCh(instObj->commRegs,
528 CSL_DSS_WB_INPUT_OVERLAY4);
529 break;
530 default:
531 GT_0trace(DssTrace,
532 GT_ERR,
533 "Wrong Overlay instance used!!!\r\n");
534 break;
535 }
536 }
538 if(NULL != instObj->commonObjRef->lockSem)
539 {
540 /* Post the instance semaphore */
541 (void) SemaphoreP_post(instObj->commonObjRef->lockSem);
542 }
543 }
544 if (NULL != createStatusArgs)
545 {
546 createStatus->retVal = retVal;
547 }
548 }
550 return (drvHandle);
551 }
553 int32_t Dss_m2mDelete(Fdrv_Handle handle, void *reserved)
554 {
555 int32_t retVal = FVID2_SOK;
556 uint32_t pipeIdx;
557 DssM2MDrv_CommonObj *m2mObj;
558 DssM2MDrv_VirtContext *virtContext;
559 DssM2MDrv_InstObj *instObj;
560 DssM2M_DrvQueObj *qObj;
562 m2mObj = &gDssM2mCommonObj;
563 GT_assert(DssTrace, (NULL != m2mObj));
565 if (NULL == handle)
566 {
567 retVal = FVID2_EBADARGS;
568 }
569 else
570 {
571 virtContext = (DssM2MDrv_VirtContext *)handle;
572 instObj = virtContext->instObj;
574 /* Set states of driver object and instance object */
575 virtContext->inUse = DSSM2M_DRV_USAGE_STATUS_NOT_USED;
576 virtContext->state = DSSM2M_DRV_STATE_IDLE;
577 m2mObj->numVirtContUsed[virtContext->contextId]--;
579 if(NULL != virtContext->doneQ)
580 {
581 /* Free-up all the queued free queue objects */
582 do
583 {
584 qObj = (DssM2M_DrvQueObj *) Fvid2Utils_dequeue(virtContext->doneQ);
585 } while (NULL != qObj);
587 /* Delete the free Q */
588 Fvid2Utils_destructQ(virtContext->doneQ);
589 virtContext->doneQ = NULL;
590 }
591 for (pipeIdx = 0U ;
592 pipeIdx < DSSM2M_NUM_PIPELINE_TO_USE_IN_M2M_MODE ;
593 pipeIdx++)
594 {
595 virtContext->pipeId[pipeIdx] = CSL_DSS_VID_PIPE_ID_MAX;
596 }
597 virtContext->numPipe = 0U;
598 virtContext->overlayId = CSL_DSS_OVERLAY_ID_MAX;
600 /* Delete Queues only on delete call for last opened Virtual context */
601 if ((0U == m2mObj->numVirtContUsed[virtContext->contextId]) &&
602 (DSSM2M_DRV_USAGE_STATUS_IN_USE == instObj->inUse))
603 {
604 for (pipeIdx = 0U ;
605 pipeIdx < DSSM2M_NUM_PIPELINE_TO_USE_IN_M2M_MODE ;
606 pipeIdx++)
607 {
608 instObj->pipeRegs[pipeIdx] = NULL;
609 instObj->pipeId[pipeIdx] = CSL_DSS_VID_PIPE_ID_MAX;
610 }
611 instObj->numPipe = 0U;
612 instObj->overlayId = CSL_DSS_OVERLAY_ID_MAX;
613 instObj->commRegs = NULL;
614 instObj->ovrRegs = NULL;
615 if(NULL != instObj->commonObjRef->lockSem)
616 {
617 /* Take the instance semaphore */
618 (void) SemaphoreP_pend(instObj->commonObjRef->lockSem,
619 SemaphoreP_WAIT_FOREVER);
620 }
622 retVal = Dss_m2mDrvDeleteInstQueues(virtContext);
624 if(NULL != instObj->commonObjRef->lockSem)
625 {
626 /* Post the instance semaphore */
627 (void) SemaphoreP_post(instObj->commonObjRef->lockSem);
628 }
629 instObj->inUse = DSSM2M_DRV_USAGE_STATUS_NOT_USED;
630 }
631 }
633 return retVal;
634 }
636 int32_t Dss_m2mProcessRequest(Fdrv_Handle handle,
637 Fvid2_FrameList *inProcessList,
638 Fvid2_FrameList *outProcessList,
639 uint32_t timeout)
640 {
641 int32_t retVal = FVID2_SOK;
642 DssM2MDrv_VirtContext *virtContext= NULL;
643 DssM2MDrv_InstObj *instObj = NULL;
644 uint32_t semTimeout, frmCnt, cookie, loopCnt;
645 DssM2M_DrvQueObj *qObj;
646 DssM2M_DrvBufManObj *bmObj;
648 /** Steps
649 * 1. Get a queue object from the freeQ. Assert error if NULL.
650 * 2. Copy handle into queue object
651 * 3. Copy frame lists into queue object
652 * 4. Move the queue object to reqQ
653 * 5. Increment Queue Count in the status
654 * 6. If number of elements in currQ < 1, then do following
655 * a. Get a queue object from the reqQ. Assert error if NULL
656 * b. Disable DSS and WB pipeline
657 * c. Re-program DSS pipeline, Overlay and WB Pipeline if needed
658 * d. Set buffer addresses in the WB & DSS Pipeline
659 * e. Enable DSS and WB pipeline
660 * f. Move the queue object to currQ
661 */
662 if ((NULL == handle) || (NULL == inProcessList) || (NULL == outProcessList))
663 {
664 retVal = FVID2_EBADARGS;
665 }
666 cookie = HwiP_disable();
667 if (FVID2_SOK == retVal)
668 {
669 virtContext = (DssM2MDrv_VirtContext *)handle;
670 instObj = virtContext->instObj;
671 GT_assert(DssTrace, (NULL != instObj));
672 bmObj = &instObj->bmObj;
673 GT_assert(DssTrace, (NULL != bmObj));
675 if ((instObj->inUse != DSSM2M_DRV_USAGE_STATUS_IN_USE) ||
676 (virtContext->inUse != DSSM2M_DRV_USAGE_STATUS_IN_USE) ||
677 ((virtContext->state == DSSM2M_DRV_STATE_IDLE) ||
678 (virtContext->state == DSSM2M_DRV_STATE_UNINIT)))
679 {
680 retVal = FVID2_EFAIL;
681 GT_0trace(DssTrace, GT_ERR,
682 "Invalid state: Can't submit request to an un-opened instance!!\r\n");
683 }
684 }
685 if (FVID2_TIMEOUT_FOREVER == timeout)
686 {
687 semTimeout = SemaphoreP_WAIT_FOREVER;
688 }
689 else if (FVID2_TIMEOUT_NONE == timeout)
690 {
691 semTimeout = SemaphoreP_NO_WAIT;
692 }
693 else
694 {
695 semTimeout = timeout;
696 }
697 if ((NULL != instObj) && (NULL != instObj->commonObjRef->lockSem))
698 {
699 /* Take the instance semaphore */
700 (void) SemaphoreP_pend(instObj->commonObjRef->lockSem, semTimeout);
701 }
702 /* Steps 1 to 5 */
703 if (FVID2_SOK == retVal)
704 {
705 /* Check frame list for error and NULL pointer check */
706 retVal = Fvid2_checkFrameList(inProcessList,
707 (uint32_t) FVID2_MAX_FRAME_PTR);
708 retVal += Fvid2_checkFrameList(outProcessList,
709 (uint32_t) FVID2_MAX_FRAME_PTR);
711 }
712 if ((FVID2_SOK == retVal) &&
713 (inProcessList->numFrames != virtContext->createParams.numPipe) &&
714 (outProcessList->numFrames != 1U))
715 {
716 retVal = FVID2_EBADARGS;
717 GT_0trace(DssTrace, GT_ERR,
718 "Number of frames in input (must be equal to number of pipes used) OR "
719 "output (must be equal to 1) frame list does not match !!\r\n");
720 }
721 if (FVID2_SOK == retVal)
722 {
723 qObj = (DssM2M_DrvQueObj *) Fvid2Utils_dequeue(bmObj->freeQ);
724 if (qObj == NULL)
725 {
726 GT_0trace(DssTrace, GT_ERR,
727 "ALLOC: Q object allocation failed\r\n");
728 retVal = FVID2_EALLOC;
729 }
730 if (FVID2_SOK == retVal)
731 {
732 qObj->virtContext = virtContext;
733 qObj->outFrm = outProcessList->frames[0U];
734 for (frmCnt = 0 ; frmCnt < inProcessList->numFrames ; frmCnt++)
735 {
736 qObj->inFrm[frmCnt] = inProcessList->frames[frmCnt];
737 }
738 Fvid2Utils_queue(bmObj->reqQ, &qObj->qElem, qObj);
739 virtContext->wbStatus.queueCount++;
740 instObj->status.queueCount++;
741 }
742 }
743 /* Step 6 */
744 if (FVID2_SOK == retVal)
745 {
746 GT_assert(DssTrace, (NULL != instObj->commRegs));
747 for (loopCnt = 0U ; loopCnt < virtContext->numPipe ; loopCnt++)
748 {
749 GT_assert(DssTrace,
750 (NULL != instObj->pipeRegs[virtContext->pipeId[loopCnt]]));
751 }
752 GT_assert(DssTrace, (NULL != instObj->ovrRegs));
753 GT_assert(DssTrace, (NULL != instObj->wbRegs));
755 if (Fvid2Utils_getNumQElem(bmObj->currQ) == 0U)
756 {
757 qObj = (DssM2M_DrvQueObj *) Fvid2Utils_dequeue(bmObj->reqQ);
758 GT_assert(DssTrace, (NULL != qObj));
759 for (loopCnt = 0U ; loopCnt < virtContext->numPipe ; loopCnt++)
760 {
761 CSL_dssVidPipeEnable(instObj->pipeRegs[virtContext->pipeId[loopCnt]],
762 (uint32_t) FALSE);
763 }
764 CSL_dssWbPipeEnable(instObj->wbRegs, (uint32_t) FALSE);
766 /* DCTRL has to be configurred before DISP */
767 retVal += Dss_m2mDrvPrgramDctrl(qObj->virtContext);
768 retVal += Dss_m2mDrvPrgramDisp(qObj->virtContext);
769 retVal += Dss_m2mDrvPrgramWbPipe(qObj->virtContext);
771 if (FVID2_SOK == retVal)
772 {
773 /* Queue to CurrQ */
774 Fvid2Utils_queue(bmObj->currQ, &qObj->qElem, qObj);
776 for (loopCnt = 0U ; loopCnt < virtContext->numPipe ; loopCnt++)
777 {
778 CSL_dssVidPipeSetBuffAddr(
779 instObj->pipeRegs[qObj->inFrm[loopCnt]->chNum],
780 FVID2_FID_TOP,
781 qObj->inFrm[loopCnt]->addr[0U],
782 qObj->inFrm[loopCnt]->addr[1U]);
783 }
784 CSL_dssWbPipeSetBuffAddr(instObj->wbRegs,
785 FVID2_FID_TOP,
786 qObj->outFrm->addr[0U],
787 qObj->outFrm->addr[1U]);
789 for (loopCnt = 0U ; loopCnt < virtContext->numPipe ; loopCnt++)
790 {
791 CSL_dssVidPipeEnable(instObj->pipeRegs[virtContext->pipeId[loopCnt]],
792 (uint32_t) TRUE);
793 }
794 CSL_dssWbPipeSetGoBit(instObj->wbRegs);
795 CSL_dssWbPipeEnable(instObj->wbRegs, (uint32_t) TRUE);
796 }
797 else
798 {
799 /* Queue back in case of failure */
800 Fvid2Utils_queue(bmObj->reqQ, &qObj->qElem, qObj);
801 GT_0trace(DssTrace, GT_ERR,
802 "Programming Failed: DSS Pipe/Disp/WB Pipe\r\n");
803 }
805 }
806 }
808 if ((NULL != instObj) && (NULL != instObj->commonObjRef->lockSem))
809 {
810 /* Post the instance semaphore */
811 (void) SemaphoreP_post(instObj->commonObjRef->lockSem);
812 }
813 HwiP_restore(cookie);
815 return retVal;
816 }
818 int32_t Dss_m2mGetProcessedRequest(Fdrv_Handle handle,
819 Fvid2_FrameList *inProcessList,
820 Fvid2_FrameList *outProcessList,
821 uint32_t timeout)
822 {
823 int32_t retVal = FVID2_SOK;
824 DssM2MDrv_VirtContext *virtContext= NULL;
825 DssM2MDrv_InstObj *instObj = NULL;
826 uint32_t semTimeout, cookie, loopCnt;
827 DssM2M_DrvQueObj *qObj;
828 DssM2M_DrvBufManObj *bmObj;
830 /** Steps
831 * 1. Get a queue object from the doneQ. Assert error if NULL.
832 * 2. Copy frames into inProcessList and outProcessList
833 * 3. Set frames and context to NULL
834 * 4. Move the queue object to freeQ
835 * 5. Increment De-queue Count in the status
836 */
837 if ((NULL == handle) || (NULL == inProcessList) || (NULL == outProcessList))
838 {
839 retVal = FVID2_EBADARGS;
840 }
841 cookie = HwiP_disable();
842 if (FVID2_SOK == retVal)
843 {
844 virtContext = (DssM2MDrv_VirtContext *)handle;
845 instObj = virtContext->instObj;
846 GT_assert(DssTrace, (NULL != instObj));
847 bmObj = &instObj->bmObj;
848 GT_assert(DssTrace, (NULL != bmObj));
850 if ((instObj->inUse != DSSM2M_DRV_USAGE_STATUS_IN_USE) ||
851 (virtContext->inUse != DSSM2M_DRV_USAGE_STATUS_IN_USE) ||
852 ((virtContext->state == DSSM2M_DRV_STATE_IDLE) ||
853 (virtContext->state == DSSM2M_DRV_STATE_UNINIT)))
854 {
855 retVal = FVID2_EFAIL;
856 GT_0trace(DssTrace, GT_ERR,
857 "Invalid state: Can't submit request to an un-opened instance!!\r\n");
858 }
859 }
860 if (FVID2_TIMEOUT_FOREVER == timeout)
861 {
862 semTimeout = SemaphoreP_WAIT_FOREVER;
863 }
864 else if (FVID2_TIMEOUT_NONE == timeout)
865 {
866 semTimeout = SemaphoreP_NO_WAIT;
867 }
868 else
869 {
870 semTimeout = timeout;
871 }
872 if ((NULL != instObj) && (NULL != instObj->commonObjRef->lockSem))
873 {
874 /* Take the instance semaphore */
875 (void) SemaphoreP_pend(instObj->commonObjRef->lockSem, semTimeout);
876 }
877 /* Steps 1 to 5 */
878 if (FVID2_SOK == retVal)
879 {
880 /* init frame list fields */
881 inProcessList->numFrames = 0U;
882 inProcessList->perListCfg = NULL;
883 outProcessList->numFrames = 0U;
884 outProcessList->perListCfg = NULL;
885 /* Only De-queue one frame per call */
886 qObj = (DssM2M_DrvQueObj *) Fvid2Utils_dequeue(virtContext->doneQ);
887 if (qObj != NULL)
888 {
889 for (loopCnt = 0U ; loopCnt < virtContext->numPipe ; loopCnt++)
890 {
891 inProcessList->frames[loopCnt] = qObj->inFrm[loopCnt];
892 inProcessList->numFrames++;
893 qObj->inFrm[loopCnt] = NULL;
894 }
896 outProcessList->frames[outProcessList->numFrames] = qObj->outFrm;
897 outProcessList->numFrames++;
898 qObj->virtContext = NULL;
899 qObj->outFrm = NULL;
900 virtContext->wbStatus.dequeueCount++;
901 instObj->status.dequeueCount++;
902 Fvid2Utils_queue(bmObj->freeQ, &qObj->qElem, qObj);
903 }
904 }
906 if ((retVal == FVID2_SOK) &&
907 (inProcessList->numFrames == 0U) &&
908 (outProcessList->numFrames == 0U))
909 {
910 if ((virtContext->state == DSSM2M_DRV_STATE_CREATED) ||
911 (virtContext->state == DSSM2M_DRV_STATE_STOPPED))
912 {
913 retVal = FVID2_ENO_MORE_BUFFERS;
914 }
915 }
917 if ((NULL != instObj) && (NULL != instObj->commonObjRef->lockSem))
918 {
919 /* Post the instance semaphore */
920 (void) SemaphoreP_post(instObj->commonObjRef->lockSem);
921 }
922 HwiP_restore(cookie);
924 return retVal;
925 }
927 int32_t Dss_m2mControl(Fdrv_Handle handle,
928 uint32_t cmd,
929 void *cmdArgs,
930 void *cmdStatusArgs)
931 {
932 int32_t retVal = FVID2_SOK;
933 DssM2MDrv_VirtContext *virtContext;
934 Fvid2_TimeStampParams *tsParams;
936 /* Check for NULL pointers */
937 if (handle == NULL)
938 {
939 GT_0trace(DssTrace, GT_ERR, "Invalid argument!!\r\n");
940 retVal = FVID2_EBADARGS;
941 }
942 else
943 {
944 virtContext = (DssM2MDrv_VirtContext *) handle;
945 switch (cmd)
946 {
947 case FVID2_START:
948 retVal = Dss_m2mDrvIoctlStart(virtContext);
949 break;
950 case FVID2_STOP:
951 retVal = Dss_m2mDrvIoctlStop(virtContext);
952 break;
953 case IOCTL_DSS_M2M_SET_WB_PIPE_PARAMS:
954 retVal = Dss_m2mDrvIoctlSetWbPipeParams(virtContext,
955 (const Dss_WbPipeCfgParams *)cmdArgs);
956 break;
957 case IOCTL_DSS_M2M_SET_WB_PIPE_MFLAG_PARAMS:
958 retVal = Dss_m2mDrvIoctlSetmFlagParams(virtContext,
959 (const Dss_WbPipeMflagParams *)cmdArgs);
960 break;
961 case IOCTL_DSS_M2M_GET_CURRENT_STATUS:
962 retVal = Dss_m2mDrvIoctlGetCurrentStatus(virtContext,
963 (Dss_WbStatus *)cmdArgs);
964 break;
965 case IOCTL_DSS_M2M_SET_WB_PIPE_CSC_COEFF:
966 retVal = Dss_m2mDrvIoctlSetWbPipeCsc(virtContext,
967 (const CSL_DssCscCoeff *)cmdArgs);
968 break;
969 case IOCTL_DSS_M2M_SET_WB_PIPE_DMA_CFG:
970 retVal = Dss_m2mDrvIoctlSetDmaCfg(virtContext,
971 (const CSL_DssWbPipeDmaCfg *)cmdArgs);
972 break;
973 case FVID2_REGISTER_TIMESTAMP_FXN:
974 tsParams = (Fvid2_TimeStampParams *)cmdArgs;
975 gDssM2mCommonObj.getTimeStamp = tsParams->timeStampFxn;
976 break;
977 case IOCTL_DSS_M2M_SET_PIPE_PARAMS:
978 retVal = Dss_m2mDrvIoctlSetDssPipeParams(virtContext,
979 (const Dss_PipeCfgParams *)cmdArgs);
980 break;
981 case IOCTL_DSS_M2M_SET_PIPE_MFLAG_PARAMS:
982 retVal = Dss_m2mDrvIoctlSetPipeMflagParams(virtContext,
983 (const Dss_PipeMflagParams *)cmdArgs);
984 break;
985 case IOCTL_DSS_M2M_SET_PIPE_CSC_COEFF:
986 retVal = Dss_m2mDrvIoctlSetPipeCsc(virtContext,
987 (const Dss_PipeCscParams *)cmdArgs);
988 break;
989 case IOCTL_DSS_DCTRL_SET_OVERLAY_PARAMS:
990 retVal = Dss_m2mDrvIoctlSetOverlayParams(virtContext,
991 (const Dss_DctrlOverlayParams *)cmdArgs);
992 break;
993 case IOCTL_DSS_DCTRL_SET_LAYER_PARAMS:
994 retVal = Dss_m2mDrvIoctlSetLayerParams(virtContext,
995 (const Dss_DctrlOverlayLayerParams *)cmdArgs);
996 break;
997 case IOCTL_DSS_DCTRL_SET_GLOBAL_DSS_PARAMS:
998 retVal = Dss_m2mDrvIoctlSetGlobalParams(virtContext,
999 (const Dss_DctrlGlobalDssParams *)cmdArgs);
1000 break;
1001 default:
1002 {
1003 GT_0trace(DssTrace, GT_ERR,
1004 "UNSUPPORTED_CMD: IOCTL not supported\r\n");
1005 retVal = FVID2_EUNSUPPORTED_CMD;
1006 }
1007 break;
1008 }
1009 }
1011 return retVal;
1012 }
1013 /* ========================================================================== */
1014 /* Static Function Definitions */
1015 /* ========================================================================== */
1016 int32_t Dss_m2mDrvSetWbPipeDmaCfg(DssM2MDrv_InstObj *instObj,
1017 const CSL_DssWbPipeDmaCfg *dmaCfg)
1018 {
1019 int32_t retVal = FVID2_SOK;
1021 if (NULL == instObj->wbRegs)
1022 {
1023 retVal = FVID2_EFAIL;
1024 }
1025 else
1026 {
1027 /* Configure HW module */
1028 CSL_dssWbPipeSetDmaConfig(instObj->wbRegs, dmaCfg);
1029 /* Update programmed configurations in the instance object */
1030 Fvid2Utils_memcpy(&instObj->progCfg.wbPipeCfg.dmaCfg,
1031 dmaCfg,
1032 sizeof(CSL_DssWbPipeDmaCfg));
1033 }
1035 return retVal;
1036 }
1038 static int32_t Dss_m2mDrvCreateInstQueues(DssM2MDrv_VirtContext *context)
1039 {
1040 int32_t retVal = FVID2_SOK;
1041 DssM2M_DrvBufManObj *bmObj;
1042 uint32_t qCnt = 0U, loopCnt;
1043 DssM2M_DrvQueObj *qObj;
1044 DssM2MDrv_InstObj *instObj;
1046 instObj = context->instObj;
1047 bmObj = &instObj->bmObj;
1049 bmObj->freeQ = NULL;
1050 bmObj->reqQ = NULL;
1051 bmObj->currQ = NULL;
1053 /* Create Queues */
1054 retVal = Fvid2Utils_constructQ(&bmObj->freeLlObj);
1055 GT_assert(DssTrace, (retVal == FVID2_SOK));
1056 bmObj->freeQ = &bmObj->freeLlObj;
1058 retVal = Fvid2Utils_constructQ(&bmObj->reqLlObj);
1059 GT_assert(DssTrace, (retVal == FVID2_SOK));
1060 bmObj->reqQ = &bmObj->reqLlObj;
1062 retVal = Fvid2Utils_constructQ(&bmObj->curLlObj);
1063 GT_assert(DssTrace, (retVal == FVID2_SOK));
1064 bmObj->currQ = &bmObj->curLlObj;
1066 if(FVID2_SOK == retVal)
1067 {
1068 for (qCnt = 0U ;
1069 qCnt < (DSS_DEF_QUEUE_LEN_PER_M2M_DRV_INST * DSSM2M_NUM_VIRTUAL_CONTEXT) ;
1070 qCnt++)
1071 {
1072 qObj = &bmObj->m2mQObj[qCnt];
1073 qObj->virtContext = context;
1074 for (loopCnt = 0U ; loopCnt < context->numPipe ; loopCnt++)
1075 {
1076 qObj->inFrm[loopCnt] = NULL;
1077 }
1078 qObj->outFrm = NULL;
1079 Fvid2Utils_queue(bmObj->freeQ, &qObj->qElem, qObj);
1080 }
1081 }
1083 return retVal;
1084 }
1086 static int32_t Dss_m2mDrvDeleteInstQueues(DssM2MDrv_VirtContext *context)
1087 {
1088 int32_t retVal = FVID2_SOK;
1089 DssM2M_DrvBufManObj *bmObj;
1090 DssM2M_DrvQueObj *qObj;
1091 DssM2MDrv_InstObj *instObj;
1093 instObj = context->instObj;
1094 bmObj = &instObj->bmObj;
1096 if(NULL != bmObj->freeQ)
1097 {
1098 /* Free-up all the queued free queue objects */
1099 do
1100 {
1101 qObj = (DssM2M_DrvQueObj *) Fvid2Utils_dequeue(bmObj->freeQ);
1102 } while (NULL != qObj);
1104 /* Delete the free Q */
1105 Fvid2Utils_destructQ(bmObj->freeQ);
1106 bmObj->freeQ = NULL;
1107 }
1109 if(NULL != bmObj->reqQ)
1110 {
1111 /* Free-up all the queued free queue objects */
1112 do
1113 {
1114 qObj = (DssM2M_DrvQueObj *) Fvid2Utils_dequeue(bmObj->reqQ);
1115 } while (NULL != qObj);
1117 /* Delete the free Q */
1118 Fvid2Utils_destructQ(bmObj->reqQ);
1119 bmObj->reqQ = NULL;
1120 }
1122 if(NULL != bmObj->currQ)
1123 {
1124 /* Free-up all the queued free queue objects */
1125 do
1126 {
1127 qObj = (DssM2M_DrvQueObj *) Fvid2Utils_dequeue(bmObj->currQ);
1128 } while (NULL != qObj);
1130 /* Delete the free Q */
1131 Fvid2Utils_destructQ(bmObj->currQ);
1132 bmObj->currQ = NULL;
1133 }
1135 return retVal;
1136 }
1138 static uint32_t Dss_m2mDrvWbPipeCfgChk(const Dss_WbPipeCfgParams *instCfg,
1139 const Dss_WbPipeCfgParams *progCfg)
1140 {
1141 uint32_t retVal = (uint32_t) TRUE;
1143 if ((instCfg->pipeCfg.wbMode != progCfg->pipeCfg.wbMode) ||
1144 (instCfg->pipeCfg.yuvAlign != progCfg->pipeCfg.yuvAlign) ||
1145 (instCfg->pipeCfg.cscRange != progCfg->pipeCfg.cscRange) ||
1146 (instCfg->pipeCfg.scEnable != progCfg->pipeCfg.scEnable) ||
1147 (instCfg->pipeCfg.alphaEnable != progCfg->pipeCfg.alphaEnable) ||
1148 (instCfg->pipeCfg.inFmt.width != progCfg->pipeCfg.inFmt.width) ||
1149 (instCfg->pipeCfg.inFmt.height != progCfg->pipeCfg.inFmt.height) ||
1150 (instCfg->pipeCfg.inFmt.dataFormat != progCfg->pipeCfg.inFmt.dataFormat) ||
1151 (instCfg->pipeCfg.outFmt.width != progCfg->pipeCfg.outFmt.width) ||
1152 (instCfg->pipeCfg.outFmt.height != progCfg->pipeCfg.outFmt.height) ||
1153 (instCfg->pipeCfg.outFmt.pitch != progCfg->pipeCfg.outFmt.pitch) ||
1154 (instCfg->pipeCfg.outFmt.dataFormat != progCfg->pipeCfg.outFmt.dataFormat) ||
1155 (instCfg->pipeCfg.outFmt.scanFormat != progCfg->pipeCfg.outFmt.scanFormat) ||
1156 (instCfg->pipeCfg.outFmt.ccsFormat != progCfg->pipeCfg.outFmt.ccsFormat) ||
1157 (instCfg->pipeCfg.outFmt.fieldMerged != progCfg->pipeCfg.outFmt.fieldMerged) ||
1158 (instCfg->pipeCfg.inPos.startX != progCfg->pipeCfg.inPos.startX) ||
1159 (instCfg->pipeCfg.inPos.startY != progCfg->pipeCfg.inPos.startY))
1160 {
1161 retVal = (uint32_t) FALSE;
1162 }
1164 return retVal;
1165 }
1167 static uint32_t Dss_m2mDrvWbDmaCfgChk(const CSL_DssWbPipeDmaCfg *instCfg,
1168 const CSL_DssWbPipeDmaCfg *progCfg)
1169 {
1170 uint32_t retVal = (uint32_t) TRUE;
1172 if ((instCfg->bufLowThreshold != progCfg->bufLowThreshold) ||
1173 (instCfg->bufHighThreshold != progCfg->bufHighThreshold) ||
1174 (instCfg->arbitration != progCfg->arbitration) ||
1175 (instCfg->frameCaptureRate != progCfg->frameCaptureRate) ||
1176 (instCfg->idleSize != progCfg->idleSize) ||
1177 (instCfg->idleNumber != progCfg->idleNumber))
1178 {
1179 retVal = (uint32_t) FALSE;
1180 }
1182 return retVal;
1183 }
1185 static uint32_t Dss_m2mDrvWbMFlagCfgChk(const Dss_WbPipeMflagParams *instCfg,
1186 const Dss_WbPipeMflagParams *progCfg)
1187 {
1188 uint32_t retVal = (uint32_t) TRUE;
1190 if ((instCfg->mFlagCfg.thresholdLow != progCfg->mFlagCfg.thresholdLow) ||
1191 (instCfg->mFlagCfg.thresholdHigh != progCfg->mFlagCfg.thresholdHigh))
1192 {
1193 retVal = (uint32_t) FALSE;
1194 }
1196 return retVal;
1197 }
1199 static uint32_t Dss_m2mDrvWbCscCfgChk(const CSL_DssCscCoeff *instCfg,
1200 const CSL_DssCscCoeff *progCfg)
1201 {
1202 uint32_t retVal = (uint32_t) TRUE;
1204 if ((instCfg->cscRange != progCfg->cscRange) ||
1205 (instCfg->c00 != progCfg->c00) ||
1206 (instCfg->c01 != progCfg->c01) ||
1207 (instCfg->c02 != progCfg->c02) ||
1208 (instCfg->c10 != progCfg->c10) ||
1209 (instCfg->c11 != progCfg->c11) ||
1210 (instCfg->c12 != progCfg->c12) ||
1211 (instCfg->c20 != progCfg->c20) ||
1212 (instCfg->c21 != progCfg->c21) ||
1213 (instCfg->c22 != progCfg->c22) ||
1214 (instCfg->preOffset1 != progCfg->preOffset1) ||
1215 (instCfg->preOffset2 != progCfg->preOffset2) ||
1216 (instCfg->preOffset3 != progCfg->preOffset3) ||
1217 (instCfg->postOffset1 != progCfg->postOffset1) ||
1218 (instCfg->postOffset2 != progCfg->postOffset2) ||
1219 (instCfg->postOffset3 != progCfg->postOffset3))
1220 {
1221 retVal = (uint32_t) FALSE;
1222 }
1224 return retVal;
1225 }
1227 static int32_t Dss_m2mDrvPrgramWbPipe(DssM2MDrv_VirtContext *context)
1228 {
1229 int32_t retVal = FVID2_SOK;
1230 uint32_t copyCfg = (uint32_t) FALSE;
1231 DssM2MDrv_InstObj *instObj;
1232 DssM2MDrv_WbPipeCfg *instCfg, *progCfg;
1234 instObj = context->instObj;
1235 instCfg = &context->instCfg.wbPipeCfg;
1236 progCfg = &instObj->progCfg.wbPipeCfg;
1237 GT_assert(DssTrace, (NULL != instObj->wbRegs));
1238 /* Re-program WB pipe only if channel/instance configurations
1239 are different than programmed */
1240 if (FVID2_SOK == retVal)
1241 {
1242 /* Check write-back pipe configuration */
1243 if (((uint32_t) FALSE) == Dss_m2mDrvWbPipeCfgChk(
1244 &instCfg->cfgParams,
1245 &progCfg->cfgParams))
1246 {
1247 /* Program WB pipeline */
1248 if (CSL_PASS != CSL_dssWbPipeSetConfig(instObj->wbRegs,
1249 &instCfg->cfgParams.pipeCfg))
1250 {
1251 retVal = FVID2_EFAIL;
1252 }
1253 else
1254 {
1255 copyCfg = (uint32_t) TRUE;
1256 }
1257 }
1258 }
1259 if (FVID2_SOK == retVal)
1260 {
1261 /* Check write-back pipe DMA configuration */
1262 if (((uint32_t) FALSE) == Dss_m2mDrvWbDmaCfgChk(
1263 &instCfg->dmaCfg,
1264 &progCfg->dmaCfg))
1265 {
1266 /* Program WB pipeline */
1267 CSL_dssWbPipeSetDmaConfig(instObj->wbRegs,
1268 &instCfg->dmaCfg);
1269 copyCfg = (uint32_t) TRUE;
1270 }
1271 }
1272 if (FVID2_SOK == retVal)
1273 {
1274 /* Check write-back pipe MFlag configuration */
1275 if (((uint32_t) FALSE) == Dss_m2mDrvWbMFlagCfgChk(
1276 &instCfg->mFlagParams,
1277 &progCfg->mFlagParams))
1278 {
1279 /* Program WB pipeline */
1280 CSL_dssWbPipeSetMflagConfig(instObj->wbRegs,
1281 &instCfg->mFlagParams.mFlagCfg);
1282 copyCfg = (uint32_t) TRUE;
1283 }
1284 }
1285 if (FVID2_SOK == retVal)
1286 {
1287 /* Check write-back pipe CSC configuration */
1288 if (((uint32_t) FALSE) == Dss_m2mDrvWbCscCfgChk(
1289 &instCfg->cscCoeff,
1290 &progCfg->cscCoeff))
1291 {
1292 /* Program WB pipeline */
1293 CSL_dssWbPipeSetCSCCoeff(instObj->wbRegs,
1294 &instCfg->cscCoeff);
1295 copyCfg = (uint32_t) TRUE;
1296 }
1297 }
1299 if ((FVID2_SOK == retVal) && (((uint32_t) TRUE) == copyCfg))
1300 {
1301 /* Update instance configurations */
1302 Fvid2Utils_memcpy(progCfg, instCfg, sizeof(DssM2MDrv_WbPipeCfg));
1303 }
1305 return retVal;
1306 }
1308 static int32_t Dss_m2mDrvIoctlStart(DssM2MDrv_VirtContext *context)
1309 {
1310 int32_t retVal = FVID2_SOK;
1311 DssM2MDrv_InstObj *instObj;
1313 /* Currently this API only does maintaining SW Driver states */
1314 instObj = context->instObj;
1315 GT_assert(DssTrace, (context != NULL));
1316 GT_assert(DssTrace, (instObj != NULL));
1318 if (NULL != instObj->commonObjRef->lockSem)
1319 {
1320 /* Take the instance semaphore */
1321 (void) SemaphoreP_pend(instObj->commonObjRef->lockSem,
1322 SemaphoreP_WAIT_FOREVER);
1323 }
1325 context->state = DSSM2M_DRV_STATE_RUNNING;
1327 if (NULL != instObj->commonObjRef->lockSem)
1328 {
1329 /* Take the instance semaphore */
1330 (void) SemaphoreP_post(instObj->commonObjRef->lockSem);
1331 }
1333 return retVal;
1334 }
1336 static int32_t Dss_m2mDrvIoctlStop(DssM2MDrv_VirtContext *context)
1337 {
1338 int32_t retVal = FVID2_SOK;
1339 uint32_t numReqQNum, loopCnt;
1340 DssM2MDrv_InstObj *instObj;
1341 DssM2M_DrvQueObj *qObj = NULL;
1342 DssM2M_DrvBufManObj *bmObj = NULL;
1344 /* Currently this API only does maintaining SW Driver states */
1345 instObj = context->instObj;
1346 GT_assert(DssTrace, (context != NULL));
1347 GT_assert(DssTrace, (instObj != NULL));
1349 if (NULL != instObj->commonObjRef->lockSem)
1350 {
1351 /* Take the instance semaphore */
1352 (void) SemaphoreP_pend(instObj->commonObjRef->lockSem,
1353 SemaphoreP_WAIT_FOREVER);
1354 }
1356 context->state = DSSM2M_DRV_STATE_STOPPED;
1358 /* When driver is stopped, put buffers from reqQ to doneQ for
1359 current virtual Context. This has to be done only for doneQ and
1360 not for reqQ as existing frame will be processed completely */
1361 if ((FVID2_SOK == retVal) &&
1362 (context->state == DSSM2M_DRV_STATE_STOPPED))
1363 {
1364 bmObj = &instObj->bmObj;
1365 GT_assert(DssTrace, (NULL != bmObj));
1366 numReqQNum = Fvid2Utils_getNumQElem(bmObj->reqQ);
1367 for (loopCnt = 0U ; loopCnt < numReqQNum ; loopCnt++)
1368 {
1369 qObj = (DssM2M_DrvQueObj *) Fvid2Utils_dequeue(bmObj->reqQ);
1370 GT_assert(DssTrace, (NULL != qObj));
1371 if (qObj->virtContext == context)
1372 {
1373 /* Move to doneQ, if it matches with currently closed context */
1374 Fvid2Utils_queue(context->doneQ, &qObj->qElem, qObj);
1375 }
1376 else
1377 {
1378 /* Queue back to reqQ */
1379 Fvid2Utils_queue(bmObj->reqQ, &qObj->qElem, qObj);
1380 }
1381 }
1382 }
1384 if (NULL != instObj->commonObjRef->lockSem)
1385 {
1386 /* Take the instance semaphore */
1387 (void) SemaphoreP_post(instObj->commonObjRef->lockSem);
1388 }
1390 return retVal;
1391 }
1393 static int32_t Dss_m2mDrvIoctlSetWbPipeParams(DssM2MDrv_VirtContext *context,
1394 const Dss_WbPipeCfgParams *pipeCfg)
1395 {
1396 int32_t retVal = FVID2_SOK;
1398 /* check for parameters */
1399 if (NULL == pipeCfg)
1400 {
1401 retVal = FVID2_EBADARGS;
1402 }
1403 else
1404 {
1405 if (pipeCfg->pipeCfg.wbMode != CSL_DSS_WB_PIPE_MODE_M2M)
1406 {
1407 /* Only M2M mode is supported in this driver */
1408 retVal = FVID2_EBADARGS;
1409 GT_0trace(DssTrace, GT_ERR, "Only M2M mode supported!!\r\n");
1410 }
1412 if (FVID2_SOK == retVal)
1413 {
1414 /* Only copy provided configurations to channel/virtual context object.
1415 This will be programmed to HW module when buffers are submitted
1416 through 'Fvid2_processRequest()' */
1417 Fvid2Utils_memcpy(&context->instCfg.wbPipeCfg.cfgParams,
1418 pipeCfg,
1419 sizeof(Dss_WbPipeCfgParams));
1420 }
1421 }
1423 return retVal;
1424 }
1426 static int32_t Dss_m2mDrvIoctlSetmFlagParams(DssM2MDrv_VirtContext *context,
1427 const Dss_WbPipeMflagParams *mFlagParams)
1428 {
1429 int32_t retVal = FVID2_SOK;
1431 /* check for parameters */
1432 if (NULL == mFlagParams)
1433 {
1434 retVal = FVID2_EBADARGS;
1435 }
1436 else
1437 {
1438 /* Only copy provided configurations to channel/virtual context object.
1439 This will be programmed to HW module when buffers are submitted
1440 through 'Fvid2_processRequest()' */
1441 Fvid2Utils_memcpy(&context->instCfg.wbPipeCfg.mFlagParams,
1442 mFlagParams,
1443 sizeof(Dss_WbPipeMflagParams));
1444 }
1446 return retVal;
1447 }
1449 static int32_t Dss_m2mDrvIoctlGetCurrentStatus(DssM2MDrv_VirtContext *context,
1450 Dss_WbStatus *status)
1451 {
1452 int32_t retVal = FVID2_SOK;
1455 /* check for parameters */
1456 if (NULL == status)
1457 {
1458 retVal = FVID2_EBADARGS;
1459 }
1460 else
1461 {
1462 /* Only copy provided configurations to channel/virtual context object.
1463 This will be programmed to HW module when buffers are submitted
1464 through 'Fvid2_processRequest()' */
1465 Fvid2Utils_memcpy(status,
1466 &context->wbStatus,
1467 sizeof(Dss_WbStatus));
1468 }
1470 return retVal;
1471 }
1473 static int32_t Dss_m2mDrvIoctlSetWbPipeCsc(DssM2MDrv_VirtContext *context,
1474 const CSL_DssCscCoeff *csc)
1475 {
1476 int32_t retVal = FVID2_SOK;
1478 /* check for parameters */
1479 if (NULL == csc)
1480 {
1481 retVal = FVID2_EBADARGS;
1482 }
1483 else
1484 {
1485 /* Only copy provided configurations to channel/virtual context object.
1486 This will be programmed to HW module when buffers are submitted
1487 through 'Fvid2_processRequest()' */
1488 Fvid2Utils_memcpy(&context->instCfg.wbPipeCfg.cscCoeff,
1489 csc,
1490 sizeof(CSL_DssCscCoeff));
1491 }
1493 return retVal;
1494 }
1496 static int32_t Dss_m2mDrvIoctlSetDmaCfg(DssM2MDrv_VirtContext *context,
1497 const CSL_DssWbPipeDmaCfg *dmaCfg)
1498 {
1499 int32_t retVal = FVID2_SOK;
1501 /* check for parameters */
1502 if (NULL == dmaCfg)
1503 {
1504 retVal = FVID2_EBADARGS;
1505 }
1506 else
1507 {
1508 /* upgrade configurations into context object and re-program HW module
1509 on buffer submission */
1510 Fvid2Utils_memcpy(&context->instCfg.wbPipeCfg.dmaCfg,
1511 dmaCfg,
1512 sizeof(CSL_DssWbPipeDmaCfg));
1513 }
1515 return retVal;
1516 }
1518 static void Dss_wbPipeCbFxn(const uint32_t *event,
1519 uint32_t numEvents,
1520 void *arg)
1521 {
1522 uint32_t loopCnt, currEvent, wbPipeId = 0U;
1523 Dss_EvtMgrClientInfo *pClientObj = (Dss_EvtMgrClientInfo *)arg;
1524 uint32_t eventGroup = pClientObj->eventGroup;
1525 DssM2MDrv_InstObj *instObj;
1527 Dss_convEventGrouptoModule(eventGroup, &wbPipeId);
1528 GT_assert(DssTrace, (CSL_DSS_MODULE_INVALID != wbPipeId));
1529 instObj = &(gDssM2mCommonObj.instObj[wbPipeId]);
1530 for(loopCnt=0U; loopCnt<numEvents; loopCnt++)
1531 {
1532 currEvent = event[loopCnt];
1533 if(DSS_WB_PIPE_EVENT_BUFF_FRAME_DONE == currEvent)
1534 {
1535 /* Application CB will be issued in the following function */
1536 Dss_wbPipeDmaCompletionCbFxn(instObj);
1537 }
1538 else if(DSS_WB_PIPE_EVENT_BUFF_OVERFLOW == currEvent)
1539 {
1540 instObj->status.underflowCount++;
1541 }
1542 else
1543 {
1544 GT_assert(DssTrace, FALSE);
1545 }
1546 }
1548 return;
1549 }
1551 static void Dss_wbPipeDmaCompletionCbFxn(DssM2MDrv_InstObj *instObj)
1552 {
1553 int32_t retVal = FVID2_SOK;
1554 uint32_t loopCnt;
1555 DssM2MDrv_VirtContext *virtContext= NULL;
1556 DssM2M_DrvQueObj *qObj = NULL;
1557 DssM2M_DrvBufManObj *bmObj = NULL;
1559 GT_assert(DssTrace, (NULL != instObj));
1560 bmObj = &instObj->bmObj;
1561 GT_assert(DssTrace, (NULL != bmObj));
1563 /** Steps
1564 * 1. Get a queue object from the currQ. Assert error if NULL.
1565 * 2. Move the queue object to doneQ
1566 * 3. Increment wb frame count Count in the status
1567 * 4. If number of elements in currQ < 1, then do following
1568 * a. Get a queue object from the reqQ. Assert error if NULL
1569 * b. Disable DSS and WB pipeline
1570 * c. Re-program DSS pipeline, Overlay and WB Pipeline if needed
1571 * d. Set buffer addresses in the WB & DSS Pipeline
1572 * e. Enable DSS and WB pipeline
1573 * f. Move the queue object to currQ
1574 */
1575 /* Steps 1 to 3 */
1576 if (FVID2_SOK == retVal)
1577 {
1578 qObj = (DssM2M_DrvQueObj *) Fvid2Utils_dequeue(bmObj->currQ);
1579 GT_assert(DssTrace, (NULL != qObj));
1580 virtContext = qObj->virtContext;
1581 GT_assert(DssTrace, (NULL != virtContext));
1582 Fvid2Utils_queue(virtContext->doneQ, &qObj->qElem, qObj);
1583 virtContext->wbStatus.wbFrmCount++;
1584 instObj->status.wbFrmCount++;
1585 /* Issue application CB */
1586 if(virtContext->fdmCbParams.fdmCbFxn != NULL)
1587 {
1588 virtContext->fdmCbParams.fdmCbFxn(virtContext->fdmCbParams.fdmData);
1589 }
1590 }
1592 /* Step 6 */
1593 if (FVID2_SOK == retVal)
1594 {
1595 GT_assert(DssTrace, (NULL != instObj->commRegs));
1596 for (loopCnt = 0U ; loopCnt < virtContext->numPipe ; loopCnt++)
1597 {
1598 GT_assert(DssTrace,
1599 (NULL != instObj->pipeRegs[virtContext->pipeId[loopCnt]]));
1600 }
1601 GT_assert(DssTrace, (NULL != instObj->ovrRegs));
1602 GT_assert(DssTrace, (NULL != instObj->wbRegs));
1604 /* Only program module if a frame is submitted */
1605 if ((Fvid2Utils_getNumQElem(bmObj->currQ) == 0U) &&
1606 (Fvid2Utils_getNumQElem(bmObj->reqQ) > 0U))
1607 {
1608 qObj = (DssM2M_DrvQueObj *) Fvid2Utils_dequeue(bmObj->reqQ);
1609 GT_assert(DssTrace, (NULL != qObj));
1610 for (loopCnt = 0U ; loopCnt < virtContext->numPipe ; loopCnt++)
1611 {
1612 CSL_dssVidPipeEnable(instObj->pipeRegs[virtContext->pipeId[loopCnt]],
1613 (uint32_t) FALSE);
1614 }
1615 CSL_dssWbPipeEnable(instObj->wbRegs, (uint32_t) FALSE);
1617 /* DCTRL has to be configurred before DISP */
1618 retVal += Dss_m2mDrvPrgramDctrl(qObj->virtContext);
1619 retVal += Dss_m2mDrvPrgramDisp(qObj->virtContext);
1620 retVal += Dss_m2mDrvPrgramWbPipe(qObj->virtContext);
1622 if (FVID2_SOK == retVal)
1623 {
1624 /* Queue to CurrQ */
1625 Fvid2Utils_queue(bmObj->currQ, &qObj->qElem, qObj);
1627 for (loopCnt = 0U ; loopCnt < virtContext->numPipe ; loopCnt++)
1628 {
1629 CSL_dssVidPipeSetBuffAddr(
1630 instObj->pipeRegs[qObj->inFrm[loopCnt]->chNum],
1631 FVID2_FID_TOP,
1632 qObj->inFrm[loopCnt]->addr[0U],
1633 qObj->inFrm[loopCnt]->addr[1U]);
1634 }
1635 CSL_dssWbPipeSetBuffAddr(instObj->wbRegs,
1636 FVID2_FID_TOP,
1637 qObj->outFrm->addr[0U],
1638 qObj->outFrm->addr[1U]);
1640 for (loopCnt = 0U ; loopCnt < virtContext->numPipe ; loopCnt++)
1641 {
1642 CSL_dssVidPipeEnable(instObj->pipeRegs[virtContext->pipeId[loopCnt]],
1643 (uint32_t) TRUE);
1644 }
1645 CSL_dssWbPipeSetGoBit(instObj->wbRegs);
1646 CSL_dssWbPipeEnable(instObj->wbRegs, (uint32_t) TRUE);
1647 }
1648 else
1649 {
1650 /* Queue back in case of failure */
1651 Fvid2Utils_queue(bmObj->reqQ, &qObj->qElem, qObj);
1652 GT_0trace(DssTrace, GT_ERR,
1653 "Programming Failed: DSS Pipe/Disp/WB Pipe\r\n");
1654 }
1656 }
1657 }
1659 GT_assert(DssTrace, (FVID2_SOK == retVal));
1661 return;
1662 }