#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; }