/** * m5mols_do_scenemode() - Change current scenemode * @mode: Desired mode of the scenemode * * WARNING: The execution order is important. Do not change the order. */ int m5mols_do_scenemode(struct m5mols_info *info, u8 mode) { struct v4l2_subdev *sd = &info->sd; struct m5mols_scenemode scenemode = m5mols_default_scenemode[mode]; int ret; if (mode > REG_SCENE_CANDLE) return -EINVAL; ret = v4l2_ctrl_s_ctrl(info->lock_3a, 0); if (!ret) ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode); if (!ret) ret = m5mols_write(sd, AE_EV_PRESET_CAPTURE, mode); if (!ret) ret = m5mols_write(sd, AE_MODE, scenemode.metering); if (!ret) ret = m5mols_write(sd, AE_INDEX, scenemode.ev_bias); if (!ret) ret = m5mols_write(sd, AWB_MODE, scenemode.wb_mode); if (!ret) ret = m5mols_write(sd, AWB_MANUAL, scenemode.wb_preset); if (!ret) ret = m5mols_write(sd, MON_CHROMA_EN, scenemode.chroma_en); if (!ret) ret = m5mols_write(sd, MON_CHROMA_LVL, scenemode.chroma_lvl); if (!ret) ret = m5mols_write(sd, MON_EDGE_EN, scenemode.edge_en); if (!ret) ret = m5mols_write(sd, MON_EDGE_LVL, scenemode.edge_lvl); if (!ret && is_available_af(info)) ret = m5mols_write(sd, AF_MODE, scenemode.af_range); if (!ret && is_available_af(info)) ret = m5mols_write(sd, FD_CTL, scenemode.fd_mode); if (!ret) ret = m5mols_write(sd, MON_TONE_CTL, scenemode.tone); if (!ret) ret = m5mols_write(sd, AE_ISO, scenemode.iso); if (!ret) ret = m5mols_set_mode(info, REG_CAPTURE); if (!ret) ret = m5mols_write(sd, CAPP_WDR_EN, scenemode.wdr); if (!ret) ret = m5mols_write(sd, CAPP_MCC_MODE, scenemode.mcc); if (!ret) ret = m5mols_write(sd, CAPP_LIGHT_CTRL, scenemode.light); if (!ret) ret = m5mols_write(sd, CAPP_FLASH_CTRL, scenemode.flash); if (!ret) ret = m5mols_write(sd, CAPC_MODE, scenemode.capt_mode); if (!ret) ret = m5mols_set_mode(info, REG_MONITOR); return ret; }
static int m5mols_into_monitor(struct v4l2_subdev *sd, int res_size) { int ret; ret = m5mols_set_mode(sd, MODE_PARMSET); if (!ret) ret = i2c_w8_param(sd, CAT1_MONITOR_SIZE, (u8)res_size); if (!ret) ret = m5mols_set_mode(sd, MODE_PARMSET); return ret; }
int m5mols_start_capture(struct m5mols_info *info) { unsigned int framesize = info->cap.buf_size - M5MOLS_JPEG_TAGS_SIZE; struct v4l2_subdev *sd = &info->sd; int ret; /* * Synchronize the controls, set the capture frame resolution and color * format. The frame capture is initiated during switching from Monitor * to Capture mode. */ ret = m5mols_set_mode(info, REG_MONITOR); if (!ret) ret = m5mols_restore_controls(info); if (!ret) ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG); if (!ret) ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution); if (!ret) ret = m5mols_write(sd, CAPP_JPEG_SIZE_MAX, framesize); if (!ret) ret = m5mols_set_mode(info, REG_CAPTURE); if (!ret) /* Wait until a frame is captured to ISP internal memory */ ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); if (ret) return ret; /* * Initiate the captured data transfer to a MIPI-CSI receiver. */ ret = m5mols_write(sd, CAPC_SEL_FRAME, 1); if (!ret) ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN); if (!ret) { bool captured = false; unsigned int size; /* Wait for the capture completion interrupt */ ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000); if (!ret) { captured = true; ret = m5mols_capture_info(info); } size = captured ? info->cap.main : 0; v4l2_dbg(1, m5mols_debug, sd, "%s: size: %d, thumb.: %d B\n", __func__, size, info->cap.thumb); v4l2_subdev_notify(sd, S5P_FIMC_TX_END_NOTIFY, &size); } return ret; }
static int m5mols_into_capture(struct v4l2_subdev *sd, int res_size) { struct m5mols_info *info = to_m5mols(sd); u32 reg; int ret, timeout = 1; u32 temp = 0; info->captured = false; /* * The sequence of preparing Capture mode. * 1. Clear Interrupt bit (for dummy) * 2. Enable Capture bit at Interrupt * 3. Lock AE/AWB * 4. Enter Still Capture mode */ ret = m5mols_set_mode(sd, MODE_MONITOR); if (!ret) /* FIXME: setting capture exposure at the middle of a amount. */ ret = i2c_w16_ae(sd, CAT3_MANUAL_GAIN_CAP, 0x90); if (!ret) ret = m5mols_set_ae_lock(info, true); if (!ret) ret = m5mols_set_awb_lock(info, true); if (!ret) ret = i2c_r8_system(sd, CAT0_INT_FACTOR, ®); if (!ret) ret = i2c_w8_system(sd, CAT0_INT_ENABLE, 1 << INT_BIT_CAPTURE); if (!ret) ret = m5mols_set_mode(sd, MODE_CAPTURE); if (!ret) timeout = wait_event_interruptible_timeout(info->cap_wait, info->captured, msecs_to_jiffies(2000)); /* disable all interrupt & clear interrupt */ ret = i2c_w8_system(sd, CAT0_INT_ENABLE, 0x0); if (!ret) ret = i2c_r8_system(sd, CAT0_INT_FACTOR, ®); if (ret) return -EPERM; /* If all timeout exhausted, return error. */ if (!timeout) return -ETIMEDOUT; ret = i2c_r32_capt_ctrl(sd, CATC_CAP_IMAGE_SIZE, &temp); info->captured = false; return ret; }
/** * m5mols_s_power - Main sensor power control function * * To prevent breaking the lens when the sensor is powered off the Soft-Landing * algorithm is called where available. The Soft-Landing algorithm availability * dependends on the firmware provider. */ static int m5mols_s_power(struct v4l2_subdev *sd, int on) { struct m5mols_info *info = to_m5mols(sd); int ret; mutex_lock(&info->lock); if (on) { ret = m5mols_sensor_power(info, true); if (!ret) ret = m5mols_fw_start(sd); } else { if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { ret = m5mols_set_mode(info, REG_MONITOR); if (!ret) ret = m5mols_auto_focus_stop(info); if (ret < 0) v4l2_warn(sd, "Soft landing lens failed\n"); } ret = m5mols_sensor_power(info, false); info->ctrl_sync = 0; } mutex_unlock(&info->lock); return ret; }
/** * m5mols_s_power - Main sensor power control function * * To prevent breaking the lens when the sensor is powered off the Soft-Landing * algorithm is called where available. The Soft-Landing algorithm availability * dependends on the firmware provider. */ static int m5mols_s_power(struct v4l2_subdev *sd, int on) { struct m5mols_info *info = to_m5mols(sd); int ret; if (on) { ret = m5mols_sensor_power(info, true); if (!ret) ret = m5mols_fw_start(sd); return ret; } if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) { ret = m5mols_set_mode(info, REG_MONITOR); if (!ret) ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP); if (!ret) ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF); if (!ret) ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE, 0xff, -1); if (ret < 0) v4l2_warn(sd, "Soft landing lens failed\n"); } ret = m5mols_sensor_power(info, false); info->ctrl_sync = 0; return ret; }
/** * m5mols_start_monitor - Start the monitor mode * * Before applying the controls setup the resolution and frame rate * in PARAMETER mode, and then switch over to MONITOR mode. */ static int m5mols_start_monitor(struct m5mols_info *info) { struct v4l2_subdev *sd = &info->sd; int ret; ret = m5mols_set_mode(info, REG_PARAMETER); if (!ret) ret = m5mols_write(sd, PARM_MON_SIZE, info->resolution); if (!ret) ret = m5mols_write(sd, PARM_MON_FPS, REG_FPS_30); if (!ret) ret = m5mols_set_mode(info, REG_MONITOR); if (!ret) ret = m5mols_restore_controls(info); return ret; }
static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) { struct m5mols_info *info = to_m5mols(sd); u32 code = info->ffmt[info->res_type].code; if (enable) { int ret = -EINVAL; if (is_code(code, M5MOLS_RESTYPE_MONITOR)) ret = m5mols_start_monitor(info); if (is_code(code, M5MOLS_RESTYPE_CAPTURE)) ret = m5mols_start_capture(info); return ret; } return m5mols_set_mode(info, REG_PARAMETER); }
static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) { struct m5mols_info *info = to_m5mols(sd); if (enable) { if (info->code == to_code(M5MOLS_RES_MON)) { v4l2_info(sd, "%s : monitor mode\n", __func__); return m5mols_start_monitor(sd); } if (info->code == to_code(M5MOLS_RES_CAPTURE)) { v4l2_info(sd, "%s : capture mode\n", __func__); return m5mols_start_capture(sd); } return -EINVAL; } else { if (is_streaming(sd)) return m5mols_set_mode(sd, MODE_PARMSET); return -EINVAL; } }
static int m5mols_start_monitor(struct v4l2_subdev *sd) { return m5mols_set_mode(sd, MODE_MONITOR); }