You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
370 lines
13 KiB
370 lines
13 KiB
/*
|
|
* Copyright (c) 2024 Rockchip Electronics Co., Ltd
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*/
|
|
|
|
#include "hwi_c/aiq_pdafStreamProcUnit.h"
|
|
|
|
#include "c_base/aiq_list.h"
|
|
#include "hwi_c/aiq_CamHwBase.h"
|
|
#include "rkcif-config.h"
|
|
|
|
#define PDAF_HELP_THREAD_MSG_MAX (3)
|
|
|
|
static int64_t get_systime_us() {
|
|
struct timespec times = {0, 0};
|
|
int64_t time;
|
|
|
|
clock_gettime(CLOCK_MONOTONIC, ×);
|
|
time = times.tv_sec * 1000000LL + times.tv_nsec / 1000LL;
|
|
|
|
return time;
|
|
}
|
|
|
|
static XCamReturn _start_stream(AiqPdafStreamProcUnit_t* pProcUnit, bool block) {
|
|
XCAM_FAIL_RETURN(ERROR, pProcUnit, XCAM_RETURN_ERROR_PARAM, "pPdafStreamProc is NULL!");
|
|
|
|
if (block) aiqMutex_lock(&pProcUnit->mStreamMutex);
|
|
if (pProcUnit->_pdafStream && !pProcUnit->mStartStreamFlag) {
|
|
pProcUnit->_pdafStream->start(pProcUnit->_pdafStream);
|
|
pProcUnit->mStartStreamFlag = true;
|
|
LOGD_AF("start pdaf stream device");
|
|
}
|
|
if (block) aiqMutex_unlock(&pProcUnit->mStreamMutex);
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
static XCamReturn _stop_stream(AiqPdafStreamProcUnit_t* pProcUnit, bool block) {
|
|
XCAM_FAIL_RETURN(ERROR, pProcUnit, XCAM_RETURN_ERROR_PARAM, "pPdafStreamProc is NULL!");
|
|
if (block) aiqMutex_lock(&pProcUnit->mStreamMutex);
|
|
if (pProcUnit->_pdafStream && pProcUnit->mStartStreamFlag) {
|
|
pProcUnit->_pdafStream->stop(pProcUnit->_pdafStream);
|
|
pProcUnit->mStartStreamFlag = false;
|
|
LOGD_AF("stop pdaf stream device");
|
|
}
|
|
if (block) aiqMutex_unlock(&pProcUnit->mStreamMutex);
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
static XCamReturn AiqPdafStreamProcUnit_poll_buffer_ready(void* ctx, AiqHwEvt_t* evt,
|
|
int dev_index) {
|
|
XCAM_FAIL_RETURN(ERROR, ctx, XCAM_RETURN_ERROR_PARAM, "pPdafStreamProc is NULL!");
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
AiqPdafStreamProcUnit_t* pProcUnit = (AiqPdafStreamProcUnit_t*)ctx;
|
|
if (pProcUnit->_camHw && pProcUnit->_camHw->_hwResListener.hwResCb) {
|
|
AiqHwPdafEvt_t *pdaf_evt = (AiqHwPdafEvt_t *)evt;
|
|
|
|
pdaf_evt->pdaf_meas = pProcUnit->mPdafMeas;
|
|
//LOGD_AF("%s: PDAF_STATS seq: %d, driver_time : %lld, aiq_time: %lld", __func__,
|
|
// evt->frame_id, evt->mTimestamp, get_systime_us());
|
|
// vicap/pdaf driver set timestamp using fs, 3a stats use fe on old platform and fs on new platform(3576/1126b).
|
|
return pProcUnit->_camHw->_hwResListener.hwResCb(pProcUnit->_camHw->_hwResListener._pCtx,
|
|
evt);
|
|
} else {
|
|
LOGD_AF("%s: poll buffer failed!", __func__);
|
|
return XCAM_RETURN_ERROR_PARAM;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static bool _PdafStreamHelperThd_push_attr(PdafStreamHelperThd_t* pHelpThd,
|
|
AiqPdafStreamParam* params) {
|
|
if (!pHelpThd->_base->_started) return false;
|
|
|
|
int ret = aiqList_push(pHelpThd->mMsgsQueue, params);
|
|
if (ret) {
|
|
LOGE_AF("push focus params failed", __func__);
|
|
return false;
|
|
}
|
|
|
|
aiqCond_broadcast(&pHelpThd->_cond);
|
|
|
|
return true;
|
|
}
|
|
|
|
static bool PdafStreamHelperThd_loop(void* user_data) {
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
ENTER_ANALYZER_FUNCTION();
|
|
|
|
PdafStreamHelperThd_t* pHdlTh = (PdafStreamHelperThd_t*)user_data;
|
|
|
|
aiqMutex_lock(&pHdlTh->_mutex);
|
|
while (!pHdlTh->bQuit && aiqList_size(pHdlTh->mMsgsQueue) <= 0) {
|
|
aiqCond_wait(&pHdlTh->_cond, &pHdlTh->_mutex);
|
|
}
|
|
if (pHdlTh->bQuit) {
|
|
aiqMutex_unlock(&pHdlTh->_mutex);
|
|
LOGE_AF("quit PdafStreamHelperThd!");
|
|
return false;
|
|
}
|
|
aiqMutex_unlock(&pHdlTh->_mutex);
|
|
|
|
AiqListItem_t* pItem = aiqList_get_item(pHdlTh->mMsgsQueue, NULL);
|
|
if (!pItem) {
|
|
// ignore error
|
|
return true;
|
|
}
|
|
AiqPdafStreamParam* attrib = (AiqPdafStreamParam*)pItem->_pData;
|
|
|
|
if (attrib->valid) {
|
|
if (attrib->stream_flag) {
|
|
ret = _start_stream(pHdlTh->mPdafStreamProc, true);
|
|
} else {
|
|
ret = _stop_stream(pHdlTh->mPdafStreamProc, true);
|
|
}
|
|
}
|
|
|
|
aiqList_erase_item(pHdlTh->mMsgsQueue, pItem);
|
|
|
|
if (ret == XCAM_RETURN_NO_ERROR) return true;
|
|
|
|
LOGE_AF("PdafStreamHelperThd failed to run command!");
|
|
|
|
EXIT_ANALYZER_FUNCTION();
|
|
|
|
return false;
|
|
}
|
|
|
|
XCamReturn PdafStreamHelperThd_init(PdafStreamHelperThd_t* pHelpThd,
|
|
AiqPdafStreamProcUnit_t* pProcUnit) {
|
|
pHelpThd->mPdafStreamProc = pProcUnit;
|
|
|
|
aiqMutex_init(&pHelpThd->_mutex);
|
|
aiqCond_init(&pHelpThd->_cond);
|
|
|
|
AiqListConfig_t msgqCfg;
|
|
msgqCfg._name = "PdafHMsgQ";
|
|
msgqCfg._item_nums = PDAF_HELP_THREAD_MSG_MAX;
|
|
msgqCfg._item_size = sizeof(AiqPdafStreamParam);
|
|
pHelpThd->mMsgsQueue = aiqList_init(&msgqCfg);
|
|
if (!pHelpThd->mMsgsQueue) {
|
|
LOGE_AF("init %s error", msgqCfg._name);
|
|
goto err_list;
|
|
}
|
|
|
|
pHelpThd->_base = aiqThread_init("AfHelpTh", PdafStreamHelperThd_loop, pHelpThd);
|
|
if (!pHelpThd->_base) goto err_thread;
|
|
|
|
return XCAM_RETURN_NO_ERROR;
|
|
err_thread:
|
|
if (pHelpThd->mMsgsQueue) aiqList_deinit(pHelpThd->mMsgsQueue);
|
|
err_list:
|
|
aiqMutex_deInit(&pHelpThd->_mutex);
|
|
aiqCond_deInit(&pHelpThd->_cond);
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
|
|
void PdafStreamHelperThd_deinit(PdafStreamHelperThd_t* pHelpThd) {
|
|
ENTER_ANALYZER_FUNCTION();
|
|
if (pHelpThd->mMsgsQueue) aiqList_deinit(pHelpThd->mMsgsQueue);
|
|
if (pHelpThd->_base) aiqThread_deinit(pHelpThd->_base);
|
|
|
|
aiqMutex_deInit(&pHelpThd->_mutex);
|
|
aiqCond_deInit(&pHelpThd->_cond);
|
|
EXIT_ANALYZER_FUNCTION();
|
|
}
|
|
|
|
XCamReturn PdafStreamHelperThd_start(PdafStreamHelperThd_t* pHelpThd) {
|
|
ENTER_ANALYZER_FUNCTION();
|
|
if (!aiqThread_start(pHelpThd->_base)) {
|
|
LOGE_AF("%s failed", __func__);
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
pHelpThd->bQuit = false;
|
|
EXIT_ANALYZER_FUNCTION();
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
XCamReturn PdafStreamHelperThd_stop(PdafStreamHelperThd_t* pHelpThd) {
|
|
ENTER_ANALYZER_FUNCTION();
|
|
aiqMutex_lock(&pHelpThd->_mutex);
|
|
pHelpThd->bQuit = true;
|
|
aiqMutex_unlock(&pHelpThd->_mutex);
|
|
aiqCond_broadcast(&pHelpThd->_cond);
|
|
aiqThread_stop(pHelpThd->_base);
|
|
AiqListItem_t* pItem = NULL;
|
|
bool rm = false;
|
|
AIQ_LIST_FOREACH(pHelpThd->mMsgsQueue, pItem, rm) {
|
|
rm = true;
|
|
pItem = aiqList_erase_item_locked(pHelpThd->mMsgsQueue, pItem);
|
|
}
|
|
EXIT_ANALYZER_FUNCTION();
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
XCamReturn AiqPdafStreamProcUnit_init(AiqPdafStreamProcUnit_t* pProcUnit, int type) {
|
|
XCAM_FAIL_RETURN(ERROR, pProcUnit, XCAM_RETURN_ERROR_PARAM, "pPdafStreamProc is NULL!");
|
|
|
|
pProcUnit->_camHw = NULL;
|
|
pProcUnit->mPdafDev = NULL;
|
|
pProcUnit->_pcb = NULL;
|
|
pProcUnit->mStartFlag = false;
|
|
pProcUnit->mStartStreamFlag = false;
|
|
pProcUnit->mBufType = type;
|
|
|
|
aiqMutex_init(&pProcUnit->mStreamMutex);
|
|
PdafStreamHelperThd_init(&pProcUnit->mHelperThd, pProcUnit);
|
|
PdafStreamHelperThd_start(&pProcUnit->mHelperThd);
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
XCamReturn AiqPdafStreamProcUnit_deinit(AiqPdafStreamProcUnit_t* pProcUnit) {
|
|
if (!pProcUnit) return XCAM_RETURN_ERROR_PARAM;
|
|
|
|
PdafStreamHelperThd_stop(&pProcUnit->mHelperThd);
|
|
PdafStreamHelperThd_deinit(&pProcUnit->mHelperThd);
|
|
|
|
if (pProcUnit->_pcb) {
|
|
aiq_free(pProcUnit->_pcb);
|
|
pProcUnit->_pcb = NULL;
|
|
}
|
|
if (pProcUnit->mPdafDev) {
|
|
pProcUnit->mPdafDev->close(pProcUnit->mPdafDev);
|
|
aiq_free(pProcUnit->mPdafDev);
|
|
pProcUnit->mPdafDev = NULL;
|
|
if (pProcUnit->_pdafStream) {
|
|
aiq_free(pProcUnit->_pdafStream);
|
|
pProcUnit->_pdafStream = NULL;
|
|
}
|
|
}
|
|
|
|
aiqMutex_deInit(&pProcUnit->mStreamMutex);
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
void AiqPdafStreamProcUnit_set_devices(AiqPdafStreamProcUnit_t* pProcUnit, AiqCamHwBase_t* camHw) {
|
|
if (!pProcUnit) return;
|
|
|
|
pProcUnit->_camHw = camHw;
|
|
}
|
|
|
|
XCamReturn AiqPdafStreamProcUnit_preapre(AiqPdafStreamProcUnit_t* pProcUnit,
|
|
rk_sensor_pdaf_info_t* pdaf_inf) {
|
|
XCAM_FAIL_RETURN(ERROR, pProcUnit, XCAM_RETURN_ERROR_PARAM, "pPdafStreamProc is NULL!");
|
|
XCAM_FAIL_RETURN(ERROR, pdaf_inf, XCAM_RETURN_ERROR_PARAM, " pdaf_inf is NULL!");
|
|
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
|
|
AiqPdafStreamProcUnit_stop(pProcUnit);
|
|
pProcUnit->mPdafInf = *pdaf_inf;
|
|
|
|
if (pProcUnit->mPdafDev) {
|
|
pProcUnit->mPdafDev->close(pProcUnit->mPdafDev);
|
|
aiq_free(pProcUnit->mPdafDev);
|
|
pProcUnit->mPdafDev = NULL;
|
|
if (pProcUnit->_pdafStream) {
|
|
aiq_free(pProcUnit->_pdafStream);
|
|
pProcUnit->_pdafStream = NULL;
|
|
}
|
|
}
|
|
|
|
pProcUnit->mPdafDev = (AiqV4l2Device_t*)aiq_mallocz(sizeof(AiqV4l2Device_t));
|
|
if (!pProcUnit->mPdafDev) {
|
|
LOGE_CAMHW_SUBM(ISP20HW_SUBM, "%d: alloc fail !", __LINE__);
|
|
goto fail;
|
|
}
|
|
AiqV4l2Device_init(pProcUnit->mPdafDev, pProcUnit->mPdafInf.pdaf_vdev);
|
|
pProcUnit->mPdafDev->open(pProcUnit->mPdafDev, false);
|
|
pProcUnit->_pdafStream = (AiqStream_t*)aiq_mallocz(sizeof(AiqStream_t));
|
|
AiqPdafStream_init(pProcUnit->_pdafStream, pProcUnit->mPdafDev, ISP_POLL_PDAF_STATS);
|
|
if (!pProcUnit->_pcb) {
|
|
AiqPollCallback_t* pcb = (AiqPollCallback_t*)aiq_mallocz(sizeof(AiqPollCallback_t));
|
|
pcb->_pCtx = pProcUnit;
|
|
pcb->poll_buffer_ready = AiqPdafStreamProcUnit_poll_buffer_ready;
|
|
pcb->poll_event_ready = NULL;
|
|
pProcUnit->_pcb = pcb;
|
|
AiqPollThread_setPollCallback(pProcUnit->_pdafStream->_poll_thread, pcb);
|
|
}
|
|
|
|
strcpy(pProcUnit->mPdafMeas.snsName, pProcUnit->mPdafInf.sns_name);
|
|
pProcUnit->mPdafMeas.pdafSensorType = pProcUnit->mPdafInf.pdaf_type;
|
|
pProcUnit->mPdafMeas.pdLRInDiffLine = pProcUnit->mPdafInf.pdaf_lrdiffline;
|
|
pProcUnit->mPdafMeas.pdWidth = pProcUnit->mPdafInf.pdaf_width;
|
|
pProcUnit->mPdafMeas.pdHeight = pProcUnit->mPdafInf.pdaf_height;
|
|
LOGD_AF("pd inf: sns_name %s, pdaf_vdev %s, pdafSensorType %d, pdLRInDiffLine %d, pdWidth %d, pdHeight %d",
|
|
pProcUnit->mPdafInf.sns_name, pProcUnit->mPdafInf.pdaf_vdev, pProcUnit->mPdafMeas.pdafSensorType, pProcUnit->mPdafMeas.pdLRInDiffLine,
|
|
pProcUnit->mPdafMeas.pdWidth, pProcUnit->mPdafMeas.pdHeight);
|
|
|
|
ret = AiqV4l2Device_setFmt(pProcUnit->mPdafDev, pProcUnit->mPdafInf.pdaf_width, pProcUnit->mPdafInf.pdaf_height,
|
|
pProcUnit->mPdafInf.pdaf_pixelformat, V4L2_FIELD_NONE, 0);
|
|
|
|
struct v4l2_format fmt;
|
|
ret |= AiqV4l2Device_getV4lFmt(pProcUnit->mPdafDev, &fmt);
|
|
pProcUnit->mPdafMeas.bytesperline = fmt.fmt.pix_mp.plane_fmt[0].bytesperline;
|
|
return ret;
|
|
fail:
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
|
|
void AiqPdafStreamProcUnit_start(AiqPdafStreamProcUnit_t* pProcUnit) {
|
|
if (!pProcUnit) return;
|
|
|
|
int32_t mem_mode = 0;
|
|
|
|
aiqMutex_lock(&pProcUnit->mStreamMutex);
|
|
if (pProcUnit->_pdafStream && !pProcUnit->mStartFlag) {
|
|
if (pProcUnit->mPdafInf.pdaf_type != PDAF_SENSOR_TYPE3) {
|
|
pProcUnit->mPdafDev->io_control(pProcUnit->mPdafDev, RKCIF_CMD_GET_CSI_MEMORY_MODE,
|
|
&mem_mode);
|
|
if (mem_mode != CSI_LVDS_MEM_WORD_LOW_ALIGN) {
|
|
mem_mode = CSI_LVDS_MEM_WORD_LOW_ALIGN;
|
|
pProcUnit->mPdafDev->io_control(pProcUnit->mPdafDev, RKCIF_CMD_SET_CSI_MEMORY_MODE,
|
|
&mem_mode);
|
|
LOGI_AF("memory mode of pdaf video need low align, mem_mode %d", mem_mode);
|
|
}
|
|
|
|
AiqPdafStreamParam attr;
|
|
|
|
memset(&attr, 0, sizeof(attr));
|
|
AiqPdafStreamParam* attrPtr = &attr;
|
|
attrPtr->valid = true;
|
|
attrPtr->stream_flag = true;
|
|
aiqList_reset(pProcUnit->mHelperThd.mMsgsQueue);
|
|
_PdafStreamHelperThd_push_attr(&pProcUnit->mHelperThd, attrPtr);
|
|
} else {
|
|
_start_stream(pProcUnit, false);
|
|
}
|
|
|
|
pProcUnit->mStartFlag = true;
|
|
}
|
|
aiqMutex_unlock(&pProcUnit->mStreamMutex);
|
|
}
|
|
|
|
void AiqPdafStreamProcUnit_stop(AiqPdafStreamProcUnit_t* pProcUnit) {
|
|
if (!pProcUnit) return;
|
|
|
|
aiqMutex_lock(&pProcUnit->mStreamMutex);
|
|
if (pProcUnit->_pdafStream && pProcUnit->mStartFlag) {
|
|
if (pProcUnit->mPdafInf.pdaf_type != PDAF_SENSOR_TYPE3) {
|
|
AiqPdafStreamParam attr;
|
|
|
|
memset(&attr, 0, sizeof(attr));
|
|
AiqPdafStreamParam* attrPtr = &attr;
|
|
attrPtr->valid = true;
|
|
attrPtr->stream_flag = false;
|
|
aiqList_reset(pProcUnit->mHelperThd.mMsgsQueue);
|
|
_PdafStreamHelperThd_push_attr(&pProcUnit->mHelperThd, attrPtr);
|
|
} else {
|
|
_stop_stream(pProcUnit, false);
|
|
}
|
|
|
|
pProcUnit->mStartFlag = false;
|
|
}
|
|
aiqMutex_unlock(&pProcUnit->mStreamMutex);
|
|
}
|