39f19e11cc7c9126d577eb45fd227cdfd37db2c9
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);
171 }
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)
178 {
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);
359 }