drivers/media/i2c/s5k6a3.c

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

File Facts

System
Linux kernel
Corpus path
drivers/media/i2c/s5k6a3.c
Extension
.c
Size
9146 bytes
Lines
374
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

struct s5k6a3 {
	struct device *dev;
	struct v4l2_subdev subdev;
	struct media_pad pad;
	struct regulator_bulk_data supplies[S5K6A3_NUM_SUPPLIES];
	struct gpio_desc *gpio_reset;
	struct mutex lock;
	struct v4l2_mbus_framefmt format;
	struct clk *clock;
	int power_count;
};

static const char * const s5k6a3_supply_names[] = {
	[S5K6A3_SUPP_VDDA]	= "svdda",
	[S5K6A3_SUPP_VDDIO]	= "svddio",
	[S5K6A3_SUPP_AFVDD]	= "afvdd",
};

static inline struct s5k6a3 *sd_to_s5k6a3(struct v4l2_subdev *sd)
{
	return container_of(sd, struct s5k6a3, subdev);
}

static const struct v4l2_mbus_framefmt s5k6a3_formats[] = {
	{
		.code = MEDIA_BUS_FMT_SGRBG10_1X10,
		.colorspace = V4L2_COLORSPACE_SRGB,
		.field = V4L2_FIELD_NONE,
	}
};

static const struct v4l2_mbus_framefmt *find_sensor_format(
	struct v4l2_mbus_framefmt *mf)
{
	int i;

	for (i = 0; i < ARRAY_SIZE(s5k6a3_formats); i++)
		if (mf->code == s5k6a3_formats[i].code)
			return &s5k6a3_formats[i];

	return &s5k6a3_formats[0];
}

static int s5k6a3_enum_mbus_code(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *sd_state,
				  struct v4l2_subdev_mbus_code_enum *code)
{
	if (code->index >= ARRAY_SIZE(s5k6a3_formats))
		return -EINVAL;

	code->code = s5k6a3_formats[code->index].code;
	return 0;
}

static void s5k6a3_try_format(struct v4l2_mbus_framefmt *mf)
{
	const struct v4l2_mbus_framefmt *fmt;

	fmt = find_sensor_format(mf);
	mf->code = fmt->code;
	mf->field = V4L2_FIELD_NONE;
	v4l_bound_align_image(&mf->width, S5K6A3_SENSOR_MIN_WIDTH,
			      S5K6A3_SENSOR_MAX_WIDTH, 0,
			      &mf->height, S5K6A3_SENSOR_MIN_HEIGHT,
			      S5K6A3_SENSOR_MAX_HEIGHT, 0, 0);
}

static struct v4l2_mbus_framefmt *__s5k6a3_get_format(
		struct s5k6a3 *sensor, struct v4l2_subdev_state *sd_state,
		u32 pad, enum v4l2_subdev_format_whence which)
{
	if (which == V4L2_SUBDEV_FORMAT_TRY)
		return sd_state ? v4l2_subdev_state_get_format(sd_state, pad) : NULL;

	return &sensor->format;
}

static int s5k6a3_set_fmt(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *sd_state,
				  struct v4l2_subdev_format *fmt)
{
	struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
	struct v4l2_mbus_framefmt *mf;

	s5k6a3_try_format(&fmt->format);

	mf = __s5k6a3_get_format(sensor, sd_state, fmt->pad, fmt->which);
	if (mf) {
		mutex_lock(&sensor->lock);
		*mf = fmt->format;

Annotation

Implementation Notes