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

Commit 4ead9630 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Mauro Carvalho Chehab
Browse files

[media] ov772x: Compute window size registers at runtime



Instead of hardcoding register arrays, compute the values at runtime.

Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
[g.liakhovetski@gmx.de: keep (Q)VGA_* macros for now]
Signed-off-by: default avatarGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent f223d5b7
Loading
Loading
Loading
Loading
+67 −95
Original line number Diff line number Diff line
@@ -318,8 +318,15 @@
#define SGLF_ON_OFF     0x02	/* Single frame ON/OFF selection */
#define SGLF_TRIG       0x01	/* Single frame transfer trigger */

/* HREF */
#define HREF_VSTART_SHIFT	6	/* VSTART LSB */
#define HREF_HSTART_SHIFT	4	/* HSTART 2 LSBs */
#define HREF_VSIZE_SHIFT	2	/* VSIZE LSB */
#define HREF_HSIZE_SHIFT	0	/* HSIZE 2 LSBs */

/* EXHCH */
#define VSIZE_LSB       0x04	/* Vertical data output size LSB */
#define EXHCH_VSIZE_SHIFT	2	/* VOUTSIZE LSB */
#define EXHCH_HSIZE_SHIFT	0	/* HOUTSIZE 2 LSBs */

/* DSP_CTRL1 */
#define FIFO_ON         0x80	/* FIFO enable/disable selection */
@@ -345,30 +352,6 @@
#define DSP_OFMT_RAW8	0x02
#define DSP_OFMT_RAW10	0x03

/* HSTART */
#define HST_VGA         0x23
#define HST_QVGA        0x3F

/* HSIZE */
#define HSZ_VGA         0xA0
#define HSZ_QVGA        0x50

/* VSTART */
#define VST_VGA         0x07
#define VST_QVGA        0x03

/* VSIZE */
#define VSZ_VGA         0xF0
#define VSZ_QVGA        0x78

/* HOUTSIZE */
#define HOSZ_VGA        0xA0
#define HOSZ_QVGA       0x50

/* VOUTSIZE */
#define VOSZ_VGA        0xF0
#define VOSZ_QVGA       0x78

/* DSPAUTO (DSP Auto Function ON/OFF Control) */
#define AWB_ACTRL       0x80 /* AWB auto threshold control */
#define DENOISE_ACTRL   0x40 /* De-noise auto threshold control */
@@ -377,6 +360,13 @@
#define SCAL0_ACTRL     0x08 /* Auto scaling factor control */
#define SCAL1_2_ACTRL   0x04 /* Auto scaling factor control */

#define VGA_WIDTH		640
#define VGA_HEIGHT		480
#define QVGA_WIDTH		320
#define QVGA_HEIGHT		240
#define OV772X_MAX_WIDTH	VGA_WIDTH
#define OV772X_MAX_HEIGHT	VGA_HEIGHT

/*
 * ID
 */
@@ -387,10 +377,6 @@
/*
 * struct
 */
struct regval_list {
	unsigned char reg_num;
	unsigned char value;
};

struct ov772x_color_format {
	enum v4l2_mbus_pixelcode code;
@@ -403,10 +389,8 @@ struct ov772x_color_format {

struct ov772x_win_size {
	char                     *name;
	__u32                     width;
	__u32                     height;
	unsigned char             com7_bit;
	const struct regval_list *regs;
	struct v4l2_rect	  rect;
};

struct ov772x_priv {
@@ -422,31 +406,6 @@ struct ov772x_priv {
	unsigned short                    band_filter;
};

#define ENDMARKER { 0xff, 0xff }

/*
 * register setting for window size
 */
static const struct regval_list ov772x_qvga_regs[] = {
	{ HSTART,   HST_QVGA },
	{ HSIZE,    HSZ_QVGA },
	{ VSTART,   VST_QVGA },
	{ VSIZE,    VSZ_QVGA  },
	{ HOUTSIZE, HOSZ_QVGA },
	{ VOUTSIZE, VOSZ_QVGA },
	ENDMARKER,
};

static const struct regval_list ov772x_vga_regs[] = {
	{ HSTART,   HST_VGA },
	{ HSIZE,    HSZ_VGA },
	{ VSTART,   VST_VGA },
	{ VSIZE,    VSZ_VGA },
	{ HOUTSIZE, HOSZ_VGA },
	{ VOUTSIZE, VOSZ_VGA },
	ENDMARKER,
};

/*
 * supported color format list
 */
@@ -525,26 +484,26 @@ static const struct ov772x_color_format ov772x_cfmts[] = {
/*
 * window size list
 */
#define VGA_WIDTH   640
#define VGA_HEIGHT  480
#define QVGA_WIDTH  320
#define QVGA_HEIGHT 240
#define MAX_WIDTH   VGA_WIDTH
#define MAX_HEIGHT  VGA_HEIGHT

static const struct ov772x_win_size ov772x_win_sizes[] = {
	{
		.name     = "VGA",
		.com7_bit = SLCT_VGA,
		.rect = {
			.left = 140,
			.top = 14,
			.width = VGA_WIDTH,
			.height = VGA_HEIGHT,
		.com7_bit = SLCT_VGA,
		.regs     = ov772x_vga_regs,
		},
	}, {
		.name     = "QVGA",
		.com7_bit = SLCT_QVGA,
		.rect = {
			.left = 252,
			.top = 6,
			.width = QVGA_WIDTH,
			.height = QVGA_HEIGHT,
		.com7_bit = SLCT_QVGA,
		.regs     = ov772x_qvga_regs,
		},
	},
};

@@ -567,18 +526,6 @@ static inline int ov772x_write(struct i2c_client *client, u8 addr, u8 value)
	return i2c_smbus_write_byte_data(client, addr, value);
}

static int ov772x_write_array(struct i2c_client        *client,
			      const struct regval_list *vals)
{
	while (vals->reg_num != 0xff) {
		int ret = ov772x_write(client, vals->reg_num, vals->value);
		if (ret < 0)
			return ret;
		vals++;
	}
	return 0;
}

static int ov772x_mask_set(struct i2c_client *client, u8  command, u8  mask,
			   u8  set)
{
@@ -726,8 +673,8 @@ static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height)
	unsigned int i;

	for (i = 0; i < ARRAY_SIZE(ov772x_win_sizes); ++i) {
		u32 diff = abs(width - ov772x_win_sizes[i].width)
			 + abs(height - ov772x_win_sizes[i].height);
		u32 diff = abs(width - ov772x_win_sizes[i].rect.width)
			 + abs(height - ov772x_win_sizes[i].rect.height);
		if (diff < best_diff) {
			best_diff = diff;
			win = &ov772x_win_sizes[i];
@@ -817,10 +764,35 @@ static int ov772x_set_params(struct ov772x_priv *priv,
			goto ov772x_set_fmt_error;
	}

	/*
	 * set size format
	 */
	ret = ov772x_write_array(client, win->regs);
	/* Format and window size */
	ret = ov772x_write(client, HSTART, win->rect.left >> 2);
	if (ret < 0)
		goto ov772x_set_fmt_error;
	ret = ov772x_write(client, HSIZE, win->rect.width >> 2);
	if (ret < 0)
		goto ov772x_set_fmt_error;
	ret = ov772x_write(client, VSTART, win->rect.top >> 1);
	if (ret < 0)
		goto ov772x_set_fmt_error;
	ret = ov772x_write(client, VSIZE, win->rect.height >> 1);
	if (ret < 0)
		goto ov772x_set_fmt_error;
	ret = ov772x_write(client, HOUTSIZE, win->rect.width >> 2);
	if (ret < 0)
		goto ov772x_set_fmt_error;
	ret = ov772x_write(client, VOUTSIZE, win->rect.height >> 1);
	if (ret < 0)
		goto ov772x_set_fmt_error;
	ret = ov772x_write(client, HREF,
			   ((win->rect.top & 1) << HREF_VSTART_SHIFT) |
			   ((win->rect.left & 3) << HREF_HSTART_SHIFT) |
			   ((win->rect.height & 1) << HREF_VSIZE_SHIFT) |
			   ((win->rect.width & 3) << HREF_HSIZE_SHIFT));
	if (ret < 0)
		goto ov772x_set_fmt_error;
	ret = ov772x_write(client, EXHCH,
			   ((win->rect.height & 1) << EXHCH_VSIZE_SHIFT) |
			   ((win->rect.width & 3) << EXHCH_HSIZE_SHIFT));
	if (ret < 0)
		goto ov772x_set_fmt_error;

@@ -901,8 +873,8 @@ static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
{
	a->bounds.left			= 0;
	a->bounds.top			= 0;
	a->bounds.width			= VGA_WIDTH;
	a->bounds.height		= VGA_HEIGHT;
	a->bounds.width			= OV772X_MAX_WIDTH;
	a->bounds.height		= OV772X_MAX_HEIGHT;
	a->defrect			= a->bounds;
	a->type				= V4L2_BUF_TYPE_VIDEO_CAPTURE;
	a->pixelaspect.numerator	= 1;
@@ -916,8 +888,8 @@ static int ov772x_g_fmt(struct v4l2_subdev *sd,
{
	struct ov772x_priv *priv = to_ov772x(sd);

	mf->width	= priv->win->width;
	mf->height	= priv->win->height;
	mf->width	= priv->win->rect.width;
	mf->height	= priv->win->rect.height;
	mf->code	= priv->cfmt->code;
	mf->colorspace	= priv->cfmt->colorspace;
	mf->field	= V4L2_FIELD_NONE;
@@ -942,8 +914,8 @@ static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
	priv->cfmt = cfmt;

	mf->code = cfmt->code;
	mf->width = win->width;
	mf->height = win->height;
	mf->width = win->rect.width;
	mf->height = win->rect.height;
	mf->field = V4L2_FIELD_NONE;
	mf->colorspace = cfmt->colorspace;

@@ -959,8 +931,8 @@ static int ov772x_try_fmt(struct v4l2_subdev *sd,
	ov772x_select_params(mf, &cfmt, &win);

	mf->code = cfmt->code;
	mf->width = win->width;
	mf->height = win->height;
	mf->width = win->rect.width;
	mf->height = win->rect.height;
	mf->field = V4L2_FIELD_NONE;
	mf->colorspace = cfmt->colorspace;