drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c

Source file repositories/reference/linux-study-clean/drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c

File Facts

System
Linux kernel
Corpus path
drivers/media/i2c/s5c73m3/s5c73m3-ctrls.c
Extension
.c
Size
15114 bytes
Lines
554
Domain
Driver Families
Bucket
drivers/media
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

switch (ctrls->exposure_metering->val) {
		case V4L2_EXPOSURE_METERING_CENTER_WEIGHTED:
			metering = COMM_METERING_CENTER;
			break;
		case V4L2_EXPOSURE_METERING_SPOT:
			metering = COMM_METERING_SPOT;
			break;
		default:
			metering = COMM_METERING_AVERAGE;
			break;
		}

		ret = s5c73m3_isp_command(state, COMM_METERING, metering);
	}

	if (!ret && ctrls->exposure_bias->is_new) {
		u16 exp_bias = ctrls->exposure_bias->val;
		ret = s5c73m3_isp_command(state, COMM_EV, exp_bias);
	}

	v4l2_dbg(1, s5c73m3_dbg, sd,
		 "%s: exposure bias: %#x, metering: %#x (%d)\n",  __func__,
		 ctrls->exposure_bias->val, ctrls->exposure_metering->val, ret);

	return ret;
}

static int s5c73m3_set_white_balance(struct s5c73m3 *state, int val)
{
	static const unsigned short wb[][2] = {
		{ V4L2_WHITE_BALANCE_INCANDESCENT,  COMM_AWB_MODE_INCANDESCENT},
		{ V4L2_WHITE_BALANCE_FLUORESCENT,   COMM_AWB_MODE_FLUORESCENT1},
		{ V4L2_WHITE_BALANCE_FLUORESCENT_H, COMM_AWB_MODE_FLUORESCENT2},
		{ V4L2_WHITE_BALANCE_CLOUDY,        COMM_AWB_MODE_CLOUDY},
		{ V4L2_WHITE_BALANCE_DAYLIGHT,      COMM_AWB_MODE_DAYLIGHT},
		{ V4L2_WHITE_BALANCE_AUTO,          COMM_AWB_MODE_AUTO},
	};
	int i;

	for (i = 0; i < ARRAY_SIZE(wb); i++) {
		if (wb[i][0] != val)
			continue;

		v4l2_dbg(1, s5c73m3_dbg, &state->sensor_sd,
			 "Setting white balance to: %s\n",
			 v4l2_ctrl_get_menu(state->ctrls.auto_wb->id)[i]);

		return s5c73m3_isp_command(state, COMM_AWB_MODE, wb[i][1]);
	}

	return -EINVAL;
}

static int s5c73m3_af_run(struct s5c73m3 *state, bool on)
{
	struct s5c73m3_ctrls *c = &state->ctrls;

	if (!on)
		return s5c73m3_isp_command(state, COMM_AF_CON,
							COMM_AF_CON_STOP);

	if (c->focus_auto->val)
		return s5c73m3_isp_command(state, COMM_AF_MODE,
					   COMM_AF_MODE_PREVIEW_CAF_START);

	return s5c73m3_isp_command(state, COMM_AF_CON, COMM_AF_CON_START);
}

static int s5c73m3_3a_lock(struct s5c73m3 *state, struct v4l2_ctrl *ctrl)
{
	bool awb_lock = ctrl->val & V4L2_LOCK_WHITE_BALANCE;
	bool ae_lock = ctrl->val & V4L2_LOCK_EXPOSURE;
	bool af_lock = ctrl->val & V4L2_LOCK_FOCUS;
	int ret = 0;

	if ((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_EXPOSURE) {
		ret = s5c73m3_isp_command(state, COMM_AE_CON,
				ae_lock ? COMM_AE_STOP : COMM_AE_START);
		if (ret)
			return ret;
	}

	if (((ctrl->val ^ ctrl->cur.val) & V4L2_LOCK_WHITE_BALANCE)
	    && state->ctrls.auto_wb->val) {
		ret = s5c73m3_isp_command(state, COMM_AWB_CON,
			awb_lock ? COMM_AWB_STOP : COMM_AWB_START);
		if (ret)
			return ret;
	}

Annotation

Implementation Notes