[media] ov772x: Compute window size registers at runtime
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Wed, 18 Jul 2012 13:58:25 +0000 (10:58 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 15 Aug 2012 20:12:23 +0000 (17:12 -0300)
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>
drivers/media/i2c/soc_camera/ov772x.c

index a19769a8142b292954a5d509ed08ed2064ae3daa..76a80b65240796e4f38635b62930304d1e57d3ac 100644 (file)
 #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 */
 #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 */
 #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
  */
 /*
  * 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;