1291 lines
37 KiB
C++
Executable File
1291 lines
37 KiB
C++
Executable File
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
/*
|
|
* libuvc-camera (camera link and rkaiq)
|
|
*
|
|
* Copyright (C) 2022 Rockchip Electronics Co., Ltd.
|
|
*
|
|
* Author: Bin Yang <yangbin@rock-chips.com>
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <getopt.h>
|
|
#include <fcntl.h>
|
|
#include <inttypes.h>
|
|
#include <unistd.h>
|
|
#include <errno.h>
|
|
#include <sys/ioctl.h>
|
|
|
|
#include <mediactl.h>
|
|
#include <mediactl/mediactl-priv.h>
|
|
#include <linux/v4l2-subdev.h>
|
|
#include <linux/videodev2.h>
|
|
#include <log/log.h>
|
|
#include <vector>
|
|
#include <map>
|
|
|
|
#include "rkisp_control_loop.h"
|
|
#include "rkisp_control_aiq.h"
|
|
#include "tinyxml2.h"
|
|
#include "uvc-camera.h"
|
|
|
|
#define CLEAR(x) memset(&(x), 0, sizeof(x))
|
|
|
|
#ifdef LOG_TAG
|
|
#undef LOG_TAG
|
|
#endif
|
|
#define LOG_TAG "UVC-RKCAM"
|
|
|
|
#define rkaiq_info(format, ...) ALOGI(format, ##__VA_ARGS__)
|
|
#define rkaiq_warn(format, ...) ALOGW(format, ##__VA_ARGS__)
|
|
#define rkaiq_err(format, ...) ALOGE(format, ##__VA_ARGS__)
|
|
|
|
/* Private v4l2 event */
|
|
#define CIFISP_V4L2_EVENT_STREAM_START \
|
|
(V4L2_EVENT_PRIVATE_START + 1)
|
|
#define CIFISP_V4L2_EVENT_STREAM_STOP \
|
|
(V4L2_EVENT_PRIVATE_START + 2)
|
|
|
|
#define FILE_PATH_LEN 64
|
|
#define CAMS_NUM_MAX 3
|
|
#define FLASH_NUM_MAX 3
|
|
|
|
#define MAX_MEDIA_DEV_NUM 2 * CAMS_NUM_MAX
|
|
|
|
enum media_type {
|
|
MEDIA_UNKNOWN = 0,
|
|
MEDIA_RKCIF,
|
|
MEDIA_RKISP
|
|
};
|
|
|
|
struct UVC_Cam_Info {
|
|
char dev_name[FILE_PATH_LEN];
|
|
char sensor_name[FILE_PATH_LEN];
|
|
char model_name[FILE_PATH_LEN];
|
|
char mipi_name[FILE_PATH_LEN];
|
|
char phy_name[FILE_PATH_LEN];
|
|
char isp_name[FILE_PATH_LEN];
|
|
struct v4l2_pix_format format;
|
|
};
|
|
|
|
/* The SensorDriverDescriptor instance that describes sensor device and
|
|
* connected sub-device informations.
|
|
* @sensor_entity_name,
|
|
* @sd_isp_path, the isp sub-device path, e.g. /dev/v4l-subdev0
|
|
* @vd_params_path, the params video device path
|
|
* @vd_stats_path, the stats video device path
|
|
* @cams, multipe cameras can attache to isp, but only one can be active
|
|
* @sd_sensor_path, the sensor sub-device path
|
|
* @sd_lens_path, the lens sub-device path that attached to sensor
|
|
* @sd_flash_path, the flash sub-device path that attached to sensor,
|
|
* can be two or more.
|
|
* @link_enabled, the link status of this sensor
|
|
*/
|
|
struct SensorDriverDescriptor {
|
|
/* sensor entity name format:
|
|
* m01_b_ov13850 1-0010, where 'm01' means
|
|
* module index number, 'b' means
|
|
* back or front, 'ov13850' is real
|
|
* sensor name, '1-0010' means the i2c bus
|
|
* and sensor i2c slave address
|
|
*/
|
|
int module_idx;
|
|
char sensor_entity_name[FILE_PATH_LEN];
|
|
char sd_sensor_path[FILE_PATH_LEN];
|
|
char sd_lens_path[FILE_PATH_LEN];
|
|
char sd_flash_path[FLASH_NUM_MAX][FILE_PATH_LEN];
|
|
bool link_enabled;
|
|
bool sensorLinkedToCIF;
|
|
char linkedModelName[32];
|
|
|
|
std::string mSensorName;
|
|
std::string mDeviceName;
|
|
std::string mParentMediaDev;
|
|
std::string mModuleRealSensorName; //parsed frome sensor entity name
|
|
std::string mModuleIndexStr; // parsed from sensor entity name
|
|
char mPhyModuleOrient; // parsed from sensor entity name
|
|
};
|
|
|
|
std::vector<struct SensorDriverDescriptor> mSensorInfos;
|
|
std::map<uint32_t, const char*> mHdrModeConfigs;
|
|
|
|
/* The media topology instance that describes video device and
|
|
* sub-device informations.
|
|
*
|
|
* @sd_isp_path, the isp sub-device path, e.g. /dev/v4l-subdev0
|
|
* @vd_params_path, the params video device path
|
|
* @vd_stats_path, the stats video device path
|
|
* @cams, multipe cameras can attache to isp, but only one can be active
|
|
* @sd_sensor_path, the sensor sub-device path
|
|
* @sd_lens_path, the lens sub-device path that attached to sensor
|
|
* @sd_flash_path, the flash sub-device path that attached to sensor,
|
|
* can be two or more.
|
|
* @link_enabled, the link status of this sensor
|
|
*/
|
|
struct rkisp_media_info {
|
|
char sd_isp_path[FILE_PATH_LEN];
|
|
char vd_params_path[FILE_PATH_LEN];
|
|
char vd_stats_path[FILE_PATH_LEN];
|
|
SensorDriverDescriptor sensorInfo;
|
|
const char *hdrmode;
|
|
|
|
char mdev_path[32];
|
|
int isp_fd;
|
|
int available;
|
|
void* aiq_ctx;
|
|
};
|
|
|
|
static struct rkisp_media_info media_infos[CAMS_NUM_MAX];
|
|
static struct UVC_Cam_Info uvc_cams[CAMS_NUM_MAX];
|
|
static void* rkisp_engine;
|
|
static const char *hdrmode = "NORMAL";
|
|
static int width = 2688;
|
|
static int height = 1520;
|
|
const char* kDefaultCfgPath = "/vendor/etc/multi_camera_config.xml";
|
|
|
|
static int xioctl(int fh, int request, void *arg)
|
|
{
|
|
int r;
|
|
|
|
do {
|
|
r = ioctl(fh, request, arg);
|
|
} while (-1 == r && EINTR == errno);
|
|
|
|
return r;
|
|
}
|
|
|
|
static int v4l2_subdev_open(struct media_entity *entity)
|
|
{
|
|
if (entity->fd != -1)
|
|
return 0;
|
|
|
|
entity->fd = open(entity->devname, O_RDWR);
|
|
if (entity->fd == -1) {
|
|
int ret = -errno;
|
|
rkaiq_err("%s: Failed to open subdev device node %s\n", __func__,
|
|
entity->devname);
|
|
return ret;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void v4l2_subdev_close(struct media_entity *entity)
|
|
{
|
|
close(entity->fd);
|
|
entity->fd = -1;
|
|
}
|
|
|
|
static int v4l2_subdev_get_format(struct media_entity *entity,
|
|
struct v4l2_mbus_framefmt *format)
|
|
{
|
|
struct v4l2_subdev_format fmt;
|
|
int ret = 0;
|
|
|
|
ret = v4l2_subdev_open(entity);
|
|
if (ret < 0)
|
|
return ret;
|
|
|
|
memset(&fmt, 0, sizeof(fmt));
|
|
fmt.pad = 0;
|
|
fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
|
|
|
ret = ioctl(entity->fd, VIDIOC_SUBDEV_G_FMT, &fmt);
|
|
if (ret < 0) {
|
|
ret = -errno;
|
|
goto err;
|
|
}
|
|
|
|
*format = fmt.format;
|
|
err:
|
|
v4l2_subdev_close(entity);
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int rkisp_get_devname(struct media_device *device, const char *name,
|
|
char *dev_name)
|
|
{
|
|
const char *devname;
|
|
media_entity *entity = NULL;
|
|
|
|
entity = media_get_entity_by_name(device, name, strlen(name));
|
|
if (!entity)
|
|
return -1;
|
|
|
|
devname = media_entity_get_devname(entity);
|
|
if (!devname) {
|
|
rkaiq_err("can't find %s device path!", name);
|
|
return -1;
|
|
}
|
|
|
|
strncpy(dev_name, devname, FILE_PATH_LEN);
|
|
rkaiq_info("get %s devname: %s\n", name, dev_name);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int parseModuleInfo(const std::string &entity_name,
|
|
SensorDriverDescriptor &drv_info)
|
|
{
|
|
int ret = 0;
|
|
|
|
/*
|
|
* sensor entity name format SHOULD be like this:
|
|
* m00_b_ov13850 1-0010
|
|
*/
|
|
if (entity_name.empty())
|
|
return -1;
|
|
|
|
int parse_index = 0;
|
|
|
|
if (entity_name.at(parse_index) != 'm') {
|
|
rkaiq_err("%d:parse sensor entity name %s error at %d, "
|
|
"please check sensor driver !\n",
|
|
__LINE__, entity_name.c_str(), parse_index);
|
|
return -1;
|
|
}
|
|
|
|
std::string index_str = entity_name.substr (parse_index, 3);
|
|
drv_info.mModuleIndexStr = index_str;
|
|
|
|
parse_index += 3;
|
|
|
|
if (entity_name.at(parse_index) != '_') {
|
|
rkaiq_err("%d:parse sensor entity name %s error at %d, "
|
|
"please check sensor driver !\n",
|
|
__LINE__, entity_name.c_str(), parse_index);
|
|
return -1;
|
|
}
|
|
|
|
parse_index++;
|
|
|
|
if (entity_name.at(parse_index) != 'b' &&
|
|
entity_name.at(parse_index) != 'f') {
|
|
rkaiq_err("%d:parse sensor entity name %s error at %d, "
|
|
"please check sensor driver !\n",
|
|
__LINE__, entity_name.c_str(), parse_index);
|
|
return -1;
|
|
}
|
|
|
|
drv_info.mPhyModuleOrient = entity_name.at(parse_index);
|
|
|
|
parse_index++;
|
|
|
|
if (entity_name.at(parse_index) != '_') {
|
|
rkaiq_err("%d:parse sensor entity name %s error at %d, "
|
|
"please check sensor driver !\n",
|
|
__LINE__, entity_name.c_str(), parse_index);
|
|
return -1;
|
|
}
|
|
|
|
parse_index++;
|
|
|
|
std::size_t real_name_end = std::string::npos;
|
|
if ((real_name_end = entity_name.find(' ')) == std::string::npos) {
|
|
rkaiq_err("%d:parse sensor entity name %s error at %d, "
|
|
"please check sensor driver !\n",
|
|
__LINE__, entity_name.c_str(), parse_index);
|
|
return -1;
|
|
}
|
|
|
|
std::string real_name_str = entity_name.substr(parse_index, real_name_end - parse_index);
|
|
drv_info.mModuleRealSensorName = real_name_str;
|
|
|
|
rkaiq_info("%s:%d, real sensor name %s, module ori %c, module id %s\n",
|
|
__FUNCTION__, __LINE__, drv_info.mModuleRealSensorName.c_str(),
|
|
drv_info.mPhyModuleOrient, drv_info.mModuleIndexStr.c_str());
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int rkisp_enumrate_modules (struct media_device *device)
|
|
{
|
|
uint32_t nents, i;
|
|
const char* subdev_path = NULL;
|
|
int active_sensor = -1;
|
|
SensorDriverDescriptor drvInfo;
|
|
int ret;
|
|
const struct media_device_info *info = NULL;
|
|
|
|
CLEAR(drvInfo);
|
|
drvInfo.mSensorName = "none";
|
|
drvInfo.link_enabled = false;
|
|
nents = media_get_entities_count (device);
|
|
for (i = 0; i < nents; ++i) {
|
|
int module_idx = -1;
|
|
struct media_entity *e;
|
|
const struct media_entity_desc *ef;
|
|
const struct media_link *link;
|
|
|
|
e = media_get_entity(device, i);
|
|
ef = media_entity_get_info(e);
|
|
|
|
if (ef->type != MEDIA_ENT_T_V4L2_SUBDEV_SENSOR &&
|
|
ef->type != MEDIA_ENT_T_V4L2_SUBDEV_FLASH &&
|
|
ef->type != MEDIA_ENT_T_V4L2_SUBDEV_LENS)
|
|
continue;
|
|
|
|
if (ef->name[0] != 'm' && ef->name[3] != '_') {
|
|
rkaiq_err("sensor/lens/flash entity name format is incorrect,"
|
|
"pls check driver version !\n");
|
|
return -1;
|
|
}
|
|
|
|
/* Retrive the sensor index from sensor name,
|
|
* which is indicated by two characters after 'm',
|
|
* e.g. m00_b_ov13850 1-0010
|
|
* ^^, 00 is the module index
|
|
*/
|
|
module_idx = atoi(ef->name + 1);
|
|
if (module_idx >= CAMS_NUM_MAX) {
|
|
rkaiq_err("multiple sensors more than two not supported, %s\n", ef->name);
|
|
continue;
|
|
}
|
|
subdev_path = media_entity_get_devname (e);
|
|
switch (ef->type) {
|
|
case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
|
|
drvInfo.module_idx = module_idx;
|
|
drvInfo.mSensorName = ef->name;
|
|
strncpy(drvInfo.sd_sensor_path,
|
|
subdev_path, FILE_PATH_LEN);
|
|
strcpy(drvInfo.sensor_entity_name, ef->name);
|
|
rkaiq_info("%s(%d) sensor_entity_name(%s)\n",
|
|
__FUNCTION__, __LINE__, drvInfo.sensor_entity_name);
|
|
ret = parseModuleInfo(drvInfo.mSensorName, drvInfo);
|
|
|
|
link = media_entity_get_link(e, 0);
|
|
if (link && (link->flags & MEDIA_LNK_FL_ENABLED)) {
|
|
drvInfo.link_enabled = true;
|
|
} else {
|
|
rkaiq_info("%s(%d) sensor(%s) not linked!\n",
|
|
__FUNCTION__, __LINE__, drvInfo.mSensorName.c_str());
|
|
}
|
|
break;
|
|
case MEDIA_ENT_T_V4L2_SUBDEV_FLASH:
|
|
// TODO, support multiple flashes attached to one module
|
|
strncpy(drvInfo.sd_flash_path[0],
|
|
subdev_path, FILE_PATH_LEN);
|
|
break;
|
|
case MEDIA_ENT_T_V4L2_SUBDEV_LENS:
|
|
strncpy(drvInfo.sd_lens_path,
|
|
subdev_path, FILE_PATH_LEN);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (drvInfo.mSensorName != "none" && drvInfo.link_enabled) {
|
|
info = media_get_info(device);
|
|
if (info && !strncmp(info->driver, "rkcif", strlen("rkcif"))) {
|
|
drvInfo.sensorLinkedToCIF = true;
|
|
} else {
|
|
drvInfo.sensorLinkedToCIF = false;
|
|
}
|
|
strncpy(drvInfo.linkedModelName, info->model, sizeof(info->model));
|
|
rkaiq_info("module_idx(%d) sensor_entity_name(%s), linkedModelName(%s).\n",
|
|
drvInfo.module_idx, drvInfo.sensor_entity_name, drvInfo.linkedModelName);
|
|
|
|
mSensorInfos.push_back(drvInfo);
|
|
//media_infos[drvInfo.module_idx].sensorInfo = drvInfo;
|
|
} else {
|
|
rkaiq_info("media path: %s, no camera sensor found!\n", device->devnode);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static bool compareFuncForSensorInfo(struct SensorDriverDescriptor s1,
|
|
struct SensorDriverDescriptor s2) {
|
|
return (s1.mModuleIndexStr < s2.mModuleIndexStr);
|
|
}
|
|
|
|
/* get sensor media info */
|
|
static int rkisp_get_sensor_info() {
|
|
int ret = 0;
|
|
unsigned int i, index = 0;
|
|
char sys_path[64];
|
|
int find_sensor = 0;
|
|
int find_isp = 0;
|
|
int linked_sensor = -1;
|
|
struct media_device *device = NULL;
|
|
|
|
while (index < MAX_MEDIA_DEV_NUM) {
|
|
snprintf(sys_path, 64, "/dev/media%d", index++);
|
|
//rkaiq_info("media get sys_path: %s\n", sys_path);
|
|
if(access(sys_path,F_OK))
|
|
continue;
|
|
|
|
device = media_device_new(sys_path);
|
|
if (device == NULL) {
|
|
rkaiq_err("Failed to create media %s\n", sys_path);
|
|
continue;
|
|
}
|
|
|
|
ret = media_device_enumerate(device);
|
|
if (ret < 0) {
|
|
rkaiq_err("Failed to enumerate %s (%d)\n", sys_path, ret);
|
|
media_device_unref(device);
|
|
continue;
|
|
}
|
|
|
|
ret = rkisp_enumrate_modules(device);
|
|
if (ret < 0) {
|
|
rkaiq_err("Failed to enumerate modules%s (%d)\n", sys_path, ret);
|
|
media_device_unref(device);
|
|
continue;
|
|
}
|
|
|
|
media_device_unref(device);
|
|
}
|
|
|
|
std:sort(mSensorInfos.begin(), mSensorInfos.end(), compareFuncForSensorInfo);
|
|
if (mSensorInfos.size() == 0) {
|
|
// No registered drivers found
|
|
rkaiq_err("ERROR no sensor driver registered in medias!\n");
|
|
ret = -1;
|
|
}
|
|
|
|
rkaiq_info("%s:%d, find available camera num:%d!\n", __FUNCTION__,
|
|
__LINE__, (unsigned int)mSensorInfos.size());
|
|
for (size_t i = 0; i < mSensorInfos.size(); i++) {
|
|
media_infos[i].sensorInfo = mSensorInfos[i];
|
|
rkaiq_info("media_infos: module_idx(%d) sensor_entity_name(%s)\n",
|
|
media_infos[i].sensorInfo.module_idx,
|
|
media_infos[i].sensorInfo.sensor_entity_name);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/* Get sensor binded isp subdevs */
|
|
static int rkisp_enumrate_ispdev_info (struct media_device *device)
|
|
{
|
|
uint32_t nents, i;
|
|
const char* subdev_path = NULL;
|
|
int active_sensor = -1;
|
|
SensorDriverDescriptor drvInfo;
|
|
int ret;
|
|
const struct media_device_info *info = NULL;
|
|
char Temp[FILE_PATH_LEN];
|
|
|
|
CLEAR(drvInfo);
|
|
drvInfo.mSensorName = "none";
|
|
for (size_t i = 0; i < mSensorInfos.size(); i++) {
|
|
drvInfo = media_infos[i].sensorInfo;
|
|
rkaiq_info("@%s, Target sensor name: %s, candidate media: %s.\n",
|
|
__FUNCTION__, drvInfo.mSensorName.c_str(), device->devnode);
|
|
if (drvInfo.sensorLinkedToCIF) {
|
|
ret = rkisp_get_devname(device, drvInfo.linkedModelName, Temp);
|
|
if (ret < 0) {
|
|
rkaiq_err("%s is direct linked to sensor, not linked to cif!\n", device->devnode);
|
|
continue;
|
|
}
|
|
ret = rkisp_get_devname(device, "rkisp-isp-subdev", media_infos[i].sd_isp_path);
|
|
ret |= rkisp_get_devname(device, "rkisp-input-params", media_infos[i].vd_params_path);
|
|
ret |= rkisp_get_devname(device, "rkisp-statistics", media_infos[i].vd_stats_path);
|
|
strncpy(media_infos[i].mdev_path, device->devnode, sizeof(media_infos[i].mdev_path));
|
|
} else {
|
|
ret = rkisp_get_devname(device, drvInfo.sensor_entity_name, Temp);
|
|
if (ret < 0) {
|
|
rkaiq_err("%s not direct linked to sensor!\n", device->devnode);
|
|
continue;
|
|
}
|
|
ret = rkisp_get_devname(device, "rkisp-isp-subdev", media_infos[i].sd_isp_path);
|
|
ret |= rkisp_get_devname(device, "rkisp-input-params", media_infos[i].vd_params_path);
|
|
ret |= rkisp_get_devname(device, "rkisp-statistics", media_infos[i].vd_stats_path);
|
|
strncpy(media_infos[i].mdev_path, device->devnode, sizeof(media_infos[i].mdev_path));
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* get sensor binded isp info */
|
|
static int rkisp_get_cif_linked_info() {
|
|
int ret = 0;
|
|
unsigned int i, index = 0;
|
|
char sys_path[64];
|
|
int find_sensor = 0;
|
|
int find_isp = 0;
|
|
int linked_sensor = -1;
|
|
struct media_device *device = NULL;
|
|
const struct media_device_info *info = NULL;
|
|
char model[64] = "\0";
|
|
|
|
while (index < MAX_MEDIA_DEV_NUM) {
|
|
info = NULL;
|
|
snprintf(sys_path, 64, "/dev/media%d", index++);
|
|
//rkaiq_info("media get sys_path: %s\n", sys_path);
|
|
if(access(sys_path,F_OK))
|
|
continue;
|
|
|
|
device = media_device_new(sys_path);
|
|
if (device == NULL) {
|
|
rkaiq_info("Failed to create media %s\n", sys_path);
|
|
continue;
|
|
}
|
|
|
|
ret = media_device_enumerate(device);
|
|
if (ret < 0) {
|
|
rkaiq_info("Failed to enumerate %s (%d)\n", sys_path, ret);
|
|
media_device_unref(device);
|
|
continue;
|
|
}
|
|
info = media_get_info(device);
|
|
if (info && !strncmp(info->driver, "rkcif", strlen("rkcif"))) {
|
|
rkaiq_info("media: %s is cif node, skip!\n", sys_path);
|
|
media_device_unref(device);
|
|
continue;
|
|
}
|
|
|
|
ret = rkisp_enumrate_ispdev_info(device);
|
|
if (ret < 0) {
|
|
rkaiq_err("Failed to enumerate ispdev info:%s (%d)\n", sys_path, ret);
|
|
media_device_unref(device);
|
|
continue;
|
|
}
|
|
media_device_unref(device);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int init_engine(struct rkisp_media_info *media_info)
|
|
{
|
|
int ret = 0;
|
|
|
|
for (int i = 0; i < CAMS_NUM_MAX; i++) {
|
|
if (!media_info->sensorInfo.link_enabled) {
|
|
rkaiq_info("Link disabled, skipped\n");
|
|
continue;
|
|
}
|
|
|
|
ret = rkisp_cl_rkaiq_init(&(media_info->aiq_ctx), NULL, NULL,
|
|
media_info->sensorInfo.sensor_entity_name);
|
|
if (ret) {
|
|
rkaiq_err("rkisp engine init failed !\n");
|
|
return -1;
|
|
}
|
|
|
|
/* Workaround: ISP read-back isuess */
|
|
if (mSensorInfos.size() > 2)
|
|
setMulCamConc(media_info->aiq_ctx, true);
|
|
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
static int prepare_engine(struct rkisp_media_info *media_info)
|
|
{
|
|
struct rkisp_cl_prepare_params_s params;
|
|
int ret = 0;
|
|
|
|
CLEAR(params);
|
|
params.isp_sd_node_path = media_info->sd_isp_path;
|
|
params.isp_vd_params_path = media_info->vd_params_path;
|
|
params.isp_vd_stats_path = media_info->vd_stats_path;
|
|
params.staticMeta = NULL;
|
|
params.width = width;
|
|
params.height = height;
|
|
params.work_mode = media_info->hdrmode;
|
|
rkaiq_info("%s--set workingmode(%s)\n", __FUNCTION__, params.work_mode);
|
|
|
|
for (int i = 0; i < CAMS_NUM_MAX; i++) {
|
|
if (!media_info->sensorInfo.link_enabled) {
|
|
rkaiq_info("Link disabled, skipped\n");
|
|
continue;
|
|
}
|
|
|
|
rkaiq_info("%s - %s: link enabled : %d\n",
|
|
media_info->sensorInfo.sd_sensor_path,
|
|
media_info->sensorInfo.sensor_entity_name,
|
|
media_info->sensorInfo.link_enabled);
|
|
|
|
if (strlen(media_info->sensorInfo.sd_lens_path))
|
|
params.lens_sd_node_path = media_info->sensorInfo.sd_lens_path;
|
|
if (strlen(media_info->sensorInfo.sd_flash_path[0]))
|
|
params.flashlight_sd_node_path[0] = media_info->sensorInfo.sd_flash_path[0];
|
|
|
|
params.sensor_sd_node_path = media_info->sensorInfo.sd_sensor_path;
|
|
|
|
if (rkisp_cl_prepare(media_info->aiq_ctx, ¶ms)) {
|
|
rkaiq_err("rkisp engine prepare failed !\n");
|
|
return -1;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int start_engine(struct rkisp_media_info *media_info)
|
|
{
|
|
rkaiq_info("rkaiq start\n");
|
|
rkisp_cl_start(media_info->aiq_ctx);
|
|
if (media_info->aiq_ctx == NULL) {
|
|
rkaiq_err("rkaiq_start engine failed\n");
|
|
return -1;
|
|
} else {
|
|
rkaiq_info("rkaiq_start engine succeed\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void stop_engine(struct rkisp_media_info *media_info)
|
|
{
|
|
rkisp_cl_stop(media_info->aiq_ctx);
|
|
}
|
|
|
|
static void deinit_engine(struct rkisp_media_info *media_info)
|
|
{
|
|
rkisp_cl_deinit(media_info->aiq_ctx);
|
|
if (media_info->aiq_ctx)
|
|
media_info->aiq_ctx = NULL;
|
|
}
|
|
|
|
/* engine process */
|
|
static int engine_process(struct rkisp_media_info *media_info)
|
|
{
|
|
int ret = 0;
|
|
int isp_fd;
|
|
|
|
isp_fd = open(media_info->vd_params_path, O_RDWR);
|
|
if (isp_fd < 0) {
|
|
rkaiq_err("open %s failed %s\n", media_info->vd_params_path, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
ret = init_engine(media_info);
|
|
if (ret)
|
|
goto err_exit;
|
|
|
|
rkaiq_info("%s: init engine success...\n", media_info->mdev_path);
|
|
ret = prepare_engine(media_info);
|
|
if (ret)
|
|
goto err_exit;
|
|
|
|
rkaiq_info("%s: wait stream start event success ...\n", media_info->mdev_path);
|
|
ret = start_engine(media_info);
|
|
if (ret)
|
|
goto err_exit;
|
|
|
|
media_info->isp_fd = isp_fd;
|
|
err_exit:
|
|
|
|
return ret;
|
|
}
|
|
|
|
static bool updateModeList(tinyxml2::XMLElement* modeList,
|
|
std::map<uint32_t, const char*>& modeConfigs) {
|
|
using namespace tinyxml2;
|
|
|
|
rkaiq_info("@%s enter!\n", __FUNCTION__);
|
|
XMLElement* row = modeList->FirstChildElement("CameraId");
|
|
while (row != nullptr) {
|
|
|
|
uint32_t moduleId;
|
|
const char * mode = nullptr;
|
|
moduleId = row->UnsignedAttribute("moduleId"),
|
|
mode = row->Attribute("hdrmode");
|
|
if (mode == nullptr) {
|
|
rkaiq_err("%s: mode Config list must config mode!", __FUNCTION__);
|
|
return false;
|
|
}
|
|
modeConfigs.insert(std::make_pair(moduleId, mode));
|
|
row = row->NextSiblingElement("CameraId");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static int loadFromCfg(const char* cfgPath) {
|
|
using namespace tinyxml2;
|
|
XMLDocument configXml;
|
|
int errorID;
|
|
|
|
errorID = configXml.LoadFile(cfgPath);
|
|
if (errorID != XML_SUCCESS) {
|
|
rkaiq_err("%s: Unable to load aiq camera config file: %s. ErrorID: %d\n",
|
|
__FUNCTION__, cfgPath, errorID);
|
|
return errorID;
|
|
} else {
|
|
rkaiq_err("%s: load aiq camera config succeed!\n", __FUNCTION__);
|
|
}
|
|
|
|
XMLElement *aiqCamConfig = configXml.FirstChildElement("AiqCameraConfig");
|
|
if (aiqCamConfig == nullptr) {
|
|
rkaiq_err("%s: no aiq camera config specified\n", __FUNCTION__);
|
|
return -1;
|
|
}
|
|
XMLElement *modelist = aiqCamConfig->FirstChildElement("modeConfigList");
|
|
if (modelist == nullptr) {
|
|
rkaiq_info("%s: no mode list specified\n", __FUNCTION__);
|
|
} else {
|
|
if (!updateModeList(modelist, mHdrModeConfigs)) {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int uvc_rkaiq_setBrightness(unsigned short level)
|
|
{
|
|
for (int i = 0; i < mSensorInfos.size(); i++) {
|
|
if ((&media_infos[i])->aiq_ctx)
|
|
rkisp_cl_setBrightness((&media_infos[i])->aiq_ctx, level);
|
|
}
|
|
rkaiq_info("uvc_rkaiq_setBrightness: %d \n", level);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int uvc_rkaiq_getBrightness(unsigned short *level)
|
|
{
|
|
if ((&media_infos[0])->aiq_ctx)
|
|
rkisp_cl_getBrightness((&media_infos[0])->aiq_ctx, (unsigned int *)level);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int uvc_rkaiq_setContrast(unsigned short level)
|
|
{
|
|
for (int i = 0; i < mSensorInfos.size(); i++) {
|
|
if ((&media_infos[i])->aiq_ctx)
|
|
rkisp_cl_setContrast((&media_infos[i])->aiq_ctx, level);
|
|
}
|
|
rkaiq_info("uvc_rkaiq_setContrast: %d \n", level);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int uvc_rkaiq_getContrast(unsigned short *level)
|
|
{
|
|
if ((&media_infos[0])->aiq_ctx)
|
|
rkisp_cl_getContrast((&media_infos[0])->aiq_ctx, (unsigned int *)level);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int uvc_rkaiq_setSaturation(unsigned short level)
|
|
{
|
|
for (int i = 0; i < mSensorInfos.size(); i++) {
|
|
if ((&media_infos[i])->aiq_ctx)
|
|
rkisp_cl_setSaturation((&media_infos[i])->aiq_ctx, level);
|
|
}
|
|
rkaiq_info("uvc_rkaiq_setSaturation: %d \n", level);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int uvc_rkaiq_getSaturation(unsigned short *level)
|
|
{
|
|
if ((&media_infos[0])->aiq_ctx)
|
|
rkisp_cl_getSaturation((&media_infos[0])->aiq_ctx, (unsigned int *)level);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int uvc_rkaiq_ct(struct uvc_request_param *param, struct uvc_request_ct *ct)
|
|
{
|
|
unsigned char scan_mode = 0x0;
|
|
|
|
switch (param->cs) {
|
|
case UVC_CT_CONTROL_UNDEFINED:
|
|
break;
|
|
|
|
case UVC_CT_SCANNING_MODE_CONTROL:
|
|
if (param->dir == USB_TRAN_IN) {
|
|
ct->scan_mode[U_CUR] = 0x0;
|
|
ct->scan_mode[U_MIN] = 0x0;
|
|
ct->scan_mode[U_MAX] = 0x0;
|
|
ct->scan_mode[U_DEF] = 0x0;
|
|
ct->scan_mode[U_RES] = 0x0;
|
|
} else {
|
|
scan_mode = ct->scan_mode[U_CUR];
|
|
}
|
|
break;
|
|
|
|
case UVC_CT_AE_MODE_CONTROL:
|
|
case UVC_CT_AE_PRIORITY_CONTROL:
|
|
case UVC_CT_EXPOSURE_TIME_ABSOLUTE_CONTROL:
|
|
case UVC_CT_EXPOSURE_TIME_RELATIVE_CONTROL:
|
|
case UVC_CT_FOCUS_ABSOLUTE_CONTROL:
|
|
case UVC_CT_FOCUS_RELATIVE_CONTROL:
|
|
case UVC_CT_FOCUS_AUTO_CONTROL:
|
|
case UVC_CT_IRIS_ABSOLUTE_CONTROL:
|
|
case UVC_CT_IRIS_RELATIVE_CONTROL:
|
|
case UVC_CT_ZOOM_ABSOLUTE_CONTROL:
|
|
case UVC_CT_ZOOM_RELATIVE_CONTROL:
|
|
case UVC_CT_PANTILT_ABSOLUTE_CONTROL:
|
|
case UVC_CT_PANTILT_RELATIVE_CONTROL:
|
|
case UVC_CT_ROLL_ABSOLUTE_CONTROL:
|
|
case UVC_CT_ROLL_RELATIVE_CONTROL:
|
|
case UVC_CT_PRIVACY_CONTROL:
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int uvc_rkaiq_pu(struct uvc_request_param *param, struct uvc_request_pu *pu)
|
|
{
|
|
switch (param->cs) {
|
|
case UVC_PU_CONTROL_UNDEFINED:
|
|
break;
|
|
|
|
case UVC_PU_BACKLIGHT_COMPENSATION_CONTROL:
|
|
break;
|
|
|
|
case UVC_PU_BRIGHTNESS_CONTROL:
|
|
if (param->dir == USB_TRAN_IN) {
|
|
uvc_rkaiq_getBrightness(&pu->brightness[U_CUR]);
|
|
pu->brightness[U_MIN] = 0;
|
|
pu->brightness[U_MAX] = 255;
|
|
pu->brightness[U_DEF] = 128;
|
|
} else if (param->dir == USB_TRAN_OUT) {
|
|
uvc_rkaiq_setBrightness(pu->brightness[U_CUR]);
|
|
}
|
|
break;
|
|
|
|
case UVC_PU_CONTRAST_CONTROL:
|
|
if (param->dir == USB_TRAN_IN) {
|
|
uvc_rkaiq_getContrast(&pu->contrast[U_CUR]);
|
|
pu->contrast[U_MIN] = 0;
|
|
pu->contrast[U_MAX] = 255;
|
|
pu->contrast[U_DEF] = 128;
|
|
} else if (param->dir == USB_TRAN_OUT) {
|
|
uvc_rkaiq_setContrast(pu->contrast[U_CUR]);
|
|
}
|
|
break;
|
|
|
|
case UVC_PU_GAIN_CONTROL:
|
|
pu->gain[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_POWER_LINE_FREQUENCY_CONTROL:
|
|
pu->pl_freq[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_HUE_CONTROL:
|
|
pu->hue[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_SATURATION_CONTROL:
|
|
if (param->dir == USB_TRAN_IN) {
|
|
uvc_rkaiq_getSaturation(&pu->saturation[U_CUR]);
|
|
pu->saturation[U_MIN] = 0;
|
|
pu->saturation[U_MAX] = 255;
|
|
pu->saturation[U_DEF] = 128;
|
|
} else if (param->dir == USB_TRAN_OUT) {
|
|
uvc_rkaiq_setSaturation(pu->saturation[U_CUR]);
|
|
}
|
|
break;
|
|
|
|
case UVC_PU_SHARPNESS_CONTROL:
|
|
pu->sharpness[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_GAMMA_CONTROL:
|
|
pu->gamma[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_WHITE_BALANCE_TEMPERATURE_CONTROL:
|
|
pu->wb_temp[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL:
|
|
pu->wb_temp_auto[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_WHITE_BALANCE_COMPONENT_CONTROL:
|
|
pu->wb_component[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL:
|
|
pu->wb_component_auto[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_DIGITAL_MULTIPLIER_CONTROL:
|
|
pu->digital_mult[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL:
|
|
pu->digital_mult_limit[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_HUE_AUTO_CONTROL:
|
|
pu->hue_auto[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_ANALOG_VIDEO_STANDARD_CONTROL:
|
|
pu->analog_video[U_CUR] = 0x0;
|
|
break;
|
|
|
|
case UVC_PU_ANALOG_LOCK_STATUS_CONTROL:
|
|
pu->analog_lock[U_CUR] = 0x0;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int uvc_rkaiq_start(void)
|
|
{
|
|
int i = 0, ret = 0;
|
|
|
|
for (i = 0; i < mSensorInfos.size(); i++) {
|
|
rkaiq_info("uvc rkaiq start.\n");
|
|
engine_process(&media_infos[i]);
|
|
rkaiq_info("uvc rkaiq start success.\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int uvc_rkaiq_stop(void)
|
|
{
|
|
int i = 0;
|
|
|
|
for (i = 0; i < mSensorInfos.size(); i++) {
|
|
rkaiq_info("uvc rkaiq stop.\n");
|
|
if (media_infos[i].isp_fd) {
|
|
stop_engine(&media_infos[i]);
|
|
deinit_engine(&media_infos[i]);
|
|
close(media_infos[i].isp_fd);
|
|
}
|
|
rkaiq_info("uvc rkaiq stop success.\n");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int uvc_camera_media_clr_index(unsigned int index)
|
|
{
|
|
char *command = NULL;
|
|
|
|
asprintf(&command,"/vendor/bin/media-ctl -d /dev/media%u -r", index);
|
|
system(command);
|
|
free(command);
|
|
rkaiq_info("clear rk camera media%u config.", index);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int uvc_camera_media_clr(void)
|
|
{
|
|
unsigned int index = 0;
|
|
char sys_path[64] = {0};
|
|
|
|
while (index < MAX_MEDIA_DEV_NUM) {
|
|
snprintf(sys_path, 64, "/dev/media%d", index);
|
|
if(!access(sys_path, F_OK))
|
|
uvc_camera_media_clr_index(index);
|
|
index++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void camera_media_link(char media, const char *in_name, char in_num,
|
|
const char *out_name, char out_num, bool enable)
|
|
{
|
|
char *command = NULL;
|
|
|
|
asprintf(&command, "/vendor/bin/media-ctl -d /dev/media%u "
|
|
"-l '\"%s\":%u->\"%s\":%u[%d]'",
|
|
media, in_name, in_num, out_name, out_num, enable);
|
|
system(command);
|
|
free(command);
|
|
}
|
|
|
|
static int uvc_camera_media_cfg_index(enum media_type type,
|
|
unsigned int index, unsigned int cam_index)
|
|
{
|
|
const char *sensor_name = uvc_cams[cam_index].sensor_name;
|
|
const char *model_name = uvc_cams[cam_index].model_name;
|
|
const char *phy_name = uvc_cams[cam_index].phy_name;
|
|
const char *mipi_name = uvc_cams[cam_index].mipi_name;
|
|
const char *isp_name = uvc_cams[cam_index].isp_name;
|
|
const char *input_name = "rkisp-input-params";
|
|
|
|
#if defined(ISP_HW_V30)
|
|
if (type == MEDIA_RKCIF) {
|
|
camera_media_link(index, sensor_name, 0, phy_name, 0, 1);
|
|
camera_media_link(index, phy_name, 1, mipi_name, 0, 1);
|
|
camera_media_link(index, mipi_name, 1, "stream_cif_mipi_id0", 0, 1);
|
|
camera_media_link(index, mipi_name, 2, "stream_cif_mipi_id1", 0, 1);
|
|
camera_media_link(index, mipi_name, 3, "stream_cif_mipi_id2", 0, 1);
|
|
camera_media_link(index, mipi_name, 4, "stream_cif_mipi_id3", 0, 1);
|
|
camera_media_link(index, mipi_name, 5, "rkcif_scale_ch0", 0, 1);
|
|
camera_media_link(index, mipi_name, 6, "rkcif_scale_ch1", 0, 1);
|
|
camera_media_link(index, mipi_name, 7, "rkcif_scale_ch2", 0, 1);
|
|
camera_media_link(index, mipi_name, 8, "rkcif_scale_ch3", 0, 1);
|
|
} else if (type == MEDIA_RKISP) {
|
|
camera_media_link(index, model_name, 0, isp_name, 0, 1);
|
|
camera_media_link(index, input_name, 0, isp_name, 1, 1);
|
|
camera_media_link(index, isp_name, 3, "rkisp-statistics", 0, 1);
|
|
camera_media_link(index, isp_name, 2, "rkisp_mainpath", 0, 1);
|
|
camera_media_link(index, isp_name, 2, "rkisp_selfpath", 0, 1);
|
|
}
|
|
rkaiq_info("start rk3588 camera media%u config.", index);
|
|
|
|
#elif defined(ISP_HW_V21)
|
|
if (type == MEDIA_RKCIF) {
|
|
/* TODO */
|
|
} else if (type == MEDIA_RKISP) {
|
|
/* TODO */
|
|
}
|
|
rkaiq_info("start rk356x camera media%u config.", index);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int uvc_camera_media_cfg(unsigned int cam_num)
|
|
{
|
|
unsigned int index = 0;
|
|
unsigned int cam_index = 0;
|
|
char sys_path[64];
|
|
enum media_type type = MEDIA_UNKNOWN;
|
|
|
|
uvc_camera_media_clr();
|
|
|
|
while (index < MAX_MEDIA_DEV_NUM) {
|
|
snprintf(sys_path, 64, "/dev/media%d", index);
|
|
if(!access(sys_path, F_OK)) {
|
|
if (index < cam_num) {
|
|
type = MEDIA_RKCIF;
|
|
cam_index = index;
|
|
uvc_camera_media_cfg_index(type, index, cam_index);
|
|
} else if (index < 2*cam_num) {
|
|
type = MEDIA_RKISP;
|
|
cam_index = index - cam_num;
|
|
uvc_camera_media_cfg_index(type, index, cam_index);
|
|
}
|
|
}
|
|
index++;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static enum media_type rkisp_get_device_info(struct media_device *device,
|
|
struct UVC_Cam_Info *uvc_cam)
|
|
{
|
|
uint32_t nents, i;
|
|
enum media_type type = MEDIA_UNKNOWN;
|
|
|
|
nents = media_get_entities_count (device);
|
|
|
|
for (i = 0; i < nents; ++i) {
|
|
const char* subdev_path = NULL;
|
|
struct media_entity *e;
|
|
const struct media_entity_desc *ef;
|
|
|
|
e = media_get_entity(device, i);
|
|
ef = media_entity_get_info(e);
|
|
subdev_path = media_entity_get_devname (e);
|
|
|
|
switch (ef->type) {
|
|
case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR:
|
|
strcpy(uvc_cam->sensor_name, ef->name);
|
|
break;
|
|
|
|
case MEDIA_ENT_T_V4L2_SUBDEV:
|
|
if (strstr(ef->name, "dphy")) {
|
|
strcpy(uvc_cam->phy_name, ef->name);
|
|
} else if (strstr(ef->name, "mipi-csi")) {
|
|
strcpy(uvc_cam->mipi_name, ef->name);
|
|
type = MEDIA_RKCIF;
|
|
} else if (strstr(ef->name, "isp-subdev")) {
|
|
struct v4l2_mbus_framefmt format;
|
|
if (!v4l2_subdev_get_format(e, &format)) {
|
|
uvc_cam->format.width = format.width;
|
|
uvc_cam->format.height = format.height;
|
|
uvc_cam->format.pixelformat = format.code;
|
|
}
|
|
strcpy(uvc_cam->isp_name, ef->name);
|
|
type = MEDIA_RKISP;
|
|
} else if (strstr(ef->name, "lvds")) {
|
|
strcpy(uvc_cam->model_name, ef->name);
|
|
}
|
|
break;
|
|
|
|
case MEDIA_ENT_T_V4L2_VIDEO:
|
|
if (!strcmp(ef->name, "rkisp_mainpath"))
|
|
strcpy(uvc_cam->dev_name, subdev_path);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return type;
|
|
}
|
|
|
|
static int rkisp_get_uvc_camera_info(unsigned int *cam_num)
|
|
{
|
|
int ret = 0;
|
|
unsigned int i, index = 0;
|
|
unsigned int cam_index = 0;
|
|
char sys_path[64];
|
|
struct media_device *device = NULL;
|
|
enum media_type type = MEDIA_UNKNOWN;
|
|
struct UVC_Cam_Info uvc_cam;
|
|
char devname[FILE_PATH_LEN];
|
|
|
|
CLEAR(uvc_cams);
|
|
|
|
while (index < MAX_MEDIA_DEV_NUM) {
|
|
snprintf(sys_path, 64, "/dev/media%d", index++);
|
|
if(access(sys_path,F_OK))
|
|
continue;
|
|
|
|
device = media_device_new(sys_path);
|
|
if (device == NULL) {
|
|
rkaiq_err("Failed to create media %s\n", sys_path);
|
|
continue;
|
|
}
|
|
|
|
ret = media_device_enumerate(device);
|
|
if (ret < 0) {
|
|
rkaiq_err("Failed to enumerate %s (%d)\n", sys_path, ret);
|
|
media_device_unref(device);
|
|
continue;
|
|
}
|
|
|
|
CLEAR(uvc_cam);
|
|
type = rkisp_get_device_info(device, &uvc_cam);
|
|
if (type == MEDIA_RKCIF) {
|
|
if ((cam_index >= CAMS_NUM_MAX) || ((index - 1) != cam_index)) {
|
|
rkaiq_err("get media cif info fail, index:%d, cam_index:%d, "
|
|
"CAMS_NUM_MAX:%d \n",
|
|
(index-1), cam_index, CAMS_NUM_MAX);
|
|
goto err;
|
|
}
|
|
memcpy(&uvc_cams[cam_index], &uvc_cam, sizeof(uvc_cam));
|
|
cam_index++;
|
|
} else if (type == MEDIA_RKISP) {
|
|
if (index - 1 < cam_index) {
|
|
rkaiq_err("get media isp info fail, index:%d, cam_index:%d\n",
|
|
(index-1), cam_index);
|
|
goto err;
|
|
}
|
|
memcpy(uvc_cams[index-cam_index-1].model_name, uvc_cam.model_name,
|
|
sizeof(uvc_cam.model_name));
|
|
memcpy(uvc_cams[index-cam_index-1].isp_name, uvc_cam.isp_name,
|
|
sizeof(uvc_cam.isp_name));
|
|
memcpy(uvc_cams[index-cam_index-1].dev_name, uvc_cam.dev_name,
|
|
sizeof(uvc_cam.dev_name));
|
|
memcpy(&uvc_cams[index-cam_index-1].format, &uvc_cam.format,
|
|
sizeof(uvc_cam.format));
|
|
}
|
|
err:
|
|
media_device_unref(device);
|
|
}
|
|
*cam_num = cam_index;
|
|
|
|
return ret;
|
|
}
|
|
|
|
int uvc_rkaiq_get_video(char ** cap_device, unsigned int index)
|
|
{
|
|
if (index >= CAMS_NUM_MAX) {
|
|
rkaiq_err("uvc get input device failed,"
|
|
"index:%d exceed %d\n", index, CAMS_NUM_MAX);
|
|
return -1;
|
|
}
|
|
*cap_device = uvc_cams[index].dev_name;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int uvc_rkaiq_get_format(struct v4l2_pix_format *format, unsigned int index)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (index >= CAMS_NUM_MAX) {
|
|
rkaiq_err("uvc get input format failed,"
|
|
"index:%d exceed %d\n", index, CAMS_NUM_MAX);
|
|
return -1;
|
|
}
|
|
|
|
*format = uvc_cams[index].format;
|
|
if (!format->width || !format->height) {
|
|
rkaiq_err("uvc get input size failed!\n");
|
|
ret = -1;
|
|
} else {
|
|
rkaiq_info("uvc get input size:%ux%u \n",
|
|
format->width, format->height);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int uvc_rkaiq_init(bool link_en)
|
|
{
|
|
int i = 0;
|
|
unsigned int cam_num = 0;
|
|
|
|
CLEAR(media_infos);
|
|
mSensorInfos.clear();
|
|
mHdrModeConfigs.clear();
|
|
|
|
rkisp_get_uvc_camera_info(&cam_num);
|
|
|
|
if (link_en)
|
|
uvc_camera_media_cfg(cam_num);
|
|
|
|
/* get physical sensor infos */
|
|
if (rkisp_get_sensor_info()) {
|
|
rkaiq_err("Bad media topology error %d, %s\n", errno, strerror(errno));
|
|
return -errno;
|
|
}
|
|
|
|
/* get sensor binded isp infos */
|
|
if (rkisp_get_cif_linked_info()) {
|
|
rkaiq_err("Bad media info error %d, %s\n", errno, strerror(errno));
|
|
return -errno;
|
|
}
|
|
|
|
/* sensor mode config & mutex init */
|
|
loadFromCfg(kDefaultCfgPath);
|
|
|
|
if (mHdrModeConfigs.empty()) {
|
|
rkaiq_err("Using default hdr configs! (%s)\n", media_infos[i].mdev_path);
|
|
for (i = 0; i < mSensorInfos.size(); i++) {
|
|
media_infos[i].hdrmode = hdrmode;
|
|
}
|
|
} else {
|
|
for (i = 0; i < mSensorInfos.size(); i++) {
|
|
media_infos[i].hdrmode = mHdrModeConfigs[i];
|
|
rkaiq_info("camera:%d, hdrmode: %s.\n", i, media_infos[i].hdrmode);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int uvc_rkaiq_deinit(bool link_en)
|
|
{
|
|
if (link_en)
|
|
uvc_camera_media_clr();
|
|
|
|
return 0;
|
|
}
|