Commit 9783b96a authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab
Browse files

media: atomisp: gc0310: Modernize and simply set_fmt(), get_fmt(), etc.



There only is 1 supported resolution allowing significant simplification
of the code; and also bring the code up2date with current subdev fmt
handling practices.

Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@kernel.org>
parent 2b2297b1
Loading
Loading
Loading
Loading
+40 −87
Original line number Diff line number Diff line
@@ -132,10 +132,6 @@ static int gc0310_init(struct v4l2_subdev *sd)
	if (ret)
		goto out_unlock;

	/* restore settings */
	gc0310_res = gc0310_res_preview;
	N_RES = N_RES_PREVIEW;

	/* restore value of all ctrls */
	ret = __v4l2_ctrl_handler_setup(&dev->ctrls.handler);

@@ -296,76 +292,50 @@ static int gc0310_s_power(struct v4l2_subdev *sd, int on)
	return gc0310_init(sd);
}

/* TODO: remove it. */
static int startup(struct v4l2_subdev *sd)
static struct v4l2_mbus_framefmt *
gc0310_get_pad_format(struct gc0310_device *dev,
		      struct v4l2_subdev_state *state,
		      unsigned int pad, enum v4l2_subdev_format_whence which)
{
	struct gc0310_device *dev = to_gc0310_sensor(sd);
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	int ret = 0;
	if (which == V4L2_SUBDEV_FORMAT_TRY)
		return v4l2_subdev_get_try_format(&dev->sd, state, pad);

	ret = gc0310_write_reg_array(client, dev->res->regs, dev->res->reg_count);
	if (ret) {
		dev_err(&client->dev, "gc0310 write register err.\n");
		return ret;
	return &dev->mode.fmt;
}

	return ret;
/* The GC0310 currently only supports 1 fixed fmt */
static void gc0310_fill_format(struct v4l2_mbus_framefmt *fmt)
{
	memset(fmt, 0, sizeof(*fmt));
	fmt->width = GC0310_NATIVE_WIDTH;
	fmt->height = GC0310_NATIVE_HEIGHT;
	fmt->field = V4L2_FIELD_NONE;
	fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;
}

static int gc0310_set_fmt(struct v4l2_subdev *sd,
			  struct v4l2_subdev_state *sd_state,
			  struct v4l2_subdev_format *format)
{
	struct v4l2_mbus_framefmt *fmt = &format->format;
	struct gc0310_device *dev = to_gc0310_sensor(sd);
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct camera_mipi_info *gc0310_info = NULL;
	struct gc0310_resolution *res;
	int ret = 0;

	if (format->pad)
		return -EINVAL;

	if (!fmt)
		return -EINVAL;

	gc0310_info = v4l2_get_subdev_hostdata(sd);
	if (!gc0310_info)
		return -EINVAL;

	mutex_lock(&dev->input_lock);

	res = v4l2_find_nearest_size(gc0310_res_preview,
				     ARRAY_SIZE(gc0310_res_preview), width,
				     height, fmt->width, fmt->height);
	if (!res)
		res = &gc0310_res_preview[N_RES - 1];
	struct gc0310_device *dev = to_gc0310_sensor(sd);
	struct v4l2_mbus_framefmt *fmt;
	int ret;

	fmt->width = res->width;
	fmt->height = res->height;
	dev->res = res;
	fmt = gc0310_get_pad_format(dev, sd_state, format->pad, format->which);
	gc0310_fill_format(fmt);

	fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;
	format->format = *fmt;

	if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
		sd_state->pads->try_fmt = *fmt;
		mutex_unlock(&dev->input_lock);
	if (format->which == V4L2_SUBDEV_FORMAT_TRY)
		return 0;
	}

	mutex_lock(&dev->input_lock);
	/* s_power has not been called yet for std v4l2 clients (camorama) */
	power_up(sd);

	dev_dbg(&client->dev, "%s: before gc0310_write_reg_array %s\n",
		__func__, dev->res->desc);
	ret = startup(sd);
	if (ret) {
		dev_err(&client->dev, "gc0310 startup err\n");
		goto err;
	}

err:
	ret = gc0310_write_reg_array(client, gc0310_VGA_30fps, ARRAY_SIZE(gc0310_VGA_30fps));
	mutex_unlock(&dev->input_lock);

	return ret;
}

@@ -373,19 +343,11 @@ static int gc0310_get_fmt(struct v4l2_subdev *sd,
			  struct v4l2_subdev_state *sd_state,
			  struct v4l2_subdev_format *format)
{
	struct v4l2_mbus_framefmt *fmt = &format->format;
	struct gc0310_device *dev = to_gc0310_sensor(sd);
	struct v4l2_mbus_framefmt *fmt;

	if (format->pad)
		return -EINVAL;

	if (!fmt)
		return -EINVAL;

	fmt->width = dev->res->width;
	fmt->height = dev->res->height;
	fmt->code = MEDIA_BUS_FMT_SGRBG8_1X8;

	fmt = gc0310_get_pad_format(dev, sd_state, format->pad, format->which);
	format->format = *fmt;
	return 0;
}

@@ -518,10 +480,8 @@ static int gc0310_s_config(struct v4l2_subdev *sd,
static int gc0310_g_frame_interval(struct v4l2_subdev *sd,
				   struct v4l2_subdev_frame_interval *interval)
{
	struct gc0310_device *dev = to_gc0310_sensor(sd);

	interval->interval.numerator = 1;
	interval->interval.denominator = dev->res->fps;
	interval->interval.denominator = GC0310_FPS;

	return 0;
}
@@ -530,7 +490,8 @@ static int gc0310_enum_mbus_code(struct v4l2_subdev *sd,
				 struct v4l2_subdev_state *sd_state,
				 struct v4l2_subdev_mbus_code_enum *code)
{
	if (code->index >= MAX_FMTS)
	/* We support only a single format */
	if (code->index)
		return -EINVAL;

	code->code = MEDIA_BUS_FMT_SGRBG8_1X8;
@@ -541,27 +502,21 @@ static int gc0310_enum_frame_size(struct v4l2_subdev *sd,
				  struct v4l2_subdev_state *sd_state,
				  struct v4l2_subdev_frame_size_enum *fse)
{
	int index = fse->index;

	if (index >= N_RES)
	/* We support only a single resolution */
	if (fse->index)
		return -EINVAL;

	fse->min_width = gc0310_res[index].width;
	fse->min_height = gc0310_res[index].height;
	fse->max_width = gc0310_res[index].width;
	fse->max_height = gc0310_res[index].height;
	fse->min_width = GC0310_NATIVE_WIDTH;
	fse->max_width = GC0310_NATIVE_WIDTH;
	fse->min_height = GC0310_NATIVE_HEIGHT;
	fse->max_height = GC0310_NATIVE_HEIGHT;

	return 0;
}

static int gc0310_g_skip_frames(struct v4l2_subdev *sd, u32 *frames)
{
	struct gc0310_device *dev = to_gc0310_sensor(sd);

	mutex_lock(&dev->input_lock);
	*frames = dev->res->skip_frames;
	mutex_unlock(&dev->input_lock);

	*frames = GC0310_SKIP_FRAMES;
	return 0;
}

@@ -638,9 +593,8 @@ static int gc0310_probe(struct i2c_client *client)
		return -ENOMEM;

	mutex_init(&dev->input_lock);

	dev->res = &gc0310_res_preview[0];
	v4l2_i2c_subdev_init(&dev->sd, client, &gc0310_ops);
	gc0310_fill_format(&dev->mode.fmt);

	pdata = gmin_camera_platform_data(&dev->sd,
					  ATOMISP_INPUT_FORMAT_RAW_8,
@@ -660,7 +614,6 @@ static int gc0310_probe(struct i2c_client *client)

	dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
	dev->pad.flags = MEDIA_PAD_FL_SOURCE;
	dev->format.code = MEDIA_BUS_FMT_SGRBG8_1X8;
	dev->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;

	ret = gc0310_init_controls(dev);
+9 −63
Original line number Diff line number Diff line
@@ -33,30 +33,14 @@

#include "../include/linux/atomisp_platform.h"

#define GC0310_FOCAL_LENGTH_NUM	278	/*2.78mm*/
#define GC0310_NATIVE_WIDTH			656
#define GC0310_NATIVE_HEIGHT			496

#define MAX_FMTS		1
#define GC0310_FPS				30
#define GC0310_SKIP_FRAMES			3

/*
 * focal length bits definition:
 * bits 31-16: numerator, bits 15-0: denominator
 */
#define GC0310_FOCAL_LENGTH_DEFAULT 0x1160064

/*
 * current f-number bits definition:
 * bits 31-16: numerator, bits 15-0: denominator
 */
#define GC0310_F_NUMBER_DEFAULT 0x1a000a
#define GC0310_FOCAL_LENGTH_NUM			278 /* 2.78mm */

/*
 * f-number range bits definition:
 * bits 31-24: max f-number numerator
 * bits 23-16: max f-number denominator
 * bits 15-8: min f-number numerator
 * bits 7-0: min f-number denominator
 */
#define GC0310_F_NUMBER_RANGE 0x1a0a1a0a
#define GC0310_ID	0xa310

#define GC0310_RESET_RELATED		0xFE
@@ -101,37 +85,21 @@
#define GC0310_START_STREAMING			0x94 /* 8-bit enable */
#define GC0310_STOP_STREAMING			0x0 /* 8-bit disable */

#define GC0310_BIN_FACTOR_MAX			3

struct gc0310_resolution {
	u8 *desc;
	const struct gc0310_reg *regs;
	int reg_count;
	int res;
	int width;
	int height;
	int fps;
	int pix_clk_freq;
	u32 skip_frames;
	u16 pixels_per_line;
	u16 lines_per_frame;
	bool used;
};

/*
 * gc0310 device structure.
 */
struct gc0310_device {
	struct v4l2_subdev sd;
	struct media_pad pad;
	struct v4l2_mbus_framefmt format;
	struct mutex input_lock;

	struct camera_sensor_platform_data *platform_data;
	struct gc0310_resolution *res;
	u8 type;
	bool power_on;

	struct gc0310_mode {
		struct v4l2_mbus_framefmt fmt;
	} mode;

	struct gc0310_ctrls {
		struct v4l2_ctrl_handler handler;
		struct v4l2_ctrl *exposure;
@@ -337,26 +305,4 @@ static struct gc0310_reg const gc0310_VGA_30fps[] = {
	{ 0xfe, 0x00 },
};

static struct gc0310_resolution gc0310_res_preview[] = {
	{
		.desc = "gc0310_VGA_30fps",
		.width = 656, // 648,
		.height = 496, // 488,
		.fps = 30,
		//.pix_clk_freq = 73,
		.used = 0,
#if 0
		.pixels_per_line = 0x0314,
		.lines_per_frame = 0x0213,
#endif
		.skip_frames = 2,
		.regs = gc0310_VGA_30fps,
		.reg_count = ARRAY_SIZE(gc0310_VGA_30fps),
	},
};

#define N_RES_PREVIEW (ARRAY_SIZE(gc0310_res_preview))

static struct gc0310_resolution *gc0310_res = gc0310_res_preview;
static unsigned long N_RES = N_RES_PREVIEW;
#endif