Files
Android11/external/rkaiq_tool_server/camera/camera_infohw.cpp
2023-10-13 14:01:41 +00:00

421 lines
14 KiB
C++

#include "camera_infohw.h"
#ifdef LOG_TAG
#undef LOG_TAG
#endif
#define LOG_TAG "aiqtool"
__u32 convert_to_v4l2fmt(struct capture_info* media_info, int code)
{
__u32 v4l2_fmt = 0;
__u32 bits = 0;
switch (code) {
/* 8bit raw bayer */
case MEDIA_BUS_FMT_SBGGR8_1X8:
v4l2_fmt = V4L2_PIX_FMT_SRGGB8;
media_info->sd_path.bits = 8;
break;
case MEDIA_BUS_FMT_SGBRG8_1X8:
v4l2_fmt = V4L2_PIX_FMT_SGBRG8;
media_info->sd_path.bits = 8;
break;
case MEDIA_BUS_FMT_SGRBG8_1X8:
v4l2_fmt = V4L2_PIX_FMT_SGRBG8;
media_info->sd_path.bits = 8;
break;
case MEDIA_BUS_FMT_SRGGB8_1X8:
v4l2_fmt = V4L2_PIX_FMT_SRGGB8;
media_info->sd_path.bits = 8;
break;
case MEDIA_BUS_FMT_Y8_1X8:
v4l2_fmt = V4L2_PIX_FMT_GREY;
media_info->sd_path.bits = 8;
break;
/* 10bit raw bayer */
case MEDIA_BUS_FMT_SBGGR10_1X10:
v4l2_fmt = V4L2_PIX_FMT_SRGGB10;
media_info->sd_path.bits = 10;
break;
case MEDIA_BUS_FMT_SGBRG10_1X10:
v4l2_fmt = V4L2_PIX_FMT_SGBRG10;
media_info->sd_path.bits = 10;
break;
case MEDIA_BUS_FMT_SGRBG10_1X10:
v4l2_fmt = V4L2_PIX_FMT_SGRBG10;
media_info->sd_path.bits = 10;
break;
case MEDIA_BUS_FMT_SRGGB10_1X10:
v4l2_fmt = V4L2_PIX_FMT_SRGGB10;
media_info->sd_path.bits = 10;
break;
case MEDIA_BUS_FMT_Y10_1X10:
v4l2_fmt = V4L2_PIX_FMT_Y10;
media_info->sd_path.bits = 10;
break;
/* 12bit raw bayer */
case MEDIA_BUS_FMT_SBGGR12_1X12:
v4l2_fmt = V4L2_PIX_FMT_SRGGB12;
media_info->sd_path.bits = 12;
break;
case MEDIA_BUS_FMT_SGBRG12_1X12:
v4l2_fmt = V4L2_PIX_FMT_SGBRG12;
media_info->sd_path.bits = 12;
break;
case MEDIA_BUS_FMT_SGRBG12_1X12:
v4l2_fmt = V4L2_PIX_FMT_SGRBG12;
media_info->sd_path.bits = 12;
break;
case MEDIA_BUS_FMT_SRGGB12_1X12:
v4l2_fmt = V4L2_PIX_FMT_SRGGB12;
media_info->sd_path.bits = 12;
break;
case MEDIA_BUS_FMT_Y12_1X12:
v4l2_fmt = V4L2_PIX_FMT_Y12;
media_info->sd_path.bits = 12;
break;
default:
LOG_ERROR("nonsupport raw bayer formats, please check sensor output fmt\n");
break;
}
return v4l2_fmt;
}
int get_isp_subdevs(struct media_device* device, const char* devpath, struct capture_info* media_info)
{
media_entity* entity = NULL;
const char* entity_name = NULL;
uint32_t nents, j = 0;
const struct media_entity_desc* entity_info = NULL;
if (!device || !media_info || !devpath) {
return -1;
}
strncpy(media_info->vd_path.media_dev_path, (char*)devpath, sizeof(media_info->vd_path.media_dev_path));
LOG_DEBUG("get isp subdev: %s \n", media_info->vd_path.media_dev_path);
entity = media_get_entity_by_name(device, "rkisp_mainpath");
if (entity) {
entity_name = media_entity_get_devname(entity);
if (entity_name) {
strncpy(media_info->vd_path.isp_main_path, (char*)entity_name, sizeof(media_info->vd_path.isp_main_path));
}
}
entity = media_get_entity_by_name(device, "rkisp-isp-subdev");
if (entity) {
entity_name = media_entity_get_devname(entity);
if (entity_name) {
strncpy(media_info->vd_path.isp_sd_path, (char*)entity_name, sizeof(media_info->vd_path.isp_sd_path));
LOG_DEBUG("isp subdev path: %s\n", media_info->vd_path.isp_sd_path);
}
}
/* Enumerate entities, pads and links. */
media_device_enumerate(device);
nents = media_get_entities_count(device);
for (j = 0; j < nents; ++j) {
entity = media_get_entity(device, j);
entity_info = media_entity_get_info(entity);
if ((NULL != entity_info) && (entity_info->type == MEDIA_ENT_T_V4L2_SUBDEV_SENSOR)) {
strncpy(media_info->sd_path.device_name, (char*)media_entity_get_devname(entity),
sizeof(media_info->sd_path.device_name));
media_info->link = link_to_isp;
LOG_DEBUG("get isp subdev: sensor link to %d \n", media_info->link);
strncpy(media_info->sd_path.sensor_name, entity_info->name, sizeof(media_info->sd_path.sensor_name));
LOG_DEBUG("sensor subdev path: %s\n", media_info->sd_path.device_name);
}
}
return 0;
}
int get_vicap_subdevs(struct media_device* device, const char* devpath, struct capture_info* media_info)
{
media_entity* entity = NULL;
const char* entity_name = NULL;
uint32_t nents, j = 0;
const struct media_entity_desc* entity_info = NULL;
if (!device || !media_info || !devpath) {
return -1;
}
entity = media_get_entity_by_name(device, "stream_cif_mipi_id0");
if (entity) {
entity_name = media_entity_get_devname(entity);
if (entity_name) {
strncpy(media_info->cif_path.cif_video_path, (char*)entity_name,
sizeof(media_info->cif_path.cif_video_path));
LOG_DEBUG("get vicap subdev: %s \n", media_info->cif_path.cif_video_path);
}
}
entity = media_get_entity_by_name(device, "rkcif_lite_mipi_lvds");
if (entity) {
entity_name = media_entity_get_devname(entity);
if (entity_name) {
strncpy(media_info->cif_path.cif_video_path, (char*)entity_name,
sizeof(media_info->cif_path.cif_video_path));
LOG_DEBUG("get vicap subdev: %s \n", media_info->cif_path.cif_video_path);
}
}
/* Enumerate entities, pads and links. */
media_device_enumerate(device);
nents = media_get_entities_count(device);
for (j = 0; j < nents; ++j) {
entity = media_get_entity(device, j);
entity_info = media_entity_get_info(entity);
if ((NULL != entity_info) && (entity_info->type == MEDIA_ENT_T_V4L2_SUBDEV_SENSOR)) {
strncpy(media_info->sd_path.device_name, (char*)media_entity_get_devname(entity),
sizeof(media_info->sd_path.device_name));
media_info->link = link_to_vicap;
LOG_DEBUG("get vicap subdev: sensor link to %d \n", media_info->link);
strncpy(media_info->sd_path.sensor_name, entity_info->name, sizeof(media_info->sd_path.sensor_name));
LOG_DEBUG("sensor subdev path: %s\n", media_info->sd_path.device_name);
}
}
return 0;
}
static int rkisp_sd_set_crop(const char* ispsd, int fd, int pad, int* w, int* h)
{
struct v4l2_subdev_selection sel;
int ret;
memset(&sel, 0, sizeof(sel));
sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
sel.pad = pad;
sel.r.width = *w;
sel.r.height = *h;
sel.r.left = 0;
sel.r.top = 0;
sel.target = V4L2_SEL_TGT_CROP;
sel.flags = V4L2_SEL_FLAG_LE;
ret = device_setsubdevcrop(fd, &sel);
if (ret) {
LOG_ERROR("subdev %s pad %d crop failed, ret = %d\n", ispsd, sel.pad, ret);
return ret;
}
*w = sel.r.width;
*h = sel.r.height;
return 0;
}
int rkisp_sd_set_fmt(const char* ispsd, int pad, int* w, int* h, int code)
{
struct v4l2_subdev_format fmt;
int ret, fd;
fd = device_open(ispsd);
if (fd < 0) {
LOG_ERROR("Open isp subdev %s failed, %s\n", ispsd, strerror(errno));
return fd;
}
if (pad == 2) { /* Source pad */
ret = rkisp_sd_set_crop(ispsd, fd, pad, w, h);
if (ret) {
goto close;
}
}
/* Get fmt and only update what we want */
memset(&fmt, 0, sizeof(fmt));
fmt.pad = pad;
fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
ret = device_getsubdevformat(fd, &fmt);
if (ret < 0) {
LOG_ERROR("subdev %s get pad: %d fmt failed %s.\n", ispsd, fmt.pad, strerror(errno));
goto close;
}
fmt.format.height = *h;
fmt.format.width = *w;
fmt.format.code = code;
ret = device_setsubdevformat(fd, &fmt);
if (ret < 0) {
LOG_ERROR("subdev %s set pad: %d fmt failed %s.\n", ispsd, fmt.pad, strerror(errno));
goto close;
}
if (fmt.format.width != *w || fmt.format.height != *h || fmt.format.code != code) {
LOG_INFO("subdev %s pad %d choose the best fit fmt: %dx%d, 0x%08x\n", ispsd, pad, fmt.format.width,
fmt.format.height, fmt.format.code);
}
*w = fmt.format.width;
*h = fmt.format.height;
if (pad == 0) {
ret = rkisp_sd_set_crop(ispsd, fd, pad, w, h);
if (ret) {
goto close;
}
}
close:
close(fd);
return ret;
}
int rkisp_set_ispsd_fmt(struct capture_info* media_info, int in_w, int in_h, int in_code, int out_w, int out_h,
int out_code)
{
const char* ispsd;
int ret;
if (media_info->link == link_to_isp) {
ispsd = media_info->vd_path.isp_sd_path;
LOG_INFO("link_to_isp, isp subdev path:%s\n", media_info->vd_path.isp_sd_path);
} else if (media_info->link == link_to_vicap) {
ispsd = media_info->cif_path.cif_video_path;
LOG_INFO("link_to_vicap, isp subdev path:%s\n", media_info->cif_path.cif_video_path);
}
// TODO: check source and sink pad
ret = rkisp_sd_set_fmt(ispsd, 0, &in_w, &in_h, in_code);
ret |= rkisp_sd_set_fmt(ispsd, 2, &out_w, &out_h, out_code);
return ret;
}
int setupLink(struct capture_info* media_info, bool raw_mode)
{
media_device* device = NULL;
media_entity* entity = NULL;
media_pad *src_pad = NULL, *sink_pad_bridge = NULL, *sink_pad_mp = NULL;
media_pad *sink_pad = NULL, *src_raw2_s = NULL;
int ret;
device = media_device_new(media_info->vd_path.media_dev_path);
LOG_INFO("%s: setup link for raw or yuv: %d\n", media_info->vd_path.media_dev_path, raw_mode);
/* Enumerate entities, pads and links. */
media_device_enumerate(device);
entity = media_get_entity_by_name(device, "rkisp-isp-subdev");
if (entity) {
src_pad = (media_pad*)media_entity_get_pad(entity, 2);
if (!src_pad) {
LOG_DEBUG("get rkisp-isp-subdev source pad failed!\n");
goto FAIL;
}
}
entity = media_get_entity_by_name(device, "rkisp-bridge-ispp");
if (entity) {
sink_pad_bridge = (media_pad*)media_entity_get_pad(entity, 0);
if (!sink_pad_bridge) {
LOG_DEBUG("get rkisp-bridge-ispp sink pad failed!\n");
goto FAIL;
}
}
entity = media_get_entity_by_name(device, "rkisp_mainpath");
if (entity) {
sink_pad_mp = (media_pad*)media_entity_get_pad(entity, 0);
if (!sink_pad_mp) {
LOG_DEBUG("get rkisp_mainpath sink pad failed!\n");
goto FAIL;
}
}
entity = media_get_entity_by_name(device, "rkisp-isp-subdev");
if (entity) {
sink_pad = (media_pad*)media_entity_get_pad(entity, 0);
if (!sink_pad) {
LOG_DEBUG("get rkisp-isp-subdev source pad failed!\n");
goto FAIL;
}
}
entity = media_get_entity_by_name(device, "rkisp_rawrd2_s");
if (entity) {
src_raw2_s = (media_pad*)media_entity_get_pad(entity, 0);
if (!src_raw2_s) {
LOG_DEBUG("get rkisp_rawrd2_s sink pad failed!\n");
goto FAIL;
}
}
if (raw_mode) {
ret = media_setup_link(device, src_raw2_s, sink_pad, 0);
if (ret) {
LOG_ERROR("media_setup_link src_raw2_s sink_pad FAILED: %d\n", ret);
}
ret = media_setup_link(device, src_pad, sink_pad_bridge, 0);
if (ret) {
LOG_ERROR("media_setup_link src_pad sink_pad_bridge FAILED: %d\n", ret);
}
ret = media_setup_link(device, src_pad, sink_pad_mp, MEDIA_LNK_FL_ENABLED);
if (ret) {
LOG_ERROR("media_setup_link src_pad src_pad FAILED: %d\n", ret);
}
} else {
ret = media_setup_link(device, src_pad, sink_pad_mp, 0);
if (ret) {
LOG_ERROR("media_setup_link src_pad sink_pad_mp FAILED: %d\n", ret);
}
ret = media_setup_link(device, src_pad, sink_pad_bridge, MEDIA_LNK_FL_ENABLED);
if (ret) {
LOG_ERROR("media_setup_link src_pad sink_pad_bridge FAILED: %d\n", ret);
}
}
media_device_unref(device);
return 0;
FAIL:
media_device_unref(device);
return -1;
}
int initCamHwInfos(struct capture_info* media_info)
{
// TODO
// (1) all sensor info
// (2) all pipeline entity infos belonged to
// the sensor
char sys_path[64], devpath[32];
FILE* fp = NULL;
struct media_device* device = NULL;
uint32_t nents, j = 0, i = 0;
const struct media_entity_desc* entity_info = NULL;
struct media_entity* entity = NULL;
int ret = 0;
LOG_INFO("init start!!!!!!\n");
while (i < MAX_MEDIA_INDEX) {
snprintf(sys_path, 64, "/dev/media%d", i++);
fp = fopen(sys_path, "r");
if (!fp) {
continue;
}
fclose(fp);
device = media_device_new(sys_path);
/* Enumerate entities, pads and links. */
media_device_enumerate(device);
if (strcmp(device->info.model, "rkisp0") == 0 || strcmp(device->info.model, "rkisp") == 0) {
ret = get_isp_subdevs(device, sys_path, media_info);
if (ret) {
return ret;
}
} else if (strcmp(device->info.model, "rkcif") == 0 ||
strcmp(device->info.model, "rkcif_lite_mipi_lvds") == 0 ||
strcmp(device->info.model, "rkcif_mipi_lvds") == 0) {
ret = get_vicap_subdevs(device, sys_path, media_info);
if (ret) {
return ret;
}
} else {
goto media_unref;
}
media_unref:
media_device_unref(device);
}
return 0;
}