[media] mt9v022: Add support for mt9v024
authorAlex Gershgorin <alexg@meprolight.com>
Thu, 2 Aug 2012 15:32:41 +0000 (12:32 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Wed, 15 Aug 2012 23:04:08 +0000 (20:04 -0300)
Driver for mt9v022 camera sensor is fully compatible for mt9v024 camera sensor
with the exception of several registers which have been changed addresses.
mt9v024 also has improved and additional features, but they are currently not in use.

Signed-off-by: Alex Gershgorin <alexg@meprolight.com>
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/i2c/soc_camera/Kconfig
drivers/media/i2c/soc_camera/mt9v022.c

index 73fe21d1b2dfe78cb41ecb8e01150a2a90fdc5c3..6dff2b7ad520f2508101878802f3a8407c8a3079 100644 (file)
@@ -34,7 +34,7 @@ config SOC_CAMERA_MT9T112
          This driver supports MT9T112 cameras from Aptina.
 
 config SOC_CAMERA_MT9V022
-       tristate "mt9v022 support"
+       tristate "mt9v022 and mt9v024 support"
        depends on SOC_CAMERA && I2C
        select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
        help
index 2edea8489092af7d2ea7978ffdd2a1e2ecd38b70..350d0d8544470caf183202f4c784108c25cd93d5 100644 (file)
@@ -57,6 +57,10 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
 #define MT9V022_AEC_AGC_ENABLE         0xAF
 #define MT9V022_MAX_TOTAL_SHUTTER_WIDTH        0xBD
 
+/* mt9v024 partial list register addresses changes with respect to mt9v022 */
+#define MT9V024_PIXCLK_FV_LV           0x72
+#define MT9V024_MAX_TOTAL_SHUTTER_WIDTH        0xAD
+
 /* Progressive scan, master, defaults */
 #define MT9V022_CHIP_CONTROL_DEFAULT   0x188
 
@@ -67,6 +71,8 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
 #define MT9V022_COLUMN_SKIP            1
 #define MT9V022_ROW_SKIP               4
 
+#define is_mt9v024(id) (id == 0x1324)
+
 /* MT9V022 has only one fixed colorspace per pixelcode */
 struct mt9v022_datafmt {
        enum v4l2_mbus_pixelcode        code;
@@ -101,6 +107,22 @@ static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = {
        {V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
 };
 
+/* only registers with different addresses on different mt9v02x sensors */
+struct mt9v02x_register {
+       u8      max_total_shutter_width;
+       u8      pixclk_fv_lv;
+};
+
+static const struct mt9v02x_register mt9v022_register = {
+       .max_total_shutter_width        = MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
+       .pixclk_fv_lv                   = MT9V022_PIXCLK_FV_LV,
+};
+
+static const struct mt9v02x_register mt9v024_register = {
+       .max_total_shutter_width        = MT9V024_MAX_TOTAL_SHUTTER_WIDTH,
+       .pixclk_fv_lv                   = MT9V024_PIXCLK_FV_LV,
+};
+
 struct mt9v022 {
        struct v4l2_subdev subdev;
        struct v4l2_ctrl_handler hdl;
@@ -117,6 +139,7 @@ struct mt9v022 {
        struct v4l2_rect rect;  /* Sensor window */
        const struct mt9v022_datafmt *fmt;
        const struct mt9v022_datafmt *fmts;
+       const struct mt9v02x_register *reg;
        int num_fmts;
        int model;      /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
        u16 chip_control;
@@ -185,7 +208,7 @@ static int mt9v022_init(struct i2c_client *client)
        if (!ret)
                ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, 480);
        if (!ret)
-               ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
+               ret = reg_write(client, mt9v022->reg->max_total_shutter_width, 480);
        if (!ret)
                /* default - auto */
                ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
@@ -238,7 +261,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
        ret = reg_read(client, MT9V022_AEC_AGC_ENABLE);
        if (ret >= 0) {
                if (ret & 1) /* Autoexposure */
-                       ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
+                       ret = reg_write(client, mt9v022->reg->max_total_shutter_width,
                                        rect.height + mt9v022->y_skip_top + 43);
                else
                        ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
@@ -585,14 +608,17 @@ static int mt9v022_video_probe(struct i2c_client *client)
        /* Read out the chip version register */
        data = reg_read(client, MT9V022_CHIP_VERSION);
 
-       /* must be 0x1311 or 0x1313 */
-       if (data != 0x1311 && data != 0x1313) {
+       /* must be 0x1311, 0x1313 or 0x1324 */
+       if (data != 0x1311 && data != 0x1313 && data != 0x1324) {
                ret = -ENODEV;
                dev_info(&client->dev, "No MT9V022 found, ID register 0x%x\n",
                         data);
                goto ei2c;
        }
 
+       mt9v022->reg = is_mt9v024(data) ? &mt9v024_register :
+                       &mt9v022_register;
+
        /* Soft reset */
        ret = reg_write(client, MT9V022_RESET, 1);
        if (ret < 0)
@@ -742,7 +768,7 @@ static int mt9v022_s_mbus_config(struct v4l2_subdev *sd,
        if (!(flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH))
                pixclk |= 0x2;
 
-       ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk);
+       ret = reg_write(client, mt9v022->reg->pixclk_fv_lv, pixclk);
        if (ret < 0)
                return ret;