1 /*
2 * Copyright (c) Texas Instruments Incorporated 2022
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_m2mDisp.c
36 *
37 * \brief File containing the DSS M2M driver DSS_DISP APIs.
38 *
39 */
41 /* ========================================================================== */
42 /* Include Files */
43 /* ========================================================================== */
44 #include <ti/drv/dss/dss.h>
45 #include <ti/drv/dss/src/drv/common/dss_evtMgr.h>
46 #include <ti/drv/dss/src/drv/disp/dss_dispDrv.h>
47 #include <ti/drv/dss/src/drv/disp/dss_dispPriv.h>
48 #include <ti/drv/dss/src/drv/dctrl/dss_dctrlDrv.h>
49 #include <ti/drv/dss/src/drv/dctrl/dss_dctrlPriv.h>
50 #include <ti/drv/dss/src/drv/m2m/dss_m2mDrv.h>
51 #include <dss_soc_priv.h>
53 /* ========================================================================== */
54 /* Macros & Typedefs */
55 /* ========================================================================== */
57 /* None */
59 /* ========================================================================== */
60 /* Structure Declarations */
61 /* ========================================================================== */
63 /* None */
65 /* ========================================================================== */
66 /* Function Declarations */
67 /* ========================================================================== */
68 /* Returns TRUE if instance and channel/context configurations matches,
69 returns FALSE otherwise */
70 uint32_t Dss_m2mDrvDispPipeCfgChk(const Dss_DispParams *instCfg,
71 const Dss_DispParams *progCfg);
73 /* Returns TRUE if instance and channel/context configurations matches,
74 returns FALSE otherwise */
75 uint32_t Dss_m2mDrvDispMFlagCfgChk(const Dss_DispPipeMflagParams *instCfg,
76 const Dss_DispPipeMflagParams *progCfg);
78 /* Returns TRUE if instance and channel/context configurations matches,
79 returns FALSE otherwise */
80 uint32_t Dss_m2mDrvDispCscCfgChk(const CSL_DssCscCoeff *instCfg,
81 const CSL_DssCscCoeff *progCfg);
83 int32_t Dss_m2mDrvPrgramDisp(DssM2MDrv_VirtContext *context);
85 /*
86 * Display IOCTLs
87 */
88 static int32_t Dss_m2mDrvValidateDispParams(DssM2MDrv_InstObj *instObj,
89 const Dss_PipeCfgParams *pipeCfg);
91 int32_t Dss_m2mDrvIoctlSetDssPipeParams(DssM2MDrv_VirtContext *context,
92 const Dss_PipeCfgParams *pipeCfg);
94 int32_t Dss_m2mDrvIoctlSetPipeMflagParams(DssM2MDrv_VirtContext *context,
95 const Dss_PipeMflagParams *mFlagParams);
97 int32_t Dss_m2mDrvIoctlSetPipeCsc(DssM2MDrv_VirtContext *context,
98 const Dss_PipeCscParams *csc);
100 /* ========================================================================== */
101 /* Global Variables */
102 /* ========================================================================== */
105 /* ========================================================================== */
106 /* Function Definitions */
107 /* ========================================================================== */
108 uint32_t Dss_m2mDrvDispPipeCfgChk(const Dss_DispParams *instCfg,
109 const Dss_DispParams *progCfg)
110 {
111 uint32_t retVal = (uint32_t) TRUE;
112 uint32_t loopCnt = 0U;
114 /* check for Pipe configurations */
115 if ((instCfg->pipeCfg.pipeType != progCfg->pipeCfg.pipeType) ||
116 (instCfg->pipeCfg.pixelInc != progCfg->pipeCfg.pixelInc) ||
117 (instCfg->pipeCfg.yuvAlign != progCfg->pipeCfg.yuvAlign) ||
118 (instCfg->pipeCfg.outWidth != progCfg->pipeCfg.outWidth) ||
119 (instCfg->pipeCfg.outHeight != progCfg->pipeCfg.outHeight) ||
120 (instCfg->pipeCfg.scEnable != progCfg->pipeCfg.scEnable) ||
121 (instCfg->pipeCfg.cscRange != progCfg->pipeCfg.cscRange) ||
122 (instCfg->pipeCfg.flipType != progCfg->pipeCfg.flipType) ||
123 (instCfg->pipeCfg.nibbleModeEnable != progCfg->pipeCfg.nibbleModeEnable) ||
124 (instCfg->pipeCfg.gammaEnable != progCfg->pipeCfg.gammaEnable) ||
125 (instCfg->pipeCfg.inFmt.width != progCfg->pipeCfg.inFmt.width) ||
126 (instCfg->pipeCfg.inFmt.height != progCfg->pipeCfg.inFmt.height) ||
127 (instCfg->pipeCfg.inFmt.pitch != progCfg->pipeCfg.inFmt.pitch) ||
128 (instCfg->pipeCfg.inFmt.dataFormat != progCfg->pipeCfg.inFmt.dataFormat) ||
129 (instCfg->pipeCfg.inFmt.scanFormat != progCfg->pipeCfg.inFmt.scanFormat) ||
130 (instCfg->pipeCfg.inFmt.ccsFormat != progCfg->pipeCfg.inFmt.ccsFormat) ||
131 (instCfg->pipeCfg.inFmt.fieldMerged != progCfg->pipeCfg.inFmt.fieldMerged))
132 {
133 retVal = (uint32_t) FALSE;
134 }
135 else
136 {
137 for (loopCnt = 0U ; loopCnt < CSL_DSS_NUM_LUT_ENTRIES ; loopCnt++)
138 {
139 if (instCfg->pipeCfg.clutData[loopCnt] !=
140 progCfg->pipeCfg.clutData[loopCnt])
141 {
142 break;
143 }
144 }
145 if (loopCnt < CSL_DSS_NUM_LUT_ENTRIES)
146 {
147 retVal = (uint32_t) FALSE;
148 }
149 }
150 /* check for DMA configurations */
151 if (retVal == ((uint32_t) TRUE))
152 {
153 if ((instCfg->dmaCfg.bufPreloadControl != progCfg->dmaCfg.bufPreloadControl) ||
154 (instCfg->dmaCfg.preloadVal != progCfg->dmaCfg.preloadVal) ||
155 (instCfg->dmaCfg.bufLowThreshold != progCfg->dmaCfg.bufLowThreshold) ||
156 (instCfg->dmaCfg.bufHighThreshold != progCfg->dmaCfg.bufHighThreshold) ||
157 (instCfg->dmaCfg.selfRefreshControl != progCfg->dmaCfg.selfRefreshControl) ||
158 (instCfg->dmaCfg.selfRefreshEnable != progCfg->dmaCfg.selfRefreshEnable) ||
159 (instCfg->dmaCfg.arbitration != progCfg->dmaCfg.arbitration))
160 {
161 retVal = (uint32_t) FALSE;
162 }
163 }
164 /* check for Alpha configurations */
165 if (retVal == ((uint32_t) TRUE))
166 {
167 if ((instCfg->alphaCfg.globalAlpha != progCfg->alphaCfg.globalAlpha) ||
168 (instCfg->alphaCfg.preMultiplyAlpha != progCfg->alphaCfg.preMultiplyAlpha))
169 {
170 retVal = (uint32_t) FALSE;
171 }
172 }
173 /* check for VC1 configurations */
174 if (retVal == ((uint32_t) TRUE))
175 {
176 if ((instCfg->vc1Cfg.vc1Enable != progCfg->vc1Cfg.vc1Enable) ||
177 (instCfg->vc1Cfg.rangeY != progCfg->vc1Cfg.rangeY) ||
178 (instCfg->vc1Cfg.rangeUV != progCfg->vc1Cfg.rangeUV))
179 {
180 retVal = (uint32_t) FALSE;
181 }
182 }
183 /* check for Crop configurations */
184 if (retVal == ((uint32_t) TRUE))
185 {
186 if ((instCfg->cropParams.cropEnable != progCfg->cropParams.cropEnable) ||
187 (instCfg->cropParams.cropCfg.cropTop != progCfg->cropParams.cropCfg.cropTop) ||
188 (instCfg->cropParams.cropCfg.cropBottom != progCfg->cropParams.cropCfg.cropBottom) ||
189 (instCfg->cropParams.cropCfg.cropLeft != progCfg->cropParams.cropCfg.cropLeft) ||
190 (instCfg->cropParams.cropCfg.cropRight != progCfg->cropParams.cropCfg.cropRight))
191 {
192 retVal = (uint32_t) FALSE;
193 }
194 }
195 /* check for Layer configurations */
196 if (retVal == ((uint32_t) TRUE))
197 {
198 if ((instCfg->layerPos.startX != progCfg->layerPos.startX) ||
199 (instCfg->layerPos.startY != progCfg->layerPos.startY))
200 {
201 retVal = (uint32_t) FALSE;
202 }
203 }
205 return retVal;
206 }
208 uint32_t Dss_m2mDrvDispMFlagCfgChk(const Dss_DispPipeMflagParams *instCfg,
209 const Dss_DispPipeMflagParams *progCfg)
210 {
211 uint32_t retVal = (uint32_t) TRUE;
213 if ((instCfg->mflagCfg.thresholdLow != progCfg->mflagCfg.thresholdLow) ||
214 (instCfg->mflagCfg.thresholdHigh != progCfg->mflagCfg.thresholdHigh))
215 {
216 retVal = (uint32_t) FALSE;
217 }
219 return retVal;
220 }
222 uint32_t Dss_m2mDrvDispCscCfgChk(const CSL_DssCscCoeff *instCfg,
223 const CSL_DssCscCoeff *progCfg)
224 {
225 uint32_t retVal = (uint32_t) TRUE;
227 if ((instCfg->cscRange != progCfg->cscRange) ||
228 (instCfg->c00 != progCfg->c00) ||
229 (instCfg->c01 != progCfg->c01) ||
230 (instCfg->c02 != progCfg->c02) ||
231 (instCfg->c10 != progCfg->c10) ||
232 (instCfg->c11 != progCfg->c11) ||
233 (instCfg->c12 != progCfg->c12) ||
234 (instCfg->c20 != progCfg->c20) ||
235 (instCfg->c21 != progCfg->c21) ||
236 (instCfg->c22 != progCfg->c22) ||
237 (instCfg->preOffset1 != progCfg->preOffset1) ||
238 (instCfg->preOffset2 != progCfg->preOffset2) ||
239 (instCfg->preOffset3 != progCfg->preOffset3) ||
240 (instCfg->postOffset1 != progCfg->postOffset1) ||
241 (instCfg->postOffset2 != progCfg->postOffset2) ||
242 (instCfg->postOffset3 != progCfg->postOffset3))
243 {
244 retVal = (uint32_t) FALSE;
245 }
247 return retVal;
248 }
250 int32_t Dss_m2mDrvPrgramDisp(DssM2MDrv_VirtContext *context)
251 {
252 int32_t retVal = FVID2_SOK;
253 uint32_t copyCfg = (uint32_t) FALSE;
254 uint32_t layerNum, pipeIdx;
255 DssM2MDrv_InstObj *instObj;
256 DssM2MDrv_DispPipeCfg *instCfg, *progCfg;
257 CSL_DssOverlayPipePosCfg overlayPosCfg;
259 instObj = context->instObj;
261 for (pipeIdx = 0U ; pipeIdx < context->numPipe ; pipeIdx++)
262 {
263 instCfg = &context->instCfg.pipeCfg[context->pipeId[pipeIdx]];
264 progCfg = &instObj->progCfg.pipeCfg[context->pipeId[pipeIdx]];
265 /* Re-program DSS pipe only if channel/instance configurations
266 are different than programmed */
267 if (FVID2_SOK == retVal)
268 {
269 /* Check DSS Pipeline configuration */
270 if (((uint32_t) FALSE) == Dss_m2mDrvDispPipeCfgChk(&instCfg->cfgParams,
271 &progCfg->cfgParams))
272 {
273 if (FVID2_SOK == retVal)
274 {
275 /* Program: DSS Pipeline */
276 retVal = CSL_dssVidPipeSetConfig(instObj->pipeRegs[context->pipeId[pipeIdx]],
277 (const CSL_DssVidPipeCfg *)(&instCfg->cfgParams.pipeCfg),
278 (const CSL_DssVidPipeVC1Cfg *)(&instCfg->cfgParams.vc1Cfg));
279 }
280 if (FVID2_SOK == retVal)
281 {
282 /* Program: DMA, Alpha, Crop, Layer configurations */
283 CSL_dssVidPipeSetDmaConfig(instObj->pipeRegs[context->pipeId[pipeIdx]],
284 (const CSL_DssVidPipeDmaCfg *)(&instCfg->cfgParams.dmaCfg));
286 CSL_dssVidPipeSetAlphaConfig(instObj->pipeRegs[context->pipeId[pipeIdx]],
287 (const CSL_DssVidPipeAlphaCfg *)(&instCfg->cfgParams.alphaCfg));
289 #if defined (SOC_J721E)
290 CSL_dssVidPipeSetCropConfig(instObj->pipeRegs[context->pipeId[pipeIdx]],
291 (const Fvid2_EdgeCropConfig *)(&instCfg->cfgParams.cropParams.cropCfg),
292 instCfg->cfgParams.cropParams.cropEnable);
293 #endif
294 layerNum = CSL_dssOverlayGetEnabledPipeLayerNum(instObj->ovrRegs,
295 context->pipeId[pipeIdx]);
296 GT_assert(DssTrace, (layerNum < CSL_DSS_OVERLAY_LAYER_MAX));
297 overlayPosCfg.layerPos.startX = instCfg->cfgParams.layerPos.startX;
298 overlayPosCfg.layerPos.startY = instCfg->cfgParams.layerPos.startY;
299 CSL_dssOverlaySetPipePosConfig(instObj->ovrRegs,
300 (const CSL_DssOverlayPipePosCfg *)(&overlayPosCfg),
301 layerNum);
302 }
303 if (FVID2_SOK == retVal)
304 {
305 copyCfg = (uint32_t) TRUE;
306 }
307 }
308 }
309 if (FVID2_SOK == retVal)
310 {
311 /* Check DSS Pipeline MFlag configuration */
312 if (((uint32_t) FALSE) == Dss_m2mDrvDispMFlagCfgChk(&instCfg->mFlagParams,
313 &progCfg->mFlagParams))
314 {
315 if (FVID2_SOK == retVal)
316 {
317 /* Program: DSS Pipeline MFlag */
318 CSL_dssVidPipeSetMflagConfig(instObj->pipeRegs[context->pipeId[pipeIdx]],
319 (const CSL_DssVidPipeMFlagCfg *)(&instCfg->mFlagParams.mflagCfg));
320 copyCfg = (uint32_t) TRUE;
321 }
322 }
323 }
324 if (FVID2_SOK == retVal)
325 {
326 /* Check DSS Pipeline Csc configuration */
327 if (((uint32_t) FALSE) == Dss_m2mDrvDispCscCfgChk(&instCfg->cscCoeff,
328 &progCfg->cscCoeff))
329 {
330 if (FVID2_SOK == retVal)
331 {
332 /* Program: DSS Pipeline Csc */
333 CSL_dssVidPipeSetCSCCoeff(instObj->pipeRegs[context->pipeId[pipeIdx]],
334 (const CSL_DssCscCoeff *)(&instCfg->cscCoeff));
335 copyCfg = (uint32_t) TRUE;
336 }
337 }
338 }
339 if ((FVID2_SOK == retVal) && (((uint32_t) TRUE) == copyCfg))
340 {
341 /* Update instance configurations */
342 Fvid2Utils_memcpy(progCfg, instCfg, sizeof(DssM2MDrv_DispPipeCfg));
343 }
344 }
346 return retVal;
347 }
349 static int32_t Dss_m2mDrvValidateDispParams(DssM2MDrv_InstObj *instObj,
350 const Dss_PipeCfgParams *pipeCfg)
351 {
352 int32_t retVal = FVID2_SOK;
353 const Dss_DispParams *dispParams;
355 dispParams = &pipeCfg->cfgParams;
356 /* Not Checked: Interlaced to progressive or vice versa, not supported in M2M */
357 /* Scaling ratio check */
358 if(((dispParams->pipeCfg.inFmt.height * 16U) <
359 (dispParams->pipeCfg.outHeight)) ||
360 ((dispParams->pipeCfg.inFmt.width * 16U) <
361 (dispParams->pipeCfg.outWidth)))
362 {
363 GT_0trace(DssTrace,
364 GT_ERR,
365 "M2M: Upscaling ratio is more than 16x \r\n");
366 retVal = FVID2_EINVALID_PARAMS;
367 }
368 if(((dispParams->pipeCfg.inFmt.height) >
369 (dispParams->pipeCfg.outHeight * 4U)) ||
370 ((dispParams->pipeCfg.inFmt.width) >
371 (dispParams->pipeCfg.outWidth * 4U)))
372 {
373 GT_0trace(DssTrace,
374 GT_ERR,
375 "M2M: Downscaling ratio is more than 0.25x \r\n");
376 retVal = FVID2_EINVALID_PARAMS;
377 }
379 if((dispParams->pipeCfg.inFmt.height != dispParams->pipeCfg.outHeight) ||
380 (dispParams->pipeCfg.inFmt.width != dispParams->pipeCfg.outWidth))
381 {
382 if(TRUE == Dss_dispIsVidLInst(pipeCfg->pipeId))
383 {
384 GT_0trace(DssTrace,
385 GT_ERR,
386 "M2M: Scaling cant be enabled for video lite pipe \r\n");
387 retVal = FVID2_EINVALID_PARAMS;
388 }
389 if(FALSE == dispParams->pipeCfg.scEnable)
390 {
391 GT_0trace(DssTrace,
392 GT_ERR,
393 "M2M: Scaling should be enabled \r\n");
394 retVal = FVID2_EINVALID_PARAMS;
395 }
396 }
398 if((dispParams->cropParams.cropCfg.cropTop >= 32U) ||
399 (dispParams->cropParams.cropCfg.cropBottom >= 32U) ||
400 (dispParams->cropParams.cropCfg.cropLeft >= 32U) ||
401 (dispParams->cropParams.cropCfg.cropRight >= 32U))
402 {
403 GT_0trace(DssTrace,
404 GT_ERR,
405 "M2M: Crop Parameter(s) should be less than 32 \r\n");
406 retVal = FVID2_EINVALID_PARAMS;
407 }
409 if(((dispParams->pipeCfg.flipType == FVID2_FLIP_TYPE_V) ||
410 (dispParams->pipeCfg.flipType == FVID2_FLIP_TYPE_H)) &&
411 ((dispParams->pipeCfg.inFmt.dataFormat == FVID2_DF_RGB24_888) ||
412 (dispParams->pipeCfg.inFmt.dataFormat == FVID2_DF_BGR24_888)))
413 {
414 GT_0trace(DssTrace,
415 GT_ERR,
416 "M2M: Flip Parameter(s) should not be used for 24-bit RGB/BGR formats \r\n");
417 retVal = FVID2_EINVALID_PARAMS;
418 }
420 /* There is a limitation with scaling in DSS, where maximum scaling ratio
421 * supported is the ratio of the DSS functional clock and Pixel Clock.
422 * Driver can't check this condition as it is unaware of Pixel Clock.
423 * So it should be checked by the application.
424 */
426 return retVal;
427 }
429 int32_t Dss_m2mDrvIoctlSetDssPipeParams(DssM2MDrv_VirtContext *context,
430 const Dss_PipeCfgParams *pipeCfg)
431 {
432 int32_t retVal = FVID2_SOK;
434 /* check for parameters */
435 if (NULL == pipeCfg)
436 {
437 retVal = FVID2_EBADARGS;
438 }
439 else if (pipeCfg->pipeId >= CSL_DSS_VID_PIPE_ID_MAX)
440 {
441 retVal = FVID2_EBADARGS;
442 }
443 else
444 {
445 retVal = Dss_m2mDrvValidateDispParams(context->instObj, pipeCfg);
446 if (retVal == FVID2_SOK)
447 {
448 /* upgrade configurations into context object and re-program HW module
449 on buffer submission */
450 Fvid2Utils_memcpy(&context->instCfg.pipeCfg[pipeCfg->pipeId].cfgParams,
451 &pipeCfg->cfgParams,
452 sizeof(Dss_DispParams));
453 }
454 }
456 return retVal;
457 }
459 int32_t Dss_m2mDrvIoctlSetPipeMflagParams(DssM2MDrv_VirtContext *context,
460 const Dss_PipeMflagParams *mFlagParams)
461 {
462 int32_t retVal = FVID2_SOK;
464 /* check for parameters */
465 if (NULL == mFlagParams)
466 {
467 retVal = FVID2_EBADARGS;
468 }
469 else if (mFlagParams->pipeId >= CSL_DSS_VID_PIPE_ID_MAX)
470 {
471 retVal = FVID2_EBADARGS;
472 }
473 else
474 {
475 /* upgrade configurations into context object and re-program HW module
476 on buffer submission */
477 Fvid2Utils_memcpy(&context->instCfg.pipeCfg[mFlagParams->pipeId].mFlagParams,
478 &mFlagParams->mFlagCfg,
479 sizeof(Dss_DispPipeMflagParams));
480 }
482 return retVal;
483 }
485 int32_t Dss_m2mDrvIoctlSetPipeCsc(DssM2MDrv_VirtContext *context,
486 const Dss_PipeCscParams *csc)
487 {
488 int32_t retVal = FVID2_SOK;
490 /* check for parameters */
491 if (NULL == csc)
492 {
493 retVal = FVID2_EBADARGS;
494 }
495 else if (csc->pipeId >= CSL_DSS_VID_PIPE_ID_MAX)
496 {
497 retVal = FVID2_EBADARGS;
498 }
499 else
500 {
501 /* upgrade configurations into context object and re-program HW module
502 on buffer submission */
503 Fvid2Utils_memcpy(&context->instCfg.pipeCfg[csc->pipeId].cscCoeff,
504 &csc->csc,
505 sizeof(CSL_DssCscCoeff));
506 }
508 return retVal;
509 }