diff options
author | Andrei Andreyanau <a.andreyanau@sam-solutions.net> | 2013-01-31 14:13:31 +0300 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2013-11-07 12:19:23 -0500 |
commit | 3b6d4316ee4c2bfc3758c09f487f5e41184e1984 (patch) | |
tree | c9c83fa7a22e0c67163a8e0801b1870c8ae16eaa /drivers | |
parent | d3a69896fc07d8a93b6a41a398b179fa0eca8508 (diff) |
Added support for mt9v024 camera
modified: drivers/media/video/mt9v022.c
Signed-off-by: Christian Hemp <c.hemp@phytec.de>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/media/video/mt9v022.c | 62 |
1 files changed, 56 insertions, 6 deletions
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index fc76ed1c08e5..a46c198d1bf4 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -47,6 +47,7 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); #define MT9V022_PIXEL_OPERATION_MODE 0x0f #define MT9V022_LED_OUT_CONTROL 0x1b #define MT9V022_ADC_MODE_CONTROL 0x1c +#define MT9V022_REG32 0x20 #define MT9V022_ANALOG_GAIN 0x35 #define MT9V022_BLACK_LEVEL_CALIB_CTRL 0x47 #define MT9V022_PIXCLK_FV_LV 0x74 @@ -54,6 +55,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 @@ -64,6 +69,9 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\""); #define MT9V022_COLUMN_SKIP 1 #define MT9V022_ROW_SKIP 4 +#define is_mt9v022_rev3(id) (id == 0x1313) +#define is_mt9v024(id) (id == 0x1324) + /* MT9V022 has only one fixed colorspace per pixelcode */ struct mt9v022_datafmt { enum v4l2_mbus_pixelcode code; @@ -98,14 +106,31 @@ static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = { {V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG}, }; +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_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; + u16 chip_version; unsigned short y_skip_top; /* Lines to skip at the top */ }; @@ -187,12 +212,32 @@ static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable) struct i2c_client *client = v4l2_get_subdevdata(sd); struct mt9v022 *mt9v022 = to_mt9v022(client); - if (enable) + if (enable) { /* Switch to master "normal" mode */ mt9v022->chip_control &= ~0x10; - else - /* Switch to snapshot mode */ - mt9v022->chip_control |= 0x10; + if (is_mt9v022_rev3(mt9v022->chip_version) || + is_mt9v024(mt9v022->chip_version)) { + /* + * Unset snapshot mode specific settings: clear bit 9 + * and bit 2 in reg. 0x20 when in normal mode. + */ + if (reg_clear(client, MT9V022_REG32, 0x204)) + return -EIO; + } + } else { + /* Switch to snapshot mode */ + mt9v022->chip_control |= 0x10; + if (is_mt9v022_rev3(mt9v022->chip_version) || + is_mt9v024(mt9v022->chip_version)) { + /* + * Required settings for snapshot mode: set bit 9 + * (RST enable) and bit 2 (CR enable) in reg. 0x20 + * See TechNote TN0960 or TN-09-225. + */ + if (reg_set(client, MT9V022_REG32, 0x204)) + return -EIO; + } + } if (reg_write(client, MT9V022_CHIP_CONTROL, mt9v022->chip_control) < 0) return -EIO; @@ -720,7 +765,7 @@ static int mt9v022_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl) * this wasn't our capture interface, so, we wait for the right one */ static int mt9v022_video_probe(struct soc_camera_device *icd, - struct i2c_client *client) + struct i2c_client *client) { struct mt9v022 *mt9v022 = to_mt9v022(client); struct soc_camera_link *icl = to_soc_camera_link(icd); @@ -736,13 +781,18 @@ static int mt9v022_video_probe(struct soc_camera_device *icd, data = reg_read(client, MT9V022_CHIP_VERSION); /* must be 0x1311 or 0x1313 */ - if (data != 0x1311 && data != 0x1313) { + 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->chip_version = data; + + mt9v022->reg = is_mt9v024(data) ? &mt9v024_register : + &mt9v022_register; + /* Soft reset */ ret = reg_write(client, MT9V022_RESET, 1); if (ret < 0) |