diff --git a/drivers/media/i2c/soc_camera/rockchip/adv7181_v4l2-i2c-subdev.c b/drivers/media/i2c/soc_camera/rockchip/adv7181_v4l2-i2c-subdev.c index 5908294b73e7..332521bb330e 100644 --- a/drivers/media/i2c/soc_camera/rockchip/adv7181_v4l2-i2c-subdev.c +++ b/drivers/media/i2c/soc_camera/rockchip/adv7181_v4l2-i2c-subdev.c @@ -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( diff --git a/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.c b/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.c index 034c12143015..96ba4f824e31 100644 --- a/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.c +++ b/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.c @@ -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, diff --git a/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.h b/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.h index 85b7442ff224..392ba60be313 100644 --- a/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.h +++ b/drivers/media/i2c/soc_camera/rockchip/adv_camera_module.h @@ -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); diff --git a/drivers/media/i2c/soc_camera/rockchip/aptina_camera_module.c b/drivers/media/i2c/soc_camera/rockchip/aptina_camera_module.c index 79a63caa7bbb..2aed92387b2d 100644 --- a/drivers/media/i2c/soc_camera/rockchip/aptina_camera_module.c +++ b/drivers/media/i2c/soc_camera/rockchip/aptina_camera_module.c @@ -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, diff --git a/drivers/media/i2c/soc_camera/rockchip/aptina_camera_module.h b/drivers/media/i2c/soc_camera/rockchip/aptina_camera_module.h index 9f053051cb9c..415f74d464af 100644 --- a/drivers/media/i2c/soc_camera/rockchip/aptina_camera_module.h +++ b/drivers/media/i2c/soc_camera/rockchip/aptina_camera_module.h @@ -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); diff --git a/drivers/media/i2c/soc_camera/rockchip/imx323_v4l2-i2c-subdev.c b/drivers/media/i2c/soc_camera/rockchip/imx323_v4l2-i2c-subdev.c index b39afa63851b..94c428357411 100644 --- a/drivers/media/i2c/soc_camera/rockchip/imx323_v4l2-i2c-subdev.c +++ b/drivers/media/i2c/soc_camera/rockchip/imx323_v4l2-i2c-subdev.c @@ -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"); diff --git a/drivers/media/i2c/soc_camera/rockchip/imx_camera_module.c b/drivers/media/i2c/soc_camera/rockchip/imx_camera_module.c index 217151826903..8cccfe425de3 100644 --- a/drivers/media/i2c/soc_camera/rockchip/imx_camera_module.c +++ b/drivers/media/i2c/soc_camera/rockchip/imx_camera_module.c @@ -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, diff --git a/drivers/media/i2c/soc_camera/rockchip/imx_camera_module.h b/drivers/media/i2c/soc_camera/rockchip/imx_camera_module.h index ffd135ab672f..d0f691d8fddd 100644 --- a/drivers/media/i2c/soc_camera/rockchip/imx_camera_module.h +++ b/drivers/media/i2c/soc_camera/rockchip/imx_camera_module.h @@ -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); diff --git a/drivers/media/i2c/soc_camera/rockchip/nt99230_v4l2-i2c-subdev.c b/drivers/media/i2c/soc_camera/rockchip/nt99230_v4l2-i2c-subdev.c index a8d9200f97fd..cb88fb06c6f5 100644 --- a/drivers/media/i2c/soc_camera/rockchip/nt99230_v4l2-i2c-subdev.c +++ b/drivers/media/i2c/soc_camera/rockchip/nt99230_v4l2-i2c-subdev.c @@ -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"); diff --git a/drivers/media/i2c/soc_camera/rockchip/ov13850_v4l2-i2c-subdev.c b/drivers/media/i2c/soc_camera/rockchip/ov13850_v4l2-i2c-subdev.c index a16a520fd993..7394ef3ce80a 100644 --- a/drivers/media/i2c/soc_camera/rockchip/ov13850_v4l2-i2c-subdev.c +++ b/drivers/media/i2c/soc_camera/rockchip/ov13850_v4l2-i2c-subdev.c @@ -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"); diff --git a/drivers/media/i2c/soc_camera/rockchip/ov2710_v4l2-i2c-subdev.c b/drivers/media/i2c/soc_camera/rockchip/ov2710_v4l2-i2c-subdev.c index 3a1b7878885a..0b600a95b4c7 100644 --- a/drivers/media/i2c/soc_camera/rockchip/ov2710_v4l2-i2c-subdev.c +++ b/drivers/media/i2c/soc_camera/rockchip/ov2710_v4l2-i2c-subdev.c @@ -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"); diff --git a/drivers/media/i2c/soc_camera/rockchip/ov4689_v4l2-i2c-subdev.c b/drivers/media/i2c/soc_camera/rockchip/ov4689_v4l2-i2c-subdev.c index 12c554e6fb6a..f327446ccd45 100644 --- a/drivers/media/i2c/soc_camera/rockchip/ov4689_v4l2-i2c-subdev.c +++ b/drivers/media/i2c/soc_camera/rockchip/ov4689_v4l2-i2c-subdev.c @@ -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"); diff --git a/drivers/media/i2c/soc_camera/rockchip/ov7675_v4l2-i2c-subdev.c b/drivers/media/i2c/soc_camera/rockchip/ov7675_v4l2-i2c-subdev.c index a3b0a12a7a1b..b4559fe4f198 100644 --- a/drivers/media/i2c/soc_camera/rockchip/ov7675_v4l2-i2c-subdev.c +++ b/drivers/media/i2c/soc_camera/rockchip/ov7675_v4l2-i2c-subdev.c @@ -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( diff --git a/drivers/media/i2c/soc_camera/rockchip/ov7750_v4l2-i2c-subdev.c b/drivers/media/i2c/soc_camera/rockchip/ov7750_v4l2-i2c-subdev.c index 190df0f1792a..6d396bbf3efe 100644 --- a/drivers/media/i2c/soc_camera/rockchip/ov7750_v4l2-i2c-subdev.c +++ b/drivers/media/i2c/soc_camera/rockchip/ov7750_v4l2-i2c-subdev.c @@ -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"); diff --git a/drivers/media/i2c/soc_camera/rockchip/ov8858_v4l2-i2c-subdev.c b/drivers/media/i2c/soc_camera/rockchip/ov8858_v4l2-i2c-subdev.c index 60bd0ea5e2f2..51680bd7f55c 100644 --- a/drivers/media/i2c/soc_camera/rockchip/ov8858_v4l2-i2c-subdev.c +++ b/drivers/media/i2c/soc_camera/rockchip/ov8858_v4l2-i2c-subdev.c @@ -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); diff --git a/drivers/media/i2c/soc_camera/rockchip/ov_camera_module.c b/drivers/media/i2c/soc_camera/rockchip/ov_camera_module.c index f58c0a84b78c..b29bf6c314bc 100644 --- a/drivers/media/i2c/soc_camera/rockchip/ov_camera_module.c +++ b/drivers/media/i2c/soc_camera/rockchip/ov_camera_module.c @@ -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, diff --git a/drivers/media/i2c/soc_camera/rockchip/ov_camera_module.h b/drivers/media/i2c/soc_camera/rockchip/ov_camera_module.h index 139406248cd5..11644dc47834 100644 --- a/drivers/media/i2c/soc_camera/rockchip/ov_camera_module.h +++ b/drivers/media/i2c/soc_camera/rockchip/ov_camera_module.h @@ -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); diff --git a/drivers/media/i2c/soc_camera/rockchip/rk_camera_module.c b/drivers/media/i2c/soc_camera/rockchip/rk_camera_module.c index 4ac9eaab06ea..dccfd4fd916a 100644 --- a/drivers/media/i2c/soc_camera/rockchip/rk_camera_module.c +++ b/drivers/media/i2c/soc_camera/rockchip/rk_camera_module.c @@ -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 diff --git a/drivers/media/i2c/soc_camera/rockchip/tc358749xbg_v4l2-i2c-subdev.c b/drivers/media/i2c/soc_camera/rockchip/tc358749xbg_v4l2-i2c-subdev.c index e93961638c61..3e30160f32dc 100644 --- a/drivers/media/i2c/soc_camera/rockchip/tc358749xbg_v4l2-i2c-subdev.c +++ b/drivers/media/i2c/soc_camera/rockchip/tc358749xbg_v4l2-i2c-subdev.c @@ -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( diff --git a/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.c b/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.c index 229444c1eed5..2fc97149be55 100644 --- a/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.c +++ b/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.c @@ -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, diff --git a/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.h b/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.h index 2cb594df2cad..673f6c284bf4 100644 --- a/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.h +++ b/drivers/media/i2c/soc_camera/rockchip/tc_camera_module.h @@ -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); diff --git a/include/linux/platform_data/rk_isp10_platform_camera_module.h b/include/linux/platform_data/rk_isp10_platform_camera_module.h index 154694d42c66..41c6c03dd488 100644 --- a/include/linux/platform_data/rk_isp10_platform_camera_module.h +++ b/include/linux/platform_data/rk_isp10_platform_camera_module.h @@ -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) diff --git a/include/media/v4l2-config_rockchip.h b/include/media/v4l2-config_rockchip.h index 0f2cfb6b3c5a..e5550903dcdb 100644 --- a/include/media/v4l2-config_rockchip.h +++ b/include/media/v4l2-config_rockchip.h @@ -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 {