コード例 #1
0
/**
 * 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;
}
コード例 #2
0
/**
 * m5mols_fw_start - M-5MOLS internal ARM controller initialization
 *
 * Execute the M-5MOLS internal ARM controller initialization sequence.
 * This function should be called after the supply voltage has been
 * applied and before any requests to the device are made.
 */
static int m5mols_fw_start(struct v4l2_subdev *sd)
{
	struct m5mols_info *info = to_m5mols(sd);
	int ret;

	atomic_set(&info->irq_done, 0);
	/* Wait until I2C slave is initialized in Flash Writer mode */
	ret = m5mols_busy_wait(sd, FLASH_CAM_START, REG_IN_FLASH_MODE,
			       M5MOLS_I2C_RDY_WAIT_FL | 0xff, -1);
	if (!ret)
		ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
	if (!ret)
		ret = m5mols_wait_interrupt(sd, REG_INT_MODE, 2000);
	if (ret < 0)
		return ret;

	info->isp_ready = 1;

	ret = m5mols_get_version(sd);
	if (!ret)
		ret = m5mols_update_fw(sd, m5mols_sensor_power);
	if (ret)
		return ret;

	v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n");

	ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI);
	if (!ret)
		ret = m5mols_enable_interrupt(sd,
				REG_INT_AF | REG_INT_CAPTURE);

	return ret;
}
コード例 #3
0
static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
{
	bool af_lock = ctrl->val & V4L2_LOCK_FOCUS;
	int ret = 0;

	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) {
		bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE;

		ret = m5mols_write(&info->sd, AE_LOCK, ae_lock ?
				   REG_AE_LOCK : REG_AE_UNLOCK);
		if (ret)
			return ret;
	}

	if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE)
	    && info->auto_wb->val) {
		bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE;

		ret = m5mols_write(&info->sd, AWB_LOCK, awb_lock ?
				   REG_AWB_LOCK : REG_AWB_UNLOCK);
		if (ret)
			return ret;
	}

	if (!info->ver.af || !af_lock)
		return ret;

	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS)
		ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);

	return ret;
}
コード例 #4
0
/* Execute the lens soft-landing algorithm */
static int m5mols_auto_focus_stop(struct m5mols_info *info)
{
	int ret;

	ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
	if (!ret)
		ret = m5mols_write(&info->sd, AF_MODE, REG_AF_POWEROFF);
	if (!ret)
		ret = m5mols_busy_wait(&info->sd, SYSTEM_STATUS, REG_AF_IDLE,
				       0xff, -1);
	return ret;
}
コード例 #5
0
ファイル: m5mols_capture.c プロジェクト: AlexShiLucky/linux
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;
}
コード例 #6
0
/**
 * 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;
}
コード例 #7
0
/**
 * m5mols_reg_mode - Write the mode and check busy status
 *
 * It always accompanies a little delay changing the M-5MOLS mode, so it is
 * needed checking current busy status to guarantee right mode.
 */
static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
{
	int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);
	if (ret < 0)
		return ret;
	return m5mols_busy_wait(sd, SYSTEM_SYSMODE, mode, 0xff,
				M5MOLS_MODE_CHANGE_TIMEOUT);
}
コード例 #8
0
ファイル: m5mols_core.c プロジェクト: 303750856/linux-3.1
/**
 * 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_sensor_armboot(sd);
		if (!ret)
			ret = m5mols_init_controls(info);
		if (ret)
			return ret;

		info->ffmt[M5MOLS_RESTYPE_MONITOR] =
			m5mols_default_ffmt[M5MOLS_RESTYPE_MONITOR];
		info->ffmt[M5MOLS_RESTYPE_CAPTURE] =
			m5mols_default_ffmt[M5MOLS_RESTYPE_CAPTURE];
		return ret;
	}

	if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
		ret = m5mols_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(sd, CAT_SYSTEM, CAT0_STATUS,
					REG_AF_IDLE);
		if (!ret)
			v4l2_info(sd, "Success soft-landing lens\n");
	}

	ret = m5mols_sensor_power(info, false);
	if (!ret) {
		v4l2_ctrl_handler_free(&info->handle);
		info->ctrl_sync = false;
	}

	return ret;
}
コード例 #9
0
/**
 * m5mols_enable_interrupt - Clear interrupt pending bits and unmask interrupts
 *
 * Before writing desired interrupt value the INT_FACTOR register should
 * be read to clear pending interrupts.
 */
int m5mols_enable_interrupt(struct v4l2_subdev *sd, u8 reg)
{
	struct m5mols_info *info = to_m5mols(sd);
	u8 mask = is_available_af(info) ? REG_INT_AF : 0;
	u8 dummy;
	int ret;

	ret = m5mols_read_u8(sd, SYSTEM_INT_FACTOR, &dummy);
	if (!ret)
		ret = m5mols_write(sd, SYSTEM_INT_ENABLE, reg & ~mask);
	return ret;
}
コード例 #10
0
static int m5mols_set_exposure(struct m5mols_info *info, int exposure)
{
	struct v4l2_subdev *sd = &info->sd;
	int ret = 0;

	if (exposure == V4L2_EXPOSURE_AUTO) {
		/* Unlock auto exposure */
		info->lock_3a->val &= ~V4L2_LOCK_EXPOSURE;
		m5mols_3a_lock(info, info->lock_3a);

		ret = m5mols_set_metering_mode(info, info->metering->val);
		if (ret < 0)
			return ret;

		v4l2_dbg(1, m5mols_debug, sd,
			 "%s: exposure bias: %#x, metering: %#x\n",
			 __func__, info->exposure_bias->val,
			 info->metering->val);

		return m5mols_write(sd, AE_INDEX, info->exposure_bias->val);
	}

	if (exposure == V4L2_EXPOSURE_MANUAL) {
		ret = m5mols_write(sd, AE_MODE, REG_AE_OFF);
		if (ret == 0)
			ret = m5mols_write(sd, AE_MAN_GAIN_MON,
					   info->exposure->val);
		if (ret == 0)
			ret = m5mols_write(sd, AE_MAN_GAIN_CAP,
					   info->exposure->val);

		v4l2_dbg(1, m5mols_debug, sd, "%s: exposure: %#x\n",
			 __func__, info->exposure->val);
	}

	return ret;
}
コード例 #11
0
ファイル: m5mols_core.c プロジェクト: 303750856/linux-3.1
/**
 * m5mols_sensor_armboot - Booting M-5MOLS internal ARM core.
 *
 * Booting internal ARM core makes the M-5MOLS is ready for getting commands
 * with I2C. It's the first thing to be done after it powered up. It must wait
 * at least 520ms recommended by M-5MOLS datasheet, after executing arm booting.
 */
static int m5mols_sensor_armboot(struct v4l2_subdev *sd)
{
	int ret;

	ret = m5mols_write(sd, FLASH_CAM_START, REG_START_ARM_BOOT);
	if (ret < 0)
		return ret;

	msleep(520);

	ret = m5mols_get_version(sd);
	if (!ret)
		ret = m5mols_update_fw(sd, m5mols_sensor_power);
	if (ret)
		return ret;

	v4l2_dbg(1, m5mols_debug, sd, "Success ARM Booting\n");

	ret = m5mols_write(sd, PARM_INTERFACE, REG_INTERFACE_MIPI);
	if (!ret)
		ret = m5mols_enable_interrupt(sd, REG_INT_AF);

	return ret;
}
コード例 #12
0
ファイル: m5mols_capture.c プロジェクト: CSCLOG/beaglebone
static int m5mols_capture_error_handler(struct m5mols_info *info,
					int timeout)
{
	int ret;

	/* Disable all interrupts and clear relevant interrupt staus bits */
	ret = m5mols_write(&info->sd, SYSTEM_INT_ENABLE,
			   info->interrupt & ~(REG_INT_CAPTURE));
	if (ret)
		return ret;

	if (timeout == 0)
		return -ETIMEDOUT;

	return 0;
}
コード例 #13
0
static int m5mols_set_metering_mode(struct m5mols_info *info, int mode)
{
	unsigned int metering;

	switch (mode) {
	case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
		metering = REG_AE_CENTER;
		break;
	case V4L2_EXPOSURE_METERING_SPOT:
		metering = REG_AE_SPOT;
		break;
	default:
		metering = REG_AE_ALL;
		break;
	}

	return m5mols_write(&info->sd, AE_MODE, metering);
}
コード例 #14
0
ファイル: m5mols_capture.c プロジェクト: CSCLOG/beaglebone
int m5mols_start_capture(struct m5mols_info *info)
{
	struct v4l2_subdev *sd = &info->sd;
	u8 resolution = info->resolution;
	int timeout;
	int ret;

	/*
	 * Preparing capture. Setting control & interrupt before entering
	 * capture mode
	 *
	 * 1) change to MONITOR mode for operating control & interrupt
	 * 2) set controls (considering v4l2_control value & lock 3A)
	 * 3) set interrupt
	 * 4) change to CAPTURE mode
	 */
	ret = m5mols_mode(info, REG_MONITOR);
	if (!ret)
		ret = m5mols_sync_controls(info);
	if (!ret)
		ret = m5mols_lock_3a(info, true);
	if (!ret)
		ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);
	if (!ret)
		ret = m5mols_mode(info, REG_CAPTURE);
	if (!ret) {
		/* Wait for capture interrupt, after changing capture mode */
		timeout = wait_event_interruptible_timeout(info->irq_waitq,
					   test_bit(ST_CAPT_IRQ, &info->flags),
					   msecs_to_jiffies(2000));
		if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags))
			ret = m5mols_capture_error_handler(info, timeout);
	}
	if (!ret)
		ret = m5mols_lock_3a(info, false);
	if (ret)
		return ret;
	/*
	 * Starting capture. Setting capture frame count and resolution and
	 * the format(available format: JPEG, Bayer RAW, YUV).
	 *
	 * 1) select single or multi(enable to 25), format, size
	 * 2) set interrupt
	 * 3) start capture(for main image, now)
	 * 4) get information
	 * 5) notify file size to v4l2 device(e.g, to s5p-fimc v4l2 device)
	 */
	ret = m5mols_write(sd, CAPC_SEL_FRAME, 1);
	if (!ret)
		ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
	if (!ret)
		ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution);
	if (!ret)
		ret = m5mols_enable_interrupt(sd, REG_INT_CAPTURE);
	if (!ret)
		ret = m5mols_write(sd, CAPC_START, REG_CAP_START_MAIN);
	if (!ret) {
		/* Wait for the capture completion interrupt */
		timeout = wait_event_interruptible_timeout(info->irq_waitq,
					   test_bit(ST_CAPT_IRQ, &info->flags),
					   msecs_to_jiffies(2000));
		if (test_and_clear_bit(ST_CAPT_IRQ, &info->flags)) {
			ret = m5mols_capture_info(info);
			if (!ret)
				v4l2_subdev_notify(sd, 0, &info->cap.total);
		}
	}

	return m5mols_capture_error_handler(info, timeout);
}
コード例 #15
0
ファイル: m5mols_core.c プロジェクト: 303750856/linux-3.1
/**
 * m5mols_reg_mode - Write the mode and check busy status
 *
 * It always accompanies a little delay changing the M-5MOLS mode, so it is
 * needed checking current busy status to guarantee right mode.
 */
static int m5mols_reg_mode(struct v4l2_subdev *sd, u8 mode)
{
	int ret = m5mols_write(sd, SYSTEM_SYSMODE, mode);

	return ret ? ret : m5mols_busy(sd, CAT_SYSTEM, CAT0_SYSMODE, mode);
}
コード例 #16
0
/**
 * 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;
}