Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9346459a authored by Sylwester Nawrocki's avatar Sylwester Nawrocki Committed by Mauro Carvalho Chehab
Browse files

[media] m5mols: Add 3A lock control



Add control for locking automatic exposure, focus and white balance
adjustments. While at it, tidy up the data structure documentation.

Signed-off-by: default avatarSylwester Nawrocki <s.nawrocki@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent dd9c471d
Loading
Loading
Loading
Loading
+4 −6
Original line number Original line Diff line number Diff line
@@ -158,7 +158,7 @@ struct m5mols_version {
 * @ffmt: current fmt according to resolution type
 * @ffmt: current fmt according to resolution type
 * @res_type: current resolution type
 * @res_type: current resolution type
 * @irq_waitq: waitqueue for the capture
 * @irq_waitq: waitqueue for the capture
 * @flags: state variable for the interrupt handler
 * @irq_done: set to 1 in the interrupt handler
 * @handle: control handler
 * @handle: control handler
 * @auto_exposure: auto/manual exposure control
 * @auto_exposure: auto/manual exposure control
 * @exposure_bias: exposure compensation control
 * @exposure_bias: exposure compensation control
@@ -167,6 +167,7 @@ struct m5mols_version {
 * @auto_iso: auto/manual ISO sensitivity control
 * @auto_iso: auto/manual ISO sensitivity control
 * @iso: manual ISO sensitivity control
 * @iso: manual ISO sensitivity control
 * @auto_wb: auto white balance control
 * @auto_wb: auto white balance control
 * @lock_3a: 3A lock control
 * @colorfx: color effect control
 * @colorfx: color effect control
 * @saturation: saturation control
 * @saturation: saturation control
 * @zoom: zoom control
 * @zoom: zoom control
@@ -175,11 +176,9 @@ struct m5mols_version {
 * @jpeg_quality: JPEG compression quality control
 * @jpeg_quality: JPEG compression quality control
 * @ver: information of the version
 * @ver: information of the version
 * @cap: the capture mode attributes
 * @cap: the capture mode attributes
 * @power: current sensor's power status
 * @isp_ready: 1 when the ISP controller has completed booting
 * @isp_ready: 1 when the ISP controller has completed booting
 * @power: current sensor's power status
 * @ctrl_sync: 1 when the control handler state is restored in H/W
 * @ctrl_sync: 1 when the control handler state is restored in H/W
 * @lock_ae: true means the Auto Exposure is locked
 * @lock_awb: true means the Aut WhiteBalance is locked
 * @resolution:	register value for current resolution
 * @resolution:	register value for current resolution
 * @mode: register value for current operation mode
 * @mode: register value for current operation mode
 * @set_power: optional power callback to the board code
 * @set_power: optional power callback to the board code
@@ -209,6 +208,7 @@ struct m5mols_info {
	};
	};
	struct v4l2_ctrl *auto_wb;
	struct v4l2_ctrl *auto_wb;


	struct v4l2_ctrl *lock_3a;
	struct v4l2_ctrl *colorfx;
	struct v4l2_ctrl *colorfx;
	struct v4l2_ctrl *saturation;
	struct v4l2_ctrl *saturation;
	struct v4l2_ctrl *zoom;
	struct v4l2_ctrl *zoom;
@@ -223,8 +223,6 @@ struct m5mols_info {
	unsigned int power:1;
	unsigned int power:1;
	unsigned int ctrl_sync:1;
	unsigned int ctrl_sync:1;


	bool lock_ae;
	bool lock_awb;
	u8 resolution;
	u8 resolution;
	u8 mode;
	u8 mode;


+1 −6
Original line number Original line Diff line number Diff line
@@ -106,7 +106,6 @@ static int m5mols_capture_info(struct m5mols_info *info)
int m5mols_start_capture(struct m5mols_info *info)
int m5mols_start_capture(struct m5mols_info *info)
{
{
	struct v4l2_subdev *sd = &info->sd;
	struct v4l2_subdev *sd = &info->sd;
	u8 resolution = info->resolution;
	int ret;
	int ret;


	/*
	/*
@@ -120,16 +119,12 @@ int m5mols_start_capture(struct m5mols_info *info)
	if (!ret)
	if (!ret)
		ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
		ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
	if (!ret)
	if (!ret)
		ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, resolution);
		ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution);
	if (!ret)
		ret = m5mols_lock_3a(info, true);
	if (!ret)
	if (!ret)
		ret = m5mols_set_mode(info, REG_CAPTURE);
		ret = m5mols_set_mode(info, REG_CAPTURE);
	if (!ret)
	if (!ret)
		/* Wait until a frame is captured to ISP internal memory */
		/* Wait until a frame is captured to ISP internal memory */
		ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
		ret = m5mols_wait_interrupt(sd, REG_INT_CAPTURE, 2000);
	if (!ret)
		ret = m5mols_lock_3a(info, false);
	if (ret)
	if (ret)
		return ret;
		return ret;


+55 −34
Original line number Original line Diff line number Diff line
@@ -139,7 +139,7 @@ int m5mols_do_scenemode(struct m5mols_info *info, u8 mode)
	if (mode > REG_SCENE_CANDLE)
	if (mode > REG_SCENE_CANDLE)
		return -EINVAL;
		return -EINVAL;


	ret = m5mols_lock_3a(info, false);
	ret = v4l2_ctrl_s_ctrl(info->lock_3a, 0);
	if (!ret)
	if (!ret)
		ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode);
		ret = m5mols_write(sd, AE_EV_PRESET_MONITOR, mode);
	if (!ret)
	if (!ret)
@@ -186,42 +186,34 @@ int m5mols_do_scenemode(struct m5mols_info *info, u8 mode)
	return ret;
	return ret;
}
}


static int m5mols_lock_ae(struct m5mols_info *info, bool lock)
static int m5mols_3a_lock(struct m5mols_info *info, struct v4l2_ctrl *ctrl)
{
{
	bool af_lock = ctrl->val & V4L2_LOCK_FOCUS;
	int ret = 0;
	int ret = 0;


	if (info->lock_ae != lock)
	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) {
		ret = m5mols_write(&info->sd, AE_LOCK,
		bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE;
				lock ? REG_AE_LOCK : REG_AE_UNLOCK);
	if (!ret)
		info->lock_ae = lock;


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


static int m5mols_lock_awb(struct m5mols_info *info, bool lock)
	if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE)
{
	    && info->auto_wb->val) {
	int ret = 0;
		bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE;

	if (info->lock_awb != lock)
		ret = m5mols_write(&info->sd, AWB_LOCK,
				lock ? REG_AWB_LOCK : REG_AWB_UNLOCK);
	if (!ret)
		info->lock_awb = lock;


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


/* m5mols_lock_3a() - Lock 3A(Auto Exposure, Auto Whitebalance, Auto Focus) */
	if (!info->ver.af || !af_lock)
int m5mols_lock_3a(struct m5mols_info *info, bool lock)
		return ret;
{
	int ret;


	ret = m5mols_lock_ae(info, lock);
	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_FOCUS)
	if (!ret)
		ret = m5mols_lock_awb(info, lock);
	/* Don't need to handle unlocking AF */
	if (!ret && is_available_af(info) && lock)
		ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
		ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);


	return ret;
	return ret;
@@ -249,13 +241,13 @@ static int m5mols_set_metering_mode(struct m5mols_info *info, int mode)
static int m5mols_set_exposure(struct m5mols_info *info, int exposure)
static int m5mols_set_exposure(struct m5mols_info *info, int exposure)
{
{
	struct v4l2_subdev *sd = &info->sd;
	struct v4l2_subdev *sd = &info->sd;
	int ret;
	int ret = 0;

	ret = m5mols_lock_ae(info, exposure != V4L2_EXPOSURE_AUTO);
	if (ret < 0)
		return ret;


	if (exposure == V4L2_EXPOSURE_AUTO) {
	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);
		ret = m5mols_set_metering_mode(info, info->metering->val);
		if (ret < 0)
		if (ret < 0)
			return ret;
			return ret;
@@ -429,6 +421,26 @@ static int m5mols_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
		if (status != REG_ISO_AUTO)
		if (status != REG_ISO_AUTO)
			info->iso->val = status - 1;
			info->iso->val = status - 1;
		break;
		break;

	case V4L2_CID_3A_LOCK:
		ctrl->val &= ~0x7;

		ret = m5mols_read_u8(sd, AE_LOCK, &status);
		if (ret)
			return ret;
		if (status)
			info->lock_3a->val |= V4L2_LOCK_EXPOSURE;

		ret = m5mols_read_u8(sd, AWB_LOCK, &status);
		if (ret)
			return ret;
		if (status)
			info->lock_3a->val |= V4L2_LOCK_EXPOSURE;

		ret = m5mols_read_u8(sd, AF_EXECUTE, &status);
		if (!status)
			info->lock_3a->val |= V4L2_LOCK_EXPOSURE;
		break;
	}
	}


	return ret;
	return ret;
@@ -461,6 +473,10 @@ static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl)
	}
	}


	switch (ctrl->id) {
	switch (ctrl->id) {
	case V4L2_CID_3A_LOCK:
		ret = m5mols_3a_lock(info, ctrl);
		break;

	case V4L2_CID_ZOOM_ABSOLUTE:
	case V4L2_CID_ZOOM_ABSOLUTE:
		ret = m5mols_write(sd, MON_ZOOM, ctrl->val);
		ret = m5mols_write(sd, MON_ZOOM, ctrl->val);
		break;
		break;
@@ -585,6 +601,9 @@ int m5mols_init_controls(struct v4l2_subdev *sd)
	info->jpeg_quality = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
	info->jpeg_quality = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
			V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 80);
			V4L2_CID_JPEG_COMPRESSION_QUALITY, 1, 100, 1, 80);


	info->lock_3a = v4l2_ctrl_new_std(&info->handle, &m5mols_ctrl_ops,
			V4L2_CID_3A_LOCK, 0, 0x7, 0, 0);

	if (info->handle.error) {
	if (info->handle.error) {
		int ret = info->handle.error;
		int ret = info->handle.error;
		v4l2_err(sd, "Failed to initialize controls: %d\n", ret);
		v4l2_err(sd, "Failed to initialize controls: %d\n", ret);
@@ -597,6 +616,8 @@ int m5mols_init_controls(struct v4l2_subdev *sd)
				V4L2_CTRL_FLAG_UPDATE;
				V4L2_CTRL_FLAG_UPDATE;
	v4l2_ctrl_auto_cluster(2, &info->auto_iso, 0, false);
	v4l2_ctrl_auto_cluster(2, &info->auto_iso, 0, false);


	info->lock_3a->flags |= V4L2_CTRL_FLAG_VOLATILE;

	m5mols_set_ctrl_mode(info->auto_exposure, REG_PARAMETER);
	m5mols_set_ctrl_mode(info->auto_exposure, REG_PARAMETER);
	m5mols_set_ctrl_mode(info->auto_wb, REG_PARAMETER);
	m5mols_set_ctrl_mode(info->auto_wb, REG_PARAMETER);
	m5mols_set_ctrl_mode(info->colorfx, REG_MONITOR);
	m5mols_set_ctrl_mode(info->colorfx, REG_MONITOR);