|
@@ -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;
|
|
|
|