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.
330 lines
11 KiB
330 lines
11 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 <stdint.h>
|
|
|
|
#include "hwi_c/aiq_camHw.h"
|
|
#include "hwi_c/aiq_cifSclStream.h"
|
|
#include "hwi_c/aiq_stream.h"
|
|
#include "xcam_log.h"
|
|
#include "xcore_c/aiq_v4l2_device.h"
|
|
|
|
static XCamReturn set_ratio_fmt(AiqCifSclStream_t* pCifSclStrm, int32_t ratio) {
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
|
|
if (ratio > 0 && ratio <= 8) {
|
|
pCifSclStrm->_ratio = 8;
|
|
} else if (ratio > 8 && ratio <= 16) {
|
|
pCifSclStrm->_ratio = 16;
|
|
} else {
|
|
pCifSclStrm->_ratio = 32;
|
|
}
|
|
|
|
uint32_t dst_width = pCifSclStrm->_width / pCifSclStrm->_ratio;
|
|
if ((dst_width % 2) != 0) dst_width -= 1;
|
|
|
|
uint32_t dst_height = pCifSclStrm->_height / pCifSclStrm->_ratio;
|
|
if ((dst_height % 2) != 0) dst_height -= 1;
|
|
|
|
for (int i = 0; i < pCifSclStrm->_index; i++) {
|
|
ret = AiqV4l2Device_setFmt(pCifSclStrm->_dev[i], dst_width, dst_height,
|
|
pCifSclStrm->_sns_v4l_pix_fmt, V4L2_FIELD_NONE, 0);
|
|
if (ret < 0) {
|
|
LOGE_CAMHW_SUBM(ISP20HW_SUBM, "device(%s) set format failed",
|
|
AiqV4l2Device_getDevName(pCifSclStrm->_dev[i]));
|
|
} else {
|
|
LOGD_CAMHW_SUBM(ISP20HW_SUBM, "device(%s) set fmt info: fmt 0x%x, %dx%d !",
|
|
AiqV4l2Device_getDevName(pCifSclStrm->_dev[i]),
|
|
pCifSclStrm->_sns_v4l_pix_fmt, dst_width, dst_height);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
XCamReturn AiqCifSclStream_init(AiqCifSclStream_t* pCifSclStrm, const rk_sensor_full_info_t* s_info,
|
|
AiqPollCallback_t* cb) {
|
|
if (!pCifSclStrm || !s_info) return XCAM_RETURN_ERROR_PARAM;
|
|
|
|
pCifSclStrm->_first_start = true;
|
|
|
|
if (!s_info->cif_info) {
|
|
LOGD_CAMHW("no link to vicap\n");
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
switch (pCifSclStrm->_working_mode) {
|
|
case 0x0:
|
|
pCifSclStrm->_index = 1;
|
|
break;
|
|
case 0x11:
|
|
case 0x12:
|
|
pCifSclStrm->_index = 2;
|
|
break;
|
|
case 0x21:
|
|
case 0x22:
|
|
pCifSclStrm->_index = 3;
|
|
break;
|
|
default:
|
|
pCifSclStrm->_index = 0;
|
|
break;
|
|
}
|
|
|
|
if (pCifSclStrm->_index >= 1) {
|
|
if (strlen(s_info->cif_info->mipi_scl0)) {
|
|
pCifSclStrm->_dev[0] = (AiqV4l2Device_t*)aiq_mallocz(sizeof(AiqV4l2Device_t));
|
|
if (!pCifSclStrm->_dev[0]) {
|
|
LOGE_CAMHW_SUBM(ISP20HW_SUBM, "%d: alloc fail !", __LINE__);
|
|
goto fail;
|
|
}
|
|
AiqV4l2Device_init(pCifSclStrm->_dev[0], s_info->cif_info->mipi_scl0);
|
|
pCifSclStrm->_dev[0]->open(pCifSclStrm->_dev[0], false);
|
|
}
|
|
}
|
|
if (pCifSclStrm->_index >= 2) {
|
|
if (strlen(s_info->cif_info->mipi_scl1)) {
|
|
pCifSclStrm->_dev[1] = (AiqV4l2Device_t*)aiq_mallocz(sizeof(AiqV4l2Device_t));
|
|
if (!pCifSclStrm->_dev[1]) {
|
|
LOGE_CAMHW_SUBM(ISP20HW_SUBM, "%d: alloc fail !", __LINE__);
|
|
goto fail;
|
|
}
|
|
AiqV4l2Device_init(pCifSclStrm->_dev[1], s_info->cif_info->mipi_scl0);
|
|
pCifSclStrm->_dev[1]->open(pCifSclStrm->_dev[1], false);
|
|
}
|
|
}
|
|
|
|
if (pCifSclStrm->_index == 3) {
|
|
if (strlen(s_info->cif_info->mipi_scl2)) {
|
|
pCifSclStrm->_dev[2] = (AiqV4l2Device_t*)aiq_mallocz(sizeof(AiqV4l2Device_t));
|
|
if (!pCifSclStrm->_dev[2]) {
|
|
LOGE_CAMHW_SUBM(ISP20HW_SUBM, "%d: alloc fail !", __LINE__);
|
|
goto fail;
|
|
}
|
|
AiqV4l2Device_init(pCifSclStrm->_dev[2], s_info->cif_info->mipi_scl0);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < pCifSclStrm->_index; i++) {
|
|
if (pCifSclStrm->_dev[i]) {
|
|
pCifSclStrm->_stream[i] = (AiqRawStream_t*)aiq_mallocz(sizeof(AiqRawStream_t));
|
|
AiqRawStream_init(pCifSclStrm->_stream[i], pCifSclStrm->_dev[i], VICAP_POLL_SCL, i);
|
|
if (cb) AiqPollThread_setPollCallback(pCifSclStrm->_stream[i]->_base._poll_thread, cb);
|
|
}
|
|
}
|
|
|
|
pCifSclStrm->_init = true;
|
|
return XCAM_RETURN_NO_ERROR;
|
|
fail:
|
|
AiqCifSclStream_deinit(pCifSclStrm);
|
|
return XCAM_RETURN_ERROR_FAILED;
|
|
}
|
|
|
|
void AiqCifSclStream_deinit(AiqCifSclStream_t* pCifSclStrm) {
|
|
if (!pCifSclStrm) return;
|
|
|
|
for (int32_t i = 0; i < 3; i++) {
|
|
if (pCifSclStrm->_dev[i]) {
|
|
pCifSclStrm->_dev[i]->close(pCifSclStrm->_dev[i]);
|
|
if (pCifSclStrm->_stream[i]) {
|
|
AiqRawStream_deinit(pCifSclStrm->_stream[i]);
|
|
aiq_free(pCifSclStrm->_stream[i]);
|
|
pCifSclStrm->_stream[i] = NULL;
|
|
}
|
|
aiq_free(pCifSclStrm->_dev[i]);
|
|
pCifSclStrm->_dev[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
XCamReturn AiqCifSclStream_start(AiqCifSclStream_t* pCifSclStrm) {
|
|
if (!pCifSclStrm) return XCAM_RETURN_ERROR_PARAM;
|
|
|
|
if (pCifSclStrm->_init && !pCifSclStrm->_active) {
|
|
for (int i = 0; i < pCifSclStrm->_index; i++) {
|
|
if (pCifSclStrm->_stream[i])
|
|
pCifSclStrm->_stream[i]->_base.start(&pCifSclStrm->_stream[i]->_base);
|
|
}
|
|
pCifSclStrm->_active = true;
|
|
}
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
XCamReturn AiqCifSclStream_stop(AiqCifSclStream_t* pCifSclStrm) {
|
|
if (!pCifSclStrm) return XCAM_RETURN_ERROR_PARAM;
|
|
|
|
for (int32_t i = 0; i < pCifSclStrm->_index; i++) {
|
|
if (pCifSclStrm->_stream[i])
|
|
pCifSclStrm->_stream[i]->_base.stop(&pCifSclStrm->_stream[i]->_base);
|
|
}
|
|
pCifSclStrm->_active = false;
|
|
return XCAM_RETURN_NO_ERROR;
|
|
}
|
|
|
|
void AiqCifSclStream_set_working_mode(AiqCifSclStream_t* pCifSclStrm, int mode) {
|
|
if (!pCifSclStrm) return;
|
|
|
|
pCifSclStrm->_working_mode = mode;
|
|
}
|
|
|
|
XCamReturn AiqCifSclStream_set_format(AiqCifSclStream_t* pCifSclStrm,
|
|
const struct v4l2_subdev_format* sns_sd_fmt,
|
|
uint32_t sns_v4l_pix_fmt, int bpp) {
|
|
if (!pCifSclStrm || !sns_sd_fmt) return XCAM_RETURN_ERROR_PARAM;
|
|
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
|
|
pCifSclStrm->_width = sns_sd_fmt->format.width;
|
|
pCifSclStrm->_height = sns_sd_fmt->format.height;
|
|
pCifSclStrm->_bpp = bpp;
|
|
|
|
switch (sns_v4l_pix_fmt) {
|
|
case V4L2_PIX_FMT_SBGGR8:
|
|
case V4L2_PIX_FMT_SBGGR10:
|
|
case V4L2_PIX_FMT_SBGGR12:
|
|
case V4L2_PIX_FMT_SBGGR14:
|
|
case V4L2_PIX_FMT_SBGGR16:
|
|
pCifSclStrm->_sns_v4l_pix_fmt = V4L2_PIX_FMT_SBGGR16;
|
|
break;
|
|
case V4L2_PIX_FMT_SGBRG8:
|
|
case V4L2_PIX_FMT_SGBRG10:
|
|
case V4L2_PIX_FMT_SGBRG12:
|
|
case V4L2_PIX_FMT_SGBRG14:
|
|
case V4L2_PIX_FMT_SGBRG16:
|
|
pCifSclStrm->_sns_v4l_pix_fmt = V4L2_PIX_FMT_SGBRG16;
|
|
break;
|
|
case V4L2_PIX_FMT_SGRBG8:
|
|
case V4L2_PIX_FMT_SGRBG10:
|
|
case V4L2_PIX_FMT_SGRBG12:
|
|
case V4L2_PIX_FMT_SGRBG14:
|
|
case V4L2_PIX_FMT_SGRBG16:
|
|
pCifSclStrm->_sns_v4l_pix_fmt = V4L2_PIX_FMT_SGRBG16;
|
|
break;
|
|
case V4L2_PIX_FMT_SRGGB8:
|
|
case V4L2_PIX_FMT_SRGGB10:
|
|
case V4L2_PIX_FMT_SRGGB12:
|
|
case V4L2_PIX_FMT_SRGGB14:
|
|
case V4L2_PIX_FMT_SRGGB16:
|
|
pCifSclStrm->_sns_v4l_pix_fmt = V4L2_PIX_FMT_SRGGB16;
|
|
break;
|
|
default:
|
|
LOGE_CAMHW_SUBM(ISP20HW_SUBM, "unknown format");
|
|
return XCAM_RETURN_ERROR_PARAM;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
XCamReturn AiqCifSclStream_set_format2(AiqCifSclStream_t* pCifSclStrm,
|
|
const struct v4l2_subdev_selection* sns_sd_sel,
|
|
uint32_t sns_v4l_pix_fmt, int bpp) {
|
|
if (!pCifSclStrm || !sns_sd_sel) return XCAM_RETURN_ERROR_PARAM;
|
|
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
pCifSclStrm->_width = sns_sd_sel->r.width;
|
|
pCifSclStrm->_height = sns_sd_sel->r.height;
|
|
pCifSclStrm->_bpp = bpp;
|
|
|
|
switch (sns_v4l_pix_fmt) {
|
|
case V4L2_PIX_FMT_SBGGR8:
|
|
case V4L2_PIX_FMT_SBGGR10:
|
|
case V4L2_PIX_FMT_SBGGR12:
|
|
case V4L2_PIX_FMT_SBGGR14:
|
|
case V4L2_PIX_FMT_SBGGR16:
|
|
pCifSclStrm->_sns_v4l_pix_fmt = V4L2_PIX_FMT_SBGGR16;
|
|
break;
|
|
case V4L2_PIX_FMT_SGBRG8:
|
|
case V4L2_PIX_FMT_SGBRG10:
|
|
case V4L2_PIX_FMT_SGBRG12:
|
|
case V4L2_PIX_FMT_SGBRG14:
|
|
case V4L2_PIX_FMT_SGBRG16:
|
|
pCifSclStrm->_sns_v4l_pix_fmt = V4L2_PIX_FMT_SGBRG16;
|
|
break;
|
|
case V4L2_PIX_FMT_SGRBG8:
|
|
case V4L2_PIX_FMT_SGRBG10:
|
|
case V4L2_PIX_FMT_SGRBG12:
|
|
case V4L2_PIX_FMT_SGRBG14:
|
|
case V4L2_PIX_FMT_SGRBG16:
|
|
pCifSclStrm->_sns_v4l_pix_fmt = V4L2_PIX_FMT_SGRBG16;
|
|
break;
|
|
case V4L2_PIX_FMT_SRGGB8:
|
|
case V4L2_PIX_FMT_SRGGB10:
|
|
case V4L2_PIX_FMT_SRGGB12:
|
|
case V4L2_PIX_FMT_SRGGB14:
|
|
case V4L2_PIX_FMT_SRGGB16:
|
|
pCifSclStrm->_sns_v4l_pix_fmt = V4L2_PIX_FMT_SRGGB16;
|
|
break;
|
|
default:
|
|
LOGE_CAMHW_SUBM(ISP20HW_SUBM, "unknown format");
|
|
return XCAM_RETURN_ERROR_PARAM;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
XCamReturn AiqCifSclStream_prepare(AiqCifSclStream_t* pCifSclStrm) {
|
|
if (!pCifSclStrm) return XCAM_RETURN_ERROR_PARAM;
|
|
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
if (!pCifSclStrm->_init || pCifSclStrm->_active) return XCAM_RETURN_NO_ERROR;
|
|
|
|
for (int i = 0; i < pCifSclStrm->_index; i++) {
|
|
ret = pCifSclStrm->_dev[i]->prepare(pCifSclStrm->_dev[i]);
|
|
if (ret < 0) LOGE_CAMHW_SUBM(ISP20HW_SUBM, "mipi tx:%d prepare err: %d\n", i, ret);
|
|
|
|
pCifSclStrm->_stream[i]->_base.set_device_prepared(&pCifSclStrm->_stream[i]->_base, true);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
XCamReturn AiqCifSclStream_restart(AiqCifSclStream_t* pCifSclStrm,
|
|
const rk_sensor_full_info_t* s_info, int ratio,
|
|
AiqPollCallback_t* callback, int mode) {
|
|
if (!pCifSclStrm) return XCAM_RETURN_ERROR_PARAM;
|
|
|
|
XCamReturn ret = XCAM_RETURN_NO_ERROR;
|
|
if (mode) {
|
|
if (!pCifSclStrm->_init) ret = AiqCifSclStream_init(pCifSclStrm, s_info, callback);
|
|
|
|
if (ratio != pCifSclStrm->_ratio) {
|
|
if (pCifSclStrm->_active) {
|
|
AiqCifSclStream_stop(pCifSclStrm);
|
|
}
|
|
ret = set_ratio_fmt(pCifSclStrm, ratio);
|
|
}
|
|
|
|
if (!pCifSclStrm->_active && pCifSclStrm->_init) {
|
|
ret = AiqCifSclStream_prepare(pCifSclStrm);
|
|
ret = AiqCifSclStream_start(pCifSclStrm);
|
|
}
|
|
} else {
|
|
if (pCifSclStrm->_active) ret = AiqCifSclStream_stop(pCifSclStrm);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
bool AiqCifSclStream_setPollCallback(AiqCifSclStream_t* pCifSclStrm, AiqPollCallback_t* cb) {
|
|
if (!pCifSclStrm || !cb) return false;
|
|
|
|
for (int i = 0; i < pCifSclStrm->_index; i++) {
|
|
AiqPollThread_setPollCallback(pCifSclStrm->_stream[i]->_base._poll_thread, cb);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool AiqCifSclStream_getIsActive(AiqCifSclStream_t* pCifSclStrm) { return pCifSclStrm->_active; }
|