cal-lld: add to PDK
[processor-sdk/pdk.git] / packages / ti / drv / cal / src / drv / cal_drvProc.c
1 /* 
2  *  Copyright (c) Texas Instruments Incorporated 2018
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *    Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  *    Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the
14  *    distribution.
15  *
16  *    Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
33 /**
34  *  \file cal_drvProc.c
35  *
36  *  \brief File containing the CAL capture driver process related functions.
37  *
38  */
40 /* ========================================================================== */
41 /*                             Include Files                                  */
42 /* ========================================================================== */
44 #include <ti/drv/cal/src/drv/cal_drvPriv.h>
46 /* ========================================================================== */
47 /*                           Macros & Typedefs                                */
48 /* ========================================================================== */
50 /* None */
52 /* ========================================================================== */
53 /*                         Structure Declarations                             */
54 /* ========================================================================== */
56 /* None */
58 /* ========================================================================== */
59 /*                          Function Declarations                             */
60 /* ========================================================================== */
62 /* None */
64 /* ========================================================================== */
65 /*                            Global Variables                                */
66 /* ========================================================================== */
68 /* None */
70 /* ========================================================================== */
71 /*                          Function Definitions                              */
72 /* ========================================================================== */
74 /**
75  *  \brief Extern function to be implemented by driver to provide a new frame
76  *  buffers from application to the core.
77  */
78 Cal_CoreFrame *calDrvCaptCoreReqFrameCb(void  *drvData,
79                                         uint32_t streamId,
80                                         uint32_t chId)
81 {
82     uintptr_t cookie;
83     CalDrv_CaptChObj   *chObj;
84     CalDrv_CaptInstObj *instObj;
85     CalDrv_CaptQueObj  *qObj;
86     Cal_CoreFrame      *coreFrm = NULL;
88     instObj = (CalDrv_CaptInstObj *) drvData;
89     GT_assert(CalTrace, (NULL != instObj));
90     GT_assert(CalTrace, (streamId < CAL_CAPT_MAX_STREAMS));
91     GT_assert(CalTrace, (chId < instObj->createPrms.numCh));
93     /* Get channel specific object in the required instance */
94     chObj = &instObj->chObj[streamId][chId];
96     cookie = HwiP_disable();
98     qObj = (CalDrv_CaptQueObj *) Fvid2Utils_dequeue(chObj->bmObj.reqQ);
99     if(NULL != qObj)
100     {
101         /*
102          * Buffer available in request queue
103          */
104         /* Copy the address and increment credit */
105         qObj->coreFrm.addr[0] = qObj->frm->addr[0];
106         qObj->coreFrm.addr[1] = qObj->frm->addr[1];
107         qObj->coreFrm.addr[2] = qObj->frm->addr[2];
108         qObj->coreFrm.addr[3] = qObj->frm->addr[3];
109         qObj->coreFrm.addr[4] = qObj->frm->addr[4];
110         qObj->coreFrm.addr[5] = qObj->frm->addr[5];
111         qObj->coreFrm.rtParams   = qObj->frm->perFrameCfg;
112         qObj->coreFrm.dropFrm = (uint32_t) FALSE;
113         /* If app passes NULL pointer, then drop the frame */
114         if (0x0U == qObj->coreFrm.addr[0])
115         {
116             qObj->coreFrm.dropFrm = (uint32_t) TRUE;
117         }
119         qObj->creditCnt++;
120         coreFrm = &qObj->coreFrm;
121         Fvid2Utils_queue(chObj->bmObj.curQ, &qObj->qElem, qObj);
122     }
123     else
124     {
125         /*
126          * No more buffers available in request queue - decide what to do
127          * based on buffer capture mode
128          */
129         if(CAL_CAPT_BCM_LAST_FRM_REPEAT == instObj->createPrms.bufCaptMode)
130         {
131             /* Repeat the last frame queued to the core */
132             qObj = (CalDrv_CaptQueObj *)
133                    Fvid2Utils_peakTail(chObj->bmObj.curQ);
134             /* This can't return NULL unless there is a bug in the buffer
135              * management */
136             GT_assert(CalTrace, (NULL != qObj));
137             qObj->creditCnt++;
138             coreFrm = &qObj->coreFrm;
139         }
140         else if(CAL_CAPT_BCM_CIRCULAR_FRM_REPEAT == 
141                 instObj->createPrms.bufCaptMode)
142         {
143             /*
144              * Repeat the oldest frame queued to the core and make it at
145              * the last element in the current queue
146              */
147             qObj = (CalDrv_CaptQueObj *)
148                    Fvid2Utils_dequeue(chObj->bmObj.curQ);
149             /* This can't return NULL unless there is a bug in the buffer
150              * management */
151             GT_assert(CalTrace, (NULL != qObj));
152             qObj->creditCnt++;
153             coreFrm = &qObj->coreFrm;
155             /* Queue back to the start */
156             Fvid2Utils_queue(chObj->bmObj.curQ, &qObj->qElem, qObj);
157         }
158         else
159         {
160             GT_assert(CalTrace, FALSE);
161         }
162     }
164     GT_1trace(CalTrace, GT_DEBUG,
165               "CaptDrv: Queued buffer 0x%0.8x to core\r\n", coreFrm->addr[0]);
167     HwiP_restore(cookie);
169     GT_assert(CalTrace, (NULL != coreFrm));
170     return (coreFrm);
173 /**
174  *  \brief Extern callback function to be implemented by driver to free
175  *  up buffers to the application specified by the core.
176  */
177 int32_t calDrvCaptCoreFrameDoneCb(void *drvData, const Cal_CoreFrame *coreFrm)
179     uintptr_t cookie;
180     uint32_t curQCnt, reqQCnt;
181     uint64_t curTimeStamp;
182     Bool   frmQueuedToDoneQ = FALSE;
183     CalDrv_CaptChObj   *chObj;
184     CalDrv_CaptInstObj *instObj;
185     CalDrv_CaptQueObj  *qObj, *qObjTemp;
186     Cal_CaptRtParams   *rtPrms;
187     uint32_t              isWrDescValid;
189     instObj = (CalDrv_CaptInstObj *) drvData;
190     GT_assert(CalTrace, (NULL != instObj));
191     GT_assert(CalTrace, (NULL != coreFrm));
192     GT_assert(CalTrace, (coreFrm->streamId < CAL_CAPT_MAX_STREAMS));
193     GT_assert(CalTrace, (coreFrm->chId < instObj->createPrms.numCh));
194     GT_assert(CalTrace, (coreFrm->fid < FVID2_MAX_FIELDS));
196     /* Get channel specific object in the required instance */
197     chObj = &instObj->chObj[coreFrm->streamId][coreFrm->chId];
199     cookie = HwiP_disable();
201     GT_assert(CalTrace, (NULL != instObj->getTimeStamp));
202     curTimeStamp = instObj->getTimeStamp(NULL);
203     GT_1trace(CalTrace, GT_DEBUG,
204               "CaptDrv: Buffer 0x%0.8x capture done\r\n", coreFrm->addr[0]);
206     /* Update channel statistics */
207     chObj->stat.captFrmCount++;
208     chObj->stat.fldCount[coreFrm->fid]++;
209     if((chObj->bmObj.isProgressive == FALSE) &&
210        (chObj->stat.lastFid == coreFrm->fid))
211     {
212         chObj->stat.fidRepeatCount++;
213     }
214     chObj->stat.lastFid = coreFrm->fid;
215     chObj->stat.lastFrmTimeStamp = (uint32_t) (curTimeStamp / 1000U);
216     isWrDescValid = (uint32_t) TRUE;
217     if ((uint32_t) TRUE == isWrDescValid)
218     {
219         if(coreFrm->width > chObj->stat.maxRecvFrmWidth)
220         {
221             chObj->stat.maxRecvFrmWidth = coreFrm->width;
222         }
223         if(coreFrm->height > chObj->stat.maxRecvFrmHeight)
224         {
225             chObj->stat.maxRecvFrmHeight = coreFrm->height;
226         }
227         /* Init min values for the first frame capture */
228         if(chObj->stat.captFrmCount == 1U)
229         {
230             chObj->stat.minRecvFrmWidth  = coreFrm->width;
231             chObj->stat.minRecvFrmHeight = coreFrm->height;
232         }
233         else
234         {
235             if(coreFrm->width < chObj->stat.minRecvFrmWidth)
236             {
237                 chObj->stat.minRecvFrmWidth = coreFrm->width;
238             }
239             if(coreFrm->height < chObj->stat.minRecvFrmHeight)
240             {
241                 chObj->stat.minRecvFrmHeight = coreFrm->height;
242             }
243         }
244         chObj->stat.lastFrmWidth     = coreFrm->width;
245         chObj->stat.lastFrmHeight    = coreFrm->height;
246     }
248     /* Get reference of the queue head */
249     qObj = (CalDrv_CaptQueObj *) coreFrm->drvData;
250     GT_assert(CalTrace, (NULL != qObj));
252     /* Decrement credit count as frame capture is complete - credit can't
253      * be zero */
254     GT_assert(CalTrace, (qObj->creditCnt > 0U));
255     qObj->creditCnt--;
256     if(qObj->creditCnt > 0U)
257     {
258         chObj->stat.repeatFrmCount++;
259     }
261     GT_assert(CalTrace, (NULL != qObj->frm));
262     qObj->frm->status = coreFrm->status;
264     if(CAL_CAPT_BCM_LAST_FRM_REPEAT == instObj->createPrms.bufCaptMode)
265     {
266         /* Get the current queue counts */
267         curQCnt = Fvid2Utils_getNumQElem(chObj->bmObj.curQ);
268         reqQCnt = Fvid2Utils_getNumQElem(chObj->bmObj.reqQ);
270         if(0U == qObj->creditCnt)
271         {
272             qObjTemp = (CalDrv_CaptQueObj *)
273                        Fvid2Utils_dequeue(chObj->bmObj.curQ);
274             /* Head node and core frame should match */
275             GT_assert(CalTrace, (qObj == qObjTemp));
277             /* In last frame repeat mode, we could return all the frames to
278              * the application if credit becomes 0 and there are some more
279              * request in the current or request queue. Current queue is
280              * checked for 1 element as the current frame is still present
281              * in the queue. */
282             if((curQCnt > 1U) || (reqQCnt > 0U))
283             {
284                 GT_1trace(CalTrace, GT_DEBUG,
285                           "CaptDrv: Dequeued buffer 0x%0.8x\r\n",
286                           coreFrm->addr[0]);
288                 qObj->coreFrm.addr[0] = 0x0U;
289                 qObj->coreFrm.addr[1] = 0x0U;
290                 qObj->coreFrm.addr[2] = 0x0U;
291                 qObj->coreFrm.dropFrm    = (uint32_t) FALSE;
293                 /* Updated runtime parameters */
294                 GT_assert(CalTrace, (NULL != qObj->frm));
295                 qObj->frm->fid = qObj->coreFrm.fid;
296                 if(NULL != qObj->frm->perFrameCfg)
297                 {
298                     rtPrms = (Cal_CaptRtParams *) qObj->frm->perFrameCfg;
299                     rtPrms->capturedOutWidth  = qObj->coreFrm.width;
300                     rtPrms->capturedOutHeight = qObj->coreFrm.height;
301                 }
303                 /* Return the frame to done queue */
304                 GT_assert(CalTrace, (NULL != qObj->frm));
305                 qObj->frm->timeStamp64 = curTimeStamp;
306                 Fvid2Utils_queue(
307                     instObj->doneQ[coreFrm->streamId],
308                     &qObj->qElem,
309                     qObj);
310                 frmQueuedToDoneQ = (Bool) TRUE;
311             }
312             /* In last frame repeat mode, if credit becomes 0 and there are
313              * no more request in the current and request queues, take this
314              * request and queue it back to request queue so that when
315              * the core asks for next buffer, we repeat the frame
316              * automatically. This is needed because the user could
317              * queue a request in between and this frame will end-up
318              * in the current queue!!
319              * Also increment the repeat frame counter here. */
320             else if((curQCnt == 1U) && (reqQCnt == 0U))
321             {
322                 chObj->stat.repeatFrmCount++;
323                 Fvid2Utils_queue(chObj->bmObj.reqQ, &qObj->qElem, qObj);
324             }
325             else
326             {
327                 /* This can't happen as curQCnt can't be zero!! */
328                 GT_assert(CalTrace, FALSE);
329             }
330         }
331     }
332     else if(CAL_CAPT_BCM_CIRCULAR_FRM_REPEAT ==
333             instObj->createPrms.bufCaptMode)
334     {
335         /* Do nothing, just increment repeat count */
336         if(0U == qObj->creditCnt)
337         {
338             chObj->stat.repeatFrmCount++;
339         }
340     }
341     else
342     {
343         GT_assert(CalTrace, FALSE);
344     }
346     HwiP_restore(cookie);
348     if(NULL != instObj->fdmCbPrms.fdmCbFxn)
349     {
350         /* Give callback to application if frame is put in done queue */
351         /* TODO - handle multi-channel case!! */
352         if((Bool) TRUE == frmQueuedToDoneQ)
353         {
354             instObj->fdmCbPrms.fdmCbFxn(instObj->fdmCbPrms.fdmData);
355         }
356     }
358     return (FVID2_SOK);