/*
* Driver for MT9V022, MT9V024, MT9V032, and MT9V034 CMOS Image Sensors
*
* Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
*
* Based on the MT9M001 driver,
*
* Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/log2.h>
#include <linux/mutex.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/v4l2-mediabus.h>
#include <linux/module.h>
#include <media/i2c/mt9v032.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-of.h>
#include <media/v4l2-subdev.h>
/* The first four rows are black rows. The active area spans 753x481 pixels. */
#define MT9V032_PIXEL_ARRAY_HEIGHT 485
#define MT9V032_PIXEL_ARRAY_WIDTH 753
#define MT9V032_SYSCLK_FREQ_DEF 26600000
#define MT9V032_CHIP_VERSION 0x00
#define MT9V032_CHIP_ID_REV1 0x1311
#define MT9V032_CHIP_ID_REV3 0x1313
#define MT9V034_CHIP_ID_REV1 0X1324
#define MT9V032_COLUMN_START 0x01
#define MT9V032_COLUMN_START_MIN 1
#define MT9V032_COLUMN_START_DEF 1
#define MT9V032_COLUMN_START_MAX 752
#define MT9V032_ROW_START 0x02
#define MT9V032_ROW_START_MIN 4
#define MT9V032_ROW_START_DEF 5
#define MT9V032_ROW_START_MAX 482
#define MT9V032_WINDOW_HEIGHT 0x03
#define MT9V032_WINDOW_HEIGHT_MIN 1
#define MT9V032_WINDOW_HEIGHT_DEF 480
#define MT9V032_WINDOW_HEIGHT_MAX 480
#define MT9V032_WINDOW_WIDTH 0x04
#define MT9V032_WINDOW_WIDTH_MIN 1
#define MT9V032_WINDOW_WIDTH_DEF 752
#define MT9V032_WINDOW_WIDTH_MAX 752
#define MT9V032_HORIZONTAL_BLANKING 0x05
#define MT9V032_HORIZONTAL_BLANKING_MIN 43
#define MT9V034_HORIZONTAL_BLANKING_MIN 61
#define MT9V032_HORIZONTAL_BLANKING_DEF 94
#define MT9V032_HORIZONTAL_BLANKING_MAX 1023
#define MT9V032_VERTICAL_BLANKING 0x06
#define MT9V032_VERTICAL_BLANKING_MIN 4
#define MT9V034_VERTICAL_BLANKING_MIN 2
#define MT9V032_VERTICAL_BLANKING_DEF 45
#define MT9V032_VERTICAL_BLANKING_MAX 3000
#define MT9V034_VERTICAL_BLANKING_MAX 32288
#define MT9V032_CHIP_CONTROL 0x07
#define MT9V032_CHIP_CONTROL_MASTER_MODE (1 << 3)
#define MT9V032_CHIP_CONTROL_DOUT_ENABLE (1 << 7)
#define MT9V032_CHIP_CONTROL_SEQUENTIAL (1 << 8)
#define MT9V032_SHUTTER_WIDTH1 0x08
#define MT9V032_SHUTTER_WIDTH2 0x09
#define MT9V032_SHUTTER_WIDTH_CONTROL 0x0a
#define MT9V032_TOTAL_SHUTTER_WIDTH 0x0b
#define MT9V032_TOTAL_SHUTTER_WIDTH_MIN 1
#define MT9V034_TOTAL_SHUTTER_WIDTH_MIN 0
#define MT9V032_TOTAL_SHUTTER_WIDTH_DEF 480
#define MT9V032_TOTAL_SHUTTER_WIDTH_MAX 32767
#define MT9V034_TOTAL_SHUTTER_WIDTH_MAX 32765
#define MT9V032_RESET 0x0c
#define MT9V032_READ_MODE 0x0d
#define MT9V032_READ_MODE_ROW_BIN_MASK (3 << 0)
#define MT9V032_READ_MODE_ROW_BIN_SHIFT 0
#define MT9V032_READ_MODE_COLUMN_BIN_MASK (3 << 2)
#define MT9V032_READ_MODE_COLUMN_BIN_SHIFT 2
#define MT9V032_READ_MODE_ROW_FLIP (1 << 4)
#define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5)
#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6)
#define MT9V032_READ_MODE_DARK_ROWS (1 << 7)
#define MT9V032_READ_MODE_RESERVED 0x0300
#define MT9V032_PIXEL_OPERATION_MODE 0x0f
#define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 0)
#define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 1)
#define MT9V032_PIXEL_OPERATION_MODE_COLOR (1 << 2)
#define MT9V032_PIXEL_OPERATION_MODE_HDR (1 << 6)
#define MT9V032_ANALOG_GAIN 0x35
#define MT9V032_ANALOG_GAIN_MIN 16
#define MT9V032_ANALOG_GAIN_DEF 16
#define MT9V032_ANALOG_GAIN_MAX 64
#define MT9V032_MAX_ANALOG_GAIN 0x36
#define MT9V032_MAX_ANALOG_GAIN_MAX 127
#define MT9V032_FRAME_DARK_AVERAGE 0x42
#define MT9V032_DARK_AVG_THRESH 0x46
#define MT9V032_DARK_AVG_LOW_THRESH_MASK (255 << 0)
#define MT9V032_DARK_AVG_LOW_THRESH_SHIFT 0
#define MT9V032_DARK_AVG_HIGH_THRESH_MASK (255 << 8)
#define MT9V032_DARK_AVG_HIGH_THRESH_SHIFT 8
#define MT9V032_ROW_NOISE_CORR_CONTROL 0x70
#define MT9V034_ROW_NOISE_CORR_ENABLE (1 << 0)
#define MT9V034_ROW_NOISE_CORR_USE_BLK_AVG (1 << 1)
#define MT9V032_ROW_NOISE_CORR_ENABLE (1 << 5)
#define MT9V032_ROW_NOISE_CORR_USE_BLK_AVG (1 << 7)
#define MT9V032_PIXEL_CLOCK 0x74
#define MT9V034_PIXEL_CLOCK 0x72
#define MT9V032_PIXEL_CLOCK_INV_LINE (1 << 0)
#define MT9V032_PIXEL_CLOCK_INV_FRAME (1 << 1)
#define MT9V032_PIXEL_CLOCK_XOR_LINE (1 << 2)
#define MT9V032_PIXEL_CLOCK_CONT_LINE (1 << 3)
#define MT9V032_PIXEL_CLOCK_INV_PXL_CLK (1 << 4)
#define MT9V032_TEST_PATTERN 0x7f
#define MT9V032_TEST_PATTERN_DATA_MASK (1023 << 0)
#define MT9V032_TEST_PATTERN_DATA_SHIFT 0
#define MT9V032_TEST_PATTERN_USE_DATA (1 << 10)
#define MT9V032_TEST_PATTERN_GRAY_MASK (3 << 11)
#define MT9V032_TEST_PATTERN_GRAY_NONE (0 << 11)
#define MT9V032_TEST_PATTERN_GRAY_VERTICAL (1 << 11)
#define MT9V032_TEST_PATTERN_GRAY_HORIZONTAL (2 << 11)
#define MT9V032_TEST_PATTERN_GRAY_DIAGONAL (3 << 11)
#define MT9V032_TEST_PATTERN_ENABLE (1 << 13)
#define MT9V032_TEST_PATTERN_FLIP (1 << 14)
#define MT9V032_AEGC_DESIRED_BIN 0xa5
#define MT9V032_AEC_UPDATE_FREQUENCY 0xa6
#define MT9V032_AEC_LPF 0xa8
#define MT9V032_AGC_UPDATE_FREQUENCY 0xa9
#define MT9V032_AGC_LPF 0xaa
#define MT9V032_AEC_AGC_ENABLE 0xaf
#define MT9V032_AEC_ENABLE (1 << 0)
#define MT9V032_AGC_ENABLE (1 << 1)
#define MT9V034_AEC_MAX_SHUTTER_WIDTH 0xad
#define MT9V032_AEC_MAX_SHUTTER_WIDTH 0xbd
#define MT9V032_THERMAL_INFO 0xc1
enum mt9v032_model {
MT9V032_MODEL_V022_COLOR, /* MT9V022IX7ATC */
MT9V032_MODEL_V022_MONO, /* MT9V022IX7ATM */
MT9V032_MODEL_V024_COLOR, /* MT9V024IA7XTC */
MT9V032_MODEL_V024_MONO, /* MT9V024IA7XTM */
MT9V032_MODEL_V032_COLOR, /* MT9V032C12STM */
MT9V032_MODEL_V032_MONO, /* MT9V032C12STC */
MT9V032_MODEL_V034_COLOR,
MT9V032_MODEL_V034_MONO,
};
struct mt9v032_model_version {
unsigned int version;
const char *name;
};
struct mt9v032_model_data