camera: rockchip: merge modification of rv1108 isp11

camera: rockchip: add sensor ioctl and max gain.
1. add RK_VIDIOC_SENSOR_CONFIGINFO;
2. add RK_VIDIOC_SENSOR_REG_ACCESS;
3. add max_exp_gain_h/max_exp_gain_l;

camera: rockchip: merge isp11: rockchip: v0.1.7
isp11: rockchip: v0.1.7
1. Direct config isp lsc table size in cifisp_lsc_config.
   Because active_lsc_width is not same with isp register
   after isp reset.
2. Support separate config sensor gain and shutter time
   for some sensor which gain and shutter isn't valid at
   the same time. for example ov2710.
   ov4689:v0.1.0;
   ov2710:v0.1.1;
   imx323:v0.1.0;

camera: rockchip: Support v4l2 subdev api
ov2710: v0.1.2
ov4689: v0.1.1
imx323: v0.1.2

camera: rockchip: add lock for stream/aec
hold reg in AEC will affect stream reg, if asynchronous.

camera: rockchip: fix sensor timing
if fps changed, vts changed, update to timing.

camera: rockchip: support set flip api

camera: rockchip: support get flip api

camera: rockchip: fix release bug
should be free pdata at the end

camera: rockchip: imx323
fix s_fmt failed for imx323 v0.1.2;

camera: rockchip: fix s_frame_interval failed

fix s_frame_interval failed when frame interval is match
active config frame interval.

camera: rockchip: imx,aptina,ov
Check xxx_camera_module_init return value in PLTFRM_CIFCAM_ATTACH

camera: rockchip: release sensor if init fail

camera: rockchip: imx,aptina,ov
support mirror/flip conifg in dts for imx323/ov4689

camera: rockchip: add s_frame_interval/g_frame_interval
camera: rockchip: ov, aptina, imx
add s_frame_interval/g_frame_interval

camera: rockchip: imx,ov,aptina
1.imx,ov: fix g_timing error if s_frame_interval before stream_on,
  because vts_cur is update in stream_on;
2.aptina: fix compile error;

camera: rockchip: imx,ov,aptina
1. fix calc vts wrong in xxx_camera_module_s_stream

Change-Id: I5a6e75f2ce3c50d69c51af9792232c60b6982128
Signed-off-by: Hu Kejun <william.hu@rock-chips.com>
This commit is contained in:
Hu Kejun 2018-06-11 16:19:08 +08:00 committed by Tao Huang
parent 6ffc8e398a
commit 9e93e6ba45
23 changed files with 1602 additions and 351 deletions

View File

@ -132,6 +132,8 @@ static struct adv_camera_module_config adv7181_configs[] = {
/
sizeof(adv7180_cvbs_30fps[0]),
.v_blanking_time_us = 0,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
.ignore_measurement_check = 1,
PLTFRM_CAM_ITF_DVP_CFG(
PLTFRM_CAM_ITF_BT656_8I,
@ -160,6 +162,8 @@ static struct adv_camera_module_config adv7181_configs[] = {
/
sizeof(adv7180_cvbs_30fps[0]),
.v_blanking_time_us = 0,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
.ignore_measurement_check = 1,
PLTFRM_CAM_ITF_DVP_CFG(
PLTFRM_CAM_ITF_BT656_8I,
@ -228,6 +232,8 @@ static int adv7181_g_timings(struct adv_camera_module *cam_mod,
cam_mod->active_config->frm_intrvl.interval.denominator *
vts * timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
adv_camera_module_pr_err(cam_mod,
@ -397,6 +403,7 @@ static struct v4l2_subdev_core_ops adv7181_camera_module_core_ops = {
static struct v4l2_subdev_video_ops adv7181_camera_module_video_ops = {
.s_frame_interval = adv_camera_module_s_frame_interval,
.g_frame_interval = adv_camera_module_g_frame_interval,
.s_stream = adv_camera_module_s_stream
};
@ -425,7 +432,13 @@ static struct adv_camera_module_custom_config adv7181_custom_config = {
.check_camera_id = adv7181_check_camera_id,
.configs = adv7181_configs,
.num_configs = ARRAY_SIZE(adv7181_configs),
.power_up_delays_ms = {5, 30, 30}
.power_up_delays_ms = {5, 30, 30},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static ssize_t adv7181_debugfs_reg_write(

View File

@ -47,8 +47,6 @@ static void adv_camera_module_reset(
cam_mod->exp_config.auto_exp = false;
cam_mod->exp_config.auto_gain = false;
cam_mod->wb_config.auto_wb = false;
cam_mod->hflip = false;
cam_mod->vflip = false;
cam_mod->auto_adjust_fps = true;
cam_mod->rotation = 0;
cam_mod->ctrl_updt = 0;
@ -306,6 +304,10 @@ int adv_camera_module_s_fmt(struct v4l2_subdev *sd,
adv_camera_module_set_active_config(cam_mod,
adv_camera_module_find_config(cam_mod,
fmt, &cam_mod->frm_intrvl));
} else {
adv_camera_module_set_active_config(cam_mod,
adv_camera_module_find_config(cam_mod,
fmt, NULL));
}
return 0;
err:
@ -346,6 +348,8 @@ int adv_camera_module_s_frame_interval(
struct adv_camera_module *cam_mod = to_adv_camera_module(sd);
unsigned long gcdiv;
struct v4l2_subdev_frame_interval norm_interval;
struct adv_camera_module_config *config;
unsigned int vts;
int ret = 0;
if ((interval->interval.denominator == 0) ||
@ -372,22 +376,62 @@ int adv_camera_module_s_frame_interval(
norm_interval.interval.denominator =
interval->interval.denominator / gcdiv;
if (IS_ERR_OR_NULL(adv_camera_module_find_config(cam_mod,
NULL, &norm_interval))) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"frame interval %d/%d not supported\n",
interval->interval.numerator,
interval->interval.denominator);
ret = -EINVAL;
goto err;
if (!cam_mod->frm_fmt_valid)
goto end;
config = adv_camera_module_find_config(
cam_mod,
&cam_mod->active_config->frm_fmt,
&norm_interval);
if (!IS_ERR_OR_NULL(config) && (config != cam_mod->active_config)) {
adv_camera_module_set_active_config(cam_mod, config);
if (cam_mod->state == ADV_CAMERA_MODULE_STREAMING) {
cam_mod->custom.stop_streaming(cam_mod);
adv_camera_module_write_config(cam_mod);
cam_mod->custom.start_streaming(cam_mod);
}
} else {
if (IS_ERR_OR_NULL(cam_mod->active_config)) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"no active sensor configuration");
ret = -EFAULT;
goto err;
}
if (cam_mod->active_config->frm_intrvl.interval.denominator <
norm_interval.interval.denominator) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"%dx%d@%dfps isn't support!",
cam_mod->active_config->frm_fmt.width,
cam_mod->active_config->frm_fmt.height,
norm_interval.interval.denominator);
ret = -EFAULT;
goto err;
}
if (!cam_mod->custom.s_vts) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"custom.s_vts isn't support!");
ret = -EFAULT;
goto err;
}
vts = cam_mod->active_config->timings.frame_length_lines;
vts *= cam_mod->active_config->frm_intrvl.interval.denominator;
vts /= norm_interval.interval.denominator;
cam_mod->vts_cur = vts;
if (cam_mod->state != ADV_CAMERA_MODULE_STREAMING)
goto end;
cam_mod->custom.s_vts(cam_mod, vts);
}
end:
cam_mod->frm_intrvl_valid = true;
cam_mod->frm_intrvl = norm_interval;
if (cam_mod->frm_fmt_valid) {
adv_camera_module_set_active_config(cam_mod,
adv_camera_module_find_config(cam_mod,
&cam_mod->frm_fmt, interval));
}
cam_mod->auto_adjust_fps = false;
return 0;
err:
pltfrm_camera_module_pr_err(&cam_mod->sd,
@ -395,12 +439,34 @@ int adv_camera_module_s_frame_interval(
return ret;
}
int adv_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval)
{
struct adv_camera_module *cam_mod = to_adv_camera_module(sd);
if (cam_mod->active_config) {
if (cam_mod->state == ADV_CAMERA_MODULE_STREAMING) {
if (cam_mod->frm_intrvl_valid) {
*interval = cam_mod->frm_intrvl;
return 0;
} else {
*interval = cam_mod->active_config->frm_intrvl;
return 0;
}
}
}
return -EFAULT;
}
/* ======================================================================== */
int adv_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
{
int ret = 0;
struct adv_camera_module *cam_mod = to_adv_camera_module(sd);
unsigned int vts;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "%d\n", enable);
@ -429,6 +495,29 @@ int adv_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
ret = cam_mod->custom.start_streaming(cam_mod);
if (IS_ERR_VALUE(ret))
goto err;
if (cam_mod->frm_intrvl_valid) {
if ((cam_mod->frm_intrvl.interval.numerator !=
cam_mod->active_config->frm_intrvl.interval.numerator) ||
(cam_mod->frm_intrvl.interval.denominator !=
cam_mod->active_config->frm_intrvl.interval.denominator)) {
if (cam_mod->frm_intrvl.interval.denominator >
cam_mod->active_config->frm_intrvl.interval.denominator) {
pltfrm_camera_module_pr_warn(&cam_mod->sd,
"sensor is not support stream: %dx%d@(%d/%d)fps!\n",
cam_mod->active_config->frm_fmt.width,
cam_mod->active_config->frm_fmt.height,
cam_mod->frm_intrvl.interval.denominator,
cam_mod->frm_intrvl.interval.numerator);
goto end;
}
vts = cam_mod->active_config->timings.frame_length_lines;
vts *= cam_mod->active_config->frm_intrvl.interval.denominator;
vts /= cam_mod->frm_intrvl.interval.denominator;
cam_mod->custom.s_vts(cam_mod, vts);
}
}
if (!cam_mod->inited && cam_mod->update_config)
cam_mod->inited = true;
cam_mod->update_config = false;
@ -473,6 +562,7 @@ int adv_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
msleep(wait_ms + 1);
}
end:
cam_mod->state_before_suspend = cam_mod->state;
return 0;
@ -584,6 +674,22 @@ int adv_camera_module_g_ctrl(struct v4l2_subdev *sd,
return 0;
}
if (ctrl->id == V4L2_CID_HFLIP) {
ctrl->value = cam_mod->hflip;
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"V4L2_CID_HFLIP %d\n",
ctrl->value);
return 0;
}
if (ctrl->id == V4L2_CID_VFLIP) {
ctrl->value = cam_mod->vflip;
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"V4L2_CID_VFLIP %d\n",
ctrl->value);
return 0;
}
if (IS_ERR_OR_NULL(cam_mod->active_config)) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"no active configuration\n");
@ -670,10 +776,6 @@ int adv_camera_module_g_ctrl(struct v4l2_subdev *sd,
"V4L2_CID_FOCUS_ABSOLUTE %d\n",
ctrl->value);
break;
case V4L2_CID_HFLIP:
case V4L2_CID_VFLIP:
/* TBD */
/* fallthrough */
default:
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"failed, unknown ctrl %d\n", ctrl->id);
@ -813,12 +915,14 @@ int adv_camera_module_s_ext_ctrls(
cam_mod->hflip = true;
else
cam_mod->hflip = false;
cam_mod->flip_flg = true;
break;
case V4L2_CID_VFLIP:
if (ctrl->value)
cam_mod->vflip = true;
else
cam_mod->vflip = false;
cam_mod->flip_flg = true;
break;
default:
pltfrm_camera_module_pr_warn(&cam_mod->sd,
@ -896,7 +1000,8 @@ long adv_camera_module_ioctl(struct v4l2_subdev *sd,
void *arg)
{
struct adv_camera_module *cam_mod = to_adv_camera_module(sd);
int ret;
int ret, i;
unsigned int flag, val;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "cmd: 0x%x\n", cmd);
@ -937,9 +1042,10 @@ long adv_camera_module_ioctl(struct v4l2_subdev *sd,
timings->fine_integration_time_min =
adv_timings.fine_integration_time_min;
if (cam_mod->custom.g_exposure_valid_frame)
timings->exposure_valid_frame[0] =
cam_mod->custom.g_exposure_valid_frame(cam_mod);
timings->exposure_valid_frame[0] =
cam_mod->custom.exposure_valid_frame[0];
timings->exposure_valid_frame[1] =
cam_mod->custom.exposure_valid_frame[1];
if (cam_mod->exp_config.exp_time)
timings->exp_time = cam_mod->exp_config.exp_time;
else
@ -948,7 +1054,52 @@ long adv_camera_module_ioctl(struct v4l2_subdev *sd,
timings->gain = cam_mod->exp_config.gain;
else
timings->gain = adv_timings.gain;
if (cam_mod->active_config) {
timings->max_exp_gain_h = cam_mod->active_config->max_exp_gain_h;
timings->max_exp_gain_l = cam_mod->active_config->max_exp_gain_l;
} else {
timings->max_exp_gain_h = cam_mod->custom.configs[0].max_exp_gain_h;
timings->max_exp_gain_l = cam_mod->custom.configs[0].max_exp_gain_l;
}
return ret;
} else if (cmd == RK_VIDIOC_SENSOR_CONFIGINFO) {
struct sensor_config_info_s *sensor_config = (struct sensor_config_info_s *)arg;
sensor_config->config_num = cam_mod->custom.num_configs;
for (i = 0; i < cam_mod->custom.num_configs; i++) {
if (i >= SENSOR_CONFIG_NUM)
break;
sensor_config->sensor_fmt[i] =
pltfrm_camera_module_pix_fmt2csi2_dt(cam_mod->custom.configs[i].frm_fmt.code);
sensor_config->reso[i].width = cam_mod->custom.configs[i].frm_fmt.width;
sensor_config->reso[i].height = cam_mod->custom.configs[i].frm_fmt.height;
}
return 0;
} else if (cmd == RK_VIDIOC_SENSOR_REG_ACCESS) {
struct sensor_reg_rw_s *sensor_rw = (struct sensor_reg_rw_s *)arg;
if (sensor_rw->reg_access_mode == SENSOR_READ_MODE) {
for (i = 0; i < cam_mod->custom.configs[0].reg_table_num_entries; i++) {
flag = cam_mod->custom.configs[0].reg_table[i].flag;
if (flag != PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT)
break;
}
if (flag == PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"Can not get sensor reg type.\n");
return -EINVAL;
}
sensor_rw->reg_addr_len = PLTFRM_CAMERA_MODULE_REG_LEN(flag);
sensor_rw->reg_data_len = PLTFRM_CAMERA_MODULE_DATA_LEN(flag);
pltfrm_camera_module_read_reg_ex(&cam_mod->sd, 1, flag, sensor_rw->addr, &val);
sensor_rw->data = val;
} else {
flag = (sensor_rw->reg_addr_len << PLTFRM_CAMERA_MODULE_REG_LEN_BIT);
flag |= (sensor_rw->reg_data_len << PLTFRM_CAMERA_MODULE_DATA_LEN_BIT);
pltfrm_camera_module_write_reg_ex(&cam_mod->sd, flag, sensor_rw->addr, sensor_rw->data);
}
return 0;
} else if (cmd == PLTFRM_CIFCAM_G_ITF_CFG) {
struct pltfrm_cam_itf *itf_cfg = (struct pltfrm_cam_itf *)arg;
struct adv_camera_module_config *config;
@ -969,10 +1120,14 @@ long adv_camera_module_ioctl(struct v4l2_subdev *sd,
pltfrm_camera_module_ioctl(sd, PLTFRM_CIFCAM_G_ITF_CFG, arg);
return 0;
} else if (cmd == PLTFRM_CIFCAM_ATTACH) {
adv_camera_module_init(cam_mod, &cam_mod->custom);
pltfrm_camera_module_pr_err(&cam_mod->sd, "test\n");
pltfrm_camera_module_ioctl(sd, cmd, arg);
return adv_camera_module_attach(cam_mod);
ret = adv_camera_module_init(cam_mod, &cam_mod->custom);
if (!IS_ERR_VALUE(ret)) {
pltfrm_camera_module_ioctl(sd, cmd, arg);
return adv_camera_module_attach(cam_mod);
} else {
adv_camera_module_release(cam_mod);
return ret;
}
}
ret = pltfrm_camera_module_ioctl(sd, cmd, arg);
@ -984,7 +1139,22 @@ long adv_camera_module_ioctl(struct v4l2_subdev *sd,
int adv_camera_module_get_flip_mirror(
struct adv_camera_module *cam_mod)
{
return pltfrm_camera_module_get_flip_mirror(&cam_mod->sd);
int mode = 0;
if (!cam_mod->flip_flg)
return -1;
if (cam_mod->hflip)
mode |= ADV_MIRROR_BIT_MASK;
else
mode &= ~ADV_MIRROR_BIT_MASK;
if (cam_mod->vflip)
mode |= ADV_FLIP_BIT_MASK;
else
mode &= ~ADV_FLIP_BIT_MASK;
return mode;
}
/* ======================================================================== */
@ -1156,9 +1326,13 @@ int adv_camera_module_init(struct adv_camera_module *cam_mod,
struct adv_camera_module_custom_config *custom)
{
int ret = 0;
int mode = 0;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "\n");
cam_mod->hflip = false;
cam_mod->vflip = false;
cam_mod->flip_flg = false;
adv_camera_module_reset(cam_mod);
if (IS_ERR_OR_NULL(custom->start_streaming) ||
@ -1186,6 +1360,13 @@ int adv_camera_module_init(struct adv_camera_module *cam_mod,
goto err;
}
mode = pltfrm_camera_module_get_flip_mirror(&cam_mod->sd);
if (mode != -1) {
cam_mod->hflip = mode & ADV_MIRROR_BIT_MASK ? true : false;
cam_mod->vflip = mode & ADV_FLIP_BIT_MASK ? true : false;
cam_mod->flip_flg = true;
}
return 0;
err:
pltfrm_camera_module_pr_err(&cam_mod->sd,

View File

@ -30,8 +30,8 @@
#define ADV_CAMERA_MODULE_REG_TYPE_TIMEOUT PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT
#define adv_camera_module_csi_config
#define adv_camera_module_reg pltfrm_camera_module_reg
#define ADV_FLIP_BIT_MASK 0x2
#define ADV_MIRROR_BIT_MASK 0x1
#define ADV_FLIP_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_FLIP_BIT)
#define ADV_MIRROR_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define ADV_CAMERA_MODULE_CTRL_UPDT_GAIN 0x01
#define ADV_CAMERA_MODULE_CTRL_UPDT_EXP_TIME 0x02
@ -90,7 +90,8 @@ struct adv_camera_module_config {
struct adv_camera_module_timings timings;
bool soft_reset;
bool ignore_measurement_check;
u8 max_exp_gain_h;
u8 max_exp_gain_l;
struct pltfrm_cam_itf itf_cfg;
};
@ -156,7 +157,8 @@ struct adv_camera_module_custom_config {
int (*g_ctrl)(struct adv_camera_module *cam_mod, u32 ctrl_id);
int (*g_timings)(struct adv_camera_module *cam_mod,
struct adv_camera_module_timings *timings);
int (*g_exposure_valid_frame)(struct adv_camera_module *cam_mod);
int (*s_vts)(struct adv_camera_module *cam_mod,
u32 vts);
int (*s_ext_ctrls)(struct adv_camera_module *cam_mod,
struct adv_camera_module_ext_ctrls *ctrls);
int (*set_flip)(
@ -168,6 +170,7 @@ struct adv_camera_module_custom_config {
struct adv_camera_module_config *configs;
u32 num_configs;
u32 power_up_delays_ms[3];
unsigned short exposure_valid_frame[2];
void *priv;
};
@ -199,9 +202,11 @@ struct adv_camera_module {
bool frm_intrvl_valid;
bool hflip;
bool vflip;
bool flip_flg;
u32 rotation;
void *pltfm_data;
bool inited;
struct mutex lock;
};
#define adv_camera_module_pr_info(cam_mod, fmt, arg...) \
@ -245,6 +250,10 @@ int adv_camera_module_s_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int adv_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int adv_camera_module_s_stream(
struct v4l2_subdev *sd,
int enable);

View File

@ -51,8 +51,6 @@ void aptina_camera_module_reset(
cam_mod->exp_config.auto_exp = false;
cam_mod->exp_config.auto_gain = false;
cam_mod->wb_config.auto_wb = false;
cam_mod->hflip = false;
cam_mod->vflip = false;
cam_mod->auto_adjust_fps = true;
cam_mod->rotation = 0;
cam_mod->ctrl_updt = 0;
@ -484,6 +482,10 @@ int aptina_camera_module_s_fmt(struct v4l2_subdev *sd,
aptina_camera_module_set_active_config(cam_mod,
aptina_camera_module_find_config(cam_mod,
fmt, &cam_mod->frm_intrvl));
} else {
aptina_camera_module_set_active_config(cam_mod,
aptina_camera_module_find_config(cam_mod,
fmt, NULL));
}
return 0;
err:
@ -525,6 +527,9 @@ int aptina_camera_module_s_frame_interval(
unsigned long gcdiv;
struct v4l2_subdev_frame_interval norm_interval;
int ret = 0;
struct aptina_camera_module_config *config;
unsigned int vts;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "\n");
if ((interval->interval.denominator == 0) ||
@ -551,22 +556,63 @@ int aptina_camera_module_s_frame_interval(
norm_interval.interval.denominator =
interval->interval.denominator / gcdiv;
if (IS_ERR_OR_NULL(aptina_camera_module_find_config(cam_mod,
NULL, &norm_interval))) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"frame interval %d/%d not supported\n",
interval->interval.numerator,
interval->interval.denominator);
ret = -EINVAL;
goto err;
if (!cam_mod->frm_fmt_valid)
goto end;
config = aptina_camera_module_find_config(
cam_mod,
&cam_mod->active_config->frm_fmt,
&norm_interval);
if (!IS_ERR_OR_NULL(config) && (config != cam_mod->active_config)) {
aptina_camera_module_set_active_config(cam_mod, config);
if (cam_mod->state == APTINA_CAMERA_MODULE_STREAMING) {
cam_mod->custom.stop_streaming(cam_mod);
aptina_camera_module_write_config(cam_mod);
cam_mod->custom.start_streaming(cam_mod);
}
} else {
if (IS_ERR_OR_NULL(cam_mod->active_config)) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"no active sensor configuration");
ret = -EFAULT;
goto err;
}
if (cam_mod->active_config->frm_intrvl.interval.denominator <
norm_interval.interval.denominator) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"%dx%d@%dfps isn't support!",
cam_mod->active_config->frm_fmt.width,
cam_mod->active_config->frm_fmt.height,
norm_interval.interval.denominator);
ret = -EFAULT;
goto err;
}
if (!cam_mod->custom.s_vts) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"custom.s_vts isn't support!");
ret = -EFAULT;
goto err;
}
vts = cam_mod->active_config->timings.frame_length_lines;
vts *= cam_mod->active_config->frm_intrvl.interval.denominator;
vts /= norm_interval.interval.denominator;
cam_mod->vts_cur = vts;
if (cam_mod->state != APTINA_CAMERA_MODULE_STREAMING)
goto end;
cam_mod->custom.s_vts(cam_mod, vts);
}
end:
cam_mod->frm_intrvl_valid = true;
cam_mod->frm_intrvl = norm_interval;
if (cam_mod->frm_fmt_valid) {
aptina_camera_module_set_active_config(cam_mod,
aptina_camera_module_find_config(cam_mod,
&cam_mod->frm_fmt, interval));
}
cam_mod->auto_adjust_fps = false;
return 0;
err:
pltfrm_camera_module_pr_err(&cam_mod->sd,
@ -574,12 +620,34 @@ int aptina_camera_module_s_frame_interval(
return ret;
}
int aptina_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval)
{
struct aptina_camera_module *cam_mod = to_aptina_camera_module(sd);
if (cam_mod->active_config) {
if (cam_mod->state == APTINA_CAMERA_MODULE_STREAMING) {
if (cam_mod->frm_intrvl_valid) {
*interval = cam_mod->frm_intrvl;
return 0;
} else {
*interval = cam_mod->active_config->frm_intrvl;
return 0;
}
}
}
return -EFAULT;
}
/* ======================================================================== */
int aptina_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
{
int ret = 0;
struct aptina_camera_module *cam_mod = to_aptina_camera_module(sd);
unsigned int vts;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "%d\n", enable);
@ -600,9 +668,6 @@ int aptina_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
goto err;
}
if (!IS_ERR_OR_NULL(cam_mod->custom.set_flip))
cam_mod->custom.set_flip(cam_mod);
if (cam_mod->update_config) {
ret = aptina_camera_module_write_config(cam_mod);
if (IS_ERR_VALUE(ret))
@ -612,6 +677,29 @@ int aptina_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
ret = cam_mod->custom.start_streaming(cam_mod);
if (IS_ERR_VALUE(ret))
goto err;
if (cam_mod->frm_intrvl_valid) {
if ((cam_mod->frm_intrvl.interval.numerator !=
cam_mod->active_config->frm_intrvl.interval.numerator) ||
(cam_mod->frm_intrvl.interval.denominator !=
cam_mod->active_config->frm_intrvl.interval.denominator)) {
if (cam_mod->frm_intrvl.interval.denominator >
cam_mod->active_config->frm_intrvl.interval.denominator) {
pltfrm_camera_module_pr_warn(&cam_mod->sd,
"sensor is not support stream: %dx%d@(%d/%d)fps!\n",
cam_mod->active_config->frm_fmt.width,
cam_mod->active_config->frm_fmt.height,
cam_mod->frm_intrvl.interval.denominator,
cam_mod->frm_intrvl.interval.numerator);
goto end;
}
vts = cam_mod->active_config->timings.frame_length_lines;
vts *= cam_mod->active_config->frm_intrvl.interval.denominator;
vts /= cam_mod->frm_intrvl.interval.denominator;
cam_mod->custom.s_vts(cam_mod, vts);
}
}
cam_mod->update_config = false;
cam_mod->ctrl_updt = 0;
mdelay(cam_mod->custom.power_up_delays_ms[2]);
@ -644,6 +732,7 @@ int aptina_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
msleep(wait_ms + 1);
}
end:
cam_mod->state_before_suspend = cam_mod->state;
return 0;
@ -674,43 +763,43 @@ int aptina_camera_module_s_power(struct v4l2_subdev *sd, int on)
}
if (cam_mod->state == APTINA_CAMERA_MODULE_HW_STANDBY) {
ret = pltfrm_camera_module_set_pin_state(&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_PWR,
PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE);
PLTFRM_CAMERA_MODULE_PIN_PWR,
PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE);
msleep(20);
ret = pltfrm_camera_module_set_pin_state(
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_PD,
PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE);
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_PD,
PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE);
msleep(20);
ret = pltfrm_camera_module_set_pin_state(
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_RESET,
PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE);
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_RESET,
PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE);
msleep(20);
ret = pltfrm_camera_module_set_pin_state(
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_RESET,
PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE);
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_RESET,
PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE);
msleep(20);
ret = pltfrm_camera_module_set_pin_state(
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_RESET,
PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE);
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_RESET,
PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE);
msleep(20);
ret = pltfrm_camera_module_set_pin_state(
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_PD,
PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE);
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_PD,
PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE);
msleep(20);
ret = pltfrm_camera_module_set_pin_state(
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_PD,
PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE);
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_PD,
PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE);
msleep(20);
if (!IS_ERR_VALUE(ret)) {
@ -742,19 +831,19 @@ int aptina_camera_module_s_power(struct v4l2_subdev *sd, int on)
}
if (cam_mod->state == APTINA_CAMERA_MODULE_SW_STANDBY) {
ret = pltfrm_camera_module_set_pin_state(
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_PD,
PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE);
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_PD,
PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE);
ret = pltfrm_camera_module_set_pin_state(
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_RESET,
PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE);
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_RESET,
PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE);
ret = pltfrm_camera_module_set_pin_state(
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_PWR,
PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE);
&cam_mod->sd,
PLTFRM_CAMERA_MODULE_PIN_PWR,
PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE);
if (!IS_ERR_VALUE(ret))
cam_mod->state =
@ -805,6 +894,22 @@ int aptina_camera_module_g_ctrl(struct v4l2_subdev *sd,
return 0;
}
if (ctrl->id == V4L2_CID_HFLIP) {
ctrl->value = cam_mod->hflip;
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"V4L2_CID_HFLIP %d\n",
ctrl->value);
return 0;
}
if (ctrl->id == V4L2_CID_VFLIP) {
ctrl->value = cam_mod->vflip;
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"V4L2_CID_VFLIP %d\n",
ctrl->value);
return 0;
}
if (IS_ERR_OR_NULL(cam_mod->active_config)) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"no active configuration\n");
@ -897,10 +1002,6 @@ int aptina_camera_module_g_ctrl(struct v4l2_subdev *sd,
"V4L2_CID_FOCUS_ABSOLUTE %d\n",
ctrl->value);
break;
case V4L2_CID_HFLIP:
case V4L2_CID_VFLIP:
/* TBD */
/* fallthrough */
default:
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"failed, unknown ctrl %d\n", ctrl->id);
@ -1038,12 +1139,14 @@ int aptina_camera_module_s_ext_ctrls(
cam_mod->hflip = true;
else
cam_mod->hflip = false;
cam_mod->flip_flg = true;
break;
case V4L2_CID_VFLIP:
if (ctrl->value)
cam_mod->vflip = true;
else
cam_mod->vflip = false;
cam_mod->flip_flg = true;
break;
default:
pltfrm_camera_module_pr_warn(&cam_mod->sd,
@ -1124,7 +1227,8 @@ long aptina_camera_module_ioctl(struct v4l2_subdev *sd,
void *arg)
{
struct aptina_camera_module *cam_mod = to_aptina_camera_module(sd);
int ret;
int ret, i;
unsigned int flag, val;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "\n");
@ -1176,16 +1280,60 @@ long aptina_camera_module_ioctl(struct v4l2_subdev *sd,
timings->fine_integration_time_min =
aptina_timings.fine_integration_time_min;
if (cam_mod->custom.g_exposure_valid_frame)
timings->exposure_valid_frame =
cam_mod->custom.g_exposure_valid_frame(cam_mod);
timings->exposure_valid_frame[0] =
cam_mod->custom.exposure_valid_frame[0];
timings->exposure_valid_frame[1] =
cam_mod->custom.exposure_valid_frame[1];
/*
*timings->exp_time = cam_mod->exp_config.exp_time;
*timings->gain = cam_mod->exp_config.gain;
*/
if (cam_mod->active_config) {
timings->max_exp_gain_h = cam_mod->active_config->max_exp_gain_h;
timings->max_exp_gain_l = cam_mod->active_config->max_exp_gain_l;
} else {
timings->max_exp_gain_h = cam_mod->custom.configs[0].max_exp_gain_h;
timings->max_exp_gain_l = cam_mod->custom.configs[0].max_exp_gain_l;
}
return ret;
} else if (cmd == RK_VIDIOC_SENSOR_CONFIGINFO) {
struct sensor_config_info_s *sensor_config = (struct sensor_config_info_s *)arg;
sensor_config->config_num = cam_mod->custom.num_configs;
for (i = 0; i < cam_mod->custom.num_configs; i++) {
if (i >= SENSOR_CONFIG_NUM)
break;
sensor_config->sensor_fmt[i] =
pltfrm_camera_module_pix_fmt2csi2_dt(cam_mod->custom.configs[i].frm_fmt.code);
sensor_config->reso[i].width = cam_mod->custom.configs[i].frm_fmt.width;
sensor_config->reso[i].height = cam_mod->custom.configs[i].frm_fmt.height;
}
return 0;
} else if (cmd == RK_VIDIOC_SENSOR_REG_ACCESS) {
struct sensor_reg_rw_s *sensor_rw = (struct sensor_reg_rw_s *)arg;
if (sensor_rw->reg_access_mode == SENSOR_READ_MODE) {
for (i = 0; i < cam_mod->custom.configs[0].reg_table_num_entries; i++) {
flag = cam_mod->custom.configs[0].reg_table[i].flag;
if (flag != PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT)
break;
}
if (flag == PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"Can not get sensor reg type.\n");
return -EINVAL;
}
sensor_rw->reg_addr_len = PLTFRM_CAMERA_MODULE_REG_LEN(flag);
sensor_rw->reg_data_len = PLTFRM_CAMERA_MODULE_DATA_LEN(flag);
pltfrm_camera_module_read_reg_ex(&cam_mod->sd, 1, flag, sensor_rw->addr, &val);
sensor_rw->data = val;
} else {
flag = (sensor_rw->reg_addr_len << PLTFRM_CAMERA_MODULE_REG_LEN_BIT);
flag |= (sensor_rw->reg_data_len << PLTFRM_CAMERA_MODULE_DATA_LEN_BIT);
pltfrm_camera_module_write_reg_ex(&cam_mod->sd, flag, sensor_rw->addr, sensor_rw->data);
}
return 0;
} else if (cmd == PLTFRM_CIFCAM_G_ITF_CFG) {
struct pltfrm_cam_itf *itf_cfg = (struct pltfrm_cam_itf *)arg;
struct aptina_camera_module_config *config;
@ -1205,9 +1353,14 @@ long aptina_camera_module_ioctl(struct v4l2_subdev *sd,
pltfrm_camera_module_ioctl(sd, PLTFRM_CIFCAM_G_ITF_CFG, arg);
return 0;
} else if (cmd == PLTFRM_CIFCAM_ATTACH) {
aptina_camera_module_init(cam_mod, &cam_mod->custom);
pltfrm_camera_module_ioctl(sd, cmd, arg);
return aptina_camera_module_attach(cam_mod);
ret = aptina_camera_module_init(cam_mod, &cam_mod->custom);
if (!IS_ERR_VALUE(ret)) {
pltfrm_camera_module_ioctl(sd, cmd, arg);
return aptina_camera_module_attach(cam_mod);
} else {
aptina_camera_module_release(cam_mod);
return ret;
}
}
ret = pltfrm_camera_module_ioctl(sd, cmd, arg);
@ -1276,7 +1429,22 @@ static int aptina_camera_module_s_flip(struct aptina_camera_module *cam_mod)
int aptina_camera_module_get_flip_mirror(
struct aptina_camera_module *cam_mod)
{
return pltfrm_camera_module_get_flip_mirror(&cam_mod->sd);
int mode = 0;
if (!cam_mod->flip_flg)
return -1;
if (cam_mod->hflip)
mode |= APTINA_MIRROR_BIT_MASK;
else
mode &= ~APTINA_MIRROR_BIT_MASK;
if (cam_mod->vflip)
mode |= APTINA_FLIP_BIT_MASK;
else
mode &= ~APTINA_FLIP_BIT_MASK;
return mode;
}
int aptina_camera_module_enum_frameintervals(
@ -1373,9 +1541,13 @@ int aptina_camera_module_init(struct aptina_camera_module *cam_mod,
struct aptina_camera_module_custom_config *custom)
{
int ret = 0;
int mode = 0;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "\n");
cam_mod->hflip = false;
cam_mod->vflip = false;
cam_mod->flip_flg = false;
aptina_camera_module_reset(cam_mod);
if (IS_ERR_OR_NULL(custom->start_streaming) ||
@ -1415,6 +1587,12 @@ int aptina_camera_module_init(struct aptina_camera_module *cam_mod,
*}
*/
mode = pltfrm_camera_module_get_flip_mirror(&cam_mod->sd);
if (mode != -1) {
cam_mod->hflip = mode & APTINA_MIRROR_BIT_MASK ? true : false;
cam_mod->vflip = mode & APTINA_FLIP_BIT_MASK ? true : false;
cam_mod->flip_flg = true;
}
return 0;
err:
pltfrm_camera_module_pr_err(&cam_mod->sd,

View File

@ -31,8 +31,8 @@
PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT
#define aptina_camera_module_csi_config
#define aptina_camera_module_reg pltfrm_camera_module_reg
#define APTINA_FLIP_BIT_MASK 0x2
#define APTINA_MIRROR_BIT_MASK 0x1
#define APTINA_FLIP_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_FLIP_BIT)
#define APTINA_MIRROR_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define APTINA_CAMERA_MODULE_CTRL_UPDT_GAIN 0x01
#define APTINA_CAMERA_MODULE_CTRL_UPDT_EXP_TIME 0x02
@ -88,6 +88,8 @@ struct aptina_camera_module_config {
struct aptina_camera_module_timings timings;
bool soft_reset;
bool ignore_measurement_check;
u8 max_exp_gain_h;
u8 max_exp_gain_l;
struct pltfrm_cam_itf itf_cfg;
};
@ -153,14 +155,19 @@ struct aptina_camera_module_custom_config {
int (*g_ctrl)(struct aptina_camera_module *cam_mod, u32 ctrl_id);
int (*g_timings)(struct aptina_camera_module *cam_mod,
struct aptina_camera_module_timings *timings);
int (*s_vts)(struct aptina_camera_module *cam_mod,
u32 vts);
int (*s_ext_ctrls)(struct aptina_camera_module *cam_mod,
struct aptina_camera_module_ext_ctrls *ctrls);
int (*set_flip)(struct aptina_camera_module *cam_mod);
int (*set_flip)(struct aptina_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len);
struct aptina_camera_module_config *configs;
int (*init_common)(struct aptina_camera_module *cam_mod);
int (*g_exposure_valid_frame)(struct aptina_camera_module *cam_mod);
u32 num_configs;
u32 power_up_delays_ms[3];
unsigned short exposure_valid_frame[2];
void *priv;
struct aptina_camera_module_timings timings;
};
@ -178,6 +185,7 @@ struct aptina_camera_module {
enum aptina_camera_module_state state_before_suspend;
struct aptina_camera_module_config *active_config;
u32 ctrl_updt;
u32 vts_cur;
u32 vts_min;
bool auto_adjust_fps;
bool update_config;
@ -185,9 +193,11 @@ struct aptina_camera_module {
bool frm_intrvl_valid;
bool hflip;
bool vflip;
bool flip_flg;
u32 rotation;
void *pltfm_data;
bool inited;
struct mutex lock;
};
#define aptina_camera_module_pr_info(cam_mod, fmt, arg...) \
@ -238,6 +248,10 @@ int aptina_camera_module_s_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int aptina_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int aptina_camera_module_s_stream(
struct v4l2_subdev *sd,
int enable);

View File

@ -124,6 +124,8 @@ static struct imx_camera_module_config imx323_configs[] = {
sizeof(imx323_init_tab_1920_1080_30fps) /
sizeof(imx323_init_tab_1920_1080_30fps[0]),
.v_blanking_time_us = 5000,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_DVP_CFG(
PLTFRM_CAM_ITF_BT601_12,
PLTFRM_CAM_SIGNAL_HIGH_LEVEL,
@ -170,10 +172,9 @@ static int imx323_auto_adjust_fps(struct imx_camera_module *cam_mod,
int ret;
u32 vts;
if ((cam_mod->exp_config.exp_time + IMX323_COARSE_INTG_TIME_MAX_MARGIN)
if ((exp_time + IMX323_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = cam_mod->exp_config.exp_time +
IMX323_COARSE_INTG_TIME_MAX_MARGIN;
vts = exp_time + IMX323_COARSE_INTG_TIME_MAX_MARGIN;
else
vts = cam_mod->vts_min;
ret = imx_camera_module_write_reg(cam_mod,
@ -181,12 +182,14 @@ static int imx323_auto_adjust_fps(struct imx_camera_module *cam_mod,
ret |= imx_camera_module_write_reg(cam_mod,
IMX323_TIMING_VTS_HIGH_REG, (vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret))
if (IS_ERR_VALUE(ret)) {
imx_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
else
imx_camera_module_pr_debug(cam_mod,
} else {
imx_camera_module_pr_info(cam_mod,
"updated vts = %d,vts_min=%d\n", vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
@ -240,6 +243,7 @@ static int imx323_write_aec(struct imx_camera_module *cam_mod)
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
mutex_lock(&cam_mod->lock);
if (!IS_ERR_VALUE(ret) && cam_mod->auto_adjust_fps)
ret = imx323_auto_adjust_fps(cam_mod,
cam_mod->exp_config.exp_time);
@ -258,6 +262,7 @@ static int imx323_write_aec(struct imx_camera_module *cam_mod)
if (!cam_mod->auto_adjust_fps)
ret |= imx323_set_vts(cam_mod, cam_mod->exp_config.vts_value);
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
@ -373,6 +378,8 @@ static int imx323_g_timings(struct imx_camera_module *cam_mod,
* vts
* timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
imx_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
@ -381,9 +388,12 @@ static int imx323_g_timings(struct imx_camera_module *cam_mod,
/*--------------------------------------------------------------------------*/
static int imx323_set_flip(struct imx_camera_module *cam_mod)
static int imx323_set_flip(
struct imx_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len)
{
int mode = 0;
int i, mode = 0;
u16 orientation = 0;
mode = imx_camera_module_get_flip_mirror(cam_mod);
@ -394,15 +404,14 @@ static int imx323_set_flip(struct imx_camera_module *cam_mod)
}
if (!IS_ERR_OR_NULL(cam_mod->active_config)) {
if (mode == IMX_FLIP_BIT_MASK)
orientation = IMX323_ORIENTATION_V;
else if (mode == IMX_MIRROR_BIT_MASK)
orientation = IMX323_ORIENTATION_H;
else if (mode == (IMX_MIRROR_BIT_MASK | IMX_FLIP_BIT_MASK))
orientation = IMX323_ORIENTATION_H |
IMX323_ORIENTATION_V;
else
orientation = 0;
if (PLTFRM_CAMERA_MODULE_IS_MIRROR(mode))
orientation |= 0x01;
if (PLTFRM_CAMERA_MODULE_IS_FLIP(mode))
orientation |= 0x02;
for (i = 0; i < len; i++) {
if (reglist[i].reg == IMX323_ORIENTATION_REG)
reglist[i].val = orientation;
}
}
return 0;
@ -443,14 +452,8 @@ static int imx323_s_ext_ctrls(struct imx_camera_module *cam_mod,
{
int ret = 0;
/* Handles only exposure and gain together special case. */
if (ctrls->count == 1)
ret = imx323_s_ctrl(cam_mod, ctrls->ctrls[0].id);
else if ((ctrls->count >= 3) &&
((ctrls->ctrls[0].id == V4L2_CID_GAIN &&
ctrls->ctrls[1].id == V4L2_CID_EXPOSURE) ||
(ctrls->ctrls[1].id == V4L2_CID_GAIN &&
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE)))
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = imx323_write_aec(cam_mod);
else
ret = -EINVAL;
@ -474,7 +477,10 @@ static int imx323_start_streaming(struct imx_camera_module *cam_mod)
if (IS_ERR_VALUE(ret))
goto err;
if (IS_ERR_VALUE(imx_camera_module_write_reg(cam_mod, 0x0100, 1)))
mutex_lock(&cam_mod->lock);
ret = imx_camera_module_write_reg(cam_mod, 0x0100, 1);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
@ -494,7 +500,9 @@ static int imx323_stop_streaming(struct imx_camera_module *cam_mod)
imx_camera_module_pr_debug(cam_mod, "\n");
mutex_lock(&cam_mod->lock);
ret = imx_camera_module_write_reg(cam_mod, 0x0100, 0);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
@ -553,6 +561,7 @@ static struct v4l2_subdev_core_ops imx323_camera_module_core_ops = {
static struct v4l2_subdev_video_ops imx323_camera_module_video_ops = {
.s_frame_interval = imx_camera_module_s_frame_interval,
.g_frame_interval = imx_camera_module_g_frame_interval,
.s_stream = imx_camera_module_s_stream
};
@ -577,9 +586,16 @@ static struct imx_camera_module_custom_config imx323_custom_config = {
.g_timings = imx323_g_timings,
.check_camera_id = imx323_check_camera_id,
.set_flip = imx323_set_flip,
.s_vts = imx323_auto_adjust_fps,
.configs = imx323_configs,
.num_configs = ARRAY_SIZE(imx323_configs),
.power_up_delays_ms = {5, 20, 0}
.power_up_delays_ms = {5, 20, 0},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int imx323_probe(
@ -590,8 +606,10 @@ static int imx323_probe(
imx323_filltimings(&imx323_custom_config);
v4l2_i2c_subdev_init(&imx323.sd, client, &imx323_camera_module_ops);
imx323.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
imx323.custom = imx323_custom_config;
mutex_init(&imx323.lock);
dev_info(&client->dev, "probing successful\n");
return 0;
}
@ -605,6 +623,7 @@ static int imx323_remove(struct i2c_client *client)
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
imx_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");

View File

@ -45,8 +45,6 @@ static void imx_camera_module_reset(
cam_mod->exp_config.auto_exp = false;
cam_mod->exp_config.auto_gain = false;
cam_mod->wb_config.auto_wb = false;
cam_mod->hflip = false;
cam_mod->vflip = false;
cam_mod->auto_adjust_fps = true;
cam_mod->rotation = 0;
cam_mod->ctrl_updt = 0;
@ -194,7 +192,8 @@ static int imx_camera_module_write_config(
}
if (!IS_ERR_OR_NULL(cam_mod->custom.set_flip))
cam_mod->custom.set_flip(cam_mod);
cam_mod->custom.set_flip(cam_mod,
reg_table, reg_table_num_entries);
ret = pltfrm_camera_module_write_reglist(&cam_mod->sd,
reg_table, reg_table_num_entries);
@ -284,6 +283,10 @@ int imx_camera_module_s_fmt(struct v4l2_subdev *sd,
imx_camera_module_set_active_config(cam_mod,
imx_camera_module_find_config(cam_mod,
fmt, &cam_mod->frm_intrvl));
} else {
imx_camera_module_set_active_config(cam_mod,
imx_camera_module_find_config(cam_mod,
fmt, NULL));
}
return 0;
err:
@ -324,6 +327,8 @@ int imx_camera_module_s_frame_interval(
struct imx_camera_module *cam_mod = to_imx_camera_module(sd);
unsigned long gcdiv;
struct v4l2_subdev_frame_interval norm_interval;
struct imx_camera_module_config *config;
unsigned int vts;
int ret = 0;
if ((interval->interval.denominator == 0) ||
@ -350,22 +355,62 @@ int imx_camera_module_s_frame_interval(
norm_interval.interval.denominator =
interval->interval.denominator / gcdiv;
if (IS_ERR_OR_NULL(imx_camera_module_find_config(cam_mod,
NULL, &norm_interval))) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"frame interval %d/%d not supported\n",
interval->interval.numerator,
interval->interval.denominator);
ret = -EINVAL;
goto err;
if (!cam_mod->frm_fmt_valid)
goto end;
config = imx_camera_module_find_config(
cam_mod,
&cam_mod->active_config->frm_fmt,
&norm_interval);
if (!IS_ERR_OR_NULL(config) && (config != cam_mod->active_config)) {
imx_camera_module_set_active_config(cam_mod, config);
if (cam_mod->state == IMX_CAMERA_MODULE_STREAMING) {
cam_mod->custom.stop_streaming(cam_mod);
imx_camera_module_write_config(cam_mod);
cam_mod->custom.start_streaming(cam_mod);
}
} else {
if (IS_ERR_OR_NULL(cam_mod->active_config)) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"no active sensor configuration");
ret = -EFAULT;
goto err;
}
if (cam_mod->active_config->frm_intrvl.interval.denominator <
norm_interval.interval.denominator) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"%dx%d@%dfps isn't support!",
cam_mod->active_config->frm_fmt.width,
cam_mod->active_config->frm_fmt.height,
norm_interval.interval.denominator);
ret = -EFAULT;
goto err;
}
if (!cam_mod->custom.s_vts) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"custom.s_vts isn't support!");
ret = -EFAULT;
goto err;
}
vts = cam_mod->active_config->timings.frame_length_lines;
vts *= cam_mod->active_config->frm_intrvl.interval.denominator;
vts /= norm_interval.interval.denominator;
cam_mod->vts_cur = vts;
if (cam_mod->state != IMX_CAMERA_MODULE_STREAMING)
goto end;
cam_mod->custom.s_vts(cam_mod, vts);
}
end:
cam_mod->frm_intrvl_valid = true;
cam_mod->frm_intrvl = norm_interval;
if (cam_mod->frm_fmt_valid) {
imx_camera_module_set_active_config(cam_mod,
imx_camera_module_find_config(cam_mod,
&cam_mod->frm_fmt, interval));
}
cam_mod->auto_adjust_fps = false;
return 0;
err:
pltfrm_camera_module_pr_err(&cam_mod->sd,
@ -373,12 +418,34 @@ int imx_camera_module_s_frame_interval(
return ret;
}
int imx_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval)
{
struct imx_camera_module *cam_mod = to_imx_camera_module(sd);
if (cam_mod->active_config) {
if (cam_mod->state == IMX_CAMERA_MODULE_STREAMING) {
if (cam_mod->frm_intrvl_valid) {
*interval = cam_mod->frm_intrvl;
return 0;
} else {
*interval = cam_mod->active_config->frm_intrvl;
return 0;
}
}
}
return -EFAULT;
}
/* ======================================================================== */
int imx_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
{
int ret = 0;
struct imx_camera_module *cam_mod = to_imx_camera_module(sd);
unsigned int vts;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "%d\n", enable);
@ -407,12 +474,36 @@ int imx_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
ret = cam_mod->custom.start_streaming(cam_mod);
if (IS_ERR_VALUE(ret))
goto err;
if (cam_mod->frm_intrvl_valid) {
if ((cam_mod->frm_intrvl.interval.numerator !=
cam_mod->active_config->frm_intrvl.interval.numerator) ||
(cam_mod->frm_intrvl.interval.denominator !=
cam_mod->active_config->frm_intrvl.interval.denominator)) {
if (cam_mod->frm_intrvl.interval.denominator >
cam_mod->active_config->frm_intrvl.interval.denominator) {
pltfrm_camera_module_pr_warn(&cam_mod->sd,
"sensor is not support stream: %dx%d@(%d/%d)fps!\n",
cam_mod->active_config->frm_fmt.width,
cam_mod->active_config->frm_fmt.height,
cam_mod->frm_intrvl.interval.denominator,
cam_mod->frm_intrvl.interval.numerator);
goto end;
}
vts = cam_mod->active_config->timings.frame_length_lines;
vts *= cam_mod->active_config->frm_intrvl.interval.denominator;
vts /= cam_mod->frm_intrvl.interval.denominator;
cam_mod->custom.s_vts(cam_mod, vts);
}
}
if (!cam_mod->inited && cam_mod->update_config)
cam_mod->inited = true;
cam_mod->update_config = false;
cam_mod->ctrl_updt = 0;
mdelay(cam_mod->custom.power_up_delays_ms[2]);
cam_mod->state = IMX_CAMERA_MODULE_STREAMING;
} else {
int pclk;
int wait_ms;
@ -451,6 +542,7 @@ int imx_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
msleep(wait_ms + 1);
}
end:
cam_mod->state_before_suspend = cam_mod->state;
return 0;
@ -558,6 +650,22 @@ int imx_camera_module_g_ctrl(struct v4l2_subdev *sd,
return 0;
}
if (ctrl->id == V4L2_CID_HFLIP) {
ctrl->value = cam_mod->hflip;
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"V4L2_CID_HFLIP %d\n",
ctrl->value);
return 0;
}
if (ctrl->id == V4L2_CID_VFLIP) {
ctrl->value = cam_mod->vflip;
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"V4L2_CID_VFLIP %d\n",
ctrl->value);
return 0;
}
if (IS_ERR_OR_NULL(cam_mod->active_config)) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"no active configuration\n");
@ -644,10 +752,6 @@ int imx_camera_module_g_ctrl(struct v4l2_subdev *sd,
"V4L2_CID_FOCUS_ABSOLUTE %d\n",
ctrl->value);
break;
case V4L2_CID_HFLIP:
case V4L2_CID_VFLIP:
/* TBD */
/* fallthrough */
default:
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"failed, unknown ctrl %d\n", ctrl->id);
@ -787,12 +891,14 @@ int imx_camera_module_s_ext_ctrls(
cam_mod->hflip = true;
else
cam_mod->hflip = false;
cam_mod->flip_flg = true;
break;
case V4L2_CID_VFLIP:
if (ctrl->value)
cam_mod->vflip = true;
else
cam_mod->vflip = false;
cam_mod->flip_flg = true;
break;
default:
pltfrm_camera_module_pr_warn(&cam_mod->sd,
@ -871,7 +977,8 @@ long imx_camera_module_ioctl(struct v4l2_subdev *sd,
void *arg)
{
struct imx_camera_module *cam_mod = to_imx_camera_module(sd);
int ret;
int ret, i;
unsigned int flag, val;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "cmd: 0x%x\n", cmd);
@ -916,9 +1023,10 @@ long imx_camera_module_ioctl(struct v4l2_subdev *sd,
timings->fine_integration_time_min =
imx_timings.fine_integration_time_min;
if (cam_mod->custom.g_exposure_valid_frame)
timings->exposure_valid_frame[0] =
cam_mod->custom.g_exposure_valid_frame(cam_mod);
timings->exposure_valid_frame[0] =
cam_mod->custom.exposure_valid_frame[0];
timings->exposure_valid_frame[1] =
cam_mod->custom.exposure_valid_frame[1];
timings->exp_time = cam_mod->exp_config.exp_time;
timings->gain = cam_mod->exp_config.gain;
@ -931,7 +1039,52 @@ long imx_camera_module_ioctl(struct v4l2_subdev *sd,
timings->gain = cam_mod->exp_config.gain;
else
timings->gain = imx_timings.gain;
if (cam_mod->active_config) {
timings->max_exp_gain_h = cam_mod->active_config->max_exp_gain_h;
timings->max_exp_gain_l = cam_mod->active_config->max_exp_gain_l;
} else {
timings->max_exp_gain_h = cam_mod->custom.configs[0].max_exp_gain_h;
timings->max_exp_gain_l = cam_mod->custom.configs[0].max_exp_gain_l;
}
return ret;
} else if (cmd == RK_VIDIOC_SENSOR_CONFIGINFO) {
struct sensor_config_info_s *sensor_config = (struct sensor_config_info_s *)arg;
sensor_config->config_num = cam_mod->custom.num_configs;
for (i = 0; i < cam_mod->custom.num_configs; i++) {
if (i >= SENSOR_CONFIG_NUM)
break;
sensor_config->sensor_fmt[i] =
pltfrm_camera_module_pix_fmt2csi2_dt(cam_mod->custom.configs[i].frm_fmt.code);
sensor_config->reso[i].width = cam_mod->custom.configs[i].frm_fmt.width;
sensor_config->reso[i].height = cam_mod->custom.configs[i].frm_fmt.height;
}
return 0;
} else if (cmd == RK_VIDIOC_SENSOR_REG_ACCESS) {
struct sensor_reg_rw_s *sensor_rw = (struct sensor_reg_rw_s *)arg;
if (sensor_rw->reg_access_mode == SENSOR_READ_MODE) {
for (i = 0; i < cam_mod->custom.configs[0].reg_table_num_entries; i++) {
flag = cam_mod->custom.configs[0].reg_table[i].flag;
if (flag != PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT)
break;
}
if (flag == PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"Can not get sensor reg type.\n");
return -EINVAL;
}
sensor_rw->reg_addr_len = PLTFRM_CAMERA_MODULE_REG_LEN(flag);
sensor_rw->reg_data_len = PLTFRM_CAMERA_MODULE_DATA_LEN(flag);
pltfrm_camera_module_read_reg_ex(&cam_mod->sd, 1, flag, sensor_rw->addr, &val);
sensor_rw->data = val;
} else {
flag = (sensor_rw->reg_addr_len << PLTFRM_CAMERA_MODULE_REG_LEN_BIT);
flag |= (sensor_rw->reg_data_len << PLTFRM_CAMERA_MODULE_DATA_LEN_BIT);
pltfrm_camera_module_write_reg_ex(&cam_mod->sd, flag, sensor_rw->addr, sensor_rw->data);
}
return 0;
} else if (cmd == PLTFRM_CIFCAM_G_ITF_CFG) {
struct pltfrm_cam_itf *itf_cfg = (struct pltfrm_cam_itf *)arg;
struct imx_camera_module_config *config;
@ -952,9 +1105,14 @@ long imx_camera_module_ioctl(struct v4l2_subdev *sd,
pltfrm_camera_module_ioctl(sd, PLTFRM_CIFCAM_G_ITF_CFG, arg);
return 0;
} else if (cmd == PLTFRM_CIFCAM_ATTACH) {
imx_camera_module_init(cam_mod, &cam_mod->custom);
pltfrm_camera_module_ioctl(sd, cmd, arg);
return imx_camera_module_attach(cam_mod);
ret = imx_camera_module_init(cam_mod, &cam_mod->custom);
if (!IS_ERR_VALUE(ret)) {
pltfrm_camera_module_ioctl(sd, cmd, arg);
return imx_camera_module_attach(cam_mod);
} else {
imx_camera_module_release(cam_mod);
return ret;
}
}
ret = pltfrm_camera_module_ioctl(sd, cmd, arg);
@ -966,7 +1124,22 @@ long imx_camera_module_ioctl(struct v4l2_subdev *sd,
int imx_camera_module_get_flip_mirror(
struct imx_camera_module *cam_mod)
{
return pltfrm_camera_module_get_flip_mirror(&cam_mod->sd);
int mode = 0;
if (!cam_mod->flip_flg)
return -1;
if (cam_mod->hflip)
mode |= IMX_MIRROR_BIT_MASK;
else
mode &= ~IMX_MIRROR_BIT_MASK;
if (cam_mod->vflip)
mode |= IMX_FLIP_BIT_MASK;
else
mode &= ~IMX_FLIP_BIT_MASK;
return mode;
}
/* ======================================================================== */
@ -1065,9 +1238,13 @@ int imx_camera_module_init(struct imx_camera_module *cam_mod,
struct imx_camera_module_custom_config *custom)
{
int ret = 0;
int mode = 0;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "\n");
cam_mod->hflip = false;
cam_mod->vflip = false;
cam_mod->flip_flg = false;
imx_camera_module_reset(cam_mod);
if (IS_ERR_OR_NULL(custom->start_streaming) ||
@ -1095,6 +1272,12 @@ int imx_camera_module_init(struct imx_camera_module *cam_mod,
goto err;
}
mode = pltfrm_camera_module_get_flip_mirror(&cam_mod->sd);
if (mode != -1) {
cam_mod->hflip = mode & IMX_MIRROR_BIT_MASK ? true : false;
cam_mod->vflip = mode & IMX_FLIP_BIT_MASK ? true : false;
cam_mod->flip_flg = true;
}
return 0;
err:
pltfrm_camera_module_pr_err(&cam_mod->sd,

View File

@ -30,8 +30,8 @@
#define imx_camera_module_csi_config
#define imx_camera_module_reg pltfrm_camera_module_reg
#define IMX_FLIP_BIT_MASK 0x2
#define IMX_MIRROR_BIT_MASK 0x1
#define IMX_FLIP_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_FLIP_BIT)
#define IMX_MIRROR_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define IMX_CAMERA_MODULE_CTRL_UPDT_GAIN 0x01
#define IMX_CAMERA_MODULE_CTRL_UPDT_EXP_TIME 0x02
@ -88,6 +88,8 @@ struct imx_camera_module_config {
struct imx_camera_module_timings timings;
bool soft_reset;
bool ignore_measurement_check;
u8 max_exp_gain_h;
u8 max_exp_gain_l;
struct pltfrm_cam_itf itf_cfg;
};
@ -153,14 +155,18 @@ struct imx_camera_module_custom_config {
int (*g_ctrl)(struct imx_camera_module *cam_mod, u32 ctrl_id);
int (*g_timings)(struct imx_camera_module *cam_mod,
struct imx_camera_module_timings *timings);
int (*g_exposure_valid_frame)(struct imx_camera_module *cam_mod);
int (*s_vts)(struct imx_camera_module *cam_mod,
u32 vts);
int (*s_ext_ctrls)(struct imx_camera_module *cam_mod,
struct imx_camera_module_ext_ctrls *ctrls);
int (*set_flip)(struct imx_camera_module *cam_mod);
int (*set_flip)(struct imx_camera_module *cam_mod,
struct pltfrm_camera_module_reg reglist[],
int len);
int (*init_common)(struct imx_camera_module *cam_mod);
struct imx_camera_module_config *configs;
u32 num_configs;
u32 power_up_delays_ms[3];
unsigned short exposure_valid_frame[2];
void *priv;
};
@ -192,9 +198,11 @@ struct imx_camera_module {
bool frm_intrvl_valid;
bool hflip;
bool vflip;
bool flip_flg;
u32 rotation;
void *pltfm_data;
bool inited;
struct mutex lock;
};
#define imx_camera_module_pr_info(cam_mod, fmt, arg...) \
@ -239,6 +247,10 @@ int imx_camera_module_s_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int imx_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int imx_camera_module_s_stream(
struct v4l2_subdev *sd,
int enable);

View File

@ -570,6 +570,8 @@ static struct ov_camera_module_config NT99230_configs[] = {
sizeof(NT99230_init_tab_1920_1080_30fps_raw) /
sizeof(NT99230_init_tab_1920_1080_30fps_raw[0]),
.v_blanking_time_us = 4052,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
.ignore_measurement_check = 1,
PLTFRM_CAM_ITF_MIPI_CFG(0, 2, 450, 24000000)
}
@ -650,6 +652,7 @@ static int NT99230_write_aec(struct ov_camera_module *cam_mod)
u32 a_gain = cam_mod->exp_config.gain;
u32 exp_time = cam_mod->exp_config.exp_time;
mutex_lock(&cam_mod->lock);
if (!IS_ERR_VALUE(ret) && cam_mod->auto_adjust_fps)
ret = NT99230_auto_adjust_fps(cam_mod, cam_mod->exp_config.exp_time);
@ -659,6 +662,7 @@ static int NT99230_write_aec(struct ov_camera_module *cam_mod)
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING)
ret = ov_camera_module_write_reg(cam_mod, NT99230_AEC_UPDATE_ADDRESS, NT99230_AEC_UPDATE_DATA);
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
@ -866,14 +870,8 @@ static int NT99230_s_ext_ctrls(struct ov_camera_module *cam_mod,
{
int ret = 0;
/* Handles only exposure and gain together special case. */
if (ctrls->count == 1)
ret = NT99230_s_ctrl(cam_mod, ctrls->ctrls[0].id);
else if (ctrls->count == 2 &&
((ctrls->ctrls[0].id == V4L2_CID_GAIN &&
ctrls->ctrls[1].id == V4L2_CID_EXPOSURE) ||
(ctrls->ctrls[1].id == V4L2_CID_GAIN &&
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE)))
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = NT99230_write_aec(cam_mod);
else
ret = -EINVAL;
@ -897,7 +895,9 @@ static int NT99230_start_streaming(struct ov_camera_module *cam_mod)
if (IS_ERR_VALUE(ret))
goto err;
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x3021, 0x02);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
@ -916,7 +916,9 @@ static int NT99230_stop_streaming(struct ov_camera_module *cam_mod)
ov_camera_module_pr_info(cam_mod, "\n");
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x3021, 0x00);;
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
@ -976,6 +978,7 @@ static struct v4l2_subdev_core_ops NT99230_camera_module_core_ops = {
static struct v4l2_subdev_video_ops NT99230_camera_module_video_ops = {
.s_frame_interval = ov_camera_module_s_frame_interval,
.g_frame_interval = ov_camera_module_g_frame_interval,
.s_stream = ov_camera_module_s_stream
};
@ -1003,7 +1006,13 @@ static struct ov_camera_module_custom_config NT99230_custom_config = {
.check_camera_id = NT99230_check_camera_id,
.configs = NT99230_configs,
.num_configs = sizeof(NT99230_configs) / sizeof(NT99230_configs[0]),
.power_up_delays_ms = {5, 30, 0}
.power_up_delays_ms = {5, 30, 0},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int NT99230_probe(
@ -1025,6 +1034,7 @@ static int NT99230_probe(
tmp_NT99230->custom = NT99230_custom_config;
num_cameras++;
mutex_init(&tmp_NT99230->lock);
dev_info(&client->dev, "probing successful\n");
return 0;
}
@ -1041,6 +1051,7 @@ static int NT99230_remove(
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
ov_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");

View File

@ -1308,6 +1308,8 @@ static struct ov_camera_module_config ov13850_configs[] = {
sizeof(ov13850_regs_2112_1568_30fps_twolane_r2a) /
sizeof(ov13850_regs_2112_1568_30fps_twolane_r2a[0]),
.v_blanking_time_us = 5000,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_MIPI_CFG(0, 2, 600, ov13850_EXT_CLK)
},
@ -1332,6 +1334,8 @@ static struct ov_camera_module_config ov13850_configs[] = {
sizeof(ov13850_regs_4224_3136_7fps_twolane_r2a) /
sizeof(ov13850_regs_4224_3136_7fps_twolane_r2a[0]),
.v_blanking_time_us = 5000,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_MIPI_CFG(0, 2, 600, ov13850_EXT_CLK)
}
};
@ -1358,6 +1362,8 @@ static struct ov_camera_module_config ov13850_onelane_configs[] = {
sizeof(ov13850_init_tab_2112_1568_15fps) /
sizeof(ov13850_init_tab_2112_1568_15fps[0]),
.v_blanking_time_us = 5000,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_MIPI_CFG(0, 1, 640, ov13850_EXT_CLK)
}
};
@ -1394,11 +1400,9 @@ static int ov13850_auto_adjust_fps(struct ov_camera_module *cam_mod,
int ret;
u32 vts;
if ((cam_mod->exp_config.exp_time +
ov13850_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = cam_mod->exp_config.exp_time +
ov13850_COARSE_INTG_TIME_MAX_MARGIN;
if ((exp_time + ov13850_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = exp_time + ov13850_COARSE_INTG_TIME_MAX_MARGIN;
else
vts = cam_mod->vts_min;
ret = ov_camera_module_write_reg(cam_mod,
@ -1407,13 +1411,15 @@ static int ov13850_auto_adjust_fps(struct ov_camera_module *cam_mod,
ov13850_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret))
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
else
ov_camera_module_pr_debug(cam_mod,
} else {
ov_camera_module_pr_info(cam_mod,
"updated vts = %d,vts_min=%d\n",
vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
@ -1468,6 +1474,7 @@ static int ov13850_write_aec(struct ov_camera_module *cam_mod)
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
mutex_lock(&cam_mod->lock);
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING)
ret = ov_camera_module_write_reg(cam_mod,
ov13850_AEC_GROUP_UPDATE_ADDRESS,
@ -1500,6 +1507,7 @@ static int ov13850_write_aec(struct ov_camera_module *cam_mod)
ov13850_AEC_GROUP_UPDATE_ADDRESS,
ov13850_AEC_GROUP_UPDATE_END_LAUNCH);
}
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
@ -1648,23 +1656,28 @@ static int ov13850_g_timings(struct ov_camera_module *cam_mod,
struct ov_camera_module_timings *timings)
{
int ret = 0;
unsigned int vts;
if (IS_ERR_OR_NULL(cam_mod->active_config))
goto err;
*timings = cam_mod->active_config->timings;
vts = (!cam_mod->vts_cur) ?
timings->frame_length_lines :
cam_mod->vts_cur;
if (cam_mod->frm_intrvl_valid)
timings->vt_pix_clk_freq_hz =
cam_mod->frm_intrvl.interval.denominator
* timings->frame_length_lines
* vts
* timings->line_length_pck;
else
timings->vt_pix_clk_freq_hz =
cam_mod->active_config->frm_intrvl.interval.denominator
* timings->frame_length_lines
* vts
* timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
@ -1771,13 +1784,8 @@ static int ov13850_s_ext_ctrls(struct ov_camera_module *cam_mod,
int ret = 0;
/* Handles only exposure and gain together special case. */
if (ctrls->count == 1)
ret = ov13850_s_ctrl(cam_mod, ctrls->ctrls[0].id);
else if ((ctrls->count >= 3) &&
((ctrls->ctrls[0].id == V4L2_CID_GAIN &&
ctrls->ctrls[1].id == V4L2_CID_EXPOSURE) ||
(ctrls->ctrls[1].id == V4L2_CID_GAIN &&
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE)))
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = ov13850_write_aec(cam_mod);
else
ret = -EINVAL;
@ -1801,7 +1809,10 @@ static int ov13850_start_streaming(struct ov_camera_module *cam_mod)
if (IS_ERR_VALUE(ret))
goto err;
if (IS_ERR_VALUE(ov_camera_module_write_reg(cam_mod, 0x0100, 1)))
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x0100, 1);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
@ -1821,7 +1832,9 @@ static int ov13850_stop_streaming(struct ov_camera_module *cam_mod)
ov_camera_module_pr_debug(cam_mod, "\n");
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x0100, 0);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
@ -1881,6 +1894,7 @@ static struct v4l2_subdev_core_ops ov13850_camera_module_core_ops = {
static struct v4l2_subdev_video_ops ov13850_camera_module_video_ops = {
.s_frame_interval = ov_camera_module_s_frame_interval,
.g_frame_interval = ov_camera_module_g_frame_interval,
.s_stream = ov_camera_module_s_stream
};
@ -1904,6 +1918,7 @@ static struct ov_camera_module_custom_config ov13850_custom_config = {
.g_ctrl = ov13850_g_ctrl,
.g_timings = ov13850_g_timings,
.check_camera_id = ov13850_check_camera_id,
.s_vts = ov13850_auto_adjust_fps,
.set_flip = ov13850_set_flip,
#ifdef OV13850_ONE_LANE
.configs = ov13850_onelane_configs,
@ -1913,7 +1928,13 @@ static struct ov_camera_module_custom_config ov13850_custom_config = {
.configs = ov13850_configs,
.num_configs = ARRAY_SIZE(ov13850_configs),
#endif
.power_up_delays_ms = {5, 20, 0}
.power_up_delays_ms = {5, 20, 0},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int ov13850_probe(struct i2c_client *client,
@ -1923,9 +1944,10 @@ static int ov13850_probe(struct i2c_client *client,
ov13850_filltimings(&ov13850_custom_config);
v4l2_i2c_subdev_init(&ov13850.sd, client, &ov13850_camera_module_ops);
ov13850.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov13850.custom = ov13850_custom_config;
mutex_init(&ov13850.lock);
dev_info(&client->dev, "probing successful\n");
return 0;
}
@ -1939,6 +1961,7 @@ static int ov13850_remove(struct i2c_client *client)
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
ov_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");

View File

@ -236,6 +236,8 @@ static struct ov_camera_module_config ov2710_configs[] = {
sizeof(ov2710_init_tab_1920_1080_30fps) /
sizeof(ov2710_init_tab_1920_1080_30fps[0]),
.v_blanking_time_us = 3078,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
.ignore_measurement_check = 1,
PLTFRM_CAM_ITF_MIPI_CFG(0, 1, 800, 24000000)
}
@ -325,18 +327,12 @@ static int OV2710_auto_adjust_fps(struct ov_camera_module *cam_mod,
int ret;
u32 vts;
if ((cam_mod->exp_config.exp_time + OV2710_COARSE_INTG_TIME_MAX_MARGIN)
if ((exp_time + OV2710_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = cam_mod->exp_config.exp_time +
OV2710_COARSE_INTG_TIME_MAX_MARGIN;
vts = exp_time + OV2710_COARSE_INTG_TIME_MAX_MARGIN;
else
vts = cam_mod->vts_min;
/*
* if (cam_mod->fps_ctrl > 0 && cam_mod->fps_ctrl < 100)
* vts = vts * 100 / cam_mod->fps_ctrl;
*/
if (vts > 0xfff)
vts = 0xfff;
else
@ -349,13 +345,15 @@ static int OV2710_auto_adjust_fps(struct ov_camera_module *cam_mod,
OV2710_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0x0F);
if (IS_ERR_VALUE(ret))
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
else
ov_camera_module_pr_debug(cam_mod,
} else {
ov_camera_module_pr_info(cam_mod,
"updated vts = 0x%x,vts_min=0x%x\n",
vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
@ -409,6 +407,7 @@ static int ov2710_write_aec(struct ov_camera_module *cam_mod)
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
mutex_lock(&cam_mod->lock);
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING)
ret = ov_camera_module_write_reg(cam_mod,
OV2710_AEC_GROUP_UPDATE_ADDRESS,
@ -441,6 +440,7 @@ static int ov2710_write_aec(struct ov_camera_module *cam_mod)
OV2710_AEC_GROUP_UPDATE_ADDRESS,
OV2710_AEC_GROUP_UPDATE_END_LAUNCH);
}
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
@ -657,6 +657,7 @@ static int ov2710_g_timings(struct ov_camera_module *cam_mod,
cam_mod->active_config->frm_intrvl.interval.denominator *
vts * timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
ov_camera_module_pr_err(cam_mod,
@ -709,14 +710,8 @@ static int ov2710_s_ext_ctrls(struct ov_camera_module *cam_mod,
{
int ret = 0;
/* Handles only exposure and gain together special case. */
if (ctrls->count == 1)
ret = ov2710_s_ctrl(cam_mod, ctrls->ctrls[0].id);
else if ((ctrls->count >= 3) &&
(ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE ||
ctrls->ctrls[1].id == V4L2_CID_GAIN ||
ctrls->ctrls[1].id == V4L2_CID_EXPOSURE))
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = ov2710_write_aec(cam_mod);
else
ret = -EINVAL;
@ -741,9 +736,12 @@ static int ov2710_start_streaming(struct ov_camera_module *cam_mod)
if (IS_ERR_VALUE(ret))
goto err;
ov_camera_module_pr_debug(cam_mod, "=====streaming on ===\n");
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x3008, 0x02);
ret |= ov_camera_module_write_reg(cam_mod, 0x4201, 0x00);
ret |= ov_camera_module_write_reg(cam_mod, 0x4202, 0x00);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
@ -762,9 +760,11 @@ static int ov2710_stop_streaming(struct ov_camera_module *cam_mod)
int ret = 0;
ov_camera_module_pr_debug(cam_mod, "\n");
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x3008, 0x42);
ret |= ov_camera_module_write_reg(cam_mod, 0x4201, 0x00);
ret |= ov_camera_module_write_reg(cam_mod, 0x4202, 0x0f);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
@ -848,6 +848,7 @@ static struct v4l2_subdev_core_ops ov2710_camera_module_core_ops = {
static struct v4l2_subdev_video_ops ov2710_camera_module_video_ops = {
.s_frame_interval = ov_camera_module_s_frame_interval,
.g_frame_interval = ov_camera_module_g_frame_interval,
.s_stream = ov_camera_module_s_stream
};
@ -874,9 +875,16 @@ static struct ov_camera_module_custom_config ov2710_custom_config = {
.g_timings = ov2710_g_timings,
.set_flip = ov2710_set_flip,
.check_camera_id = ov2710_check_camera_id,
.s_vts = OV2710_auto_adjust_fps,
.configs = ov2710_configs,
.num_configs = ARRAY_SIZE(ov2710_configs),
.power_up_delays_ms = {5, 30, 30}
.power_up_delays_ms = {5, 30, 30},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 2}
};
static int ov2710_probe(
@ -889,8 +897,10 @@ static int ov2710_probe(
v4l2_i2c_subdev_init(&ov2710.sd, client,
&ov2710_camera_module_ops);
ov2710.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov2710.custom = ov2710_custom_config;
mutex_init(&ov2710.lock);
dev_info(&client->dev, "probing successful\n");
return 0;
}
@ -907,6 +917,7 @@ static int ov2710_remove(
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
ov_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");

View File

@ -365,6 +365,8 @@ static struct ov_camera_module_config ov4689_configs[] = {
sizeof(ov4689_init_tab_2688_1520_30fps) /
sizeof(ov4689_init_tab_2688_1520_30fps[0]),
.v_blanking_time_us = 5000,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_MIPI_CFG(0, 2, 999, ov4689_EXT_CLK)
}
};
@ -402,11 +404,9 @@ static int ov4689_auto_adjust_fps(struct ov_camera_module *cam_mod,
int ret;
u32 vts;
if ((cam_mod->exp_config.exp_time +
ov4689_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = cam_mod->exp_config.exp_time +
ov4689_COARSE_INTG_TIME_MAX_MARGIN;
if ((exp_time + ov4689_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = exp_time + ov4689_COARSE_INTG_TIME_MAX_MARGIN;
else
vts = cam_mod->vts_min;
ret = ov_camera_module_write_reg(cam_mod,
@ -415,13 +415,15 @@ static int ov4689_auto_adjust_fps(struct ov_camera_module *cam_mod,
ov4689_TIMING_VTS_HIGH_REG,
(vts >> 8) & 0xFF);
if (IS_ERR_VALUE(ret))
if (IS_ERR_VALUE(ret)) {
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
else
ov_camera_module_pr_debug(cam_mod,
} else {
ov_camera_module_pr_info(cam_mod,
"updated vts = %d,vts_min=%d\n",
vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
return ret;
}
@ -474,6 +476,7 @@ static int ov4689_write_aec(struct ov_camera_module *cam_mod)
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
mutex_lock(&cam_mod->lock);
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING)
ret = ov_camera_module_write_reg(cam_mod,
ov4689_AEC_GROUP_UPDATE_ADDRESS,
@ -506,6 +509,7 @@ static int ov4689_write_aec(struct ov_camera_module *cam_mod)
ov4689_AEC_GROUP_UPDATE_ADDRESS,
ov4689_AEC_GROUP_UPDATE_END_LAUNCH);
}
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
@ -654,23 +658,28 @@ static int ov4689_g_timings(struct ov_camera_module *cam_mod,
struct ov_camera_module_timings *timings)
{
int ret = 0;
unsigned int vts;
if (IS_ERR_OR_NULL(cam_mod->active_config))
goto err;
*timings = cam_mod->active_config->timings;
vts = (!cam_mod->vts_cur) ?
timings->frame_length_lines :
cam_mod->vts_cur;
if (cam_mod->frm_intrvl_valid)
timings->vt_pix_clk_freq_hz =
cam_mod->frm_intrvl.interval.denominator
* timings->frame_length_lines
* vts
* timings->line_length_pck;
else
timings->vt_pix_clk_freq_hz =
cam_mod->active_config->frm_intrvl.interval.denominator
* timings->frame_length_lines
* vts
* timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
ov_camera_module_pr_err(cam_mod, "failed with error (%d)\n", ret);
@ -777,14 +786,8 @@ static int ov4689_s_ext_ctrls(struct ov_camera_module *cam_mod,
{
int ret = 0;
/* Handles only exposure and gain together special case. */
if (ctrls->count == 1)
ret = ov4689_s_ctrl(cam_mod, ctrls->ctrls[0].id);
else if ((ctrls->count >= 3) &&
((ctrls->ctrls[0].id == V4L2_CID_GAIN &&
ctrls->ctrls[1].id == V4L2_CID_EXPOSURE) ||
(ctrls->ctrls[1].id == V4L2_CID_GAIN &&
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE)))
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = ov4689_write_aec(cam_mod);
else
ret = -EINVAL;
@ -808,7 +811,10 @@ static int ov4689_start_streaming(struct ov_camera_module *cam_mod)
if (IS_ERR_VALUE(ret))
goto err;
if (IS_ERR_VALUE(ov_camera_module_write_reg(cam_mod, 0x0100, 1)))
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x0100, 1);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
@ -828,7 +834,9 @@ static int ov4689_stop_streaming(struct ov_camera_module *cam_mod)
ov_camera_module_pr_debug(cam_mod, "\n");
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x0100, 0);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
@ -888,6 +896,7 @@ static struct v4l2_subdev_core_ops ov4689_camera_module_core_ops = {
static struct v4l2_subdev_video_ops ov4689_camera_module_video_ops = {
.s_frame_interval = ov_camera_module_s_frame_interval,
.g_frame_interval = ov_camera_module_g_frame_interval,
.s_stream = ov_camera_module_s_stream
};
@ -912,9 +921,16 @@ static struct ov_camera_module_custom_config ov4689_custom_config = {
.g_timings = ov4689_g_timings,
.check_camera_id = ov4689_check_camera_id,
.set_flip = ov4689_set_flip,
.s_vts = ov4689_auto_adjust_fps,
.configs = ov4689_configs,
.num_configs = ARRAY_SIZE(ov4689_configs),
.power_up_delays_ms = {5, 20, 0}
.power_up_delays_ms = {5, 20, 0},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int ov4689_probe(
@ -925,9 +941,10 @@ static int ov4689_probe(
ov4689_filltimings(&ov4689_custom_config);
v4l2_i2c_subdev_init(&ov4689.sd, client, &ov4689_camera_module_ops);
ov4689.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov4689.custom = ov4689_custom_config;
mutex_init(&ov4689.lock);
dev_info(&client->dev, "probing successful\n");
return 0;
}
@ -941,6 +958,7 @@ static int ov4689_remove(struct i2c_client *client)
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
ov_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");

View File

@ -285,6 +285,8 @@ static struct ov_camera_module_config ov7675_configs[] = {
sizeof(ov7675_init_tab_640_480_30fps) /
sizeof(ov7675_init_tab_640_480_30fps[0]),
.v_blanking_time_us = 1000,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_DVP_CFG(
PLTFRM_CAM_ITF_BT601_8,
PLTFRM_CAM_SIGNAL_HIGH_LEVEL,
@ -371,14 +373,8 @@ static int ov7675_s_ext_ctrls(struct ov_camera_module *cam_mod,
ov_camera_module_pr_info(cam_mod, "\n");
/* Handles only exposure and gain together special case. */
if (ctrls->count == 1)
ret = ov7675_s_ctrl(cam_mod, ctrls->ctrls[0].id);
else if ((ctrls->count >= 3) &&
((ctrls->ctrls[0].id == V4L2_CID_GAIN &&
ctrls->ctrls[1].id == V4L2_CID_EXPOSURE) ||
(ctrls->ctrls[1].id == V4L2_CID_GAIN &&
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE)))
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = ov7675_write_aec(cam_mod);
else
ret = -EINVAL;
@ -483,6 +479,7 @@ static struct v4l2_subdev_core_ops ov7675_camera_module_core_ops = {
static struct v4l2_subdev_video_ops ov7675_camera_module_video_ops = {
.s_frame_interval = ov_camera_module_s_frame_interval,
.g_frame_interval = ov_camera_module_g_frame_interval,
.s_stream = ov_camera_module_s_stream
};
@ -509,7 +506,13 @@ static struct ov_camera_module_custom_config ov7675_custom_config = {
.set_flip = ov7675_set_flip,
.configs = ov7675_configs,
.num_configs = ARRAY_SIZE(ov7675_configs),
.power_up_delays_ms = {20, 20, 0}
.power_up_delays_ms = {20, 20, 0},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int ov7675_probe(

View File

@ -334,6 +334,8 @@ static struct ov_camera_module_config ov7750_configs[] = {
.reg_diff_table = NULL,
.reg_diff_table_num_entries = 0,
.v_blanking_time_us = 7251,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_MIPI_CFG(0, 1, 800, 24000000)
}
};
@ -373,10 +375,9 @@ static int ov7750_auto_adjust_fps(struct ov_camera_module *cam_mod,
int ret;
u32 vts;
if ((cam_mod->exp_config.exp_time + ov7750_COARSE_INTG_TIME_MAX_MARGIN)
if ((exp_time + ov7750_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = cam_mod->exp_config.exp_time +
ov7750_COARSE_INTG_TIME_MAX_MARGIN;
vts = exp_time + ov7750_COARSE_INTG_TIME_MAX_MARGIN;
else
vts = cam_mod->vts_min;
ret = ov_camera_module_write_reg(cam_mod,
@ -390,7 +391,7 @@ static int ov7750_auto_adjust_fps(struct ov_camera_module *cam_mod,
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
} else {
ov_camera_module_pr_debug(cam_mod,
ov_camera_module_pr_info(cam_mod,
"updated vts = %d,vts_min=%d\n", vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
@ -448,6 +449,8 @@ static int ov7750_write_aec(struct ov_camera_module *cam_mod)
a_gain = a_gain > 0x7ff ? 0x7ff : a_gain;
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
exp_time = cam_mod->exp_config.exp_time << 4;
mutex_lock(&cam_mod->lock);
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING)
ret = ov_camera_module_write_reg(cam_mod,
ov7750_AEC_GROUP_UPDATE_ADDRESS,
@ -480,6 +483,7 @@ static int ov7750_write_aec(struct ov_camera_module *cam_mod)
ov7750_AEC_GROUP_UPDATE_ADDRESS,
ov7750_AEC_GROUP_UPDATE_END_LAUNCH);
}
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
@ -698,6 +702,7 @@ static int ov7750_g_timings(struct ov_camera_module *cam_mod,
cam_mod->active_config->frm_intrvl.interval.denominator *
vts * timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
ov_camera_module_pr_err(cam_mod,
@ -735,14 +740,8 @@ static int ov7750_s_ext_ctrls(struct ov_camera_module *cam_mod,
{
int ret = 0;
/* Handles only exposure and gain together special case. */
if (ctrls->count == 1)
ret = ov7750_s_ctrl(cam_mod, ctrls->ctrls[0].id);
else if ((ctrls->count >= 3) &&
((ctrls->ctrls[0].id == V4L2_CID_GAIN &&
ctrls->ctrls[1].id == V4L2_CID_EXPOSURE) ||
(ctrls->ctrls[1].id == V4L2_CID_GAIN &&
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE)))
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = ov7750_write_aec(cam_mod);
else
ret = -EINVAL;
@ -828,7 +827,10 @@ static int ov7750_start_streaming(struct ov_camera_module *cam_mod)
if (IS_ERR_VALUE(ret))
goto err;
if (IS_ERR_VALUE(ov_camera_module_write_reg(cam_mod, 0x0100, 1)))
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x0100, 1);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
@ -846,7 +848,9 @@ static int ov7750_stop_streaming(struct ov_camera_module *cam_mod)
ov_camera_module_pr_debug(cam_mod, "\n");
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x0100, 0);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
@ -905,6 +909,7 @@ static struct v4l2_subdev_core_ops ov7750_camera_module_core_ops = {
static struct v4l2_subdev_video_ops ov7750_camera_module_video_ops = {
.s_frame_interval = ov_camera_module_s_frame_interval,
.g_frame_interval = ov_camera_module_g_frame_interval,
.s_stream = ov_camera_module_s_stream
};
@ -928,10 +933,17 @@ static struct ov_camera_module_custom_config ov7750_custom_config = {
.g_ctrl = ov7750_g_ctrl,
.g_timings = ov7750_g_timings,
.check_camera_id = ov7750_check_camera_id,
.s_vts = ov7750_auto_adjust_fps,
.set_flip = ov7750_set_flip,
.configs = ov7750_configs,
.num_configs = ARRAY_SIZE(ov7750_configs),
.power_up_delays_ms = {5, 20, 0}
.power_up_delays_ms = {5, 20, 0},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int ov7750_probe(
@ -942,9 +954,10 @@ static int ov7750_probe(
ov7750_filltimings(&ov7750_custom_config);
v4l2_i2c_subdev_init(&ov7750.sd, client, &ov7750_camera_module_ops);
ov7750.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov7750.custom = ov7750_custom_config;
mutex_init(&ov7750.lock);
dev_info(&client->dev, "probing successful\n");
return 0;
}
@ -958,6 +971,7 @@ static int ov7750_remove(struct i2c_client *client)
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
ov_camera_module_release(cam_mod);
dev_info(&client->dev, "removed\n");

View File

@ -1122,6 +1122,8 @@ static struct ov_camera_module_config ov8858_configs[] = {
.reg_diff_table = NULL,
.reg_diff_table_num_entries = 0,
.v_blanking_time_us = 7251,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_MIPI_CFG(0, 4, 481, 24000000)
}
};
@ -1148,6 +1150,8 @@ static struct ov_camera_module_config ov8858_configs_R1A[] = {
sizeof(ov8858_init_tab_1632_1224_30fps_R1A) /
sizeof(ov8858_init_tab_1632_1224_30fps_R1A[0]),
.v_blanking_time_us = 6579,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_MIPI_CFG(0, 2, 720, 24000000)
},
{
@ -1171,6 +1175,8 @@ static struct ov_camera_module_config ov8858_configs_R1A[] = {
sizeof(ov8858_init_tab_3264_2448_15fps_R1A) /
sizeof(ov8858_init_tab_3264_2448_15fps_R1A[0]),
.v_blanking_time_us = 6579,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
PLTFRM_CAM_ITF_MIPI_CFG(0, 2, 720, 24000000)
}
};
@ -1214,10 +1220,9 @@ static int ov8858_auto_adjust_fps(struct ov_camera_module *cam_mod,
int ret;
u32 vts;
if ((cam_mod->exp_config.exp_time + ov8858_COARSE_INTG_TIME_MAX_MARGIN)
if ((exp_time + ov8858_COARSE_INTG_TIME_MAX_MARGIN)
> cam_mod->vts_min)
vts = cam_mod->exp_config.exp_time +
ov8858_COARSE_INTG_TIME_MAX_MARGIN;
vts = exp_time + ov8858_COARSE_INTG_TIME_MAX_MARGIN;
else
vts = cam_mod->vts_min;
ret = ov_camera_module_write_reg(cam_mod,
@ -1231,7 +1236,7 @@ static int ov8858_auto_adjust_fps(struct ov_camera_module *cam_mod,
ov_camera_module_pr_err(cam_mod,
"failed with error (%d)\n", ret);
} else {
ov_camera_module_pr_debug(cam_mod,
ov_camera_module_pr_info(cam_mod,
"updated vts = %d,vts_min=%d\n", vts, cam_mod->vts_min);
cam_mod->vts_cur = vts;
}
@ -1290,6 +1295,8 @@ static int ov8858_write_aec(struct ov_camera_module *cam_mod)
a_gain = a_gain > 0x7ff ? 0x7ff : a_gain;
a_gain = a_gain * cam_mod->exp_config.gain_percent / 100;
exp_time = cam_mod->exp_config.exp_time << 4;
mutex_lock(&cam_mod->lock);
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING)
ret = ov_camera_module_write_reg(cam_mod,
ov8858_AEC_GROUP_UPDATE_ADDRESS,
@ -1322,6 +1329,7 @@ static int ov8858_write_aec(struct ov_camera_module *cam_mod)
ov8858_AEC_GROUP_UPDATE_ADDRESS,
ov8858_AEC_GROUP_UPDATE_END_LAUNCH);
}
mutex_unlock(&cam_mod->lock);
}
if (IS_ERR_VALUE(ret))
@ -1543,6 +1551,8 @@ static int ov8858_g_timings(struct ov_camera_module *cam_mod,
cam_mod->active_config->frm_intrvl.interval.denominator *
vts * timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
ov_camera_module_pr_err(cam_mod,
@ -1584,14 +1594,8 @@ static int ov8858_s_ext_ctrls(struct ov_camera_module *cam_mod,
{
int ret = 0;
/* Handles only exposure and gain together special case. */
if (ctrls->count == 1)
ret = ov8858_s_ctrl(cam_mod, ctrls->ctrls[0].id);
else if ((ctrls->count >= 3) &&
((ctrls->ctrls[0].id == V4L2_CID_GAIN &&
ctrls->ctrls[1].id == V4L2_CID_EXPOSURE) ||
(ctrls->ctrls[1].id == V4L2_CID_GAIN &&
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE)))
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = ov8858_write_aec(cam_mod);
else
ret = -EINVAL;
@ -1685,7 +1689,10 @@ static int ov8858_start_streaming(struct ov_camera_module *cam_mod)
if (IS_ERR_VALUE(ret))
goto err;
if (IS_ERR_VALUE(ov_camera_module_write_reg(cam_mod, 0x0100, 1)))
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x0100, 1);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
msleep(25);
@ -1705,7 +1712,9 @@ static int ov8858_stop_streaming(struct ov_camera_module *cam_mod)
ov_camera_module_pr_debug(cam_mod, "\n");
mutex_lock(&cam_mod->lock);
ret = ov_camera_module_write_reg(cam_mod, 0x0100, 0);
mutex_unlock(&cam_mod->lock);
if (IS_ERR_VALUE(ret))
goto err;
@ -2095,11 +2104,6 @@ static int ov8858_check_camera_id(struct ov_camera_module *cam_mod)
return ret;
}
static int ov8858_g_exposure_valid_frame(struct ov_camera_module *cam_mod)
{
return ov8858_EXP_VALID_FRAMES;
}
/* ======================================================================== */
/* This part is platform dependent */
/* ======================================================================== */
@ -2114,6 +2118,7 @@ static struct v4l2_subdev_core_ops ov8858_camera_module_core_ops = {
static struct v4l2_subdev_video_ops ov8858_camera_module_video_ops = {
.s_frame_interval = ov_camera_module_s_frame_interval,
.g_frame_interval = ov_camera_module_g_frame_interval,
.s_stream = ov_camera_module_s_stream
};
@ -2137,11 +2142,17 @@ static struct ov_camera_module_custom_config ov8858_custom_config = {
.g_ctrl = ov8858_g_ctrl,
.g_timings = ov8858_g_timings,
.check_camera_id = ov8858_check_camera_id,
.g_exposure_valid_frame = ov8858_g_exposure_valid_frame,
.s_vts = ov8858_auto_adjust_fps,
.read_otp = ov8858_otp_read,
.configs = ov8858_configs,
.num_configs = ARRAY_SIZE(ov8858_configs),
.power_up_delays_ms = {5, 20, 0}
.power_up_delays_ms = {5, 20, 0},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int ov8858_probe(
@ -2151,8 +2162,10 @@ static int ov8858_probe(
dev_info(&client->dev, "probing...\n");
ov8858_filltimings(&ov8858_custom_config);
v4l2_i2c_subdev_init(&ov8858.sd, client, &ov8858_camera_module_ops);
ov8858.sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ov8858.custom = ov8858_custom_config;
mutex_init(&ov8858.lock);
dev_info(&client->dev, "probing successful\n");
return 0;
@ -2167,6 +2180,7 @@ static int ov8858_remove(struct i2c_client *client)
if (!client->adapter)
return -ENODEV; /* our client isn't attached */
mutex_destroy(&cam_mod->lock);
ov_camera_module_release(cam_mod);
kfree(otp_ptr);

View File

@ -45,8 +45,6 @@ static void ov_camera_module_reset(
cam_mod->exp_config.auto_exp = false;
cam_mod->exp_config.auto_gain = false;
cam_mod->wb_config.auto_wb = false;
cam_mod->hflip = false;
cam_mod->vflip = false;
cam_mod->auto_adjust_fps = true;
cam_mod->rotation = 0;
cam_mod->ctrl_updt = 0;
@ -304,6 +302,10 @@ int ov_camera_module_s_fmt(struct v4l2_subdev *sd,
ov_camera_module_set_active_config(cam_mod,
ov_camera_module_find_config(cam_mod,
fmt, &cam_mod->frm_intrvl));
} else {
ov_camera_module_set_active_config(cam_mod,
ov_camera_module_find_config(cam_mod,
fmt, NULL));
}
return 0;
err:
@ -344,6 +346,8 @@ int ov_camera_module_s_frame_interval(
struct ov_camera_module *cam_mod = to_ov_camera_module(sd);
unsigned long gcdiv;
struct v4l2_subdev_frame_interval norm_interval;
struct ov_camera_module_config *config;
unsigned int vts;
int ret = 0;
if ((interval->interval.denominator == 0) ||
@ -370,22 +374,62 @@ int ov_camera_module_s_frame_interval(
norm_interval.interval.denominator =
interval->interval.denominator / gcdiv;
if (IS_ERR_OR_NULL(ov_camera_module_find_config(cam_mod,
NULL, &norm_interval))) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"frame interval %d/%d not supported\n",
interval->interval.numerator,
interval->interval.denominator);
ret = -EINVAL;
goto err;
if (!cam_mod->frm_fmt_valid)
goto end;
config = ov_camera_module_find_config(
cam_mod,
&cam_mod->active_config->frm_fmt,
&norm_interval);
if (!IS_ERR_OR_NULL(config) && (config != cam_mod->active_config)) {
ov_camera_module_set_active_config(cam_mod, config);
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING) {
cam_mod->custom.stop_streaming(cam_mod);
ov_camera_module_write_config(cam_mod);
cam_mod->custom.start_streaming(cam_mod);
}
} else {
if (IS_ERR_OR_NULL(cam_mod->active_config)) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"no active sensor configuration");
ret = -EFAULT;
goto err;
}
if (cam_mod->active_config->frm_intrvl.interval.denominator <
norm_interval.interval.denominator) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"%dx%d@%dfps isn't support!",
cam_mod->active_config->frm_fmt.width,
cam_mod->active_config->frm_fmt.height,
norm_interval.interval.denominator);
ret = -EFAULT;
goto err;
}
if (!cam_mod->custom.s_vts) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"custom.s_vts isn't support!");
ret = -EFAULT;
goto err;
}
vts = cam_mod->active_config->timings.frame_length_lines;
vts *= cam_mod->active_config->frm_intrvl.interval.denominator;
vts /= norm_interval.interval.denominator;
cam_mod->vts_cur = vts;
if (cam_mod->state != OV_CAMERA_MODULE_STREAMING)
goto end;
cam_mod->custom.s_vts(cam_mod, vts);
}
end:
cam_mod->frm_intrvl_valid = true;
cam_mod->frm_intrvl = norm_interval;
if (cam_mod->frm_fmt_valid) {
ov_camera_module_set_active_config(cam_mod,
ov_camera_module_find_config(cam_mod,
&cam_mod->frm_fmt, interval));
}
cam_mod->auto_adjust_fps = false;
return 0;
err:
pltfrm_camera_module_pr_err(&cam_mod->sd,
@ -393,12 +437,34 @@ int ov_camera_module_s_frame_interval(
return ret;
}
int ov_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval)
{
struct ov_camera_module *cam_mod = to_ov_camera_module(sd);
if (cam_mod->active_config) {
if (cam_mod->state == OV_CAMERA_MODULE_STREAMING) {
if (cam_mod->frm_intrvl_valid) {
*interval = cam_mod->frm_intrvl;
return 0;
} else {
*interval = cam_mod->active_config->frm_intrvl;
return 0;
}
}
}
return -EFAULT;
}
/* ======================================================================== */
int ov_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
{
int ret = 0;
struct ov_camera_module *cam_mod = to_ov_camera_module(sd);
unsigned int vts;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "%d\n", enable);
@ -427,6 +493,29 @@ int ov_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
ret = cam_mod->custom.start_streaming(cam_mod);
if (IS_ERR_VALUE(ret))
goto err;
if (cam_mod->frm_intrvl_valid) {
if ((cam_mod->frm_intrvl.interval.numerator !=
cam_mod->active_config->frm_intrvl.interval.numerator) ||
(cam_mod->frm_intrvl.interval.denominator !=
cam_mod->active_config->frm_intrvl.interval.denominator)) {
if (cam_mod->frm_intrvl.interval.denominator >
cam_mod->active_config->frm_intrvl.interval.denominator) {
pltfrm_camera_module_pr_warn(&cam_mod->sd,
"sensor is not support stream: %dx%d@(%d/%d)fps!\n",
cam_mod->active_config->frm_fmt.width,
cam_mod->active_config->frm_fmt.height,
cam_mod->frm_intrvl.interval.denominator,
cam_mod->frm_intrvl.interval.numerator);
goto end;
}
vts = cam_mod->active_config->timings.frame_length_lines;
vts *= cam_mod->active_config->frm_intrvl.interval.denominator;
vts /= cam_mod->frm_intrvl.interval.denominator;
cam_mod->custom.s_vts(cam_mod, vts);
}
}
if (!cam_mod->inited && cam_mod->update_config)
cam_mod->inited = true;
cam_mod->update_config = false;
@ -471,6 +560,7 @@ int ov_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
msleep(wait_ms + 1);
}
end:
cam_mod->state_before_suspend = cam_mod->state;
return 0;
@ -582,6 +672,22 @@ int ov_camera_module_g_ctrl(struct v4l2_subdev *sd,
return 0;
}
if (ctrl->id == V4L2_CID_HFLIP) {
ctrl->value = cam_mod->hflip;
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"V4L2_CID_HFLIP %d\n",
ctrl->value);
return 0;
}
if (ctrl->id == V4L2_CID_VFLIP) {
ctrl->value = cam_mod->vflip;
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"V4L2_CID_VFLIP %d\n",
ctrl->value);
return 0;
}
if (IS_ERR_OR_NULL(cam_mod->active_config)) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"no active configuration\n");
@ -668,10 +774,6 @@ int ov_camera_module_g_ctrl(struct v4l2_subdev *sd,
"V4L2_CID_FOCUS_ABSOLUTE %d\n",
ctrl->value);
break;
case V4L2_CID_HFLIP:
case V4L2_CID_VFLIP:
/* TBD */
/* fallthrough */
default:
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"failed, unknown ctrl %d\n", ctrl->id);
@ -811,12 +913,14 @@ int ov_camera_module_s_ext_ctrls(
cam_mod->hflip = true;
else
cam_mod->hflip = false;
cam_mod->flip_flg = true;
break;
case V4L2_CID_VFLIP:
if (ctrl->value)
cam_mod->vflip = true;
else
cam_mod->vflip = false;
cam_mod->flip_flg = true;
break;
default:
pltfrm_camera_module_pr_warn(&cam_mod->sd,
@ -894,7 +998,8 @@ long ov_camera_module_ioctl(struct v4l2_subdev *sd,
void *arg)
{
struct ov_camera_module *cam_mod = to_ov_camera_module(sd);
int ret;
int ret, i;
unsigned int flag, val;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "cmd: 0x%x\n", cmd);
@ -935,9 +1040,10 @@ long ov_camera_module_ioctl(struct v4l2_subdev *sd,
timings->fine_integration_time_min =
ov_timings.fine_integration_time_min;
if (cam_mod->custom.g_exposure_valid_frame)
timings->exposure_valid_frame[0] =
cam_mod->custom.g_exposure_valid_frame(cam_mod);
timings->exposure_valid_frame[0] =
cam_mod->custom.exposure_valid_frame[0];
timings->exposure_valid_frame[1] =
cam_mod->custom.exposure_valid_frame[1];
if (cam_mod->exp_config.exp_time)
timings->exp_time = cam_mod->exp_config.exp_time;
else
@ -946,7 +1052,52 @@ long ov_camera_module_ioctl(struct v4l2_subdev *sd,
timings->gain = cam_mod->exp_config.gain;
else
timings->gain = ov_timings.gain;
if (cam_mod->active_config) {
timings->max_exp_gain_h = cam_mod->active_config->max_exp_gain_h;
timings->max_exp_gain_l = cam_mod->active_config->max_exp_gain_l;
} else {
timings->max_exp_gain_h = cam_mod->custom.configs[0].max_exp_gain_h;
timings->max_exp_gain_l = cam_mod->custom.configs[0].max_exp_gain_l;
}
return ret;
} else if (cmd == RK_VIDIOC_SENSOR_CONFIGINFO) {
struct sensor_config_info_s *sensor_config = (struct sensor_config_info_s *)arg;
sensor_config->config_num = cam_mod->custom.num_configs;
for (i = 0; i < cam_mod->custom.num_configs; i++) {
if (i >= SENSOR_CONFIG_NUM)
break;
sensor_config->sensor_fmt[i] =
pltfrm_camera_module_pix_fmt2csi2_dt(cam_mod->custom.configs[i].frm_fmt.code);
sensor_config->reso[i].width = cam_mod->custom.configs[i].frm_fmt.width;
sensor_config->reso[i].height = cam_mod->custom.configs[i].frm_fmt.height;
}
return 0;
} else if (cmd == RK_VIDIOC_SENSOR_REG_ACCESS) {
struct sensor_reg_rw_s *sensor_rw = (struct sensor_reg_rw_s *)arg;
if (sensor_rw->reg_access_mode == SENSOR_READ_MODE) {
for (i = 0; i < cam_mod->custom.configs[0].reg_table_num_entries; i++) {
flag = cam_mod->custom.configs[0].reg_table[i].flag;
if (flag != PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT)
break;
}
if (flag == PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"Can not get sensor reg type.\n");
return -EINVAL;
}
sensor_rw->reg_addr_len = PLTFRM_CAMERA_MODULE_REG_LEN(flag);
sensor_rw->reg_data_len = PLTFRM_CAMERA_MODULE_DATA_LEN(flag);
pltfrm_camera_module_read_reg_ex(&cam_mod->sd, 1, flag, sensor_rw->addr, &val);
sensor_rw->data = val;
} else {
flag = (sensor_rw->reg_addr_len << PLTFRM_CAMERA_MODULE_REG_LEN_BIT);
flag |= (sensor_rw->reg_data_len << PLTFRM_CAMERA_MODULE_DATA_LEN_BIT);
pltfrm_camera_module_write_reg_ex(&cam_mod->sd, flag, sensor_rw->addr, sensor_rw->data);
}
return 0;
} else if (cmd == PLTFRM_CIFCAM_G_ITF_CFG) {
struct pltfrm_cam_itf *itf_cfg = (struct pltfrm_cam_itf *)arg;
struct ov_camera_module_config *config;
@ -967,9 +1118,14 @@ long ov_camera_module_ioctl(struct v4l2_subdev *sd,
pltfrm_camera_module_ioctl(sd, PLTFRM_CIFCAM_G_ITF_CFG, arg);
return 0;
} else if (cmd == PLTFRM_CIFCAM_ATTACH) {
ov_camera_module_init(cam_mod, &cam_mod->custom);
pltfrm_camera_module_ioctl(sd, cmd, arg);
return ov_camera_module_attach(cam_mod);
ret = ov_camera_module_init(cam_mod, &cam_mod->custom);
if (!IS_ERR_VALUE(ret)) {
pltfrm_camera_module_ioctl(sd, cmd, arg);
return ov_camera_module_attach(cam_mod);
} else {
ov_camera_module_release(cam_mod);
return ret;
}
}
ret = pltfrm_camera_module_ioctl(sd, cmd, arg);
@ -981,7 +1137,22 @@ long ov_camera_module_ioctl(struct v4l2_subdev *sd,
int ov_camera_module_get_flip_mirror(
struct ov_camera_module *cam_mod)
{
return pltfrm_camera_module_get_flip_mirror(&cam_mod->sd);
int mode = 0;
if (!cam_mod->flip_flg)
return -1;
if (cam_mod->hflip)
mode |= OV_MIRROR_BIT_MASK;
else
mode &= ~OV_MIRROR_BIT_MASK;
if (cam_mod->vflip)
mode |= OV_FLIP_BIT_MASK;
else
mode &= ~OV_FLIP_BIT_MASK;
return mode;
}
/* ======================================================================== */
@ -1078,9 +1249,13 @@ int ov_camera_module_init(struct ov_camera_module *cam_mod,
struct ov_camera_module_custom_config *custom)
{
int ret = 0;
int mode = 0;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "\n");
cam_mod->hflip = false;
cam_mod->vflip = false;
cam_mod->flip_flg = false;
ov_camera_module_reset(cam_mod);
if (IS_ERR_OR_NULL(custom->start_streaming) ||
@ -1108,6 +1283,12 @@ int ov_camera_module_init(struct ov_camera_module *cam_mod,
goto err;
}
mode = pltfrm_camera_module_get_flip_mirror(&cam_mod->sd);
if (mode != -1) {
cam_mod->hflip = mode & OV_MIRROR_BIT_MASK ? true : false;
cam_mod->vflip = mode & OV_FLIP_BIT_MASK ? true : false;
cam_mod->flip_flg = true;
}
return 0;
err:
pltfrm_camera_module_pr_err(&cam_mod->sd,

View File

@ -30,8 +30,8 @@
#define OV_CAMERA_MODULE_REG_TYPE_TIMEOUT PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT
#define ov_camera_module_csi_config
#define ov_camera_module_reg pltfrm_camera_module_reg
#define OV_FLIP_BIT_MASK 0x2
#define OV_MIRROR_BIT_MASK 0x1
#define OV_FLIP_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_FLIP_BIT)
#define OV_MIRROR_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define OV_CAMERA_MODULE_CTRL_UPDT_GAIN 0x01
#define OV_CAMERA_MODULE_CTRL_UPDT_EXP_TIME 0x02
@ -90,7 +90,8 @@ struct ov_camera_module_config {
struct ov_camera_module_timings timings;
bool soft_reset;
bool ignore_measurement_check;
u8 max_exp_gain_h;
u8 max_exp_gain_l;
struct pltfrm_cam_itf itf_cfg;
};
@ -156,7 +157,8 @@ struct ov_camera_module_custom_config {
int (*g_ctrl)(struct ov_camera_module *cam_mod, u32 ctrl_id);
int (*g_timings)(struct ov_camera_module *cam_mod,
struct ov_camera_module_timings *timings);
int (*g_exposure_valid_frame)(struct ov_camera_module *cam_mod);
int (*s_vts)(struct ov_camera_module *cam_mod,
u32 vts);
int (*s_ext_ctrls)(struct ov_camera_module *cam_mod,
struct ov_camera_module_ext_ctrls *ctrls);
int (*set_flip)(
@ -168,6 +170,7 @@ struct ov_camera_module_custom_config {
struct ov_camera_module_config *configs;
u32 num_configs;
u32 power_up_delays_ms[3];
unsigned short exposure_valid_frame[2];
void *priv;
};
@ -199,10 +202,12 @@ struct ov_camera_module {
bool frm_intrvl_valid;
bool hflip;
bool vflip;
bool flip_flg;
u32 rotation;
void *pltfm_data;
bool inited;
bool as_master;
struct mutex lock;
};
#define ov_camera_module_pr_info(cam_mod, fmt, arg...) \
@ -247,6 +252,10 @@ int ov_camera_module_s_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int ov_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int ov_camera_module_s_stream(
struct v4l2_subdev *sd,
int enable);

View File

@ -80,6 +80,20 @@ const char *PLTFRM_CAMERA_MODULE_PIN_RESET = OF_OV_GPIO_RESET;
#define I2C_M_WR 0
#define I2C_MSG_MAX 300
#define I2C_DATA_MAX (I2C_MSG_MAX * 3)
#define CSI2_DT_YUV420_8b (0x18)
#define CSI2_DT_YUV420_10b (0x19)
#define CSI2_DT_YUV422_8b (0x1E)
#define CSI2_DT_YUV422_10b (0x1F)
#define CSI2_DT_RGB444 (0x20)
#define CSI2_DT_RGB555 (0x21)
#define CSI2_DT_RGB565 (0x22)
#define CSI2_DT_RGB666 (0x23)
#define CSI2_DT_RGB888 (0x24)
#define CSI2_DT_RAW6 (0x28)
#define CSI2_DT_RAW7 (0x29)
#define CSI2_DT_RAW8 (0x2A)
#define CSI2_DT_RAW10 (0x2B)
#define CSI2_DT_RAW12 (0x2C)
struct pltfrm_camera_module_gpio {
int pltfrm_gpio;
@ -885,10 +899,9 @@ static int pltfrm_camera_module_write_reglist_node(
}
reg_table_num_entries /= 12;
reg_table = (struct pltfrm_camera_module_reg *)
kmalloc(reg_table_num_entries *
sizeof(struct pltfrm_camera_module_reg),
GFP_KERNEL);
reg_table = kmalloc_array(reg_table_num_entries,
sizeof(struct pltfrm_camera_module_reg),
GFP_KERNEL);
if (IS_ERR_OR_NULL(reg_table)) {
pltfrm_camera_module_pr_err(sd,
"memory allocation failed\n");
@ -1662,7 +1675,6 @@ int pltfrm_camera_module_init(
void **pldata)
{
int ret = 0;
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct pltfrm_camera_module_data *pdata;
pltfrm_camera_module_pr_debug(sd, "\n");
@ -1675,13 +1687,11 @@ int pltfrm_camera_module_init(
}
ret = pltfrm_camera_module_init_gpio(sd);
if (ret) {
if (ret)
pltfrm_camera_module_pr_err(sd,
"GPIO initialization failed (%d)\n", ret);
devm_kfree(&client->dev, pdata);
} else {
else
*(struct pltfrm_camera_module_data **)pldata = pdata;
}
return ret;
}
@ -1710,8 +1720,18 @@ void pltfrm_camera_module_release(
devm_regulator_put(
pdata->regulators.regulator[i].regulator);
}
if (!IS_ERR_OR_NULL(pdata->regulators.regulator)) {
devm_kfree(&client->dev,
pdata->regulators.regulator);
pdata->regulators.regulator = NULL;
}
if (pdata->pinctrl)
devm_pinctrl_put(pdata->pinctrl);
if (!IS_ERR_OR_NULL(pdata)) {
devm_kfree(&client->dev, pdata);
pdata = NULL;
}
}
/* ======================================================================== */
@ -1840,5 +1860,134 @@ int pltfrm_camera_module_get_flip_mirror(
return mode;
}
int pltfrm_camera_module_pix_fmt2csi2_dt(int src_pix_fmt)
{
int ret = 0;
switch (src_pix_fmt) {
case MEDIA_BUS_FMT_RGB444_1X12:
case MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE:
case MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE:
ret = CSI2_DT_RGB444;
break;
case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
ret = CSI2_DT_RGB555;
break;
case MEDIA_BUS_FMT_RGB565_1X16:
case MEDIA_BUS_FMT_BGR565_2X8_BE:
case MEDIA_BUS_FMT_BGR565_2X8_LE:
case MEDIA_BUS_FMT_RGB565_2X8_BE:
case MEDIA_BUS_FMT_RGB565_2X8_LE:
ret = CSI2_DT_RGB565;
break;
case MEDIA_BUS_FMT_RGB666_1X18:
case MEDIA_BUS_FMT_RGB666_1X24_CPADHI:
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
ret = CSI2_DT_RGB666;
break;
case MEDIA_BUS_FMT_RBG888_1X24:
case MEDIA_BUS_FMT_BGR888_1X24:
case MEDIA_BUS_FMT_GBR888_1X24:
case MEDIA_BUS_FMT_RGB888_1X24:
case MEDIA_BUS_FMT_RGB888_2X12_BE:
case MEDIA_BUS_FMT_RGB888_2X12_LE:
case MEDIA_BUS_FMT_RGB888_1X7X4_SPWG:
case MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA:
case MEDIA_BUS_FMT_ARGB8888_1X32:
case MEDIA_BUS_FMT_RGB888_1X32_PADHI:
case MEDIA_BUS_FMT_RGB101010_1X30:
case MEDIA_BUS_FMT_RGB121212_1X36:
case MEDIA_BUS_FMT_RGB161616_1X48:
ret = CSI2_DT_RGB888;
break;
case MEDIA_BUS_FMT_Y8_1X8:
case MEDIA_BUS_FMT_UV8_1X8:
case MEDIA_BUS_FMT_UYVY8_1_5X8:
case MEDIA_BUS_FMT_VYUY8_1_5X8:
case MEDIA_BUS_FMT_YUYV8_1_5X8:
case MEDIA_BUS_FMT_YVYU8_1_5X8:
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_VYUY8_2X8:
case MEDIA_BUS_FMT_YUYV8_2X8:
case MEDIA_BUS_FMT_YVYU8_2X8:
ret = CSI2_DT_YUV420_8b;
break;
case MEDIA_BUS_FMT_Y10_1X10:
case MEDIA_BUS_FMT_UYVY10_2X10:
case MEDIA_BUS_FMT_VYUY10_2X10:
case MEDIA_BUS_FMT_YUYV10_2X10:
case MEDIA_BUS_FMT_YVYU10_2X10:
ret = CSI2_DT_YUV420_10b;
break;
case MEDIA_BUS_FMT_Y12_1X12:
case MEDIA_BUS_FMT_UYVY12_2X12:
case MEDIA_BUS_FMT_VYUY12_2X12:
case MEDIA_BUS_FMT_YUYV12_2X12:
case MEDIA_BUS_FMT_YVYU12_2X12:
case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_VYUY8_1X16:
case MEDIA_BUS_FMT_YUYV8_1X16:
case MEDIA_BUS_FMT_YVYU8_1X16:
case MEDIA_BUS_FMT_YDYUYDYV8_1X16:
ret = CSI2_DT_YUV422_8b;
break;
case MEDIA_BUS_FMT_UYVY10_1X20:
case MEDIA_BUS_FMT_VYUY10_1X20:
case MEDIA_BUS_FMT_YUYV10_1X20:
case MEDIA_BUS_FMT_YVYU10_1X20:
case MEDIA_BUS_FMT_VUY8_1X24:
case MEDIA_BUS_FMT_YUV8_1X24:
case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
case MEDIA_BUS_FMT_UYVY12_1X24:
case MEDIA_BUS_FMT_VYUY12_1X24:
case MEDIA_BUS_FMT_YUYV12_1X24:
case MEDIA_BUS_FMT_YVYU12_1X24:
case MEDIA_BUS_FMT_YUV10_1X30:
case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
case MEDIA_BUS_FMT_AYUV8_1X32:
case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
case MEDIA_BUS_FMT_YUV12_1X36:
case MEDIA_BUS_FMT_YUV16_1X48:
case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
ret = CSI2_DT_YUV422_10b;
break;
case MEDIA_BUS_FMT_SBGGR8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SRGGB8_1X8:
ret = CSI2_DT_RAW8;
break;
case MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8:
case MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8:
case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8:
case MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8:
case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
case MEDIA_BUS_FMT_SBGGR10_1X10:
case MEDIA_BUS_FMT_SGBRG10_1X10:
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SRGGB10_1X10:
ret = CSI2_DT_RAW10;
break;
case MEDIA_BUS_FMT_SBGGR12_1X12:
case MEDIA_BUS_FMT_SGBRG12_1X12:
case MEDIA_BUS_FMT_SGRBG12_1X12:
case MEDIA_BUS_FMT_SRGGB12_1X12:
ret = CSI2_DT_RAW12;
break;
default:
break;
}
return ret;
}
#endif

View File

@ -448,6 +448,8 @@ static struct tc_camera_module_config tc358749xbg_configs[] = {
sizeof(tc358749xbg_init_tab_1920_1080_60fps) /
sizeof(tc358749xbg_init_tab_1920_1080_60fps[0]),
.v_blanking_time_us = 3078,
.max_exp_gain_h = 16,
.max_exp_gain_l = 0,
.ignore_measurement_check = 1,
PLTFRM_CAM_ITF_MIPI_CFG(0, 4, 800, 24000000)
}
@ -649,6 +651,8 @@ static int tc358749xbg_g_timings(
cam_mod->active_config->frm_intrvl.interval.denominator *
vts * timings->line_length_pck;
timings->frame_length_lines = vts;
return ret;
err:
tc_camera_module_pr_err(cam_mod,
@ -704,14 +708,8 @@ static int tc358749xbg_s_ext_ctrls(
{
int ret = 0;
/* Handles only exposure and gain together special case. */
if (ctrls->count == 1)
ret = tc358749xbg_s_ctrl(cam_mod, ctrls->ctrls[0].id);
else if ((ctrls->count >= 3) &&
(ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE ||
ctrls->ctrls[1].id == V4L2_CID_GAIN ||
ctrls->ctrls[1].id == V4L2_CID_EXPOSURE))
if ((ctrls->ctrls[0].id == V4L2_CID_GAIN ||
ctrls->ctrls[0].id == V4L2_CID_EXPOSURE))
ret = tc358749xbg_write_aec(cam_mod);
else
ret = -EINVAL;
@ -798,6 +796,7 @@ static struct v4l2_subdev_core_ops tc358749xbg_camera_module_core_ops = {
static struct v4l2_subdev_video_ops tc358749xbg_camera_module_video_ops = {
.s_frame_interval = tc_camera_module_s_frame_interval,
.g_frame_interval = tc_camera_module_g_frame_interval,
.s_stream = tc_camera_module_s_stream
};
@ -826,7 +825,13 @@ static struct tc_camera_module_custom_config tc358749xbg_custom_config = {
.s_power = tc358749xbg_s_power,
.configs = tc358749xbg_configs,
.num_configs = ARRAY_SIZE(tc358749xbg_configs),
.power_up_delays_ms = {5, 30, 30}
.power_up_delays_ms = {5, 30, 30},
/*
*0: Exposure time valid fileds;
*1: Exposure gain valid fileds;
*(2 fileds == 1 frames)
*/
.exposure_valid_frame = {4, 4}
};
static int test_parse_dts(

View File

@ -51,8 +51,6 @@ static void tc_camera_module_reset(
cam_mod->exp_config.auto_exp = false;
cam_mod->exp_config.auto_gain = false;
cam_mod->wb_config.auto_wb = false;
cam_mod->hflip = false;
cam_mod->vflip = false;
cam_mod->auto_adjust_fps = true;
cam_mod->rotation = 0;
cam_mod->ctrl_updt = 0;
@ -308,6 +306,10 @@ int tc_camera_module_s_fmt(struct v4l2_subdev *sd,
tc_camera_module_set_active_config(cam_mod,
tc_camera_module_find_config(cam_mod,
fmt, &cam_mod->frm_intrvl));
} else {
tc_camera_module_set_active_config(cam_mod,
tc_camera_module_find_config(cam_mod,
fmt, NULL));
}
return 0;
err:
@ -348,6 +350,8 @@ int tc_camera_module_s_frame_interval(
struct tc_camera_module *cam_mod = to_tc_camera_module(sd);
unsigned long gcdiv;
struct v4l2_subdev_frame_interval norm_interval;
struct tc_camera_module_config *config;
unsigned int vts;
int ret = 0;
if ((interval->interval.denominator == 0) ||
@ -374,22 +378,65 @@ int tc_camera_module_s_frame_interval(
norm_interval.interval.denominator =
interval->interval.denominator / gcdiv;
if (IS_ERR_OR_NULL(tc_camera_module_find_config(cam_mod,
NULL, &norm_interval))) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"frame interval %d/%d not supported\n",
interval->interval.numerator,
interval->interval.denominator);
ret = -EINVAL;
goto err;
config = tc_camera_module_find_config(cam_mod,
NULL, &norm_interval);
if (!cam_mod->frm_fmt_valid)
goto end;
config = tc_camera_module_find_config(
cam_mod,
&cam_mod->active_config->frm_fmt,
&norm_interval);
if (!IS_ERR_OR_NULL(config) && (config != cam_mod->active_config)) {
tc_camera_module_set_active_config(cam_mod, config);
if (cam_mod->state == TC_CAMERA_MODULE_STREAMING) {
cam_mod->custom.enable_stream(cam_mod, false);
tc_camera_module_write_config(cam_mod);
cam_mod->custom.enable_stream(cam_mod, true);
}
} else {
if (IS_ERR_OR_NULL(cam_mod->active_config)) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"no active sensor configuration");
ret = -EFAULT;
goto err;
}
if (cam_mod->active_config->frm_intrvl.interval.denominator <
norm_interval.interval.denominator) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"%dx%d@%dfps isn't support!",
cam_mod->active_config->frm_fmt.width,
cam_mod->active_config->frm_fmt.height,
norm_interval.interval.denominator);
ret = -EFAULT;
goto err;
}
if (!cam_mod->custom.s_vts) {
pltfrm_camera_module_pr_err(
&cam_mod->sd,
"custom.s_vts isn't support!");
ret = -EFAULT;
goto err;
}
vts = cam_mod->active_config->timings.frame_length_lines;
vts *= cam_mod->active_config->frm_intrvl.interval.denominator;
vts /= norm_interval.interval.denominator;
cam_mod->vts_cur = vts;
if (cam_mod->state != TC_CAMERA_MODULE_STREAMING)
goto end;
cam_mod->custom.s_vts(cam_mod, vts);
}
end:
cam_mod->frm_intrvl_valid = true;
cam_mod->frm_intrvl = norm_interval;
if (cam_mod->frm_fmt_valid) {
tc_camera_module_set_active_config(cam_mod,
tc_camera_module_find_config(cam_mod,
&cam_mod->frm_fmt, interval));
}
cam_mod->auto_adjust_fps = false;
return 0;
err:
pltfrm_camera_module_pr_err(&cam_mod->sd,
@ -397,12 +444,34 @@ int tc_camera_module_s_frame_interval(
return ret;
}
int tc_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval)
{
struct tc_camera_module *cam_mod = to_tc_camera_module(sd);
if (cam_mod->active_config) {
if (cam_mod->state == TC_CAMERA_MODULE_STREAMING) {
if (cam_mod->frm_intrvl_valid) {
*interval = cam_mod->frm_intrvl;
return 0;
} else {
*interval = cam_mod->active_config->frm_intrvl;
return 0;
}
}
}
return -EFAULT;
}
/* ======================================================================== */
int tc_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
{
int ret = 0;
struct tc_camera_module *cam_mod = to_tc_camera_module(sd);
unsigned int vts;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "%d\n", enable);
@ -431,6 +500,29 @@ int tc_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
ret = cam_mod->custom.enable_stream(cam_mod, true);
if (IS_ERR_VALUE(ret))
goto err;
if (cam_mod->frm_intrvl_valid) {
if ((cam_mod->frm_intrvl.interval.numerator !=
cam_mod->active_config->frm_intrvl.interval.numerator) ||
(cam_mod->frm_intrvl.interval.denominator !=
cam_mod->active_config->frm_intrvl.interval.denominator)) {
if (cam_mod->frm_intrvl.interval.denominator >
cam_mod->active_config->frm_intrvl.interval.denominator) {
pltfrm_camera_module_pr_warn(&cam_mod->sd,
"sensor is not support stream: %dx%d@(%d/%d)fps!\n",
cam_mod->active_config->frm_fmt.width,
cam_mod->active_config->frm_fmt.height,
cam_mod->frm_intrvl.interval.denominator,
cam_mod->frm_intrvl.interval.numerator);
goto end;
}
vts = cam_mod->active_config->timings.frame_length_lines;
vts *= cam_mod->active_config->frm_intrvl.interval.denominator;
vts /= cam_mod->frm_intrvl.interval.denominator;
cam_mod->custom.s_vts(cam_mod, vts);
}
}
if (!cam_mod->inited && cam_mod->update_config)
cam_mod->inited = true;
cam_mod->update_config = false;
@ -475,6 +567,7 @@ int tc_camera_module_s_stream(struct v4l2_subdev *sd, int enable)
msleep(wait_ms + 1);
}
end:
cam_mod->state_before_suspend = cam_mod->state;
return 0;
@ -589,6 +682,22 @@ int tc_camera_module_g_ctrl(struct v4l2_subdev *sd,
return 0;
}
if (ctrl->id == V4L2_CID_HFLIP) {
ctrl->value = cam_mod->hflip;
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"V4L2_CID_HFLIP %d\n",
ctrl->value);
return 0;
}
if (ctrl->id == V4L2_CID_VFLIP) {
ctrl->value = cam_mod->vflip;
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"V4L2_CID_VFLIP %d\n",
ctrl->value);
return 0;
}
if (ctrl->id == V4L2_CID_FLASH_LED_MODE) {
ctrl->value = cam_mod->exp_config.flash_mode;
pltfrm_camera_module_pr_debug(&cam_mod->sd,
@ -683,10 +792,6 @@ int tc_camera_module_g_ctrl(struct v4l2_subdev *sd,
"V4L2_CID_FOCUS_ABSOLUTE %d\n",
ctrl->value);
break;
case V4L2_CID_HFLIP:
case V4L2_CID_VFLIP:
/* TBD */
/* fallthrough */
default:
pltfrm_camera_module_pr_debug(&cam_mod->sd,
"failed, unknown ctrl %d\n", ctrl->id);
@ -835,12 +940,14 @@ int tc_camera_module_s_ext_ctrls(
cam_mod->hflip = true;
else
cam_mod->hflip = false;
cam_mod->flip_flg = true;
break;
case V4L2_CID_VFLIP:
if (ctrl->value)
cam_mod->vflip = true;
else
cam_mod->vflip = false;
cam_mod->flip_flg = true;
break;
default:
pltfrm_camera_module_pr_warn(
@ -920,7 +1027,8 @@ long tc_camera_module_ioctl(struct v4l2_subdev *sd,
void *arg)
{
struct tc_camera_module *cam_mod = to_tc_camera_module(sd);
int ret;
int ret, i;
unsigned int flag, val;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "cmd: 0x%x\n", cmd);
@ -963,9 +1071,10 @@ long tc_camera_module_ioctl(struct v4l2_subdev *sd,
timings->fine_integration_time_min =
tc_timings.fine_integration_time_min;
if (cam_mod->custom.g_exposure_valid_frame)
timings->exposure_valid_frame[0] =
cam_mod->custom.g_exposure_valid_frame(cam_mod);
timings->exposure_valid_frame[0] =
cam_mod->custom.exposure_valid_frame[0];
timings->exposure_valid_frame[1] =
cam_mod->custom.exposure_valid_frame[1];
if (cam_mod->exp_config.exp_time)
timings->exp_time = cam_mod->exp_config.exp_time;
else
@ -974,7 +1083,52 @@ long tc_camera_module_ioctl(struct v4l2_subdev *sd,
timings->gain = cam_mod->exp_config.gain;
else
timings->gain = tc_timings.gain;
if (cam_mod->active_config) {
timings->max_exp_gain_h = cam_mod->active_config->max_exp_gain_h;
timings->max_exp_gain_l = cam_mod->active_config->max_exp_gain_l;
} else {
timings->max_exp_gain_h = cam_mod->custom.configs[0].max_exp_gain_h;
timings->max_exp_gain_l = cam_mod->custom.configs[0].max_exp_gain_l;
}
return ret;
} else if (cmd == RK_VIDIOC_SENSOR_CONFIGINFO) {
struct sensor_config_info_s *sensor_config = (struct sensor_config_info_s *)arg;
sensor_config->config_num = cam_mod->custom.num_configs;
for (i = 0; i < cam_mod->custom.num_configs; i++) {
if (i >= SENSOR_CONFIG_NUM)
break;
sensor_config->sensor_fmt[i] =
pltfrm_camera_module_pix_fmt2csi2_dt(cam_mod->custom.configs[i].frm_fmt.code);
sensor_config->reso[i].width = cam_mod->custom.configs[i].frm_fmt.width;
sensor_config->reso[i].height = cam_mod->custom.configs[i].frm_fmt.height;
}
return 0;
} else if (cmd == RK_VIDIOC_SENSOR_REG_ACCESS) {
struct sensor_reg_rw_s *sensor_rw = (struct sensor_reg_rw_s *)arg;
if (sensor_rw->reg_access_mode == SENSOR_READ_MODE) {
for (i = 0; i < cam_mod->custom.configs[0].reg_table_num_entries; i++) {
flag = cam_mod->custom.configs[0].reg_table[i].flag;
if (flag != PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT)
break;
}
if (flag == PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT) {
pltfrm_camera_module_pr_err(&cam_mod->sd,
"Can not get sensor reg type.\n");
return -EINVAL;
}
sensor_rw->reg_addr_len = PLTFRM_CAMERA_MODULE_REG_LEN(flag);
sensor_rw->reg_data_len = PLTFRM_CAMERA_MODULE_DATA_LEN(flag);
pltfrm_camera_module_read_reg_ex(&cam_mod->sd, 1, flag, sensor_rw->addr, &val);
sensor_rw->data = val;
} else {
flag = (sensor_rw->reg_addr_len << PLTFRM_CAMERA_MODULE_REG_LEN_BIT);
flag |= (sensor_rw->reg_data_len << PLTFRM_CAMERA_MODULE_DATA_LEN_BIT);
pltfrm_camera_module_write_reg_ex(&cam_mod->sd, flag, sensor_rw->addr, sensor_rw->data);
}
return 0;
} else if (cmd == PLTFRM_CIFCAM_G_ITF_CFG) {
struct pltfrm_cam_itf *itf_cfg = (struct pltfrm_cam_itf *)arg;
struct tc_camera_module_config *config;
@ -995,9 +1149,14 @@ long tc_camera_module_ioctl(struct v4l2_subdev *sd,
pltfrm_camera_module_ioctl(sd, PLTFRM_CIFCAM_G_ITF_CFG, arg);
return 0;
} else if (cmd == PLTFRM_CIFCAM_ATTACH) {
tc_camera_module_init(cam_mod, &cam_mod->custom);
pltfrm_camera_module_ioctl(sd, cmd, arg);
return tc_camera_module_attach(cam_mod);
ret = tc_camera_module_init(cam_mod, &cam_mod->custom);
if (!IS_ERR_VALUE(ret)) {
pltfrm_camera_module_ioctl(sd, cmd, arg);
return tc_camera_module_attach(cam_mod);
} else {
tc_camera_module_release(cam_mod);
return ret;
}
}
ret = pltfrm_camera_module_ioctl(sd, cmd, arg);
@ -1009,7 +1168,22 @@ long tc_camera_module_ioctl(struct v4l2_subdev *sd,
int tc_camera_module_get_flip_mirror(
struct tc_camera_module *cam_mod)
{
return pltfrm_camera_module_get_flip_mirror(&cam_mod->sd);
int mode = 0;
if (!cam_mod->flip_flg)
return -1;
if (cam_mod->hflip)
mode |= TC_MIRROR_BIT_MASK;
else
mode &= ~TC_MIRROR_BIT_MASK;
if (cam_mod->vflip)
mode |= TC_FLIP_BIT_MASK;
else
mode &= ~TC_FLIP_BIT_MASK;
return mode;
}
/* ======================================================================== */
@ -1038,7 +1212,7 @@ int tc_camera_module_enum_frameintervals(
/* ======================================================================== */
static int tc_camera_module_i2c_write(struct v4l2_subdev *sd, u16 reg,
u8 *values, u32 len)
u8 *values, u32 len)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret, i;
@ -1082,7 +1256,7 @@ static int tc_camera_module_i2c_write(struct v4l2_subdev *sd, u16 reg,
/* ======================================================================== */
static int tc_camera_module_i2c_read(struct v4l2_subdev *sd, u16 reg,
u32 *value, u32 len)
u32 *value, u32 len)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
int ret = 0;
@ -1261,9 +1435,13 @@ int tc_camera_module_init(struct tc_camera_module *cam_mod,
struct tc_camera_module_custom_config *custom)
{
int ret = 0;
int mode = 0;
pltfrm_camera_module_pr_debug(&cam_mod->sd, "\n");
cam_mod->hflip = false;
cam_mod->vflip = false;
cam_mod->flip_flg = false;
tc_camera_module_reset(cam_mod);
if (IS_ERR_OR_NULL(custom->s_ctrl) ||
@ -1289,6 +1467,12 @@ int tc_camera_module_init(struct tc_camera_module *cam_mod,
goto err;
}
mode = pltfrm_camera_module_get_flip_mirror(&cam_mod->sd);
if (mode != -1) {
cam_mod->hflip = mode & TC_MIRROR_BIT_MASK ? true : false;
cam_mod->vflip = mode & TC_FLIP_BIT_MASK ? true : false;
cam_mod->flip_flg = true;
}
return 0;
err:
pltfrm_camera_module_pr_err(&cam_mod->sd,

View File

@ -34,8 +34,8 @@
#define TC_CAMERA_MOUDLE_REG_VALUE_LEN_16BIT 2
#define TC_CAMERA_MOUDLE_REG_VALUE_LEN_32BIT 4
#define tc_camera_module_csi_config
#define TC_FLIP_BIT_MASK 0x2
#define TC_MIRROR_BIT_MASK 0x1
#define TC_FLIP_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_FLIP_BIT)
#define TC_MIRROR_BIT_MASK (1 << PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define TC_CAMERA_MODULE_CTRL_UPDT_GAIN 0x01
#define TC_CAMERA_MODULE_CTRL_UPDT_EXP_TIME 0x02
@ -101,7 +101,8 @@ struct tc_camera_module_config {
struct tc_camera_module_timings timings;
bool soft_reset;
bool ignore_measurement_check;
u8 max_exp_gain_h;
u8 max_exp_gain_l;
struct pltfrm_cam_itf itf_cfg;
};
@ -165,7 +166,8 @@ struct tc_camera_module_custom_config {
int (*g_ctrl)(struct tc_camera_module *cam_mod, u32 ctrl_id);
int (*g_timings)(struct tc_camera_module *cam_mod,
struct tc_camera_module_timings *timings);
int (*g_exposure_valid_frame)(struct tc_camera_module *cam_mod);
int (*s_vts)(struct tc_camera_module *cam_mod,
u32 vts);
int (*s_ext_ctrls)(struct tc_camera_module *cam_mod,
struct tc_camera_module_ext_ctrls *ctrls);
int (*set_flip)(
@ -179,6 +181,7 @@ struct tc_camera_module_custom_config {
struct tc_camera_module_config *configs;
u32 num_configs;
u32 power_up_delays_ms[3];
unsigned short exposure_valid_frame[2];
void *priv;
};
@ -210,9 +213,11 @@ struct tc_camera_module {
bool frm_intrvl_valid;
bool hflip;
bool vflip;
bool flip_flg;
u32 rotation;
void *pltfm_data;
bool inited;
struct mutex lock;
};
struct tc35x_priv {
@ -286,6 +291,10 @@ int tc_camera_module_s_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int tc_camera_module_g_frame_interval(
struct v4l2_subdev *sd,
struct v4l2_subdev_frame_interval *interval);
int tc_camera_module_s_stream(
struct v4l2_subdev *sd,
int enable);

View File

@ -46,6 +46,13 @@
#define PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT 0x01
#define PLTFRM_CAMERA_MODULE_REG_TYPE_DATA_SINGLE 0x1100
#define PLTFRM_CAMERA_MODULE_MIRROR_BIT 0
#define PLTFRM_CAMERA_MODULE_FLIP_BIT 1
#define PLTFRM_CAMERA_MODULE_IS_MIRROR(a) \
((a & PLTFRM_CAMERA_MODULE_MIRROR_BIT) == PLTFRM_CAMERA_MODULE_MIRROR_BIT)
#define PLTFRM_CAMERA_MODULE_IS_FLIP(a) \
((a & PLTFRM_CAMERA_MODULE_FLIP_BIT) == PLTFRM_CAMERA_MODULE_FLIP_BIT)
extern const char *PLTFRM_CAMERA_MODULE_PIN_PD;
extern const char *PLTFRM_CAMERA_MODULE_PIN_PWR;
extern const char *PLTFRM_CAMERA_MODULE_PIN_FLASH;
@ -143,6 +150,8 @@ const char *pltfrm_dev_string(struct v4l2_subdev *sd);
int pltfrm_camera_module_get_flip_mirror(
struct v4l2_subdev *sd);
int pltfrm_camera_module_pix_fmt2csi2_dt(int src_pix_fmt);
#define pltfrm_camera_module_pr_debug(dev, fmt, arg...) \
pr_debug("%s.%s: " fmt, \
pltfrm_dev_string(dev), __func__, ## arg)

View File

@ -56,6 +56,8 @@ struct isp_supplemental_sensor_mode_data {
unsigned char exposure_valid_frame[2];
int exp_time;
unsigned short gain;
unsigned char max_exp_gain_h;
unsigned char max_exp_gain_l;
};
struct camera_module_info_s {