On Wed, 24 Jun 2009, [email protected] wrote:

> From: Muralidharan Karicheri <[email protected]>
> 
> This patch migrates mt9t031 driver from SOC Camera interface to
> sub device interface. This is sent to get a feedback about the
> changes done since I am not sure if some of the functionality
> that is removed works okay with SOC Camera bridge driver or
> not. Following functions are to be discussed and added as needed:-
>  
>       1) query bus parameters
>       2) set bus parameters
>       3) set crop
> 
> I have tested this with vpfe capture driver and I could capture
> 640x...@17fps and 2048x1...@12fps resolution frames from the sensor.
> 
> Reviewed by: Hans Verkuil <[email protected]>
> Reviewed by: Guennadi Liakhovetski <[email protected]>

Excuse me? This is the first time I see this patch. FYI, "Reviewed-by" 
means that the respective person has actually reviewed the patch and 
submitted that line _him_ or _her_self!

Thanks
Guennadi

> 
> Signed-off-by: Murali Karicheri <[email protected]>
> ---
>  drivers/media/video/mt9t031.c |  596 
> ++++++++++++++++++++---------------------
>  1 files changed, 293 insertions(+), 303 deletions(-)
> 
> diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
> index f72aeb7..0f32ff2 100644
> --- a/drivers/media/video/mt9t031.c
> +++ b/drivers/media/video/mt9t031.c
> @@ -13,9 +13,9 @@
>  #include <linux/i2c.h>
>  #include <linux/log2.h>
>  
> +#include <media/v4l2-device.h>
>  #include <media/v4l2-common.h>
>  #include <media/v4l2-chip-ident.h>
> -#include <media/soc_camera.h>
>  
>  /* mt9t031 i2c address 0x5d
>   * The platform has to define i2c_board_info
> @@ -52,33 +52,108 @@
>  #define MT9T031_VERTICAL_BLANK               25
>  #define MT9T031_COLUMN_SKIP          32
>  #define MT9T031_ROW_SKIP             20
> +#define MT9T031_DEFAULT_WIDTH                640
> +#define MT9T031_DEFAULT_HEIGHT               480
>  
>  #define MT9T031_BUS_PARAM    (SOCAM_PCLK_SAMPLE_RISING |     \
>       SOCAM_PCLK_SAMPLE_FALLING | SOCAM_HSYNC_ACTIVE_HIGH |   \
>       SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_DATA_ACTIVE_HIGH |      \
>       SOCAM_MASTER | SOCAM_DATAWIDTH_10)
>  
> -static const struct soc_camera_data_format mt9t031_colour_formats[] = {
> +
> +/* Debug functions */
> +static int debug;
> +module_param(debug, bool, 0644);
> +MODULE_PARM_DESC(debug, "Debug level (0-1)");
> +
> +static const struct v4l2_fmtdesc mt9t031_formats[] = {
> +     {
> +             .index = 0,
> +             .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
> +             .description = "Bayer (sRGB) 10 bit",
> +             .pixelformat = V4L2_PIX_FMT_SGRBG10,
> +     },
> +};
> +static const unsigned int mt9t031_num_formats = ARRAY_SIZE(mt9t031_formats);
> +
> +static const struct v4l2_queryctrl mt9t031_controls[] = {
>       {
> -             .name           = "Bayer (sRGB) 10 bit",
> -             .depth          = 10,
> -             .fourcc         = V4L2_PIX_FMT_SGRBG10,
> -             .colorspace     = V4L2_COLORSPACE_SRGB,
> +             .id             = V4L2_CID_VFLIP,
> +             .type           = V4L2_CTRL_TYPE_BOOLEAN,
> +             .name           = "Flip Vertically",
> +             .minimum        = 0,
> +             .maximum        = 1,
> +             .step           = 1,
> +             .default_value  = 0,
> +     }, {
> +             .id             = V4L2_CID_HFLIP,
> +             .type           = V4L2_CTRL_TYPE_BOOLEAN,
> +             .name           = "Flip Horizontally",
> +             .minimum        = 0,
> +             .maximum        = 1,
> +             .step           = 1,
> +             .default_value  = 0,
> +     }, {
> +             .id             = V4L2_CID_GAIN,
> +             .type           = V4L2_CTRL_TYPE_INTEGER,
> +             .name           = "Gain",
> +             .minimum        = 0,
> +             .maximum        = 127,
> +             .step           = 1,
> +             .default_value  = 64,
> +             .flags          = V4L2_CTRL_FLAG_SLIDER,
> +     }, {
> +             .id             = V4L2_CID_EXPOSURE,
> +             .type           = V4L2_CTRL_TYPE_INTEGER,
> +             .name           = "Exposure",
> +             .minimum        = 1,
> +             .maximum        = 255,
> +             .step           = 1,
> +             .default_value  = 255,
> +             .flags          = V4L2_CTRL_FLAG_SLIDER,
> +     }, {
> +             .id             = V4L2_CID_EXPOSURE_AUTO,
> +             .type           = V4L2_CTRL_TYPE_BOOLEAN,
> +             .name           = "Automatic Exposure",
> +             .minimum        = 0,
> +             .maximum        = 1,
> +             .step           = 1,
> +             .default_value  = 1,
>       }
>  };
> +static const unsigned int mt9t031_num_controls = 
> ARRAY_SIZE(mt9t031_controls);
>  
>  struct mt9t031 {
> -     struct i2c_client *client;
> -     struct soc_camera_device icd;
> +     struct v4l2_subdev sd;
>       int model;      /* V4L2_IDENT_MT9T031* codes from v4l2-chip-ident.h */
>       unsigned char autoexposure;
>       u16 xskip;
>       u16 yskip;
> +     u32 width;
> +     u32 height;
> +     unsigned short x_min;           /* Camera capabilities */
> +     unsigned short y_min;
> +     unsigned short x_current;       /* Current window location */
> +     unsigned short y_current;
> +     unsigned short width_min;
> +     unsigned short width_max;
> +     unsigned short height_min;
> +     unsigned short height_max;
> +     unsigned short y_skip_top;      /* Lines to skip at the top */
> +     unsigned short gain;
> +     unsigned short exposure;
>  };
>  
> +static inline struct mt9t031 *to_mt9t031(struct v4l2_subdev *sd)
> +{
> +     return container_of(sd, struct mt9t031, sd);
> +}
> +
>  static int reg_read(struct i2c_client *client, const u8 reg)
>  {
> -     s32 data = i2c_smbus_read_word_data(client, reg);
> +     s32 data;
> +
> +     data = i2c_smbus_read_word_data(client, reg);
>       return data < 0 ? data : swab16(data);
>  }
>  
> @@ -110,8 +185,9 @@ static int reg_clear(struct i2c_client *client, const u8 
> reg,
>       return reg_write(client, reg, ret & ~data);
>  }
>  
> -static int set_shutter(struct i2c_client *client, const u32 data)
> +static int set_shutter(struct v4l2_subdev *sd, const u32 data)
>  {
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);
>       int ret;
>  
>       ret = reg_write(client, MT9T031_SHUTTER_WIDTH_UPPER, data >> 16);
> @@ -122,9 +198,10 @@ static int set_shutter(struct i2c_client *client, const 
> u32 data)
>       return ret;
>  }
>  
> -static int get_shutter(struct i2c_client *client, u32 *data)
> +static int get_shutter(struct v4l2_subdev *sd, u32 *data)
>  {
>       int ret;
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);
>  
>       ret = reg_read(client, MT9T031_SHUTTER_WIDTH_UPPER);
>       *data = ret << 16;
> @@ -136,20 +213,10 @@ static int get_shutter(struct i2c_client *client, u32 
> *data)
>       return ret < 0 ? ret : 0;
>  }
>  
> -static int mt9t031_init(struct soc_camera_device *icd)
> +static int mt9t031_init(struct v4l2_subdev *sd, u32 val)
>  {
> -     struct i2c_client *client = to_i2c_client(icd->control);
> -     struct soc_camera_link *icl = client->dev.platform_data;
>       int ret;
> -
> -     if (icl->power) {
> -             ret = icl->power(&client->dev, 1);
> -             if (ret < 0) {
> -                     dev_err(icd->vdev->parent,
> -                             "Platform failed to power-on the camera.\n");
> -                     return ret;
> -             }
> -     }
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);
>  
>       /* Disable chip output, synchronous option update */
>       ret = reg_write(client, MT9T031_RESET, 1);
> @@ -158,99 +225,67 @@ static int mt9t031_init(struct soc_camera_device *icd)
>       if (ret >= 0)
>               ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
>  
> -     if (ret < 0 && icl->power)
> -             icl->power(&client->dev, 0);
> -
>       return ret >= 0 ? 0 : -EIO;
>  }
>  
> -static int mt9t031_release(struct soc_camera_device *icd)
> -{
> -     struct i2c_client *client = to_i2c_client(icd->control);
> -     struct soc_camera_link *icl = client->dev.platform_data;
> -
> -     /* Disable the chip */
> -     reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
> -
> -     if (icl->power)
> -             icl->power(&client->dev, 0);
> -
> -     return 0;
> -}
> -
> -static int mt9t031_start_capture(struct soc_camera_device *icd)
> +static int mt9t031_s_stream(struct v4l2_subdev *sd, int enable)
>  {
> -     struct i2c_client *client = to_i2c_client(icd->control);
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);
>  
>       /* Switch to master "normal" mode */
> -     if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
> -             return -EIO;
> -     return 0;
> -}
> -
> -static int mt9t031_stop_capture(struct soc_camera_device *icd)
> -{
> -     struct i2c_client *client = to_i2c_client(icd->control);
> -
> -     /* Stop sensor readout */
> -     if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
> -             return -EIO;
> +     if (enable) {
> +             if (reg_set(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
> +                     return -EIO;
> +     } else {
> +     /* Switch to master "" mode */
> +             if (reg_clear(client, MT9T031_OUTPUT_CONTROL, 2) < 0)
> +                     return -EIO;
> +     }
>       return 0;
>  }
>  
> -static int mt9t031_set_bus_param(struct soc_camera_device *icd,
> -                              unsigned long flags)
> +/* Round up minima and round down maxima */
> +static void recalculate_limits(struct mt9t031 *mt9t031,
> +                            u16 xskip, u16 yskip)
>  {
> -     struct i2c_client *client = to_i2c_client(icd->control);
> -
> -     /* The caller should have queried our parameters, check anyway */
> -     if (flags & ~MT9T031_BUS_PARAM)
> -             return -EINVAL;
> -
> -     if (flags & SOCAM_PCLK_SAMPLE_FALLING)
> -             reg_clear(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
> -     else
> -             reg_set(client, MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
> -
> -     return 0;
> +     mt9t031->x_min = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip;
> +     mt9t031->y_min = (MT9T031_ROW_SKIP + yskip - 1) / yskip;
> +     mt9t031->width_min = (MT9T031_MIN_WIDTH + xskip - 1) / xskip;
> +     mt9t031->height_min = (MT9T031_MIN_HEIGHT + yskip - 1) / yskip;
> +     mt9t031->width_max = MT9T031_MAX_WIDTH / xskip;
> +     mt9t031->height_max = MT9T031_MAX_HEIGHT / yskip;
>  }
>  
> -static unsigned long mt9t031_query_bus_param(struct soc_camera_device *icd)
> +const struct v4l2_queryctrl *mt9t031_find_qctrl(u32 id)
>  {
> -     struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> -     struct soc_camera_link *icl = mt9t031->client->dev.platform_data;
> +     int i;
>  
> -     return soc_camera_apply_sensor_flags(icl, MT9T031_BUS_PARAM);
> -}
> -
> -/* Round up minima and round down maxima */
> -static void recalculate_limits(struct soc_camera_device *icd,
> -                            u16 xskip, u16 yskip)
> -{
> -     icd->x_min = (MT9T031_COLUMN_SKIP + xskip - 1) / xskip;
> -     icd->y_min = (MT9T031_ROW_SKIP + yskip - 1) / yskip;
> -     icd->width_min = (MT9T031_MIN_WIDTH + xskip - 1) / xskip;
> -     icd->height_min = (MT9T031_MIN_HEIGHT + yskip - 1) / yskip;
> -     icd->width_max = MT9T031_MAX_WIDTH / xskip;
> -     icd->height_max = MT9T031_MAX_HEIGHT / yskip;
> +     for (i = 0; i < mt9t031_num_controls; i++) {
> +             if (mt9t031_controls[i].id == id)
> +                     return &mt9t031_controls[i];
> +     }
> +     return NULL;
>  }
>  
> -static int mt9t031_set_params(struct soc_camera_device *icd,
> +static int mt9t031_set_params(struct v4l2_subdev *sd,
>                             struct v4l2_rect *rect, u16 xskip, u16 yskip)
>  {
> -     struct i2c_client *client = to_i2c_client(icd->control);
> -     struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +     struct mt9t031 *mt9t031 = to_mt9t031(sd);
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);
> +
>       int ret;
>       u16 xbin, ybin, width, height, left, top;
>       const u16 hblank = MT9T031_HORIZONTAL_BLANK,
>               vblank = MT9T031_VERTICAL_BLANK;
>  
>       /* Make sure we don't exceed sensor limits */
> -     if (rect->left + rect->width > icd->width_max)
> -             rect->left = (icd->width_max - rect->width) / 2 + icd->x_min;
> +     if (rect->left + rect->width > mt9t031->width_max)
> +             rect->left =
> +             (mt9t031->width_max - rect->width) / 2 + mt9t031->x_min;
>  
> -     if (rect->top + rect->height > icd->height_max)
> -             rect->top = (icd->height_max - rect->height) / 2 + icd->y_min;
> +     if (rect->top + rect->height > mt9t031->height_max)
> +             rect->top =
> +             (mt9t031->height_max - rect->height) / 2 + mt9t031->y_min;
>  
>       width = rect->width * xskip;
>       height = rect->height * yskip;
> @@ -260,8 +295,9 @@ static int mt9t031_set_params(struct soc_camera_device 
> *icd,
>       xbin = min(xskip, (u16)3);
>       ybin = min(yskip, (u16)3);
>  
> -     dev_dbg(&icd->dev, "xskip %u, width %u/%u, yskip %u, height %u/%u\n",
> -             xskip, width, rect->width, yskip, height, rect->height);
> +     v4l2_dbg(1, debug, sd, "xskip %u, width %u/%u, yskip %u,"
> +             "height %u/%u\n", xskip, width, rect->width, yskip,
> +             height, rect->height);
>  
>       /* Could just do roundup(rect->left, [xy]bin * 2); but this is cheaper 
> */
>       switch (xbin) {
> @@ -299,7 +335,7 @@ static int mt9t031_set_params(struct soc_camera_device 
> *icd,
>                       ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE,
>                                       ((ybin - 1) << 4) | (yskip - 1));
>       }
> -     dev_dbg(&icd->dev, "new physical left %u, top %u\n", left, top);
> +     v4l2_dbg(1, debug, sd, "new physical left %u, top %u\n", left, top);
>  
>       /* The caller provides a supported format, as guaranteed by
>        * icd->try_fmt_cap(), soc_camera_s_crop() and soc_camera_cropcap() */
> @@ -311,46 +347,41 @@ static int mt9t031_set_params(struct soc_camera_device 
> *icd,
>               ret = reg_write(client, MT9T031_WINDOW_WIDTH, width - 1);
>       if (ret >= 0)
>               ret = reg_write(client, MT9T031_WINDOW_HEIGHT,
> -                             height + icd->y_skip_top - 1);
> +                             height + mt9t031->y_skip_top - 1);
>       if (ret >= 0 && mt9t031->autoexposure) {
> -             ret = set_shutter(client, height + icd->y_skip_top + vblank);
> +             ret = set_shutter(sd, height + mt9t031->y_skip_top + vblank);
>               if (ret >= 0) {
>                       const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
>                       const struct v4l2_queryctrl *qctrl =
> -                             soc_camera_find_qctrl(icd->ops,
> -                                                   V4L2_CID_EXPOSURE);
> -                     icd->exposure = (shutter_max / 2 + (height +
> -                                      icd->y_skip_top + vblank - 1) *
> +                             mt9t031_find_qctrl(V4L2_CID_EXPOSURE);
> +                     mt9t031->exposure = (shutter_max / 2 + (height +
> +                                      mt9t031->y_skip_top + vblank - 1) *
>                                        (qctrl->maximum - qctrl->minimum)) /
>                               shutter_max + qctrl->minimum;
>               }
>       }
>  
>       /* Re-enable register update, commit all changes */
> -     if (ret >= 0)
> +     if (ret >= 0) {
>               ret = reg_clear(client, MT9T031_OUTPUT_CONTROL, 1);
> -
> +             /* update the values */
> +             mt9t031->width  = rect->width,
> +             mt9t031->height = rect->height,
> +             mt9t031->x_current = rect->left;
> +             mt9t031->y_current = rect->top;
> +     }
>       return ret < 0 ? ret : 0;
>  }
>  
> -static int mt9t031_set_crop(struct soc_camera_device *icd,
> -                         struct v4l2_rect *rect)
> -{
> -     struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> -
> -     /* CROP - no change in scaling, or in limits */
> -     return mt9t031_set_params(icd, rect, mt9t031->xskip, mt9t031->yskip);
> -}
> -
> -static int mt9t031_set_fmt(struct soc_camera_device *icd,
> +static int mt9t031_set_fmt(struct v4l2_subdev *sd,
>                          struct v4l2_format *f)
>  {
> -     struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +     struct mt9t031 *mt9t031 = to_mt9t031(sd);
>       int ret;
>       u16 xskip, yskip;
>       struct v4l2_rect rect = {
> -             .left   = icd->x_current,
> -             .top    = icd->y_current,
> +             .left   = mt9t031->x_current,
> +             .top    = mt9t031->y_current,
>               .width  = f->fmt.pix.width,
>               .height = f->fmt.pix.height,
>       };
> @@ -369,18 +400,17 @@ static int mt9t031_set_fmt(struct soc_camera_device 
> *icd,
>               if (rect.height * yskip <= MT9T031_MAX_HEIGHT)
>                       break;
>  
> -     recalculate_limits(icd, xskip, yskip);
> +     recalculate_limits(mt9t031, xskip, yskip);
>  
> -     ret = mt9t031_set_params(icd, &rect, xskip, yskip);
> +     ret = mt9t031_set_params(sd, &rect, xskip, yskip);
>       if (!ret) {
>               mt9t031->xskip = xskip;
>               mt9t031->yskip = yskip;
>       }
> -
>       return ret;
>  }
>  
> -static int mt9t031_try_fmt(struct soc_camera_device *icd,
> +static int mt9t031_try_fmt(struct v4l2_subdev *sd,
>                          struct v4l2_format *f)
>  {
>       struct v4l2_pix_format *pix = &f->fmt.pix;
> @@ -396,19 +426,19 @@ static int mt9t031_try_fmt(struct soc_camera_device 
> *icd,
>  
>       pix->width &= ~0x01; /* has to be even */
>       pix->height &= ~0x01; /* has to be even */
> -
>       return 0;
>  }
>  
> -static int mt9t031_get_chip_id(struct soc_camera_device *icd,
> +static int mt9t031_get_chip_id(struct v4l2_subdev *sd,
>                              struct v4l2_dbg_chip_ident *id)
>  {
> -     struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +     struct mt9t031 *mt9t031 = to_mt9t031(sd);
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);;
>  
>       if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
>               return -EINVAL;
>  
> -     if (id->match.addr != mt9t031->client->addr)
> +     if (id->match.addr != client->addr)
>               return -ENODEV;
>  
>       id->ident       = mt9t031->model;
> @@ -418,10 +448,11 @@ static int mt9t031_get_chip_id(struct soc_camera_device 
> *icd,
>  }
>  
>  #ifdef CONFIG_VIDEO_ADV_DEBUG
> -static int mt9t031_get_register(struct soc_camera_device *icd,
> +static int mt9t031_get_register(struct v4l2_subdev *sd,
>                               struct v4l2_dbg_register *reg)
>  {
> -     struct i2c_client *client = to_i2c_client(icd->control);
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);;
> +     struct mt9t031 *mt9t031 = to_mt9t031(sd);
>  
>       if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
>               return -EINVAL;
> @@ -437,10 +468,11 @@ static int mt9t031_get_register(struct 
> soc_camera_device *icd,
>       return 0;
>  }
>  
> -static int mt9t031_set_register(struct soc_camera_device *icd,
> +static int mt9t031_set_register(struct v4l2_subdev *sd,
>                               struct v4l2_dbg_register *reg)
>  {
> -     struct i2c_client *client = to_i2c_client(icd->control);
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);
> +     struct mt9t031 *mt9t031 = to_mt9t031(sd);
>  
>       if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
>               return -EINVAL;
> @@ -455,85 +487,53 @@ static int mt9t031_set_register(struct 
> soc_camera_device *icd,
>  }
>  #endif
>  
> -static const struct v4l2_queryctrl mt9t031_controls[] = {
> -     {
> -             .id             = V4L2_CID_VFLIP,
> -             .type           = V4L2_CTRL_TYPE_BOOLEAN,
> -             .name           = "Flip Vertically",
> -             .minimum        = 0,
> -             .maximum        = 1,
> -             .step           = 1,
> -             .default_value  = 0,
> -     }, {
> -             .id             = V4L2_CID_HFLIP,
> -             .type           = V4L2_CTRL_TYPE_BOOLEAN,
> -             .name           = "Flip Horizontally",
> -             .minimum        = 0,
> -             .maximum        = 1,
> -             .step           = 1,
> -             .default_value  = 0,
> -     }, {
> -             .id             = V4L2_CID_GAIN,
> -             .type           = V4L2_CTRL_TYPE_INTEGER,
> -             .name           = "Gain",
> -             .minimum        = 0,
> -             .maximum        = 127,
> -             .step           = 1,
> -             .default_value  = 64,
> -             .flags          = V4L2_CTRL_FLAG_SLIDER,
> -     }, {
> -             .id             = V4L2_CID_EXPOSURE,
> -             .type           = V4L2_CTRL_TYPE_INTEGER,
> -             .name           = "Exposure",
> -             .minimum        = 1,
> -             .maximum        = 255,
> -             .step           = 1,
> -             .default_value  = 255,
> -             .flags          = V4L2_CTRL_FLAG_SLIDER,
> -     }, {
> -             .id             = V4L2_CID_EXPOSURE_AUTO,
> -             .type           = V4L2_CTRL_TYPE_BOOLEAN,
> -             .name           = "Automatic Exposure",
> -             .minimum        = 0,
> -             .maximum        = 1,
> -             .step           = 1,
> -             .default_value  = 1,
> -     }
> -};
>  
> -static int mt9t031_video_probe(struct soc_camera_device *);
> -static void mt9t031_video_remove(struct soc_camera_device *);
> -static int mt9t031_get_control(struct soc_camera_device *, struct 
> v4l2_control *);
> -static int mt9t031_set_control(struct soc_camera_device *, struct 
> v4l2_control *);
> -
> -static struct soc_camera_ops mt9t031_ops = {
> -     .owner                  = THIS_MODULE,
> -     .probe                  = mt9t031_video_probe,
> -     .remove                 = mt9t031_video_remove,
> -     .init                   = mt9t031_init,
> -     .release                = mt9t031_release,
> -     .start_capture          = mt9t031_start_capture,
> -     .stop_capture           = mt9t031_stop_capture,
> -     .set_crop               = mt9t031_set_crop,
> -     .set_fmt                = mt9t031_set_fmt,
> -     .try_fmt                = mt9t031_try_fmt,
> -     .set_bus_param          = mt9t031_set_bus_param,
> -     .query_bus_param        = mt9t031_query_bus_param,
> -     .controls               = mt9t031_controls,
> -     .num_controls           = ARRAY_SIZE(mt9t031_controls),
> -     .get_control            = mt9t031_get_control,
> -     .set_control            = mt9t031_set_control,
> -     .get_chip_id            = mt9t031_get_chip_id,
> +static int mt9t031_get_control(struct v4l2_subdev *, struct v4l2_control *);
> +static int mt9t031_set_control(struct v4l2_subdev *, struct v4l2_control *);
> +static int mt9t031_queryctrl(struct v4l2_subdev *, struct v4l2_queryctrl *);
> +
> +static const struct v4l2_subdev_core_ops mt9t031_core_ops = {
> +     .g_chip_ident = mt9t031_get_chip_id,
> +     .init = mt9t031_init,
> +     .queryctrl = mt9t031_queryctrl,
> +     .g_ctrl = mt9t031_get_control,
> +     .s_ctrl = mt9t031_set_control,
>  #ifdef CONFIG_VIDEO_ADV_DEBUG
> -     .get_register           = mt9t031_get_register,
> -     .set_register           = mt9t031_set_register,
> +     .get_register = mt9t031_get_register,
> +     .set_register = mt9t031_set_register,
>  #endif
>  };
>  
> -static int mt9t031_get_control(struct soc_camera_device *icd, struct 
> v4l2_control *ctrl)
> +static const struct v4l2_subdev_video_ops mt9t031_video_ops = {
> +     .s_fmt = mt9t031_set_fmt,
> +     .try_fmt = mt9t031_try_fmt,
> +     .s_stream = mt9t031_s_stream,
> +};
> +
> +static const struct v4l2_subdev_ops mt9t031_ops = {
> +     .core = &mt9t031_core_ops,
> +     .video = &mt9t031_video_ops,
> +};
> +
> +static int mt9t031_queryctrl(struct v4l2_subdev *sd,
> +                         struct v4l2_queryctrl *qctrl)
>  {
> -     struct i2c_client *client = to_i2c_client(icd->control);
> -     struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> +     const struct v4l2_queryctrl *temp_qctrl;
> +
> +     temp_qctrl = mt9t031_find_qctrl(qctrl->id);
> +     if (!temp_qctrl) {
> +             v4l2_err(sd, "control id %d not supported", qctrl->id);
> +             return -EINVAL;
> +     }
> +     memcpy(qctrl, temp_qctrl, sizeof(*qctrl));
> +     return 0;
> +}
> +
> +static int mt9t031_get_control(struct v4l2_subdev *sd,
> +                            struct v4l2_control *ctrl)
> +{
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);
> +     struct mt9t031 *mt9t031 = to_mt9t031(sd);
>       int data;
>  
>       switch (ctrl->id) {
> @@ -556,17 +556,22 @@ static int mt9t031_get_control(struct soc_camera_device 
> *icd, struct v4l2_contro
>       return 0;
>  }
>  
> -static int mt9t031_set_control(struct soc_camera_device *icd, struct 
> v4l2_control *ctrl)
> +static int mt9t031_set_control(struct v4l2_subdev *sd,
> +                            struct v4l2_control *ctrl)
>  {
> -     struct i2c_client *client = to_i2c_client(icd->control);
> -     struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> -     const struct v4l2_queryctrl *qctrl;
> +     struct mt9t031 *mt9t031 = to_mt9t031(sd);
> +     const struct v4l2_queryctrl *qctrl = NULL;
>       int data;
> +     struct i2c_client *client = v4l2_get_subdevdata(sd);
>  
> -     qctrl = soc_camera_find_qctrl(&mt9t031_ops, ctrl->id);
> +     if (NULL == ctrl)
> +             return -EINVAL;
>  
> -     if (!qctrl)
> +     qctrl = mt9t031_find_qctrl(ctrl->id);
> +     if (!qctrl) {
> +             v4l2_err(sd, "control id %d not supported", ctrl->id);
>               return -EINVAL;
> +     }
>  
>       switch (ctrl->id) {
>       case V4L2_CID_VFLIP:
> @@ -594,7 +599,7 @@ static int mt9t031_set_control(struct soc_camera_device 
> *icd, struct v4l2_contro
>                       unsigned long range = qctrl->default_value - 
> qctrl->minimum;
>                       data = ((ctrl->value - qctrl->minimum) * 8 + range / 2) 
> / range;
>  
> -                     dev_dbg(&icd->dev, "Setting gain %d\n", data);
> +                     v4l2_dbg(1, debug, sd, "Setting gain %d\n", data);
>                       data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
>                       if (data < 0)
>                               return -EIO;
> @@ -606,40 +611,51 @@ static int mt9t031_set_control(struct soc_camera_device 
> *icd, struct v4l2_contro
>                       unsigned long gain = ((ctrl->value - 
> qctrl->default_value - 1) *
>                                              1015 + range / 2) / range + 9;
>  
> -                     if (gain <= 32)         /* calculated gain 9..32 -> 
> 9..32 */
> +                     if (gain <= 32)
> +                             /* calculated gain 9..32 -> 9..32 */
>                               data = gain;
> -                     else if (gain <= 64)    /* calculated gain 33..64 -> 
> 0x51..0x60 */
> +                     else if (gain <= 64)
> +                             /* calculated gain 33..64 -> 0x51..0x60 */
>                               data = ((gain - 32) * 16 + 16) / 32 + 80;
>                       else
> -                             /* calculated gain 65..1024 -> (1..120) << 8 + 
> 0x60 */
> +                             /*
> +                              * calculated gain 65..1024 -> (1..120) << 8 +
> +                              * 0x60
> +                              */
>                               data = (((gain - 64 + 7) * 32) & 0xff00) | 0x60;
>  
> -                     dev_dbg(&icd->dev, "Setting gain from 0x%x to 0x%x\n",
> -                             reg_read(client, MT9T031_GLOBAL_GAIN), data);
> +                     v4l2_dbg(1, debug, sd, "Setting gain from 0x%x to"
> +                              "0x%x\n",
> +                              reg_read(client, MT9T031_GLOBAL_GAIN), data);
> +
>                       data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
>                       if (data < 0)
>                               return -EIO;
>               }
>  
>               /* Success */
> -             icd->gain = ctrl->value;
> +             mt9t031->gain = ctrl->value;
>               break;
>       case V4L2_CID_EXPOSURE:
>               /* mt9t031 has maximum == default */
> -             if (ctrl->value > qctrl->maximum || ctrl->value < 
> qctrl->minimum)
> +             if (ctrl->value > qctrl->maximum ||
> +                 ctrl->value < qctrl->minimum)
>                       return -EINVAL;
>               else {
> -                     const unsigned long range = qctrl->maximum - 
> qctrl->minimum;
> -                     const u32 shutter = ((ctrl->value - qctrl->minimum) * 
> 1048 +
> -                                          range / 2) / range + 1;
> +                     const unsigned long range =
> +                             qctrl->maximum - qctrl->minimum;
> +                     const u32 shutter =
> +                             ((ctrl->value - qctrl->minimum) * 1048 +
> +                                     range / 2) / range + 1;
>                       u32 old;
>  
> -                     get_shutter(client, &old);
> -                     dev_dbg(&icd->dev, "Setting shutter width from %u to 
> %u\n",
> +                     get_shutter(sd, &old);
> +                     v4l2_dbg(1, debug, sd,
> +                             "Setting shutter width from %u to %u\n",
>                               old, shutter);
> -                     if (set_shutter(client, shutter) < 0)
> +                     if (set_shutter(sd, shutter) < 0)
>                               return -EIO;
> -                     icd->exposure = ctrl->value;
> +                     mt9t031->exposure = ctrl->value;
>                       mt9t031->autoexposure = 0;
>               }
>               break;
> @@ -647,13 +663,15 @@ static int mt9t031_set_control(struct soc_camera_device 
> *icd, struct v4l2_contro
>               if (ctrl->value) {
>                       const u16 vblank = MT9T031_VERTICAL_BLANK;
>                       const u32 shutter_max = MT9T031_MAX_HEIGHT + vblank;
> -                     if (set_shutter(client, icd->height +
> -                                     icd->y_skip_top + vblank) < 0)
> +                     if (set_shutter(sd, mt9t031->height +
> +                                     mt9t031->y_skip_top + vblank) < 0)
>                               return -EIO;
> -                     qctrl = soc_camera_find_qctrl(icd->ops, 
> V4L2_CID_EXPOSURE);
> -                     icd->exposure = (shutter_max / 2 + (icd->height +
> -                                      icd->y_skip_top + vblank - 1) *
> -                                      (qctrl->maximum - qctrl->minimum)) /
> +
> +                     qctrl = mt9t031_find_qctrl(V4L2_CID_EXPOSURE);
> +                     mt9t031->exposure =
> +                             (shutter_max / 2 + (mt9t031->height +
> +                             mt9t031->y_skip_top + vblank - 1) *
> +                             (qctrl->maximum - qctrl->minimum)) /
>                               shutter_max + qctrl->minimum;
>                       mt9t031->autoexposure = 1;
>               } else
> @@ -665,130 +683,102 @@ static int mt9t031_set_control(struct 
> soc_camera_device *icd, struct v4l2_contro
>  
>  /* Interface active, can use i2c. If it fails, it can indeed mean, that
>   * this wasn't our capture interface, so, we wait for the right one */
> -static int mt9t031_video_probe(struct soc_camera_device *icd)
> +static int mt9t031_detect(struct i2c_client *client, int *model)
>  {
> -     struct i2c_client *client = to_i2c_client(icd->control);
> -     struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
>       s32 data;
> -     int ret;
> -
> -     /* We must have a parent by now. And it cannot be a wrong one.
> -      * So this entire test is completely redundant. */
> -     if (!icd->dev.parent ||
> -         to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
> -             return -ENODEV;
>  
>       /* Enable the chip */
>       data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
> -     dev_dbg(&icd->dev, "write: %d\n", data);
> +     dev_dbg(&client->dev, "write: %d\n", data);
>  
>       /* Read out the chip version register */
>       data = reg_read(client, MT9T031_CHIP_VERSION);
>  
>       switch (data) {
>       case 0x1621:
> -             mt9t031->model = V4L2_IDENT_MT9T031;
> -             icd->formats = mt9t031_colour_formats;
> -             icd->num_formats = ARRAY_SIZE(mt9t031_colour_formats);
> +             *model = V4L2_IDENT_MT9T031;
>               break;
>       default:
> -             ret = -ENODEV;
> -             dev_err(&icd->dev,
> +             dev_err(&client->dev,
>                       "No MT9T031 chip detected, register read %x\n", data);
> -             goto ei2c;
> +             return -ENODEV;
>       }
>  
> -     dev_info(&icd->dev, "Detected a MT9T031 chip ID %x\n", data);
> -
> -     /* Now that we know the model, we can start video */
> -     ret = soc_camera_video_start(icd);
> -     if (ret)
> -             goto evstart;
> -
> +     dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data);
>       return 0;
> -
> -evstart:
> -ei2c:
> -     return ret;
> -}
> -
> -static void mt9t031_video_remove(struct soc_camera_device *icd)
> -{
> -     struct mt9t031 *mt9t031 = container_of(icd, struct mt9t031, icd);
> -
> -     dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9t031->client->addr,
> -             icd->dev.parent, icd->vdev);
> -     soc_camera_video_stop(icd);
>  }
>  
>  static int mt9t031_probe(struct i2c_client *client,
>                        const struct i2c_device_id *did)
>  {
>       struct mt9t031 *mt9t031;
> -     struct soc_camera_device *icd;
> -     struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
> -     struct soc_camera_link *icl = client->dev.platform_data;
> +     struct v4l2_subdev *sd;
> +     int pclk_pol;
>       int ret;
>  
> -     if (!icl) {
> -             dev_err(&client->dev, "MT9T031 driver needs platform data\n");
> -             return -EINVAL;
> -     }
> -
> -     if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
> -             dev_warn(&adapter->dev,
> +     if (!i2c_check_functionality(client->adapter,
> +                                  I2C_FUNC_SMBUS_WORD_DATA)) {
> +             dev_warn(&client->dev,
>                        "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
>               return -EIO;
>       }
>  
> +     if (!client->dev.platform_data) {
> +             dev_err(&client->dev, "No platform data!!\n");
> +             return -ENODEV;
> +     }
> +
> +     pclk_pol = (int)client->dev.platform_data;
> +
>       mt9t031 = kzalloc(sizeof(struct mt9t031), GFP_KERNEL);
>       if (!mt9t031)
>               return -ENOMEM;
>  
> -     mt9t031->client = client;
> -     i2c_set_clientdata(client, mt9t031);
> -
> -     /* Second stage probe - when a capture adapter is there */
> -     icd = &mt9t031->icd;
> -     icd->ops        = &mt9t031_ops;
> -     icd->control    = &client->dev;
> -     icd->x_min      = MT9T031_COLUMN_SKIP;
> -     icd->y_min      = MT9T031_ROW_SKIP;
> -     icd->x_current  = icd->x_min;
> -     icd->y_current  = icd->y_min;
> -     icd->width_min  = MT9T031_MIN_WIDTH;
> -     icd->width_max  = MT9T031_MAX_WIDTH;
> -     icd->height_min = MT9T031_MIN_HEIGHT;
> -     icd->height_max = MT9T031_MAX_HEIGHT;
> -     icd->y_skip_top = 0;
> -     icd->iface      = icl->bus_id;
> -     /* Simulated autoexposure. If enabled, we calculate shutter width
> -      * ourselves in the driver based on vertical blanking and frame width */
> +     ret = mt9t031_detect(client, &mt9t031->model);
> +     if (ret)
> +             goto clean;
> +
> +     mt9t031->x_min          = MT9T031_COLUMN_SKIP;
> +     mt9t031->y_min          = MT9T031_ROW_SKIP;
> +     mt9t031->width          = MT9T031_DEFAULT_WIDTH;
> +     mt9t031->height         = MT9T031_DEFAULT_WIDTH;
> +     mt9t031->x_current      = mt9t031->x_min;
> +     mt9t031->y_current      = mt9t031->y_min;
> +     mt9t031->width_min      = MT9T031_MIN_WIDTH;
> +     mt9t031->width_max      = MT9T031_MAX_WIDTH;
> +     mt9t031->height_min     = MT9T031_MIN_HEIGHT;
> +     mt9t031->height_max     = MT9T031_MAX_HEIGHT;
> +     mt9t031->y_skip_top     = 0;
>       mt9t031->autoexposure = 1;
> -
>       mt9t031->xskip = 1;
>       mt9t031->yskip = 1;
>  
> -     ret = soc_camera_device_register(icd);
> -     if (ret)
> -             goto eisdr;
> +     /* Register with V4L2 layer as slave device */
> +     sd = &mt9t031->sd;
> +     v4l2_i2c_subdev_init(sd, client, &mt9t031_ops);
> +     if (!pclk_pol)
> +             reg_clear(v4l2_get_subdevdata(sd),
> +                       MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
> +     else
> +             reg_set(v4l2_get_subdevdata(sd),
> +                     MT9T031_PIXEL_CLOCK_CONTROL, 0x8000);
>  
> +     v4l2_info(sd, "%s decoder driver registered !!\n", sd->name);
>       return 0;
>  
> -eisdr:
> -     i2c_set_clientdata(client, NULL);
> +clean:
>       kfree(mt9t031);
>       return ret;
>  }
>  
>  static int mt9t031_remove(struct i2c_client *client)
>  {
> -     struct mt9t031 *mt9t031 = i2c_get_clientdata(client);
> +     struct v4l2_subdev *sd = i2c_get_clientdata(client);
> +     struct mt9t031 *mt9t031 = to_mt9t031(sd);
>  
> -     soc_camera_device_unregister(&mt9t031->icd);
> -     i2c_set_clientdata(client, NULL);
> -     kfree(mt9t031);
> +     v4l2_device_unregister_subdev(sd);
>  
> +     kfree(mt9t031);
>       return 0;
>  }
>  
> -- 
> 1.6.0.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to [email protected]
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to