diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2012-07-18 10:58:25 -0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-08-15 17:12:23 -0300 |
commit | 4ead963009f295dc8589720d22fa4fb288be9edb (patch) | |
tree | be89c14f39f93827a002a79a40e62fcdab9b39d3 /drivers | |
parent | f223d5b7184a743bf2b724698f7a84a963638bb6 (diff) | |
download | linux-stable-4ead963009f295dc8589720d22fa4fb288be9edb.tar.gz linux-stable-4ead963009f295dc8589720d22fa4fb288be9edb.tar.bz2 linux-stable-4ead963009f295dc8589720d22fa4fb288be9edb.zip |
[media] ov772x: Compute window size registers at runtime
Instead of hardcoding register arrays, compute the values at runtime.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
[g.liakhovetski@gmx.de: keep (Q)VGA_* macros for now]
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/i2c/soc_camera/ov772x.c | 162 |
1 files changed, 67 insertions, 95 deletions
diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c index a19769a8142b..76a80b652407 100644 --- a/drivers/media/i2c/soc_camera/ov772x.c +++ b/drivers/media/i2c/soc_camera/ov772x.c @@ -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", - .width = VGA_WIDTH, - .height = VGA_HEIGHT, .com7_bit = SLCT_VGA, - .regs = ov772x_vga_regs, + .rect = { + .left = 140, + .top = 14, + .width = VGA_WIDTH, + .height = VGA_HEIGHT, + }, }, { .name = "QVGA", - .width = QVGA_WIDTH, - .height = QVGA_HEIGHT, .com7_bit = SLCT_QVGA, - .regs = ov772x_qvga_regs, + .rect = { + .left = 252, + .top = 6, + .width = QVGA_WIDTH, + .height = QVGA_HEIGHT, + }, }, }; @@ -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; |