summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Lavnikevich <d.lavnikevich@sam-solutions.net>2012-10-12 15:52:15 +0300
committerJustin Waters <justin.waters@timesys.com>2013-11-07 12:19:17 -0500
commite931ef1741fa54626700cdc3c9d21ba5d7db741b (patch)
tree10a0171ae7c57ab0fe0a007f87f294e69a2dcb58
parent7115ba5a14c5aa6c947b380ddfedb6fb19cb1dbb (diff)
Camera driver mt9m111 cloned from mt9v111 and enabled
Signed-off-by: Christian Hemp <c.hemp@phytec.de>
-rw-r--r--drivers/media/video/mxc/capture/Kconfig8
-rw-r--r--drivers/media/video/mxc/capture/Makefile2
-rw-r--r--drivers/media/video/mxc/capture/mt9m111.c1182
-rw-r--r--drivers/media/video/mxc/capture/mt9m111.h431
4 files changed, 1623 insertions, 0 deletions
diff --git a/drivers/media/video/mxc/capture/Kconfig b/drivers/media/video/mxc/capture/Kconfig
index a862636dbed0..ae1a5958afaa 100644
--- a/drivers/media/video/mxc/capture/Kconfig
+++ b/drivers/media/video/mxc/capture/Kconfig
@@ -57,6 +57,14 @@ config MXC_CAMERA_MICRON111
---help---
If you plan to use the mt9v111 Camera with your MXC system, say Y here.
+config MXC_CAMERA_MICRON111_M
+ tristate "Micron mt9m111 camera support"
+ select I2C_MXC
+ depends on ! VIDEO_MXC_EMMA_CAMERA
+ select MXC_CAMERA_SENSOR_CLK
+ ---help---
+ If you plan to use the mt9m111 Camera with your MXC system, say Y here.
+
config MXC_CAMERA_OV2640
tristate "OmniVision ov2640 camera support"
depends on !VIDEO_MXC_EMMA_CAMERA
diff --git a/drivers/media/video/mxc/capture/Makefile b/drivers/media/video/mxc/capture/Makefile
index 7f8b168f6f5e..630f31dd2a83 100644
--- a/drivers/media/video/mxc/capture/Makefile
+++ b/drivers/media/video/mxc/capture/Makefile
@@ -22,6 +22,8 @@ obj-$(CONFIG_MXC_EMMA_CAMERA_MICRON111) += emma_mt9v111_camera.o
mt9v111_camera-objs := mt9v111.o
obj-$(CONFIG_MXC_CAMERA_MICRON111) += mt9v111_camera.o
+mt9m111_camera-objs := mt9m111.o
+obj-$(CONFIG_MXC_CAMERA_MICRON111_M) += mt9m111_camera.o
hv7161_camera-objs := hv7161.o
obj-$(CONFIG_MXC_CAMERA_HV7161) += hv7161_camera.o
diff --git a/drivers/media/video/mxc/capture/mt9m111.c b/drivers/media/video/mxc/capture/mt9m111.c
new file mode 100644
index 000000000000..73808e5fb97c
--- /dev/null
+++ b/drivers/media/video/mxc/capture/mt9m111.c
@@ -0,0 +1,1182 @@
+/*
+ * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @file mt9m111.c
+ *
+ * @brief mt9m111 camera driver functions
+ *
+ * @ingroup Camera
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ctype.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <media/v4l2-int-device.h>
+#include "mxc_v4l2_capture.h"
+#include "mt9m111.h"
+
+#ifdef MT9M111_DEBUG
+static u16 testpattern;
+#endif
+
+static mt9m111_conf mt9m111_device;
+
+/*!
+ * Holds the current frame rate.
+ */
+static int reset_frame_rate = MT9M111_FRAME_RATE;
+
+struct sensor {
+ const struct mt9m111_platform_data *platform_data;
+ struct v4l2_int_device *v4l2_int_device;
+ struct i2c_client *i2c_client;
+ struct v4l2_pix_format pix;
+ struct v4l2_captureparm streamcap;
+ bool on;
+
+ /* control settings */
+ int brightness;
+ int hue;
+ int contrast;
+ int saturation;
+ int red;
+ int green;
+ int blue;
+ int ae_mode;
+
+} mt9m111_data;
+
+extern void gpio_sensor_active(void);
+extern void gpio_sensor_inactive(void);
+
+static int mt9m111_probe(struct i2c_client *client,
+ const struct i2c_device_id *id);
+static int mt9m111_remove(struct i2c_client *client);
+
+static const struct i2c_device_id mt9m111_id[] = {
+ {"mt9m111", 0},
+ {},
+};
+
+MODULE_DEVICE_TABLE(i2c, mt9m111_id);
+
+static struct i2c_driver mt9m111_i2c_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "mt9m111",
+ },
+ .probe = mt9m111_probe,
+ .remove = mt9m111_remove,
+ .id_table = mt9m111_id,
+/* To add power management add .suspend and .resume functions */
+};
+
+/*
+ * Function definitions
+ */
+
+#ifdef MT9M111_DEBUG
+static inline int mt9m111_read_reg(u8 reg)
+{
+ printk("::: mt9m111_read_reg\n");
+
+ int val = i2c_smbus_read_word_data(mt9m111_data.i2c_client, reg);
+ if (val != -1)
+ val = cpu_to_be16(val);
+
+ printk("::: mt9m111_read_reg (END, ret=%d)\n", val);
+ return val;
+}
+#endif
+
+/*!
+ * Writes to the register via I2C.
+ */
+static inline int mt9m111_write_reg(u8 reg, u16 val)
+{
+ printk("::: mt9m111_write_reg\n");
+
+ pr_debug("In mt9m111_write_reg (0x%x, 0x%x)\n", reg, val);
+ pr_debug(" write reg %x val %x.\n", reg, val);
+
+ int ret = i2c_smbus_write_word_data(mt9m111_data.i2c_client,
+ reg, cpu_to_be16(val));
+
+ printk("::: mt9m111_write_reg (END, ret=%d)\n", ret);
+
+ return ret;
+}
+
+/*!
+ * Initialize mt9m111_sensor_lib
+ * Libarary for Sensor configuration through I2C
+ *
+ * @param coreReg Core Registers
+ * @param ifpReg IFP Register
+ *
+ * @return status
+ */
+static u8 mt9m111_sensor_lib(mt9m111_coreReg *coreReg, mt9m111_IFPReg *ifpReg)
+{
+ printk("::: mt9m111_sensor_lib\n");
+
+ u8 reg;
+ u16 data;
+ u8 error = 0;
+
+ pr_debug("In mt9m111_sensor_lib\n");
+
+ /*
+ * setup to IFP registers
+ */
+ reg = MT9M111I_ADDR_SPACE_SEL;
+ data = ifpReg->addrSpaceSel;
+ mt9m111_write_reg(reg, data);
+
+ /* Operation Mode Control */
+ reg = MT9M111I_MODE_CONTROL;
+ data = ifpReg->modeControl;
+ mt9m111_write_reg(reg, data);
+
+ /* Output format */
+ reg = MT9M111I_FORMAT_CONTROL;
+ data = ifpReg->formatControl; /* Set bit 12 */
+ mt9m111_write_reg(reg, data);
+
+ /* AE limit 4 */
+ reg = MT9M111I_SHUTTER_WIDTH_LIMIT_AE;
+ data = ifpReg->gainLimitAE;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111I_OUTPUT_FORMAT_CTRL2;
+ data = ifpReg->outputFormatCtrl2;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111I_AE_SPEED;
+ data = ifpReg->AESpeed;
+ mt9m111_write_reg(reg, data);
+
+ /* output image size */
+ reg = MT9M111i_H_PAN;
+ data = 0x8000 | ifpReg->HPan;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111i_H_ZOOM;
+ data = 0x8000 | ifpReg->HZoom;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111i_H_SIZE;
+ data = 0x8000 | ifpReg->HSize;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111i_V_PAN;
+ data = 0x8000 | ifpReg->VPan;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111i_V_ZOOM;
+ data = 0x8000 | ifpReg->VZoom;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111i_V_SIZE;
+ data = 0x8000 | ifpReg->VSize;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111i_H_PAN;
+ data = ~0x8000 & ifpReg->HPan;
+ mt9m111_write_reg(reg, data);
+#if 0
+ reg = MT9M111I_UPPER_SHUTTER_DELAY_LIM;
+ data = ifpReg->upperShutterDelayLi;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111I_SHUTTER_60;
+ data = ifpReg->shutter_width_60;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111I_SEARCH_FLICK_60;
+ data = ifpReg->search_flicker_60;
+ mt9m111_write_reg(reg, data);
+#endif
+
+ /*
+ * setup to sensor core registers
+ */
+ reg = MT9M111I_ADDR_SPACE_SEL;
+ data = coreReg->addressSelect;
+ mt9m111_write_reg(reg, data);
+
+ /* enable changes and put the Sync bit on */
+ reg = MT9M111S_OUTPUT_CTRL;
+ data = MT9M111S_OUTCTRL_SYNC | MT9M111S_OUTCTRL_CHIP_ENABLE | 0x3000;
+ mt9m111_write_reg(reg, data);
+
+ /* min PIXCLK - Default */
+ reg = MT9M111S_PIXEL_CLOCK_SPEED;
+ data = coreReg->pixelClockSpeed;
+ mt9m111_write_reg(reg, data);
+
+ /* Setup image flipping / Dark rows / row/column skip */
+ reg = MT9M111S_READ_MODE;
+ data = coreReg->readMode;
+ mt9m111_write_reg(reg, data);
+
+ /* zoom 0 */
+ reg = MT9M111S_DIGITAL_ZOOM;
+ data = coreReg->digitalZoom;
+ mt9m111_write_reg(reg, data);
+
+ /* min H-blank */
+ reg = MT9M111S_HOR_BLANKING;
+ data = coreReg->horizontalBlanking;
+ mt9m111_write_reg(reg, data);
+
+ /* min V-blank */
+ reg = MT9M111S_VER_BLANKING;
+ data = coreReg->verticalBlanking;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111S_SHUTTER_WIDTH;
+ data = coreReg->shutterWidth;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111S_SHUTTER_DELAY;
+ data = ifpReg->upperShutterDelayLi;
+ mt9m111_write_reg(reg, data);
+
+ /* changes become effective */
+ reg = MT9M111S_OUTPUT_CTRL;
+ data = MT9M111S_OUTCTRL_CHIP_ENABLE | 0x3000;
+ mt9m111_write_reg(reg, data);
+
+ printk("::: mt9m111_sensor_lib (END, error=%d)\n", error);
+
+ return error;
+}
+
+/*!
+ * MT9M111 frame rate calculate
+ *
+ * @param frame_rate int *
+ * @param mclk int
+ * @return None
+ */
+static void mt9m111_rate_cal(int *frame_rate, int mclk)
+{
+ printk("::: mt9m111_rate_cal\n");
+
+ int num_clock_per_row;
+ int max_rate = 0;
+
+ pr_debug("In mt9m111_rate_cal\n");
+
+ num_clock_per_row = (MT9M111_MAX_WIDTH + 114 + MT9M111_HORZBLANK_MIN)
+ * 2;
+ max_rate = mclk / (num_clock_per_row *
+ (MT9M111_MAX_HEIGHT + MT9M111_VERTBLANK_DEFAULT));
+
+ if ((*frame_rate > max_rate) || (*frame_rate == 0)) {
+ *frame_rate = max_rate;
+ }
+
+ mt9m111_device.coreReg->verticalBlanking
+ = mclk / (*frame_rate * num_clock_per_row) - MT9M111_MAX_HEIGHT;
+
+ reset_frame_rate = *frame_rate;
+
+ printk("::: mt9m111_rate_cal (END)\n");
+}
+
+/*!
+ * MT9M111 sensor configuration
+ */
+void mt9m111_config(void)
+{
+ printk("::: mt9m111_config\n");
+
+ pr_debug("In mt9m111_config\n");
+
+ mt9m111_device.coreReg->addressSelect = MT9M111I_SEL_SCA;
+ mt9m111_device.ifpReg->addrSpaceSel = MT9M111I_SEL_IFP;
+
+ mt9m111_device.coreReg->windowHeight = MT9M111_WINHEIGHT;
+ mt9m111_device.coreReg->windowWidth = MT9M111_WINWIDTH;
+ mt9m111_device.coreReg->zoomColStart = 0;
+ mt9m111_device.coreReg->zomRowStart = 0;
+ mt9m111_device.coreReg->digitalZoom = 0x0;
+
+ mt9m111_device.coreReg->verticalBlanking = MT9M111_VERTBLANK_DEFAULT;
+ mt9m111_device.coreReg->horizontalBlanking = MT9M111_HORZBLANK_MIN;
+ mt9m111_device.coreReg->pixelClockSpeed = 0;
+ mt9m111_device.coreReg->readMode = 0xd0a1;
+
+ mt9m111_device.ifpReg->outputFormatCtrl2 = 0;
+ mt9m111_device.ifpReg->gainLimitAE = 0x300;
+ mt9m111_device.ifpReg->AESpeed = 0x80;
+
+ /* here is the default value */
+ mt9m111_device.ifpReg->formatControl = 0xc800;
+ mt9m111_device.ifpReg->modeControl = 0x708e;
+ mt9m111_device.ifpReg->awbSpeed = 0x4514;
+ mt9m111_device.coreReg->shutterWidth = 0xf8;
+
+ /* output size */
+ mt9m111_device.ifpReg->HPan = 0;
+ mt9m111_device.ifpReg->HZoom = MT9M111_MAX_WIDTH;
+ mt9m111_device.ifpReg->HSize = MT9M111_MAX_WIDTH;
+ mt9m111_device.ifpReg->VPan = 0;
+ mt9m111_device.ifpReg->VZoom = MT9M111_MAX_HEIGHT;
+ mt9m111_device.ifpReg->VSize = MT9M111_MAX_HEIGHT;
+
+ printk("::: mt9m111_config (END)\n");
+}
+
+/*!
+ * mt9m111 sensor set saturtionn
+ *
+ * @param saturation int
+
+ * @return Error code of 0.
+ */
+static int mt9m111_set_saturation(int saturation)
+{
+ printk("::: mt9m111_set_saturation\n");
+
+ u8 reg;
+ u16 data;
+ pr_debug("In mt9m111_set_saturation(%d)\n",
+ saturation);
+
+ switch (saturation) {
+ case 150:
+ mt9m111_device.ifpReg->awbSpeed = 0x6D14;
+ break;
+ case 100:
+ mt9m111_device.ifpReg->awbSpeed = 0x4514;
+ break;
+ case 75:
+ mt9m111_device.ifpReg->awbSpeed = 0x4D14;
+ break;
+ case 50:
+ mt9m111_device.ifpReg->awbSpeed = 0x5514;
+ break;
+ case 37:
+ mt9m111_device.ifpReg->awbSpeed = 0x5D14;
+ break;
+ case 25:
+ mt9m111_device.ifpReg->awbSpeed = 0x6514;
+ break;
+ default:
+ mt9m111_device.ifpReg->awbSpeed = 0x4514;
+ break;
+ }
+
+ reg = MT9M111I_ADDR_SPACE_SEL;
+ data = mt9m111_device.ifpReg->addrSpaceSel;
+ mt9m111_write_reg(reg, data);
+
+ /* Operation Mode Control */
+ reg = MT9M111I_AWB_SPEED;
+ data = mt9m111_device.ifpReg->awbSpeed;
+ mt9m111_write_reg(reg, data);
+
+ printk("::: mt9m111_set_saturation (END)\n");
+
+ return 0;
+}
+
+/*!
+ * mt9m111 sensor set Auto Exposure measurement window mode configuration
+ *
+ * @param ae_mode int
+ * @return Error code of 0 (no Error)
+ */
+static int mt9m111_set_ae_mode(int ae_mode)
+{
+ printk("::: mt9m111_set_ae_mode\n");
+
+ u8 reg;
+ u16 data;
+
+ pr_debug("In mt9m111_set_ae_mode(%d)\n",
+ ae_mode);
+
+ /* Currently this driver only supports auto and manual exposure
+ * modes. */
+ if ((ae_mode > 1) || (ae_mode << 0))
+ {
+ printk("::: mt9m111_set_ae_mode (END, error=-EPERM)\n");
+
+ return -EPERM;
+ }
+
+ /*
+ * The auto exposure is set in bit 14.
+ * Other values are set for:
+ * -on the fly defect correction is on (bit 13).
+ * -aperature correction knee enabled (bit 12).
+ * -ITU_R BT656 synchronization codes are embedded in the image (bit 7)
+ * -AE measurement window is weighted sum of large and center windows
+ * (bits 2-3).
+ * -auto white balance is on (bit 1).
+ * -normal color processing (bit 4 = 0).
+ */
+ /* V4L2_EXPOSURE_AUTO = 0; needs register setting of 0x708E */
+ /* V4L2_EXPOSURE_MANUAL = 1 needs register setting of 0x308E */
+ mt9m111_device.ifpReg->modeControl &= 0x3fff;
+ mt9m111_device.ifpReg->modeControl |= (ae_mode & 0x03) << 14;
+ mt9m111_data.ae_mode = ae_mode;
+
+ reg = MT9M111I_ADDR_SPACE_SEL;
+ data = mt9m111_device.ifpReg->addrSpaceSel;
+ mt9m111_write_reg(reg, data);
+
+ reg = MT9M111I_MODE_CONTROL;
+ data = mt9m111_device.ifpReg->modeControl;
+ mt9m111_write_reg(reg, data);
+
+ printk("::: mt9m111_set_ae_mode (END)\n");
+
+ return 0;
+}
+
+/*!
+ * mt9m111 sensor get AE measurement window mode configuration
+ *
+ * @param ae_mode int *
+ * @return None
+ */
+static void mt9m111_get_ae_mode(int *ae_mode)
+{
+ printk("::: mt9m111_get_ae_mode\n");
+
+ pr_debug("In mt9m111_get_ae_mode(%d)\n", *ae_mode);
+
+ if (ae_mode != NULL) {
+ *ae_mode = (mt9m111_device.ifpReg->modeControl & 0xc) >> 2;
+ }
+
+ printk("::: mt9m111_get_ae_mode (END)\n");
+}
+
+#ifdef MT9M111_DEBUG
+/*!
+ * Set sensor to test mode, which will generate test pattern.
+ *
+ * @return none
+ */
+static void mt9m111_test_pattern(bool flag)
+{
+ printk("::: mt9m111_test_pattern\n");
+
+ u16 data;
+
+ /* switch to sensor registers */
+ mt9m111_write_reg(MT9M111I_ADDR_SPACE_SEL, MT9M111I_SEL_SCA);
+
+ if (flag == true) {
+ testpattern = MT9M111S_OUTCTRL_TEST_MODE;
+
+ data = mt9m111_read_reg(MT9M111S_ROW_NOISE_CTRL) & 0xBF;
+ mt9m111_write_reg(MT9M111S_ROW_NOISE_CTRL, data);
+
+ mt9m111_write_reg(MT9M111S_TEST_DATA, 0);
+
+ /* changes take effect */
+ data = MT9M111S_OUTCTRL_CHIP_ENABLE | testpattern | 0x3000;
+ mt9m111_write_reg(MT9M111S_OUTPUT_CTRL, data);
+ } else {
+ testpattern = 0;
+
+ data = mt9m111_read_reg(MT9M111S_ROW_NOISE_CTRL) | 0x40;
+ mt9m111_write_reg(MT9M111S_ROW_NOISE_CTRL, data);
+
+ /* changes take effect */
+ data = MT9M111S_OUTCTRL_CHIP_ENABLE | testpattern | 0x3000;
+ mt9m111_write_reg(MT9M111S_OUTPUT_CTRL, data);
+ }
+
+ printk("::: mt9m111_test_pattern (END)\n");
+}
+#endif
+
+
+/* --------------- IOCTL functions from v4l2_int_ioctl_desc --------------- */
+
+/*!
+ * ioctl_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_ifparm_num
+ * s: pointer to standard V4L2 device structure
+ * p: pointer to standard V4L2 vidioc_int_g_ifparm_num ioctl structure
+ *
+ * Gets slave interface parameters.
+ * Calculates the required xclk value to support the requested
+ * clock parameters in p. This value is returned in the p
+ * parameter.
+ *
+ * vidioc_int_g_ifparm returns platform-specific information about the
+ * interface settings used by the sensor.
+ *
+ * Given the image capture format in pix, the nominal frame period in
+ * timeperframe, calculate the required xclk frequency.
+ *
+ * Called on open.
+ */
+static int ioctl_g_ifparm(struct v4l2_int_device *s, struct v4l2_ifparm *p)
+{
+ printk("::: ioctl_g_ifparm\n");
+
+ pr_debug("In mt9m111:ioctl_g_ifparm\n");
+
+ if (s == NULL) {
+ printk("::: ioctl_g_ifparm (END, error)\n");
+
+ pr_err(" ERROR!! no slave device set!\n");
+ return -1;
+ }
+
+ memset(p, 0, sizeof(*p));
+ p->u.bt656.clock_curr = MT9M111_MCLK;
+ p->if_type = V4L2_IF_TYPE_BT656;
+ p->u.bt656.mode = V4L2_IF_TYPE_BT656_MODE_NOBT_8BIT;
+ p->u.bt656.clock_min = MT9M111_CLK_MIN;
+ p->u.bt656.clock_max = MT9M111_CLK_MAX;
+
+ printk("::: ioctl_g_ifparm (END)\n");
+
+ return 0;
+}
+
+/*!
+ * Sets the camera power.
+ *
+ * s pointer to the camera device
+ * on if 1, power is to be turned on. 0 means power is to be turned off
+ *
+ * ioctl_s_power - V4L2 sensor interface handler for vidioc_int_s_power_num
+ * @s: pointer to standard V4L2 device structure
+ * @on: power state to which device is to be set
+ *
+ * Sets devices power state to requrested state, if possible.
+ * This is called on suspend and resume.
+ */
+static int ioctl_s_power(struct v4l2_int_device *s, int on)
+{
+ printk("::: ioctl_s_power\n");
+
+ struct sensor *sensor = s->priv;
+
+ pr_debug("In mt9m111:ioctl_s_power\n");
+
+ sensor->on = on;
+
+ if (on)
+ gpio_sensor_active();
+ else
+ gpio_sensor_inactive();
+
+ printk("::: ioctl_s_power (END)\n");
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_parm - V4L2 sensor interface handler for VIDIOC_G_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_G_PARM ioctl structure
+ *
+ * Returns the sensor's video CAPTURE parameters.
+ */
+static int ioctl_g_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ printk("::: ioctl_g_parm\n");
+
+ int ret = 0;
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+ /* s->priv points to mt9m111_data */
+
+ pr_debug("In mt9m111:ioctl_g_parm\n");
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+ memset(a, 0, sizeof(*a));
+ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ cparm->capability = mt9m111_data.streamcap.capability;
+ cparm->timeperframe =
+ mt9m111_data.streamcap.timeperframe;
+ cparm->capturemode = mt9m111_data.streamcap.capturemode;
+ ret = 0;
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ pr_err(" type is not V4L2_BUF_TYPE_VIDEO_CAPTURE " \
+ "but %d\n", a->type);
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_err(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ printk("::: ioctl_g_parm (END, ret=%d)\n", ret);
+
+ return ret;
+}
+
+/*!
+ * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
+ *
+ * Configures the sensor to use the input parameters, if possible. If
+ * not possible, reverts to the old parameters and returns the
+ * appropriate error code.
+ */
+static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
+{
+ printk("::: ioctl_s_parm\n");
+
+ int ret = 0;
+ struct v4l2_captureparm *cparm = &a->parm.capture;
+ /* s->priv points to mt9m111_data */
+
+ pr_debug("In mt9m111:ioctl_s_parm\n");
+
+ switch (a->type) {
+ /* This is the only case currently handled. */
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ pr_debug(" type is V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
+
+ /* Check that the new frame rate is allowed.
+ * Changing the frame rate is not allowed on this
+ *camera. */
+ if (cparm->timeperframe.denominator !=
+ mt9m111_data.streamcap.timeperframe.denominator) {
+ pr_err("ERROR: mt9m111: ioctl_s_parm: " \
+ "This camera does not allow frame rate "
+ "changes.\n");
+ ret = -EINVAL;
+ } else {
+ mt9m111_data.streamcap.timeperframe =
+ cparm->timeperframe;
+ /* Call any camera functions to match settings. */
+ }
+
+ /* Check that new capture mode is supported. */
+ if ((cparm->capturemode != 0) &&
+ !(cparm->capturemode & V4L2_MODE_HIGHQUALITY)) {
+ pr_err("ERROR: mt9m111: ioctl_s_parm: " \
+ "unsupported capture mode\n");
+ ret = -EINVAL;
+ } else {
+ mt9m111_data.streamcap.capturemode =
+ cparm->capturemode;
+ /* Call any camera functions to match settings. */
+ /* Right now this camera only supports 1 mode. */
+ }
+ break;
+
+ /* These are all the possible cases. */
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_VBI_OUTPUT:
+ case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+ case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
+ pr_err(" type is not V4L2_BUF_TYPE_VIDEO_CAPTURE " \
+ "but %d\n", a->type);
+ ret = -EINVAL;
+ break;
+
+ default:
+ pr_err(" type is unknown - %d\n", a->type);
+ ret = -EINVAL;
+ break;
+ }
+
+ printk("::: ioctl_s_parm (END, ret=%d)\n", ret);
+
+ return 0; // TODO: wtf, must return 'ret'
+}
+
+/*!
+ * ioctl_g_fmt_cap - V4L2 sensor interface handler for ioctl_g_fmt_cap
+ * @s: pointer to standard V4L2 device structure
+ * @f: pointer to standard V4L2 v4l2_format structure
+ *
+ * Returns the sensor's current pixel format in the v4l2_format
+ * parameter.
+ */
+static int ioctl_g_fmt_cap(struct v4l2_int_device *s, struct v4l2_format *f)
+{
+ printk("::: ioctl_g_fmt_cap\n");
+
+ struct sensor *sensor = s->priv;
+ /* s->priv points to mt9m111_data */
+
+ pr_debug("In mt9m111:ioctl_g_fmt_cap.\n");
+ pr_debug(" Returning size of %dx%d\n",
+ sensor->pix.width, sensor->pix.height);
+
+ f->fmt.pix = sensor->pix;
+
+ printk("::: ioctl_g_fmt_cap (END)\n");
+
+ return 0;
+}
+
+/*!
+ * ioctl_queryctrl - V4L2 sensor interface handler for VIDIOC_QUERYCTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @qc: standard V4L2 VIDIOC_QUERYCTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control information
+ * from the video_control[] array. Otherwise, returns -EINVAL if the
+ * control is not supported.
+ */
+static int ioctl_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qc)
+{
+ printk("::: ioctl_queryctrl\n");
+
+ pr_debug("In mt9m111:ioctl_queryctrl\n");
+
+ printk("::: ioctl_queryctrl (END)\n");
+
+ return 0;
+}
+
+/*!
+ * ioctl_g_ctrl - V4L2 sensor interface handler for VIDIOC_G_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_G_CTRL ioctl structure
+ *
+ * If the requested control is supported, returns the control's current
+ * value from the video_control[] array. Otherwise, returns -EINVAL
+ * if the control is not supported.
+ */
+static int ioctl_g_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ printk("::: ioctl_g_ctrl\n");
+
+ pr_debug("In mt9m111:ioctl_g_ctrl\n");
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ pr_debug(" V4L2_CID_BRIGHTNESS\n");
+ vc->value = mt9m111_data.brightness;
+ break;
+ case V4L2_CID_CONTRAST:
+ pr_debug(" V4L2_CID_CONTRAST\n");
+ vc->value = mt9m111_data.contrast;
+ break;
+ case V4L2_CID_SATURATION:
+ pr_debug(" V4L2_CID_SATURATION\n");
+ vc->value = mt9m111_data.saturation;
+ break;
+ case V4L2_CID_HUE:
+ pr_debug(" V4L2_CID_HUE\n");
+ vc->value = mt9m111_data.hue;
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ pr_debug(
+ " V4L2_CID_AUTO_WHITE_BALANCE\n");
+ vc->value = 0;
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ pr_debug(
+ " V4L2_CID_DO_WHITE_BALANCE\n");
+ vc->value = 0;
+ break;
+ case V4L2_CID_RED_BALANCE:
+ pr_debug(" V4L2_CID_RED_BALANCE\n");
+ vc->value = mt9m111_data.red;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ pr_debug(" V4L2_CID_BLUE_BALANCE\n");
+ vc->value = mt9m111_data.blue;
+ break;
+ case V4L2_CID_GAMMA:
+ pr_debug(" V4L2_CID_GAMMA\n");
+ vc->value = 0;
+ break;
+ case V4L2_CID_EXPOSURE:
+ pr_debug(" V4L2_CID_EXPOSURE\n");
+ vc->value = mt9m111_data.ae_mode;
+ break;
+ case V4L2_CID_AUTOGAIN:
+ pr_debug(" V4L2_CID_AUTOGAIN\n");
+ vc->value = 0;
+ break;
+ case V4L2_CID_GAIN:
+ pr_debug(" V4L2_CID_GAIN\n");
+ vc->value = 0;
+ break;
+ case V4L2_CID_HFLIP:
+ pr_debug(" V4L2_CID_HFLIP\n");
+ vc->value = 0;
+ break;
+ case V4L2_CID_VFLIP:
+ pr_debug(" V4L2_CID_VFLIP\n");
+ vc->value = 0;
+ break;
+ default:
+ pr_debug(" Default case\n");
+ printk("::: ioctl_g_ctrl (END, error=-EPERM)\n");
+ return -EPERM;
+ break;
+ }
+
+ printk("::: ioctl_g_ctrl (END)\n");
+
+ return 0;
+}
+
+/*!
+ * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
+ * @s: pointer to standard V4L2 device structure
+ * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
+ *
+ * If the requested control is supported, sets the control's current
+ * value in HW (and updates the video_control[] array). Otherwise,
+ * returns -EINVAL if the control is not supported.
+ */
+static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
+{
+ printk("::: ioctl_s_ctrl\n");
+
+ int retval = 0;
+
+ pr_debug("In mt9m111:ioctl_s_ctrl %d\n",
+ vc->id);
+
+ switch (vc->id) {
+ case V4L2_CID_BRIGHTNESS:
+ pr_debug(" V4L2_CID_BRIGHTNESS\n");
+ break;
+ case V4L2_CID_CONTRAST:
+ pr_debug(" V4L2_CID_CONTRAST\n");
+ break;
+ case V4L2_CID_SATURATION:
+ pr_debug(" V4L2_CID_SATURATION\n");
+ retval = mt9m111_set_saturation(vc->value);
+ break;
+ case V4L2_CID_HUE:
+ pr_debug(" V4L2_CID_HUE\n");
+ break;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ pr_debug(
+ " V4L2_CID_AUTO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_DO_WHITE_BALANCE:
+ pr_debug(
+ " V4L2_CID_DO_WHITE_BALANCE\n");
+ break;
+ case V4L2_CID_RED_BALANCE:
+ pr_debug(" V4L2_CID_RED_BALANCE\n");
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ pr_debug(" V4L2_CID_BLUE_BALANCE\n");
+ break;
+ case V4L2_CID_GAMMA:
+ pr_debug(" V4L2_CID_GAMMA\n");
+ break;
+ case V4L2_CID_EXPOSURE:
+ pr_debug(" V4L2_CID_EXPOSURE\n");
+ retval = mt9m111_set_ae_mode(vc->value);
+ break;
+ case V4L2_CID_AUTOGAIN:
+ pr_debug(" V4L2_CID_AUTOGAIN\n");
+ break;
+ case V4L2_CID_GAIN:
+ pr_debug(" V4L2_CID_GAIN\n");
+ break;
+ case V4L2_CID_HFLIP:
+ pr_debug(" V4L2_CID_HFLIP\n");
+ break;
+ case V4L2_CID_VFLIP:
+ pr_debug(" V4L2_CID_VFLIP\n");
+ break;
+ default:
+ pr_debug(" Default case\n");
+ retval = -EPERM;
+ break;
+ }
+
+ printk("::: ioctl_s_ctrl (END, ret=%d)\n", retval);
+
+ return retval;
+}
+
+/*!
+ * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
+ * @s: pointer to standard V4L2 device structure
+ */
+static int ioctl_init(struct v4l2_int_device *s)
+{
+ printk("::: ioctl_init\n");
+
+ pr_debug("In mt9m111:ioctl_init\n");
+
+ printk("::: ioctl_init (END)\n");
+
+ return 0;
+}
+
+/*!
+ * ioctl_dev_init - V4L2 sensor interface handler for vidioc_int_dev_init_num
+ * @s: pointer to standard V4L2 device structure
+ *
+ * Initialise the device when slave attaches to the master.
+ */
+static int ioctl_dev_init(struct v4l2_int_device *s)
+{
+ printk("::: ioctl_dev_init\n");
+
+ uint32_t clock_rate = MT9M111_MCLK;
+
+ pr_debug("In mt9m111:ioctl_dev_init\n");
+
+ gpio_sensor_active();
+
+ set_mclk_rate(&clock_rate, 0); // TODO: unhardcode '0' csi
+ mt9m111_rate_cal(&reset_frame_rate, clock_rate);
+ mt9m111_sensor_lib(mt9m111_device.coreReg, mt9m111_device.ifpReg);
+
+ printk("::: ioctl_dev_init (END)\n");
+
+ return 0;
+}
+
+/*!
+ * This structure defines all the ioctls for this module and links them to the
+ * enumeration.
+ */
+static struct v4l2_int_ioctl_desc mt9m111_ioctl_desc[] = {
+
+ {vidioc_int_dev_init_num, (v4l2_int_ioctl_func *)ioctl_dev_init},
+
+ /*!
+ * Delinitialise the dev. at slave detach.
+ * The complement of ioctl_dev_init.
+ */
+/* {vidioc_int_dev_exit_num, (v4l2_int_ioctl_func *) ioctl_dev_exit}, */
+
+ {vidioc_int_s_power_num, (v4l2_int_ioctl_func *) ioctl_s_power},
+ {vidioc_int_g_ifparm_num, (v4l2_int_ioctl_func *) ioctl_g_ifparm},
+/* {vidioc_int_g_needs_reset_num,
+ (v4l2_int_ioctl_func *) ioctl_g_needs_reset}, */
+/* {vidioc_int_reset_num, (v4l2_int_ioctl_func *) ioctl_reset}, */
+ {vidioc_int_init_num, (v4l2_int_ioctl_func *) ioctl_init},
+
+ /*!
+ * VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type.
+ */
+/* {vidioc_int_enum_fmt_cap_num,
+ (v4l2_int_ioctl_func *) ioctl_enum_fmt_cap}, */
+
+ /*!
+ * VIDIOC_TRY_FMT ioctl for the CAPTURE buffer type.
+ * This ioctl is used to negotiate the image capture size and
+ * pixel format without actually making it take effect.
+ */
+/* {vidioc_int_try_fmt_cap_num,
+ (v4l2_int_ioctl_func *) ioctl_try_fmt_cap}, */
+
+ {vidioc_int_g_fmt_cap_num, (v4l2_int_ioctl_func *) ioctl_g_fmt_cap},
+
+ /*!
+ * If the requested format is supported, configures the HW to use that
+ * format, returns error code if format not supported or HW can't be
+ * correctly configured.
+ */
+/* {vidioc_int_s_fmt_cap_num, (v4l2_int_ioctl_func *)ioctl_s_fmt_cap}, */
+
+ {vidioc_int_g_parm_num, (v4l2_int_ioctl_func *) ioctl_g_parm},
+ {vidioc_int_s_parm_num, (v4l2_int_ioctl_func *) ioctl_s_parm},
+/* {vidioc_int_queryctrl_num, (v4l2_int_ioctl_func *) ioctl_queryctrl}, */
+ {vidioc_int_g_ctrl_num, (v4l2_int_ioctl_func *) ioctl_g_ctrl},
+ {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func *) ioctl_s_ctrl},
+};
+
+static struct v4l2_int_slave mt9m111_slave = {
+ .ioctls = mt9m111_ioctl_desc,
+ .num_ioctls = ARRAY_SIZE(mt9m111_ioctl_desc),
+};
+
+static struct v4l2_int_device mt9m111_int_device = {
+ .module = THIS_MODULE,
+ .name = "mt9m111",
+ .type = v4l2_int_type_slave,
+ .u = {
+ .slave = &mt9m111_slave,
+ },
+};
+
+/*!
+ * mt9m111 I2C probe function
+ * Function set in i2c_driver struct.
+ * Called by insmod mt9m111_camera.ko.
+ *
+ * @return Error code indicating success or failure
+ */
+static int mt9m111_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ printk("::: mt9m111_probe\n");
+
+ int retval;
+
+ pr_debug("In mt9m111_probe device id is %s\n", id->name);
+
+ /* Set initial values for the sensor struct. */
+ memset(&mt9m111_data, 0, sizeof(mt9m111_data));
+ mt9m111_data.i2c_client = client;
+ pr_debug(" client name is %s\n", client->name);
+ mt9m111_data.pix.pixelformat = V4L2_PIX_FMT_UYVY;
+ mt9m111_data.pix.width = MT9M111_MAX_WIDTH;
+ mt9m111_data.pix.height = MT9M111_MAX_HEIGHT;
+ mt9m111_data.streamcap.capability = 0; /* No higher resolution or frame
+ * frame rate changes supported.
+ */
+ mt9m111_data.streamcap.timeperframe.denominator = MT9M111_FRAME_RATE;
+ mt9m111_data.streamcap.timeperframe.numerator = 1;
+
+ mt9m111_int_device.priv = &mt9m111_data;
+
+ pr_debug(" type is %d (expect %d)\n",
+ mt9m111_int_device.type, v4l2_int_type_slave);
+ pr_debug(" num ioctls is %d\n",
+ mt9m111_int_device.u.slave->num_ioctls);
+
+ /* This function attaches this structure to the /dev/video0 device.
+ * The pointer in priv points to the mt9m111_data structure here.*/
+ retval = v4l2_int_device_register(&mt9m111_int_device);
+
+ printk("::: mt9m111_probe (END, ret=%d)\n", retval);
+
+ return retval;
+}
+
+/*!
+ * Function set in i2c_driver struct.
+ * Called on rmmod mt9m111_camera.ko
+ */
+static int mt9m111_remove(struct i2c_client *client)
+{
+ printk("====:: mt9m111_remove\n");
+
+ pr_debug("In mt9m111_remove\n");
+
+ v4l2_int_device_unregister(&mt9m111_int_device);
+
+ printk("====:: mt9m111_remove (END)\n");
+
+ return 0;
+}
+
+/*!
+ * MT9M111 init function.
+ * Called by insmod mt9m111_camera.ko.
+ *
+ * @return Error code indicating success or failure
+ */
+static __init int mt9m111_init(void)
+{
+ printk("::: mt9m111_init\n");
+
+ u8 err;
+
+ pr_debug("In mt9m111_init\n");
+
+ /* Allocate memory for state structures. */
+ mt9m111_device.coreReg = (mt9m111_coreReg *)
+ kmalloc(sizeof(mt9m111_coreReg), GFP_KERNEL);
+ if (!mt9m111_device.coreReg)
+ {
+ printk("::: mt9m111_init (END, error-0)\n");
+ return -1;
+ }
+ memset(mt9m111_device.coreReg, 0, sizeof(mt9m111_coreReg));
+
+ mt9m111_device.ifpReg = (mt9m111_IFPReg *)
+ kmalloc(sizeof(mt9m111_IFPReg), GFP_KERNEL);
+ if (!mt9m111_device.ifpReg) {
+ kfree(mt9m111_device.coreReg);
+ mt9m111_device.coreReg = NULL;
+ printk("::: mt9m111_init (END, error-1)\n");
+ return -1;
+ }
+ memset(mt9m111_device.ifpReg, 0, sizeof(mt9m111_IFPReg));
+
+ /* Set contents of the just created structures. */
+ mt9m111_config();
+
+ /* Tells the i2c driver what functions to call for this driver. */
+ err = i2c_add_driver(&mt9m111_i2c_driver);
+ if (err != 0)
+ pr_err("%s:driver registration failed, error=%d \n",
+ __func__, err);
+
+ printk("::: mt9m111_init (END, ret=%d)\n", err);
+
+ return err;
+}
+
+/*!
+ * MT9M111 cleanup function.
+ * Called on rmmod mt9m111_camera.ko
+ *
+ * @return Error code indicating success or failure
+ */
+static void __exit mt9m111_clean(void)
+{
+ printk("::: mt9m111_clean\n");
+
+ pr_debug("In mt9m111_clean()\n");
+
+ i2c_del_driver(&mt9m111_i2c_driver);
+ gpio_sensor_inactive();
+
+ if (mt9m111_device.coreReg) {
+ kfree(mt9m111_device.coreReg);
+ mt9m111_device.coreReg = NULL;
+ }
+
+ if (mt9m111_device.ifpReg) {
+ kfree(mt9m111_device.ifpReg);
+ mt9m111_device.ifpReg = NULL;
+ }
+
+ printk("::: mt9m111_clean (END)\n");
+}
+
+module_init(mt9m111_init);
+module_exit(mt9m111_clean);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("Mt9m111 Camera Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/video/mxc/capture/mt9m111.h b/drivers/media/video/mxc/capture/mt9m111.h
new file mode 100644
index 000000000000..80bba1345992
--- /dev/null
+++ b/drivers/media/video/mxc/capture/mt9m111.h
@@ -0,0 +1,431 @@
+/*
+ * Copyright 2004-2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @defgroup Camera Sensor Drivers
+ */
+
+/*!
+ * @file mt9m111.h
+ *
+ * @brief MT9M111 Camera Header file
+ *
+ * This header file contains defines and structures for the iMagic mi8012
+ * aka the Micron mt9m111 camera.
+ *
+ * @ingroup Camera
+ */
+
+#ifndef MT9M111_H_
+#define MT9M111_H_
+
+/*!
+ * Basic camera values
+ */
+#define MT9M111_FRAME_RATE 30
+#define MT9M111_MCLK 27000000 /* Desired clock rate */
+#define MT9M111_CLK_MIN 12000000 /* This clock rate yields 15 fps */
+#define MT9M111_CLK_MAX 27000000
+#define MT9M111_MAX_WIDTH 640 /* Max width for this camera */
+#define MT9M111_MAX_HEIGHT 480 /* Max height for this camera */
+
+/*!
+ * mt9m111 IFP REGISTER BANK MAP
+ */
+#define MT9M111I_ADDR_SPACE_SEL 0x1
+#define MT9M111I_BASE_MAXTRIX_SIGN 0x2
+#define MT9M111I_BASE_MAXTRIX_SCALE15 0x3
+#define MT9M111I_BASE_MAXTRIX_SCALE69 0x4
+#define MT9M111I_APERTURE_GAIN 0x5
+#define MT9M111I_MODE_CONTROL 0x6
+#define MT9M111I_SOFT_RESET 0x7
+#define MT9M111I_FORMAT_CONTROL 0x8
+#define MT9M111I_BASE_MATRIX_CFK1 0x9
+#define MT9M111I_BASE_MATRIX_CFK2 0xa
+#define MT9M111I_BASE_MATRIX_CFK3 0xb
+#define MT9M111I_BASE_MATRIX_CFK4 0xc
+#define MT9M111I_BASE_MATRIX_CFK5 0xd
+#define MT9M111I_BASE_MATRIX_CFK6 0xe
+#define MT9M111I_BASE_MATRIX_CFK7 0xf
+#define MT9M111I_BASE_MATRIX_CFK8 0x10
+#define MT9M111I_BASE_MATRIX_CFK9 0x11
+#define MT9M111I_AWB_POSITION 0x12
+#define MT9M111I_AWB_RED_GAIN 0x13
+#define MT9M111I_AWB_BLUE_GAIN 0x14
+#define MT9M111I_DELTA_MATRIX_CF_SIGN 0x15
+#define MT9M111I_DELTA_MATRIX_CF_D1 0x16
+#define MT9M111I_DELTA_MATRIX_CF_D2 0x17
+#define MT9M111I_DELTA_MATRIX_CF_D3 0x18
+#define MT9M111I_DELTA_MATRIX_CF_D4 0x19
+#define MT9M111I_DELTA_MATRIX_CF_D5 0x1a
+#define MT9M111I_DELTA_MATRIX_CF_D6 0x1b
+#define MT9M111I_DELTA_MATRIX_CF_D7 0x1c
+#define MT9M111I_DELTA_MATRIX_CF_D8 0x1d
+#define MT9M111I_DELTA_MATRIX_CF_D9 0x1e
+#define MT9M111I_LUMINANCE_LIMIT_WB 0x20
+#define MT9M111I_RBG_MANUUAL_WB 0x21
+#define MT9M111I_AWB_RED_LIMIT 0x22
+#define MT9M111I_AWB_BLUE_LIMIT 0x23
+#define MT9M111I_MATRIX_ADJUST_LIMIT 0x24
+#define MT9M111I_AWB_SPEED 0x25
+#define MT9M111I_H_BOUND_AE 0x26
+#define MT9M111I_V_BOUND_AE 0x27
+#define MT9M111I_H_BOUND_AE_CEN_WIN 0x2b
+#define MT9M111I_V_BOUND_AE_CEN_WIN 0x2c
+#define MT9M111I_BOUND_AWB_WIN 0x2d
+#define MT9M111I_AE_PRECISION_TARGET 0x2e
+#define MT9M111I_AE_SPEED 0x2f
+#define MT9M111I_RED_AWB_MEASURE 0x30
+#define MT9M111I_LUMA_AWB_MEASURE 0x31
+#define MT9M111I_BLUE_AWB_MEASURE 0x32
+#define MT9M111I_LIMIT_SHARP_SATU_CTRL 0x33
+#define MT9M111I_LUMA_OFFSET 0x34
+#define MT9M111I_CLIP_LIMIT_OUTPUT_LUMI 0x35
+#define MT9M111I_GAIN_LIMIT_AE 0x36
+#define MT9M111I_SHUTTER_WIDTH_LIMIT_AE 0x37
+#define MT9M111I_UPPER_SHUTTER_DELAY_LIM 0x39
+#define MT9M111I_OUTPUT_FORMAT_CTRL2 0x3a
+#define MT9M111I_IPF_BLACK_LEVEL_SUB 0x3b
+#define MT9M111I_IPF_BLACK_LEVEL_ADD 0x3c
+#define MT9M111I_ADC_LIMIT_AE_ADJ 0x3d
+#define MT9M111I_GAIN_THRE_CCAM_ADJ 0x3e
+#define MT9M111I_LINEAR_AE 0x3f
+#define MT9M111I_THRESHOLD_EDGE_DEFECT 0x47
+#define MT9M111I_LUMA_SUM_MEASURE 0x4c
+#define MT9M111I_TIME_ADV_SUM_LUMA 0x4d
+#define MT9M111I_MOTION 0x52
+#define MT9M111I_GAMMA_KNEE_Y12 0x53
+#define MT9M111I_GAMMA_KNEE_Y34 0x54
+#define MT9M111I_GAMMA_KNEE_Y56 0x55
+#define MT9M111I_GAMMA_KNEE_Y78 0x56
+#define MT9M111I_GAMMA_KNEE_Y90 0x57
+#define MT9M111I_GAMMA_VALUE_Y0 0x58
+#define MT9M111I_SHUTTER_60 0x59
+#define MT9M111I_SEARCH_FLICK_60 0x5c
+#define MT9M111I_RATIO_IMAGE_GAIN_BASE 0x5e
+#define MT9M111I_RATIO_IMAGE_GAIN_DELTA 0x5f
+#define MT9M111I_SIGN_VALUE_REG5F 0x60
+#define MT9M111I_AE_GAIN 0x62
+#define MT9M111I_MAX_GAIN_AE 0x67
+#define MT9M111I_LENS_CORRECT_CTRL 0x80
+#define MT9M111I_SHADING_PARAMETER1 0x81
+#define MT9M111I_SHADING_PARAMETER2 0x82
+#define MT9M111I_SHADING_PARAMETER3 0x83
+#define MT9M111I_SHADING_PARAMETER4 0x84
+#define MT9M111I_SHADING_PARAMETER5 0x85
+#define MT9M111I_SHADING_PARAMETER6 0x86
+#define MT9M111I_SHADING_PARAMETER7 0x87
+#define MT9M111I_SHADING_PARAMETER8 0x88
+#define MT9M111I_SHADING_PARAMETER9 0x89
+#define MT9M111I_SHADING_PARAMETER10 0x8A
+#define MT9M111I_SHADING_PARAMETER11 0x8B
+#define MT9M111I_SHADING_PARAMETER12 0x8C
+#define MT9M111I_SHADING_PARAMETER13 0x8D
+#define MT9M111I_SHADING_PARAMETER14 0x8E
+#define MT9M111I_SHADING_PARAMETER15 0x8F
+#define MT9M111I_SHADING_PARAMETER16 0x90
+#define MT9M111I_SHADING_PARAMETER17 0x91
+#define MT9M111I_SHADING_PARAMETER18 0x92
+#define MT9M111I_SHADING_PARAMETER19 0x93
+#define MT9M111I_SHADING_PARAMETER20 0x94
+#define MT9M111I_SHADING_PARAMETER21 0x95
+#define MT9M111i_FLASH_CTRL 0x98
+#define MT9M111i_LINE_COUNTER 0x99
+#define MT9M111i_FRAME_COUNTER 0x9A
+#define MT9M111i_H_PAN 0xA5
+#define MT9M111i_H_ZOOM 0xA6
+#define MT9M111i_H_SIZE 0xA7
+#define MT9M111i_V_PAN 0xA8
+#define MT9M111i_V_ZOOM 0xA9
+#define MT9M111i_V_SIZE 0xAA
+
+#define MT9M111I_SEL_IFP 0x1
+#define MT9M111I_SEL_SCA 0x4
+#define MT9M111I_FC_RGB_OR_YUV 0x1000
+
+/*!
+ * Mt9m111 SENSOR CORE REGISTER BANK MAP
+ */
+#define MT9M111S_ADDR_SPACE_SEL 0x1
+#define MT9M111S_COLUMN_START 0x2
+#define MT9M111S_WIN_HEIGHT 0x3
+#define MT9M111S_WIN_WIDTH 0x4
+#define MT9M111S_HOR_BLANKING 0x5
+#define MT9M111S_VER_BLANKING 0x6
+#define MT9M111S_OUTPUT_CTRL 0x7
+#define MT9M111S_ROW_START 0x8
+#define MT9M111S_SHUTTER_WIDTH 0x9
+#define MT9M111S_PIXEL_CLOCK_SPEED 0xa
+#define MT9M111S_RESTART 0xb
+#define MT9M111S_SHUTTER_DELAY 0xc
+#define MT9M111S_RESET 0xd
+#define MT9M111S_COLUMN_START_IN_ZOOM 0x12
+#define MT9M111S_ROW_START_IN_ZOOM 0x13
+#define MT9M111S_DIGITAL_ZOOM 0x1e
+#define MT9M111S_READ_MODE 0x20
+#define MT9M111S_DAC_CTRL 0x27
+#define MT9M111S_GREEN1_GAIN 0x2b
+#define MT9M111S_BLUE_GAIN 0x2c
+#define MT9M111S_READ_GAIN 0x2d
+#define MT9M111S_GREEN2_GAIN 0x2e
+#define MT9M111S_ROW_NOISE_CTRL 0x30
+#define MT9M111S_DARK_TARGET_W 0x31
+#define MT9M111S_TEST_DATA 0x32
+#define MT9M111S_GLOBAL_GAIN 0x35
+#define MT9M111S_SENSOR_CORE_VERSION 0x36
+#define MT9M111S_DARK_TARGET_WO 0x37
+#define MT9M111S_VERF_DAC 0x41
+#define MT9M111S_VCM_VCL 0x42
+#define MT9M111S_DISABLE_BYPASS 0x58
+#define MT9M111S_CALIB_MEAN_TEST 0x59
+#define MT9M111S_DARK_G1_AVE 0x5B
+#define MT9M111S_DARK_G2_AVE 0x5C
+#define MT9M111S_DARK_R_AVE 0x5D
+#define MT9M111S_DARK_B_AVE 0x5E
+#define MT9M111S_CAL_THRESHOLD 0x5f
+#define MT9M111S_CAL_G1 0x60
+#define MT9M111S_CAL_G2 0x61
+#define MT9M111S_CAL_CTRL 0x62
+#define MT9M111S_CAL_R 0x63
+#define MT9M111S_CAL_B 0x64
+#define MT9M111S_CHIP_ENABLE 0xF1
+#define MT9M111S_CHIP_VERSION 0xFF
+
+/* OUTPUT_CTRL */
+#define MT9M111S_OUTCTRL_SYNC 0x1
+#define MT9M111S_OUTCTRL_CHIP_ENABLE 0x2
+#define MT9M111S_OUTCTRL_TEST_MODE 0x40
+
+/* READ_MODE */
+#define MT9M111S_RM_NOBADFRAME 0x1
+#define MT9M111S_RM_NODESTRUCT 0x2
+#define MT9M111S_RM_COLUMNSKIP 0x4
+#define MT9M111S_RM_ROWSKIP 0x8
+#define MT9M111S_RM_BOOSTEDRESET 0x1000
+#define MT9M111S_RM_COLUMN_LATE 0x10
+#define MT9M111S_RM_ROW_LATE 0x80
+#define MT9M111S_RM_RIGTH_TO_LEFT 0x4000
+#define MT9M111S_RM_BOTTOM_TO_TOP 0x8000
+
+/*! I2C Slave Address */
+#define MT9M111_I2C_ADDRESS 0x48
+
+/*!
+ * The image resolution enum for the mt9m111 sensor
+ */
+typedef enum {
+ MT9M111_OutputResolution_VGA = 0, /*!< VGA size */
+ MT9M111_OutputResolution_QVGA, /*!< QVGA size */
+ MT9M111_OutputResolution_CIF, /*!< CIF size */
+ MT9M111_OutputResolution_QCIF, /*!< QCIF size */
+ MT9M111_OutputResolution_QQVGA, /*!< QQVGA size */
+ MT9M111_OutputResolution_SXGA /*!< SXGA size */
+} MT9M111_OutputResolution;
+
+enum {
+ MT9M111_WINWIDTH = 0x287,
+ MT9M111_WINWIDTH_DEFAULT = 0x287,
+ MT9M111_WINWIDTH_MIN = 0x9,
+
+ MT9M111_WINHEIGHT = 0x1E7,
+ MT9M111_WINHEIGHT_DEFAULT = 0x1E7,
+
+ MT9M111_HORZBLANK_DEFAULT = 0x26,
+ MT9M111_HORZBLANK_MIN = 0x9,
+ MT9M111_HORZBLANK_MAX = 0x3FF,
+
+ MT9M111_VERTBLANK_DEFAULT = 0x4,
+ MT9M111_VERTBLANK_MIN = 0x3,
+ MT9M111_VERTBLANK_MAX = 0xFFF,
+};
+
+/*!
+ * Mt9m111 Core Register structure.
+ */
+typedef struct {
+ u32 addressSelect; /*!< select address bank for Core Register 0x4 */
+ u32 columnStart; /*!< Starting Column */
+ u32 windowHeight; /*!< Window Height */
+ u32 windowWidth; /*!< Window Width */
+ u32 horizontalBlanking; /*!< Horizontal Blank time, in pixels */
+ u32 verticalBlanking; /*!< Vertical Blank time, in pixels */
+ u32 outputControl; /*!< Register to control sensor output */
+ u32 rowStart; /*!< Starting Row */
+ u32 shutterWidth;
+ u32 pixelClockSpeed; /*!< pixel date rate */
+ u32 restart; /*!< Abandon the readout of current frame */
+ u32 shutterDelay;
+ u32 reset; /*!< reset the sensor to the default mode */
+ u32 zoomColStart; /*!< Column start in the Zoom mode */
+ u32 zomRowStart; /*!< Row start in the Zoom mode */
+ u32 digitalZoom; /*!< 1 means zoom by 2 */
+ u32 readMode; /*!< Readmode: aspects of the readout of the sensor */
+ u32 dACStandbyControl;
+ u32 green1Gain; /*!< Gain Settings */
+ u32 blueGain;
+ u32 redGain;
+ u32 green2Gain;
+ u32 rowNoiseControl;
+ u32 darkTargetwNC;
+ u32 testData; /*!< test mode */
+ u32 globalGain;
+ u32 chipVersion;
+ u32 darkTargetwoNC;
+ u32 vREFDACs;
+ u32 vCMandVCL;
+ u32 disableBypass;
+ u32 calibMeanTest;
+ u32 darkG1average;
+ u32 darkG2average;
+ u32 darkRaverage;
+ u32 darkBaverage;
+ u32 calibThreshold;
+ u32 calibGreen1;
+ u32 calibGreen2;
+ u32 calibControl;
+ u32 calibRed;
+ u32 calibBlue;
+ u32 chipEnable; /*!< Image core Registers written by image flow processor */
+} mt9m111_coreReg;
+
+/*!
+ * Mt9m111 IFP Register structure.
+ */
+typedef struct {
+ u32 addrSpaceSel; /*!< select address bank for Core Register 0x1 */
+ u32 baseMaxtrixSign; /*!< sign of coefficient for base color correction matrix */
+ u32 baseMaxtrixScale15; /*!< scaling of color correction coefficient K1-5 */
+ u32 baseMaxtrixScale69; /*!< scaling of color correction coefficient K6-9 */
+ u32 apertureGain; /*!< sharpening */
+ u32 modeControl; /*!< bit 7 CCIR656 sync codes are embedded in the image */
+ u32 softReset; /*!< Image processing mode: 1 reset mode, 0 operational mode */
+ u32 formatControl; /*!< bit12 1 for RGB565, 0 for YcrCb */
+ u32 baseMatrixCfk1; /*!< K1 Color correction coefficient */
+ u32 baseMatrixCfk2; /*!< K2 Color correction coefficient */
+ u32 baseMatrixCfk3; /*!< K3 Color correction coefficient */
+ u32 baseMatrixCfk4; /*!< K4 Color correction coefficient */
+ u32 baseMatrixCfk5; /*!< K5 Color correction coefficient */
+ u32 baseMatrixCfk6; /*!< K6 Color correction coefficient */
+ u32 baseMatrixCfk7; /*!< K7 Color correction coefficient */
+ u32 baseMatrixCfk8; /*!< K8 Color correction coefficient */
+ u32 baseMatrixCfk9; /*!< K9 Color correction coefficient */
+ u32 awbPosition; /*!< Current position of AWB color correction matrix */
+ u32 awbRedGain; /*!< Current value of AWB red channel gain */
+ u32 awbBlueGain; /*!< Current value of AWB blue channel gain */
+ u32 deltaMatrixCFSign; /*!< Sign of coefficients of delta color correction matrix register */
+ u32 deltaMatrixCFD1; /*!< D1 Delta coefficient */
+ u32 deltaMatrixCFD2; /*!< D2 Delta coefficient */
+ u32 deltaMatrixCFD3; /*!< D3 Delta coefficient */
+ u32 deltaMatrixCFD4; /*!< D4 Delta coefficient */
+ u32 deltaMatrixCFD5; /*!< D5 Delta coefficient */
+ u32 deltaMatrixCFD6; /*!< D6 Delta coefficient */
+ u32 deltaMatrixCFD7; /*!< D7 Delta coefficient */
+ u32 deltaMatrixCFD8; /*!< D8 Delta coefficient */
+ u32 deltaMatrixCFD9; /*!< D9 Delta coefficient */
+ u32 lumLimitWB; /*!< Luminance range of pixels considered in WB statistics */
+ u32 RBGManualWB; /*!< Red and Blue color channel gains for manual white balance */
+ u32 awbRedLimit; /*!< Limits on Red channel gain adjustment through AWB */
+ u32 awbBlueLimit; /*!< Limits on Blue channel gain adjustment through AWB */
+ u32 matrixAdjLimit; /*!< Limits on color correction matrix adjustment through AWB */
+ u32 awbSpeed; /*!< AWB speed and color saturation control */
+ u32 HBoundAE; /*!< Horizontal boundaries of AWB measurement window */
+ u32 VBoundAE; /*!< Vertical boundaries of AWB measurement window */
+ u32 HBoundAECenWin; /*!< Horizontal boundaries of AE measurement window for backlight compensation */
+ u32 VBoundAECenWin; /*!< Vertical boundaries of AE measurement window for backlight compensation */
+ u32 boundAwbWin; /*!< Boundaries of AWB measurement window */
+ u32 AEPrecisionTarget; /*!< Auto exposure target and precision control */
+ u32 AESpeed; /*!< AE speed and sensitivity control register */
+ u32 redAWBMeasure; /*!< Measure of the red channel value used by AWB */
+ u32 lumaAWBMeasure; /*!< Measure of the luminance channel value used by AWB */
+ u32 blueAWBMeasure; /*!< Measure of the blue channel value used by AWB */
+ u32 limitSharpSatuCtrl; /*!< Automatic control of sharpness and color saturation */
+ u32 lumaOffset; /*!< Luminance offset control (brightness control) */
+ u32 clipLimitOutputLumi; /*!< Clipping limits for output luminance */
+ u32 gainLimitAE; /*!< Imager gain limits for AE adjustment */
+ u32 shutterWidthLimitAE; /*!< Shutter width (exposure time) limits for AE adjustment */
+ u32 upperShutterDelayLi; /*!< Upper Shutter Delay Limit */
+ u32 outputFormatCtrl2; /*!< Output Format Control 2
+ 00 = 16-bit RGB565.
+ 01 = 15-bit RGB555.
+ 10 = 12-bit RGB444x.
+ 11 = 12-bit RGBx444. */
+ u32 ipfBlackLevelSub; /*!< IFP black level subtraction */
+ u32 ipfBlackLevelAdd; /*!< IFP black level addition */
+ u32 adcLimitAEAdj; /*!< ADC limits for AE adjustment */
+ u32 agimnThreCamAdj; /*!< Gain threshold for CCM adjustment */
+ u32 linearAE;
+ u32 thresholdEdgeDefect; /*!< Edge threshold for interpolation and defect correction */
+ u32 lumaSumMeasure; /*!< Luma measured by AE engine */
+ u32 timeAdvSumLuma; /*!< Time-averaged luminance value tracked by auto exposure */
+ u32 motion; /*!< 1 when motion is detected */
+ u32 gammaKneeY12; /*!< Gamma knee points Y1 and Y2 */
+ u32 gammaKneeY34; /*!< Gamma knee points Y3 and Y4 */
+ u32 gammaKneeY56; /*!< Gamma knee points Y5 and Y6 */
+ u32 gammaKneeY78; /*!< Gamma knee points Y7 and Y8 */
+ u32 gammaKneeY90; /*!< Gamma knee points Y9 and Y10 */
+ u32 gammaKneeY0; /*!< Gamma knee point Y0 */
+ u32 shutter_width_60;
+ u32 search_flicker_60;
+ u32 ratioImageGainBase;
+ u32 ratioImageGainDelta;
+ u32 signValueReg5F;
+ u32 aeGain;
+ u32 maxGainAE;
+ u32 lensCorrectCtrl;
+ u32 shadingParameter1; /*!< Shade Parameters */
+ u32 shadingParameter2;
+ u32 shadingParameter3;
+ u32 shadingParameter4;
+ u32 shadingParameter5;
+ u32 shadingParameter6;
+ u32 shadingParameter7;
+ u32 shadingParameter8;
+ u32 shadingParameter9;
+ u32 shadingParameter10;
+ u32 shadingParameter11;
+ u32 shadingParameter12;
+ u32 shadingParameter13;
+ u32 shadingParameter14;
+ u32 shadingParameter15;
+ u32 shadingParameter16;
+ u32 shadingParameter17;
+ u32 shadingParameter18;
+ u32 shadingParameter19;
+ u32 shadingParameter20;
+ u32 shadingParameter21;
+ u32 flashCtrl; /*!< Flash control */
+ u32 lineCounter; /*!< Line counter */
+ u32 frameCounter; /*!< Frame counter */
+ u32 HPan; /*!< Horizontal pan in decimation */
+ u32 HZoom; /*!< Horizontal zoom in decimation */
+ u32 HSize; /*!< Horizontal output size iIn decimation */
+ u32 VPan; /*!< Vertical pan in decimation */
+ u32 VZoom; /*!< Vertical zoom in decimation */
+ u32 VSize; /*!< Vertical output size in decimation */
+} mt9m111_IFPReg;
+
+/*!
+ * mt9m111 Config structure
+ */
+typedef struct {
+ mt9m111_coreReg *coreReg; /*!< Sensor Core Register Bank */
+ mt9m111_IFPReg *ifpReg; /*!< IFP Register Bank */
+} mt9m111_conf;
+
+typedef struct {
+ u8 index;
+ u16 width;
+ u16 height;
+} mt9m111_image_format;
+
+#endif /* MT9M111_H_ */