aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKoen Kooi <koen@dominion.thruhere.net>2011-05-01 19:47:45 +0200
committerKoen Kooi <koen@openembedded.org>2011-05-01 19:59:50 +0200
commit528e2ac6a5285c4625dbd439ae8ead8d18577b25 (patch)
treee94ccc7cfaf980e66817ec5e5e296094001aa243
parentc2e89f1361d9e5cba440f234fa6b38f9cfefb5b2 (diff)
downloadopenembedded-528e2ac6a5285c4625dbd439ae8ead8d18577b25.tar.gz
linux-omap-psp 2.6.32: add support for 5MP camera board
Also enable cpuidle for beagle Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
-rw-r--r--recipes/linux/linux-omap-psp-2.6.32/beagleboard/defconfig36
-rw-r--r--recipes/linux/linux-omap-psp-2.6.32/cam/5m03/0001-mt9p031-import-driver-from-https-github.com-Aptina-B.patch1547
-rw-r--r--recipes/linux/linux-omap-psp-2.6.32/cam/5m03/0002-board-omap3beagle-import-li5m03-driver-from-https-gi.patch294
-rw-r--r--recipes/linux/linux-omap-psp_2.6.32.bb4
4 files changed, 1871 insertions, 10 deletions
diff --git a/recipes/linux/linux-omap-psp-2.6.32/beagleboard/defconfig b/recipes/linux/linux-omap-psp-2.6.32/beagleboard/defconfig
index eff98b4ac3..2abbd1a7cb 100644
--- a/recipes/linux/linux-omap-psp-2.6.32/beagleboard/defconfig
+++ b/recipes/linux/linux-omap-psp-2.6.32/beagleboard/defconfig
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Linux kernel version: 2.6.32
-# Wed Jul 21 12:01:38 2010
+# Sun May 1 17:33:44 2011
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
@@ -85,7 +85,7 @@ CONFIG_KALLSYMS=y
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
-# CONFIG_ELF_CORE is not set
+CONFIG_ELF_CORE=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
CONFIG_EPOLL=y
@@ -269,6 +269,7 @@ CONFIG_MACH_OMAP3_BEAGLE=y
# CONFIG_MACH_OVERO is not set
# CONFIG_MACH_OMAP3EVM is not set
# CONFIG_MACH_OMAP3517EVM is not set
+# CONFIG_MACH_CRANEBOARD is not set
# CONFIG_MACH_OMAP3_PANDORA is not set
# CONFIG_MACH_OMAP3_TOUCHBOOK is not set
# CONFIG_MACH_OMAP_3430SDP is not set
@@ -380,9 +381,9 @@ CONFIG_CPU_FREQ_TABLE=y
CONFIG_CPU_FREQ_DEBUG=y
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_STAT_DETAILS=y
-# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
-CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
@@ -390,7 +391,9 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y
CONFIG_CPU_FREQ_GOV_USERSPACE=y
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
-# CONFIG_CPU_IDLE is not set
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
#
# Floating point emulation
@@ -407,6 +410,7 @@ CONFIG_NEON=y
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
CONFIG_HAVE_AOUT=y
CONFIG_BINFMT_AOUT=m
CONFIG_BINFMT_MISC=y
@@ -1617,6 +1621,7 @@ CONFIG_MFD_CORE=y
# CONFIG_TPS65010 is not set
CONFIG_TWL4030_CORE=y
CONFIG_TWL4030_POWER=y
+# CONFIG_TPS65910_CORE is not set
CONFIG_TWL4030_CODEC=y
# CONFIG_TWL4030_MADC is not set
# CONFIG_MFD_TMIO is not set
@@ -1791,7 +1796,18 @@ CONFIG_VIDEO_OMAP3=y
CONFIG_VIDEO_OMAP3_ISP=y
CONFIG_VIDEO_OMAP34XX_ISP_PREVIEWER=y
CONFIG_VIDEO_OMAP34XX_ISP_RESIZER=y
-# CONFIG_SOC_CAMERA is not set
+CONFIG_SOC_CAMERA=y
+# CONFIG_SOC_CAMERA_MT9M001 is not set
+# CONFIG_SOC_CAMERA_MT9M111 is not set
+CONFIG_SOC_CAMERA_MT9P031=m
+# CONFIG_SOC_CAMERA_MT9T031 is not set
+# CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_RJ54N1 is not set
+# CONFIG_SOC_CAMERA_TW9910 is not set
+# CONFIG_SOC_CAMERA_PLATFORM is not set
+# CONFIG_SOC_CAMERA_OV772X is not set
+# CONFIG_SOC_CAMERA_OV9640 is not set
+# CONFIG_VIDEO_SH_MOBILE_CEU is not set
CONFIG_V4L_USB_DRIVERS=y
CONFIG_USB_VIDEO_CLASS=m
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
@@ -3021,6 +3037,11 @@ CONFIG_CRYPTO_LZO=y
#
CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_CRYPTO_HW=y
+
+#
+# OCF Configuration
+#
+# CONFIG_OCF_OCF is not set
CONFIG_BINARY_PRINTF=y
#
@@ -3048,6 +3069,3 @@ CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
CONFIG_NLATTR=y
-CONFIG_ELF_CORE=y
-# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
-
diff --git a/recipes/linux/linux-omap-psp-2.6.32/cam/5m03/0001-mt9p031-import-driver-from-https-github.com-Aptina-B.patch b/recipes/linux/linux-omap-psp-2.6.32/cam/5m03/0001-mt9p031-import-driver-from-https-github.com-Aptina-B.patch
new file mode 100644
index 0000000000..ee728b9d59
--- /dev/null
+++ b/recipes/linux/linux-omap-psp-2.6.32/cam/5m03/0001-mt9p031-import-driver-from-https-github.com-Aptina-B.patch
@@ -0,0 +1,1547 @@
+From eefcf5de4689fbd00119d7a7df75244ca6ca1187 Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Sun, 1 May 2011 16:40:54 +0200
+Subject: [PATCH 1/2] mt9p031: import driver from https://github.com/Aptina/BeagleBoard-xM/tree/master/Angstrom/MT9P031
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ drivers/media/video/Kconfig | 6 +
+ drivers/media/video/Makefile | 1 +
+ drivers/media/video/mt9p031.c | 1445 +++++++++++++++++++++++++++++++++++++++
+ include/media/mt9p031.h | 30 +
+ include/media/v4l2-chip-ident.h | 1 +
+ 5 files changed, 1483 insertions(+), 0 deletions(-)
+ create mode 100644 drivers/media/video/mt9p031.c
+ create mode 100644 include/media/mt9p031.h
+
+diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
+index 4c1fb0f..59f1133 100644
+--- a/drivers/media/video/Kconfig
++++ b/drivers/media/video/Kconfig
+@@ -832,6 +832,12 @@ config SOC_CAMERA_MT9M111
+ help
+ This driver supports MT9M111 and MT9M112 cameras from Micron
+
++config SOC_CAMERA_MT9P031
++ tristate "mt9p031 support"
++ depends on SOC_CAMERA && I2C
++ help
++ This driver supports MT9P031 cameras from Micron.
++
+ config SOC_CAMERA_MT9T031
+ tristate "mt9t031 support"
+ depends on SOC_CAMERA && I2C
+diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
+index fb7e46c..f3110e7 100644
+--- a/drivers/media/video/Makefile
++++ b/drivers/media/video/Makefile
+@@ -79,6 +79,7 @@ obj-$(CONFIG_VIDEO_MT9V113) += mt9v113.o
+
+ obj-$(CONFIG_SOC_CAMERA_MT9M001) += mt9m001.o
+ obj-$(CONFIG_SOC_CAMERA_MT9M111) += mt9m111.o
++obj-$(CONFIG_SOC_CAMERA_MT9P031) += mt9p031.o
+ obj-$(CONFIG_SOC_CAMERA_MT9T031) += mt9t031.o
+ obj-$(CONFIG_SOC_CAMERA_MT9V022) += mt9v022.o
+ obj-$(CONFIG_SOC_CAMERA_OV772X) += ov772x.o
+diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c
+new file mode 100644
+index 0000000..3047e43
+--- /dev/null
++++ b/drivers/media/video/mt9p031.c
+@@ -0,0 +1,1445 @@
++/*
++ * drivers/media/video/mt9p031.c
++ *
++ * Aptina mt9p031 sensor driver
++ *
++ *
++ * Copyright (C) 2010 Aptina Imaging
++ *
++ *
++ * Leverage mt9p012.c
++ *
++ * 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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++
++
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/init.h>
++#include <linux/module.h>
++#include <linux/slab.h>
++#include <linux/kernel.h>
++#include <linux/videodev2.h>
++#include <linux/sysfs.h>
++
++#include <media/mt9p031.h>
++#include <media/v4l2-int-device.h>
++#include <media/v4l2-chip-ident.h>
++
++#define MT9P031_DEBUG
++
++#ifdef MT9P031_DEBUG
++#define DPRINTK_DRIVER(format, ...) \
++ printk(KERN_INFO "_MT9P031_DRIVER: " format, ## __VA_ARGS__)
++#else
++#define DPRINTK_DRIVER(format, ...)
++#endif
++/************************************************************************
++ macro
++************************************************************************/
++// Macro to configure I2c level shifter. Use only for MT9P031 Headboards from Aptina; not required for Leopard Imaging or elsewise.
++#define MT9P031_HEADBOARD
++
++#define MT9P031_CHIP_ID 0x1801
++#define MT9P031_MAX_HEIGHT 1944
++#define MT9P031_MAX_WIDTH 2592
++#define MT9P031_MIN_HEIGHT 2
++#define MT9P031_MIN_WIDTH 2
++
++#define VGA_HEIGHT 480
++#define VGA_WIDTH 640
++
++#define MT9P031_NORMAL_OPERATION_MODE (0x1F82) //write
++#define MT9P031_OUTPUT_CTRL_CHIP_UNSELECT (0x1F80)
++#define MT9P031_OUTPUT_CTRL_HALT (0x1F83)
++
++/* FPS Capabilities */
++#define MT9P031_MIN_FPS 10
++#define MT9P031_DEF_FPS 30
++#define MT9P031_MAX_FPS 50
++
++#define MT9P031_XCLK_NOM_1 12000000
++#define MT9P031_XCLK_NOM_2 24000000
++
++/* Analog gain values */
++#define MT9P031_EV_MIN_GAIN 0
++#define MT9P031_EV_MAX_GAIN 47
++#define MT9P031_EV_DEF_GAIN 24
++#define MT9P031_EV_GAIN_STEP 1
++
++/* Exposure time values */
++#define MT9P031_MIN_EXPOSURE 15000
++#define MT9P031_MAX_EXPOSURE 128000
++#define MT9P031_DEF_EXPOSURE 33000
++#define MT9P031_EXPOSURE_STEP 100
++#define Q12 4096
++/************************************************************************
++ Register Address
++************************************************************************/
++
++#define REG_MT9P031_CHIP_VERSION 0x00
++#define REG_MT9P031_ROWSTART 0x01
++#define REG_MT9P031_COLSTART 0x02
++#define REG_MT9P031_HEIGHT 0x03
++#define REG_MT9P031_WIDTH 0x04
++#define REG_MT9P031_HBLANK 0x05
++#define REG_MT9P031_VBLANK 0x06
++#define REG_MT9P031_OUT_CTRL 0x07
++#define REG_MT9P031_SHUTTER_WIDTH_U 0x08
++#define REG_MT9P031_SHUTTER_WIDTH_L 0x09
++#define REG_MT9P031_PCLK_CTRL 0x0a
++#define REG_MT9P031_RESTART 0x0b
++#define REG_MT9P031_SHUTTER_DELAY 0x0c
++#define REG_MT9P031_RESET 0x0d
++
++#define REG_MT9P031_PLL_CTRL 0x10
++#define REG_MT9P031_PLL_CONF1 0x11
++#define REG_MT9P031_PLL_CONF2 0x12
++
++#define REG_MT9P031_READ_MODE1 0x1e
++#define REG_MT9P031_READ_MODE2 0x20
++#define REG_MT9P031_ROW_ADDR_MODE 0x22
++#define REG_MT9P031_COL_ADDR_MODE 0x23
++#define REG_MT9P031_GREEN_1_GAIN 0x2b
++#define REG_MT9P031_BLUE_GAIN 0x2c
++#define REG_MT9P031_RED_GAIN 0x2d
++#define REG_MT9P031_GREEN_2_GAIN 0x2e
++#define REG_MT9P031_GLOBAL_GAIN 0x35
++#define REG_MT9P031_CHIP_VERSION_ALT 0x0FF
++
++/************************************************************************
++ struct
++************************************************************************/
++struct mt9p031_frame_size {
++ u16 width;
++ u16 height;
++};
++
++struct mt9p031_priv {
++ struct mt9p031_platform_data *pdata;
++ struct v4l2_int_device *v4l2_int_device;
++ struct i2c_client *client;
++ struct v4l2_pix_format pix;
++ struct v4l2_fract timeperframe;
++ unsigned long xclk_current;
++ int fps;
++ int scaler;
++ int ver;
++ int model;
++ u32 flags;
++/* for flags */
++#define INIT_DONE (1<<0)
++};
++
++struct mt9p031_priv sysPriv;
++
++static const struct v4l2_fmtdesc mt9p031_formats[] = {
++ {
++ .description = "Bayer (sRGB) 10 bit",
++ .pixelformat = V4L2_PIX_FMT_SRGGB10,
++ },
++};
++
++static const unsigned int mt9p031_num_formats = ARRAY_SIZE(mt9p031_formats);
++
++/***********************Minimum Horizontal blanking*********************/
++int hb_min[4][4] = {
++ { 450, 430, 0, 420 },
++ { 796, 776, 0, 766 },
++ { 0, 0, 0, 0 },
++ { 1488, 1468, 0, 1458 },
++};
++
++/**************************supported sizes******************************/
++const static struct mt9p031_frame_size mt9p031_sizes[] = {
++ { 640, 480 },
++ { 1280, 720 },
++ { 1920, 1080 },
++ { 2048, 1536 }, //3MP
++ { 2592, 1944 }, //5MP
++};
++
++
++struct mt9p031_format_params {
++ int width;
++ int height;
++ int row_start;
++ int col_start;
++ int row_size;
++ int col_size;
++ int hblank;
++ int vblank;
++ int integ_time;
++ int row_addr_mode;
++ int col_addr_mode;
++ int read_mode_2_config;
++ int shutter_width_hi;
++ int shutter_delay;
++ int row_bin;
++ int col_bin;
++};
++
++enum mt9p031_image_size {
++ VGA_BIN_30FPS,
++ HDV_720P_30FPS,
++ //HDV_720P_60FPS,
++ //HDV_720P_60FPS_LVB,
++ HDV_1080P_30FPS,
++ MT9P031_THREE_MP,
++ MT9P031_FIVE_MP,
++};
++
++enum mt9p031_image_size mt9p031_current_format;
++
++const struct mt9p031_format_params mt9p031_supported_formats[] = {
++ { 640, 480, 64, 24, 1919, 2559, 0, 0, 0x0296, 0x0033, 0x0033, 0x0060, 0, 0, 3, 3 }, // VGA_BIN_30FPS
++ { 1280, 720, 64, 24, 1439, 2559, 0, 0, 0x0296, 0x0011, 0x0011, 0x0060, 0, 0, 1, 1 }, // 720P_HD_30FPS
++ //{ 1280, 720, 0x0040, 0x0018, 0x059F, 0x09FF, 0, 0, 0x0296, 0x0011, 0x0011, 0x0060, 0, 0, 1, 1 }, // 720P_HD_60FPS
++ //{ 1280, 720, 0x0040, 0x0018, 0x059F, 0x09FF, 0, 0x02D0, 0x0296, 0x0011, 0x0011, 0x0060, 0, 0, 1, 1 }, // 720P_HD_60FPS_LVB
++ { 1920, 1080, 431, 335, 1079, 1919, 0, 0x0037, 0x01AC, 0, 0, 0x0040, 0, 0, 0, 0 }, // 1080P_30FPS
++ { 2048, 1536, 431, 335, 1535, 2047, 0, 0x0037, 0x01AC, 0, 0, 0x0040, 0, 0, 0, 0 }, // 3MP CAPTURE
++ { 2592, 1944, 431, 335, 1943, 2591, 0, 0x0037, 0x01AC, 0, 0, 0x0040, 0, 0, 0, 0 }, // 5MP CAPTURE
++};
++
++
++const struct v4l2_fract mt9p031_frameintervals[] = {
++ { .numerator = 1, .denominator = 10 },
++ { .numerator = 1, .denominator = 20 },
++ { .numerator = 1, .denominator = 30 },
++ { .numerator = 1, .denominator = 40 },
++ { .numerator = 1, .denominator = 50 },
++};
++
++
++const u16 MT9P031_EV_GAIN_TBL[48] = {
++ /* Gain x1 */
++ 8, 9, 10, 11, 12, 13, 14, 15,
++ /* Gain x2 */
++ 16, 17, 18, 19, 20, 21, 22, 23,
++ /* Gain x3 */
++ 24, 25, 26, 27, 28, 29, 30, 31,
++ /* Gain x4 */
++ 32, 33, 34, 35,
++ /* Gain x5 */
++ 81, 82, 83,
++ /* Gain x6 */
++ 84, 85, 86, 87, 88, 89, 90, 91,
++ /* Gain x7 */
++ 92, 93, 94, 95, 96, 97, 98, 99,
++ /* Gain x8 */
++ 100,
++};
++
++#ifdef MT9P031_HEADBOARD
++/**
++ * mt9p031_config_PCA9543A - configure on-board I2c level-shifter PCA9543A of MT9P031 Headboards from Aptina
++ * @client: pointer to i2c client
++ * Configures the level shifter to enable channel 0
++ */
++static int mt9p031_config_PCA9543A(const struct i2c_client *client)
++{
++ struct i2c_msg msg;
++ int ret;
++ u8 buf;
++ buf = 0x21;
++
++ msg.addr = (0xE6 >> 1); //slave address of PCA9543A
++ msg.flags = 0;
++ msg.len = 1;
++ msg.buf = &buf;
++
++ ret = i2c_transfer(client->adapter, &msg, 1);
++
++ return 0;
++
++}
++#endif //MT9P031_HEADBOARD
++
++/**
++ * mt9p031_reg_read - read resgiter value
++ * @client: pointer to i2c client
++ * @command: register address
++ */
++static int mt9p031_reg_read(const struct i2c_client *client, u16 command, u16 *val)
++{
++ struct i2c_msg msg[2];
++ u8 buf[2];
++ int ret;
++
++ // 8-bit/ byte addressable register
++ buf[0] = command & 0xff;
++
++ msg[0].addr = client->addr;
++ msg[0].flags = 0;
++ msg[0].len = 1;
++ msg[0].buf = buf ;
++ ret = i2c_transfer(client->adapter, &msg[0], 1);
++
++ if(ret >= 0) {
++ msg[1].addr = client->addr;
++ msg[1].flags = I2C_M_RD; //1
++ msg[1].len = 2;
++ msg[1].buf = buf;
++ ret = i2c_transfer(client->adapter, &msg[1], 1);
++ }
++ /*
++ * if return value of this function is < 0,
++ * it mean error.
++ * else, under 16bit is valid data.
++ */
++ if(ret >= 0) {
++ *val = 0;
++ *val = buf[1] + (buf[0] << 8);
++ return 0;
++ }
++
++ v4l_err(client, "read from offset 0x%x error %d", command, ret);
++ return ret;
++}
++
++/**
++ * mt9p031_reg_write - read resgiter value
++ * @client: pointer to i2c client
++ * @command: register address
++ * @data: value to be written
++ */
++static int mt9p031_reg_write(const struct i2c_client *client,
++ u16 command, u16 data)
++{
++ struct i2c_msg msg;
++ u8 buf[3];
++ int ret;
++
++ // 8-bit/ byte addressable register
++
++ buf[0] = command & 0xff;
++ data = swab16(data);
++ memcpy(buf + 1, &data, 2);
++
++ msg.addr = client->addr;
++ msg.flags = 0;
++ msg.len = 3;
++ msg.buf = buf;
++
++ /*
++ * i2c_transfer return message length,
++ * but this function should return 0 if correct case
++ */
++ ret = i2c_transfer(client->adapter, &msg, 1);
++ if (ret >= 0)
++ ret = 0;
++
++ return ret;
++}
++
++/**
++ * struct vcontrol - Video controls
++ * @v4l2_queryctrl: V4L2 VIDIOC_QUERYCTRL ioctl structure
++ * @current_value: current value of this control
++ */
++static struct vcontrol {
++ struct v4l2_queryctrl qc;
++ int current_value;
++} mt9p031_video_control[] = {
++ {
++ {
++ .id = V4L2_CID_EXPOSURE,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Exposure",
++ .minimum = MT9P031_MIN_EXPOSURE,
++ .maximum = MT9P031_MAX_EXPOSURE,
++ .step = MT9P031_EXPOSURE_STEP,
++ .default_value = MT9P031_DEF_EXPOSURE,
++ },
++ .current_value = MT9P031_DEF_EXPOSURE,
++ },
++ {
++ {
++ .id = V4L2_CID_GAIN,
++ .type = V4L2_CTRL_TYPE_INTEGER,
++ .name = "Analog Gain",
++ .minimum = MT9P031_EV_MIN_GAIN,
++ .maximum = MT9P031_EV_MAX_GAIN,
++ .step = MT9P031_EV_GAIN_STEP,
++ .default_value = MT9P031_EV_DEF_GAIN,
++ },
++ .current_value = MT9P031_EV_DEF_GAIN,
++ },
++};
++
++/**
++ * find_vctrl - Finds the requested ID in the video control structure array
++ * @id: ID of control to search the video control array for
++ *
++ * Returns the index of the requested ID from the control structure array
++ */
++static int
++find_vctrl(int id)
++{
++ int i;
++
++ if (id < V4L2_CID_BASE)
++ return -EDOM;
++
++ for (i = (ARRAY_SIZE(mt9p031_video_control) - 1); i >= 0; i--)
++ if (mt9p031_video_control[i].qc.id == id)
++ break;
++ if (i < 0)
++ i = -EINVAL;
++ return i;
++}
++
++/**
++ * mt9p031_calc_size - Find the best match for a requested image capture size
++ * @width: requested image width in pixels
++ * @height: requested image height in pixels
++ *
++ * Find the best match for a requested image capture size. The best match
++ * is chosen as the nearest match that has the same number or fewer pixels
++ * as the requested size, or the smallest image size if the requested size
++ * has fewer pixels than the smallest image.
++ */
++static enum mt9p031_image_size mt9p031_calc_size(unsigned int width,
++ unsigned int height)
++{
++ enum mt9p031_image_size isize;
++ unsigned long pixels = width * height;
++
++ for (isize = VGA_BIN_30FPS; isize <= MT9P031_FIVE_MP; isize++) {
++ if (mt9p031_sizes[isize].height *
++ mt9p031_sizes[isize].width >= pixels) {
++
++ return isize;
++ }
++ }
++
++ return MT9P031_FIVE_MP;
++}
++
++/**
++ * mt9p031_find_isize - Find the best match for a requested image capture size
++ * @width: requested image width in pixels
++ * @height: requested image height in pixels
++ *
++ * Find the best match for a requested image capture size. The best match
++ * is chosen as the nearest match that has the same number or fewer pixels
++ * as the requested size, or the smallest image size if the requested size
++ * has fewer pixels than the smallest image.
++ */
++static enum mt9p031_image_size mt9p031_find_isize(unsigned int width)
++{
++ enum mt9p031_image_size isize;
++
++ for (isize = VGA_BIN_30FPS; isize <= MT9P031_FIVE_MP; isize++) {
++ if (mt9p031_sizes[isize].width >= width)
++ break;
++ }
++
++ return isize;
++}
++
++/**
++ * mt9p031_calc_xclk - Calculate the required xclk frequency
++ * @c: i2c client driver structure
++ *
++ * Given the image capture format in pix, the nominal frame period in
++ * timeperframe, calculate and return the required xclk frequency
++ */
++static unsigned long mt9p031_calc_xclk(struct i2c_client *c)
++{
++ struct mt9p031_priv *priv = i2c_get_clientdata(c);
++ struct v4l2_fract *timeperframe = &priv->timeperframe;
++
++ if (timeperframe->numerator == 0 ||
++ timeperframe->denominator == 0) {
++ /* supply a default nominal_timeperframe */
++ timeperframe->numerator = 1;
++ timeperframe->denominator = MT9P031_DEF_FPS;
++ }
++
++ priv->fps = timeperframe->denominator / timeperframe->numerator;
++ if (priv->fps < MT9P031_MIN_FPS)
++ priv->fps = MT9P031_MIN_FPS;
++ else if (priv->fps > MT9P031_MAX_FPS)
++ priv->fps = MT9P031_MAX_FPS;
++
++ timeperframe->numerator = 1;
++ timeperframe->denominator = priv->fps;
++
++ return MT9P031_XCLK_NOM_1;
++}
++
++/**
++ * mt9p031_set_params - sets register settings according to resolution
++ * @client: pointer to standard i2c client
++ * @width: width as queried by ioctl
++ * @height: height as queried by ioctl
++ */
++static int mt9p031_set_params(struct i2c_client *client, u32 width, u32 height)
++{
++ struct mt9p031_priv *priv = i2c_get_clientdata(client);
++ struct v4l2_pix_format *pix = &priv->pix;
++ int ret;
++ enum mt9p031_image_size i;
++
++ i = mt9p031_find_isize(pix->width);
++ priv->pix.width = mt9p031_supported_formats[i].width;
++ priv->pix.height = mt9p031_supported_formats[i].height;
++
++ ret = mt9p031_reg_write(client, REG_MT9P031_ROWSTART, mt9p031_supported_formats[i].row_start); //ROW_WINDOW_START_REG
++ ret |= mt9p031_reg_write(client, REG_MT9P031_COLSTART, mt9p031_supported_formats[i].col_start); //COL_WINDOW_START_REG
++ ret |= mt9p031_reg_write(client, REG_MT9P031_HEIGHT, mt9p031_supported_formats[i].row_size); //ROW_WINDOW_SIZE_REG=1439
++ ret |= mt9p031_reg_write(client, REG_MT9P031_WIDTH, mt9p031_supported_formats[i].col_size); //COL_WINDOW_SIZE_REG=2559
++ ret |= mt9p031_reg_write(client, REG_MT9P031_HBLANK, mt9p031_supported_formats[i].hblank); //HORZ_BLANK=0
++ ret |= mt9p031_reg_write(client, REG_MT9P031_VBLANK, mt9p031_supported_formats[i].vblank); //VERT_BLANK_REG=720
++ ret |= mt9p031_reg_write(client, REG_MT9P031_SHUTTER_WIDTH_L, 0x0400); //SHUTTER_WIDTH_LOW (INTEG_TIME_REG = 1024)
++ ret |= mt9p031_reg_write(client, REG_MT9P031_ROW_ADDR_MODE, mt9p031_supported_formats[i].row_addr_mode); //ROW_MODE, ROW_SKIP=1, ROW_BIN=1
++ ret |= mt9p031_reg_write(client, REG_MT9P031_COL_ADDR_MODE, mt9p031_supported_formats[i].col_addr_mode); //COL_MODE, COL_SKIP=1, COL_BIN=1
++ ret |= mt9p031_reg_write(client, REG_MT9P031_READ_MODE2, mt9p031_supported_formats[i].read_mode_2_config); //READ_MODE_2, COL_SUM
++ ret |= mt9p031_reg_write(client, REG_MT9P031_SHUTTER_WIDTH_U, mt9p031_supported_formats[i].shutter_width_hi); //SHUTTER_WIDTH_HI
++ ret |= mt9p031_reg_write(client, REG_MT9P031_SHUTTER_WIDTH_L, mt9p031_supported_formats[i].integ_time); //SHUTTER_WIDTH_LOW (INTEG_TIME_REG)
++ ret |= mt9p031_reg_write(client, REG_MT9P031_SHUTTER_DELAY, mt9p031_supported_formats[i].shutter_delay); //SHUTTER_DELAY_REG
++
++ return ret;
++}
++
++/**
++ * mt9p031_init_camera - initialize camera settings
++ * @client: pointer to i2c client
++ * Initialize camera settings
++ */
++static int mt9p031_init_camera(const struct i2c_client *client)
++{
++ int ret;
++ struct mt9p031_priv *priv = i2c_get_clientdata(client);
++ struct v4l2_pix_format *pix = &priv->pix;
++
++ ret = mt9p031_reg_write(client, REG_MT9P031_PLL_CTRL, 0x0051); //PLL_CTRL; power up pll
++ ret |= mt9p031_reg_write(client, REG_MT9P031_PLL_CONF1, 0x1801); //PLL_CONFIG_1: m=24, n=1
++ ret |= mt9p031_reg_write(client, REG_MT9P031_PLL_CONF2, 0x0002); //PLL_CONFIG_2: p1=2, p2=0
++ mdelay(10); //wait 10 ms for VCO to lock
++ ret |= mt9p031_reg_write(client, REG_MT9P031_PLL_CTRL, 0x0053); //PLL_CONTROL; use PLL
++ mdelay(200);
++
++ ret |= mt9p031_set_params(priv->client, pix->width, pix->height);
++
++ ret |= mt9p031_reg_write(client, REG_MT9P031_RESET, 0x0001); //High
++ ret |= mt9p031_reg_write(client, REG_MT9P031_RESET, 0x0000); //Low
++ mdelay(100);
++
++ ret |= mt9p031_reg_write(client, REG_MT9P031_GREEN_1_GAIN, 0x0051); //Green1_gain_reg
++ ret |= mt9p031_reg_write(client, REG_MT9P031_BLUE_GAIN, 0x0051); //Blue_gain_reg
++ ret |= mt9p031_reg_write(client, REG_MT9P031_RED_GAIN, 0x0051); //Red_gain_reg
++ ret |= mt9p031_reg_write(client, REG_MT9P031_GREEN_2_GAIN, 0x0051); //Green2_gain_reg
++ ret |= mt9p031_reg_write(client, REG_MT9P031_GLOBAL_GAIN, 0x0008); //Analog Gain
++ ret |= mt9p031_reg_write(client, REG_MT9P031_READ_MODE1, 0x0006); //Read_mode_1 //disable AB
++ ret |= mt9p031_reg_write(client, REG_MT9P031_OUT_CTRL, 0x1F8E); //Enable parll fifo data
++
++ return ret>= 0 ? 0 : -EIO;
++}
++
++/************************************************************************
++ i2c driver
++************************************************************************/
++/**
++ * mt9p031_detect - Detect if an mt9p031 is present, and if so which revision
++ * @client: pointer to the i2c client driver structure
++ *
++ * Returns a negative error number if no device is detected
++ */
++static int mt9p031_detect(struct i2c_client *client)
++{
++ struct mt9p031_priv *priv = i2c_get_clientdata(client);
++ const char *devname;
++ u16 chipid;
++
++ if (!client)
++ return -ENODEV;
++ /*
++ * Set Normal Mode
++ */
++ if(mt9p031_reg_write(client, REG_MT9P031_OUT_CTRL, MT9P031_NORMAL_OPERATION_MODE))
++ return -ENODEV;
++ /*
++ * check and show chip ID
++ */
++ if(mt9p031_reg_read(client, REG_MT9P031_CHIP_VERSION, &chipid))
++ return -ENODEV;
++
++ if(chipid == MT9P031_CHIP_ID) {
++ devname = "mt9p031";
++ priv->model = V4L2_IDENT_MT9P031;
++ dev_info(&client->dev, "%s chip ID %04x\n", devname, chipid);
++ return 0;
++ }
++
++ dev_err(&client->dev, "Product ID error %04x\n", chipid);
++ return -ENODEV;
++}
++
++/**
++ * mt9p031_set_exposure_time - sets exposure time per input value
++ * @exp_time: exposure time to be set on device
++ * @client: pointer to standard i2c client
++ * @lvc: pointer to V4L2 exposure entry in video_controls array
++ *
++ * If the requested exposure time is within the allowed limits, the HW
++ * is configured to use the new exposure time, and the video_controls
++ * array is updated with the new current value.
++ * The function returns 0 upon success. Otherwise an error code is
++ * returned.
++ */
++static int mt9p031_set_exposure_time(u32 exp_time, struct i2c_client *client,
++ struct vcontrol *lvc)
++{
++ int ret = 0, i, shutter_width, so_p, t_pix_clk, sd_p, shutter_delay;
++ int sw_l ,sw_u ,W ,h_blanking, t_row;
++
++ if(exp_time < MT9P031_MIN_EXPOSURE)
++ exp_time = MT9P031_MIN_EXPOSURE;
++ else if(exp_time > MT9P031_MAX_EXPOSURE)
++ exp_time = MT9P031_MAX_EXPOSURE;
++
++ shutter_delay = mt9p031_supported_formats[mt9p031_current_format].shutter_delay;
++ sd_p = min(shutter_delay + 1, 1504);
++ so_p = 208 * (mt9p031_supported_formats[mt9p031_current_format].row_bin + 1) + 98 + sd_p - 94;
++ t_pix_clk = (Q12/96 );
++ h_blanking = mt9p031_supported_formats[mt9p031_current_format].hblank + 1;
++ W = 2 * (int)((mt9p031_supported_formats[mt9p031_current_format].row_size + 1) / (2 * (mt9p031_supported_formats[mt9p031_current_format].row_bin + 1)) + 1);
++ t_row = 2 * t_pix_clk * max(W/2 + max(h_blanking, hb_min[mt9p031_supported_formats[mt9p031_current_format].row_bin][mt9p031_supported_formats[mt9p031_current_format].col_bin]),
++ (41 + 346 * (mt9p031_supported_formats[mt9p031_current_format].row_bin + 1) + 99))/Q12;
++
++ shutter_width = (exp_time + 2*so_p*t_pix_clk) / t_row;
++
++ if (shutter_width< 3) {
++ sd_p = 1232 > shutter_delay ? 1232 : shutter_delay;
++ so_p = 208 * (mt9p031_supported_formats[mt9p031_current_format].row_bin + 1) + 98 + sd_p - 94;
++ shutter_width = ((exp_time*Q12 + 2*so_p*t_pix_clk) / (t_row * Q12));
++ }
++
++ if (shutter_width < 1)
++ shutter_width = 1;
++ sw_l = shutter_width& 0xffff;
++ sw_u = (shutter_width)>> 16;
++ ret = mt9p031_reg_write(client, REG_MT9P031_SHUTTER_WIDTH_L,sw_l);
++ mdelay(1);
++ ret = mt9p031_reg_write(client, REG_MT9P031_SHUTTER_WIDTH_U,sw_u);
++
++ if (ret)
++ dev_err(&client->dev, "Error setting exposure time %d\n",
++ ret);
++ else{
++ i = find_vctrl(V4L2_CID_EXPOSURE);
++ if (i >= 0) {
++ lvc = &mt9p031_video_control[i];
++ lvc->current_value = exp_time;
++ }
++ }
++
++ return ret;
++}
++
++/**
++ * mt9p031_set_gain - sets sensor analog gain per input value
++ * @lineargain: analog gain value index to be set on device
++ * @client: pointer to standard i2c client
++ * @lvc: pointer to V4L2 analog gain entry in video_controls array
++ *
++ * If the requested analog gain is within the allowed limits, the HW
++ * is configured to use the new gain value, and the video_controls
++ * array is updated with the new current value.
++ * The function returns 0 upon success. Otherwise an error code is
++ * returned.
++ */
++int mt9p031_set_gain(u16 lineargain, struct i2c_client *client,
++ struct vcontrol *lvc)
++{
++ int ret= 0, i;
++ u16 reg_gain = 0;
++
++ if (lineargain < MT9P031_EV_MIN_GAIN) {
++ lineargain = MT9P031_EV_MIN_GAIN;
++ v4l_err(client, "Gain out of legal range.");
++ }
++ if (lineargain > MT9P031_EV_MAX_GAIN) {
++ lineargain = MT9P031_EV_MAX_GAIN;
++ v4l_err(client, "Gain out of legal range.");
++ }
++
++ reg_gain = MT9P031_EV_GAIN_TBL[lineargain];
++ ret = mt9p031_reg_write(client, REG_MT9P031_GLOBAL_GAIN,
++ reg_gain);
++
++ if (ret) {
++ dev_err(&client->dev, "Error setting gain.%d", ret);
++ return ret;
++ }
++ else {
++ i = find_vctrl(V4L2_CID_GAIN);
++ if (i >= 0) {
++ lvc = &mt9p031_video_control[i];
++ lvc->current_value = lineargain;
++ }
++ }
++
++ return ret;
++}
++
++/************************************************************************
++ v4l2_ioctls
++************************************************************************/
++
++/**
++ * mt9p031_v4l2_int_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.
++ */
++static int mt9p031_v4l2_int_s_power(struct v4l2_int_device *s,
++ enum v4l2_power power)
++{
++ struct mt9p031_priv *priv = s->priv;
++ struct i2c_client *client = priv->client;
++
++ int ret;
++
++ switch (power) {
++ case V4L2_POWER_STANDBY:
++ /* FALLTHROUGH */
++ case V4L2_POWER_OFF:
++ ret = priv->pdata->power_set(s, power);
++ if (ret < 0) {
++ dev_err(&client->dev, "Unable to set target board power "
++ "state (OFF/STANDBY)\n");
++ return ret;
++ }
++ break;
++ case V4L2_POWER_ON:
++ ret = priv->pdata->power_set(s, power);
++
++ if (ret < 0) {
++ dev_err(&client->dev, "Unable to set target board power "
++ "state (ON)\n");
++ return ret;
++ }
++ if (!(priv->flags & INIT_DONE)) {
++ ret = mt9p031_detect(client);
++ if (ret < 0) {
++ dev_err(&client->dev, "Unable to detect sensor\n");
++ return ret;
++ }
++ priv->flags |= INIT_DONE;
++ }
++
++ ret = mt9p031_init_camera(client);
++ if (ret < 0) {
++ dev_err(&client->dev, "Unable to initialize sensor\n");
++ return ret;
++ }
++ }
++
++ return 0;
++}
++
++/**
++ * mt9p031_v4l2_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 mt9p031_v4l2_s_ctrl(struct v4l2_int_device *s,
++ struct v4l2_control *vc)
++{
++ int retval = -EINVAL;
++ int i;
++ struct vcontrol *lvc;
++ struct mt9p031_priv *priv = s->priv;
++ struct i2c_client *client = priv->client;
++
++ i = find_vctrl(vc->id);
++ if (i < 0)
++ return -EINVAL;
++ lvc = &mt9p031_video_control[i];
++
++ switch (vc->id) {
++ case V4L2_CID_EXPOSURE:
++ retval = mt9p031_set_exposure_time(vc->value, client, lvc);
++ break;
++ case V4L2_CID_GAIN:
++ retval = mt9p031_set_gain(vc->value, client, lvc);
++ break;
++ }
++
++ return retval;
++}
++
++/**
++ * mt9p031_v4l2_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 mt9p031_v4l2_g_ctrl(struct v4l2_int_device *s,
++ struct v4l2_control *vc)
++{
++ struct vcontrol *lvc;
++ int i;
++
++ i = find_vctrl(vc->id);
++ if (i < 0)
++ return -EINVAL;
++ lvc = &mt9p031_video_control[i];
++
++ switch (vc->id) {
++ case V4L2_CID_EXPOSURE:
++ vc->value = lvc->current_value;
++ break;
++ case V4L2_CID_GAIN:
++ vc->value = lvc->current_value;
++ break;
++ }
++
++ return 0;
++}
++
++/**
++ * mt9p031_v4l2_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 mt9p031_v4l2_queryctrl(struct v4l2_int_device *s, struct v4l2_queryctrl *qc)
++{
++ int i;
++
++ i = find_vctrl(qc->id);
++ if (i == -EINVAL)
++ qc->flags = V4L2_CTRL_FLAG_DISABLED;
++
++ if (i < 0)
++ return -EINVAL;
++
++ *qc = mt9p031_video_control[i].qc;
++ return 0;
++}
++
++
++/**
++ * mt9p031_v4l2_int_enum_fmt_cap - Implement the CAPTURE buffer VIDIOC_ENUM_FMT ioctl
++ * @s: pointer to standard V4L2 device structure
++ * @fmt: standard V4L2 VIDIOC_ENUM_FMT ioctl structure
++ *
++ * Implement the VIDIOC_ENUM_FMT ioctl for the CAPTURE buffer type.
++ */
++static int mt9p031_v4l2_int_enum_fmt_cap(struct v4l2_int_device *s,
++ struct v4l2_fmtdesc *fmt)
++{
++ int index = fmt->index;
++ enum v4l2_buf_type type = fmt->type;
++
++ memset(fmt, 0, sizeof(*fmt));
++ fmt->index = index;
++ fmt->type = type;
++
++ switch (fmt->type) {
++ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
++ if (index >= ARRAY_SIZE(mt9p031_formats))
++ return -EINVAL;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ strlcpy(fmt->description, mt9p031_formats[index].description,
++ sizeof(fmt->description));
++ fmt->pixelformat = mt9p031_formats[index].pixelformat;
++
++ return 0;
++}
++
++/**
++ * mt9p031_v4l2_int_try_fmt_cap - Implement the CAPTURE buffer VIDIOC_TRY_FMT ioctl
++ * @s: pointer to standard V4L2 device structure
++ * @f: pointer to standard V4L2 VIDIOC_TRY_FMT ioctl structure
++ *
++ * Implement the 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.
++ */
++static int mt9p031_v4l2_int_try_fmt_cap(struct v4l2_int_device *s,
++ struct v4l2_format *f)
++{
++ enum mt9p031_image_size isize;
++ int ifmt;
++ struct v4l2_pix_format *pix = &f->fmt.pix;
++ struct mt9p031_priv *priv = s->priv;
++ struct v4l2_pix_format *pix2 = &priv->pix;
++
++ isize = mt9p031_calc_size(pix->width, pix->height);
++ mt9p031_current_format = isize;
++
++ pix->width = mt9p031_sizes[isize].width;
++ pix->height = mt9p031_sizes[isize].height;
++ for (ifmt = 0; ifmt < mt9p031_num_formats; ifmt++) {
++ if (pix->pixelformat == mt9p031_formats[ifmt].pixelformat)
++ break;
++ }
++ if (ifmt == mt9p031_num_formats)
++ ifmt = 0;
++ pix->pixelformat = mt9p031_formats[ifmt].pixelformat;
++ pix->field = V4L2_FIELD_NONE;
++ pix->bytesperline = pix->width * 2;
++ pix->sizeimage = pix->bytesperline * pix->height;
++ pix->priv = 0;
++ pix->colorspace = V4L2_COLORSPACE_SRGB;
++
++ *pix2 = *pix;
++
++ return 0;
++}
++
++/**
++ * mt9p031_v4l2_int_s_fmt_cap - V4L2 sensor interface handler for VIDIOC_S_FMT ioctl
++ * @s: pointer to standard V4L2 device structure
++ * @f: pointer to standard V4L2 VIDIOC_S_FMT ioctl structure
++ *
++ * 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.
++ */
++static int mt9p031_v4l2_int_s_fmt_cap(struct v4l2_int_device *s,
++ struct v4l2_format *f)
++{
++ struct mt9p031_priv *priv = s->priv;
++ struct v4l2_pix_format *pix = &f->fmt.pix;
++ int rval;
++
++ rval = mt9p031_v4l2_int_try_fmt_cap(s, f);
++ if (!rval)
++ priv->pix = *pix;
++
++ return rval;
++}
++
++/**
++ * mt9p031_v4l2_int_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 mt9p031_v4l2_int_g_fmt_cap(struct v4l2_int_device *s,
++ struct v4l2_format *f)
++{
++ struct mt9p031_priv *priv = s->priv;
++
++ f->fmt.pix.width = priv->pix.width;
++ f->fmt.pix.height = priv->pix.height;
++ f->fmt.pix.pixelformat = V4L2_COLORSPACE_SRGB;
++ f->fmt.pix.pixelformat = priv->pix.pixelformat;
++ f->fmt.pix.field = V4L2_FIELD_NONE;
++
++ return 0;
++}
++
++/**
++ * mt9p031_v4l2_int_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 mt9p031_v4l2_int_s_parm(struct v4l2_int_device *s,
++ struct v4l2_streamparm *a)
++{
++ struct mt9p031_priv *priv = s->priv;
++ struct i2c_client *client = priv->client;
++ struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
++
++ priv->timeperframe = *timeperframe;
++ priv->xclk_current = mt9p031_calc_xclk(client);
++ *timeperframe = priv->timeperframe;
++
++ return 0;
++}
++
++/**
++ * mt9p031_v4l2_int_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 mt9p031_v4l2_int_g_parm(struct v4l2_int_device *s,
++ struct v4l2_streamparm *a)
++{
++ struct mt9p031_priv *priv = s->priv;
++ struct v4l2_captureparm *cparm = &a->parm.capture;
++
++ if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
++ return -EINVAL;
++
++ memset(a, 0, sizeof(*a));
++ a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
++
++ cparm->capability = V4L2_CAP_TIMEPERFRAME;
++ cparm->timeperframe.numerator = 1;
++ cparm->timeperframe = priv->timeperframe;
++
++ return 0;
++}
++
++/**
++ * mt9p031_v4l2_int_g_priv - V4L2 sensor interface handler for vidioc_int_g_priv_num
++ * @s: pointer to standard V4L2 device structure
++ * @p: void pointer to hold sensor's private data address
++ *
++ * Returns device's (sensor's) private data area address in p parameter
++ */
++static int mt9p031_v4l2_int_g_priv(struct v4l2_int_device *s, void *p)
++{
++ struct mt9p031_priv *priv = s->priv;
++
++ return priv->pdata->priv_data_set(p);
++}
++
++/**
++ * mt9p031_v4l2_int_g_ifparm - V4L2 sensor interface handler for vidioc_int_g_priv_num
++ * @s: pointer to standard V4L2 device structure
++ * @p: void pointer to hold sensor's ifparm
++ *
++ * Returns device's (sensor's) ifparm in p parameter
++ */
++static int mt9p031_v4l2_int_g_ifparm(struct v4l2_int_device *s,
++ struct v4l2_ifparm *p)
++{
++ struct mt9p031_priv *priv = s->priv;
++ int rval;
++
++ if (p == NULL)
++ return -EINVAL;
++
++ if (!priv->pdata->ifparm)
++ return -EINVAL;
++
++ rval = priv->pdata->ifparm(p);
++ if (rval) {
++ v4l_err(priv->client, "g_ifparm.Err[%d]\n", rval);
++ return rval;
++ }
++
++ return 0;
++}
++
++/**
++ * mt9p031_v4l2_int_enum_framesizes - V4L2 sensor if handler for vidioc_int_enum_framesizes
++ * @s: pointer to standard V4L2 device structure
++ * @frms: pointer to standard V4L2 framesizes enumeration structure
++ *
++ * Returns possible framesizes depending on choosen pixel format
++ */
++static int mt9p031_v4l2_int_enum_framesizes(struct v4l2_int_device *s,
++ struct v4l2_frmsizeenum *frms)
++{
++ int ifmt;
++
++ for (ifmt = 0; ifmt < ARRAY_SIZE(mt9p031_formats); ifmt++)
++ if (mt9p031_formats[ifmt].pixelformat == frms->pixel_format)
++ break;
++
++ if (ifmt == ARRAY_SIZE(mt9p031_formats))
++ return -EINVAL;
++
++ /* Do we already reached all discrete framesizes? */
++ if (frms->index >= ARRAY_SIZE(mt9p031_sizes))
++ return -EINVAL;
++
++ frms->type = V4L2_FRMSIZE_TYPE_DISCRETE;
++ frms->discrete.width = mt9p031_sizes[frms->index].width;
++ frms->discrete.height = mt9p031_sizes[frms->index].height;
++
++ return 0;
++}
++
++static int mt9p031_v4l2_int_enum_frameintervals(struct v4l2_int_device *s,
++ struct v4l2_frmivalenum *frmi)
++{
++ int ifmt;
++ int max_size;
++
++ for (ifmt = 0; ifmt < ARRAY_SIZE(mt9p031_formats); ifmt++)
++ if (mt9p031_formats[ifmt].pixelformat == frmi->pixel_format)
++ break;
++
++ if (ifmt == ARRAY_SIZE(mt9p031_formats))
++ return -EINVAL;
++
++ max_size = ARRAY_SIZE(mt9p031_sizes);
++
++ for(ifmt = 0; ifmt < max_size; ifmt++) {
++ if(frmi->width <= mt9p031_sizes[ifmt].width) {
++ frmi->type = V4L2_FRMSIZE_TYPE_DISCRETE;
++ frmi->discrete.numerator =
++ mt9p031_frameintervals[frmi->index].numerator;
++ frmi->discrete.denominator =
++ mt9p031_frameintervals[frmi->index].denominator;
++
++ if(frmi->discrete.denominator <= mt9p031_frameintervals[max_size - ifmt - 1].denominator)
++ return 0;
++ else
++ return -EINVAL;
++ }
++ }
++
++ return 0;
++}
++
++static struct v4l2_int_ioctl_desc mt9p031_ioctl_desc[] = {
++ { .num = vidioc_int_enum_framesizes_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_enum_framesizes },
++ { .num = vidioc_int_enum_frameintervals_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_enum_frameintervals },
++ { .num = vidioc_int_s_power_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_s_power },
++ { .num = vidioc_int_g_priv_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_g_priv },
++ { .num = vidioc_int_g_ifparm_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_g_ifparm },
++ { .num = vidioc_int_enum_fmt_cap_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_enum_fmt_cap },
++ { .num = vidioc_int_try_fmt_cap_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_try_fmt_cap },
++ { .num = vidioc_int_g_fmt_cap_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_g_fmt_cap },
++ { .num = vidioc_int_s_fmt_cap_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_s_fmt_cap },
++ { .num = vidioc_int_g_parm_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_g_parm },
++ { .num = vidioc_int_s_parm_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_int_s_parm },
++ { .num = vidioc_int_g_ctrl_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_g_ctrl },
++ { .num = vidioc_int_s_ctrl_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_s_ctrl },
++ { .num = vidioc_int_queryctrl_num,
++ .func = (v4l2_int_ioctl_func *)mt9p031_v4l2_queryctrl },
++};
++
++#ifdef MT9P031_DEBUG
++/**
++ * ---------------------------------------------------------------------------------
++ * Sysfs
++ * ---------------------------------------------------------------------------------
++ */
++
++/* Basic register read write support */
++static u16 mt9p031_attr_basic_addr = 0x0000;
++
++static ssize_t
++mt9p031_basic_reg_addr_show( struct device *dev, struct device_attribute *attr, char *buf)
++{
++ return sprintf(buf, "0x%x\n", mt9p031_attr_basic_addr);
++}
++
++static ssize_t
++mt9p031_basic_reg_addr_store( struct device *dev, struct device_attribute *attr, const char *buf, size_t n)
++{
++ u16 val;
++ sscanf(buf, "%hx", &val);
++ mt9p031_attr_basic_addr = (u16) val;
++ return n;
++}
++
++static DEVICE_ATTR( basic_reg_addr, S_IRUGO|S_IWUSR, mt9p031_basic_reg_addr_show, mt9p031_basic_reg_addr_store);
++
++
++static ssize_t
++mt9p031_basic_reg_val_show( struct device *dev, struct device_attribute *attr, char *buf)
++{
++ u16 val;
++ int ret;
++ ret = mt9p031_reg_read(sysPriv.client, mt9p031_attr_basic_addr, &val);
++ if(ret < 0){
++ printk(KERN_INFO "mt9p031: Basic register read failed");
++ return 1; // nothing processed
++ } else {
++ return sprintf(buf, "0x%x\n", val);
++ }
++}
++
++static ssize_t
++mt9p031_basic_reg_val_store( struct device *dev, struct device_attribute *attr, const char *buf, size_t n)
++{
++ u32 val;
++ sscanf(buf, "%x", &val);
++
++ if (mt9p031_reg_write(sysPriv.client, mt9p031_attr_basic_addr, (u16)val)) {
++ printk(KERN_INFO "mt9p031: Basic regiser write failed");
++ return n; // nothing processed
++ } else {
++ return n;
++ }
++}
++static DEVICE_ATTR( basic_reg_val, S_IRUGO|S_IWUSR, mt9p031_basic_reg_val_show, mt9p031_basic_reg_val_store);
++
++
++/* Exposure time access support */
++static ssize_t
++mt9p031_exposure_val_show( struct device *dev, struct device_attribute *attr, char *buf)
++{
++ u32 val;
++ struct vcontrol *lvc;
++ int i = find_vctrl(V4L2_CID_EXPOSURE);
++ if (i < 0)
++ return -EINVAL;
++ lvc = &mt9p031_video_control[i];
++ val = lvc->current_value;
++
++ if(val < 0){
++ printk(KERN_INFO "mt9p031: Exposure value read failed");
++ return 1; // nothing processed
++ } else {
++ return sprintf(buf, "%d\n", val);
++ }
++}
++
++
++static ssize_t
++mt9p031_exposure_val_store( struct device *dev, struct device_attribute *attr, const char *buf, size_t n)
++{
++ u32 val;
++ struct i2c_client *client;
++ struct vcontrol *lvc;
++
++ sscanf(buf, "%d", &val);
++ client = sysPriv.client;
++
++ lvc = &mt9p031_video_control[V4L2_CID_EXPOSURE];
++
++ if (mt9p031_set_exposure_time((u32)val, client, lvc)) {
++ printk(KERN_INFO "mt9p031: Exposure write failed");
++ return n; // nothing processed
++ } else {
++ return n;
++ }
++}
++
++static DEVICE_ATTR( exposure_val, S_IRUGO|S_IWUSR, mt9p031_exposure_val_show, mt9p031_exposure_val_store);
++
++
++/* Global Gain access support */
++static ssize_t
++mt9p031_gain_val_show( struct device *dev, struct device_attribute *attr, char *buf)
++{
++ u16 val;
++ struct vcontrol *lvc;
++
++ int i = find_vctrl(V4L2_CID_GAIN);
++ if (i < 0)
++ return -EINVAL;
++ lvc = &mt9p031_video_control[i];
++ val = lvc->current_value;
++
++ if(val < 0){
++ printk(KERN_INFO "mt9p031: Global Gain value read failed");
++ return 1; // nothing processed
++ } else {
++ return sprintf(buf, "%d\n", val);
++ }
++}
++
++static ssize_t
++mt9p031_gain_val_store( struct device *dev, struct device_attribute *attr, const char *buf, size_t n)
++{
++ u16 val;
++ struct i2c_client *client;
++ struct vcontrol *lvc;
++
++ sscanf(buf, "%hd", &val);
++ client = sysPriv.client;
++
++ lvc = &mt9p031_video_control[V4L2_CID_GAIN];
++
++ if (mt9p031_set_gain(val, client, lvc)) {
++ printk(KERN_INFO "mt9p031: Global gain write failed");
++ return n; // nothing processed
++ } else {
++ return n;
++ }
++}
++
++static DEVICE_ATTR( gain_val, S_IRUGO|S_IWUSR, mt9p031_gain_val_show, mt9p031_gain_val_store);
++
++
++static struct attribute *mt9p031_sysfs_attr[] = {
++ &dev_attr_basic_reg_addr.attr,
++ &dev_attr_basic_reg_val.attr,
++ &dev_attr_exposure_val.attr,
++ &dev_attr_gain_val.attr,
++};
++
++static int mt9p031_sysfs_add(struct kobject *kobj)
++{
++ int i = ARRAY_SIZE(mt9p031_sysfs_attr);
++ int rval = 0;
++
++ do {
++ rval = sysfs_create_file(kobj, mt9p031_sysfs_attr[--i]);
++ } while((i > 0) && (rval == 0));
++ return rval;
++}
++
++static int mt9p031_sysfs_rm(struct kobject *kobj)
++{
++ int i = ARRAY_SIZE(mt9p031_sysfs_attr);
++ int rval = 0;
++
++ do {
++ sysfs_remove_file(kobj, mt9p031_sysfs_attr[--i]);
++ } while(i > 0);
++ return rval;
++}
++#endif //MT9P031_DEBUG
++
++static struct v4l2_int_slave mt9p031_slave = {
++ .ioctls = mt9p031_ioctl_desc,
++ .num_ioctls = ARRAY_SIZE(mt9p031_ioctl_desc),
++};
++
++static int mt9p031_probe(struct i2c_client *client,
++ const struct i2c_device_id *did)
++{
++ struct mt9p031_priv *priv;
++ struct v4l2_int_device *v4l2_int_device;
++ int ret;
++ if (!client->dev.platform_data) {
++ dev_err(&client->dev, "no platform data?\n");
++ return -ENODEV;
++ }
++
++ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
++ if (!priv)
++ return -ENOMEM;
++
++ v4l2_int_device = kzalloc(sizeof(*v4l2_int_device), GFP_KERNEL);
++ if (!v4l2_int_device) {
++ kfree(priv);
++ return -ENOMEM;
++ }
++
++#ifdef MT9P031_HEADBOARD
++ mt9p031_config_PCA9543A(client); //configure i2c level shifter on mt9p031 head-board, no need for Leopard module
++ mdelay(10);
++#endif //MT9P031_HEADBOARD
++
++ v4l2_int_device->module = THIS_MODULE;
++ strncpy(v4l2_int_device->name, "mt9p031", sizeof(v4l2_int_device->name));
++
++ v4l2_int_device->type = v4l2_int_type_slave;
++ v4l2_int_device->u.slave = &mt9p031_slave;
++
++ v4l2_int_device->priv = priv;
++
++ priv->v4l2_int_device = v4l2_int_device;
++ priv->client = client;
++ priv->pdata = client->dev.platform_data;
++
++ priv->pdata->flags = MT9P031_FLAG_PCLK_RISING_EDGE;
++
++ /* Setting Pixel Values */
++ priv->pix.width = mt9p031_sizes[0].width;
++ priv->pix.height = mt9p031_sizes[0].height;
++ priv->pix.pixelformat = mt9p031_formats[0].pixelformat;
++
++ i2c_set_clientdata(client, priv);
++
++ sysPriv.client = priv->client;
++
++ ret = v4l2_int_device_register(priv->v4l2_int_device);
++ if (ret) {
++ i2c_set_clientdata(client, NULL);
++ kfree(v4l2_int_device);
++ kfree(priv);
++ }
++
++#ifdef MT9P031_DEBUG
++ mt9p031_sysfs_add(&client->dev.kobj);
++#endif //MT9P031_DEBUG
++ return ret;
++}
++
++static int mt9p031_remove(struct i2c_client *client)
++{
++ struct mt9p031_priv *priv = i2c_get_clientdata(client);
++
++ v4l2_int_device_unregister(priv->v4l2_int_device);
++ i2c_set_clientdata(client, NULL);
++ mt9p031_sysfs_rm(&client->dev.kobj);
++
++ kfree(priv->v4l2_int_device);
++ kfree(priv);
++ return 0;
++}
++
++static const struct i2c_device_id mt9p031_id[] = {
++ { "mt9p031", 0 },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, mt9p031_id);
++
++static struct i2c_driver mt9p031_i2c_driver = {
++ .driver = {
++ .name = "mt9p031",
++ },
++ .probe = mt9p031_probe,
++ .remove = mt9p031_remove,
++ .id_table = mt9p031_id,
++};
++
++/************************************************************************
++ module function
++************************************************************************/
++static int __init mt9p031_module_init(void)
++{
++ return i2c_add_driver(&mt9p031_i2c_driver);
++}
++
++static void __exit mt9p031_module_exit(void)
++{
++ i2c_del_driver(&mt9p031_i2c_driver);
++}
++
++module_init(mt9p031_module_init);
++module_exit(mt9p031_module_exit);
++
++MODULE_DESCRIPTION("mt9p031 sensor driver");
++MODULE_AUTHOR("Aptina");
++MODULE_LICENSE("GPL v2");
++
+diff --git a/include/media/mt9p031.h b/include/media/mt9p031.h
+new file mode 100644
+index 0000000..d119589
+--- /dev/null
++++ b/include/media/mt9p031.h
+@@ -0,0 +1,30 @@
++/* mt9p031 Camera
++ *
++ * 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.
++ */
++
++#ifndef __MT9P031_H__
++#define __MT9P031_H__
++
++#include <media/v4l2-int-device.h>
++
++#define MT9P031_I2C_ADDR 0x48 //(0x90 >> 1)
++
++#define MT9P031_CLK_MAX (27000000) /* 27MHz */
++#define MT9P031_CLK_MIN (6000000) /* 6Mhz */
++
++#define MT9P031_FLAG_PCLK_RISING_EDGE (1 << 0)
++#define MT9P031_FLAG_DATAWIDTH_8 (1 << 1) /* default width is 10 */
++
++struct mt9p031_platform_data {
++ char *master;
++ int (*power_set) (struct v4l2_int_device *s, enum v4l2_power on);
++ int (*ifparm) (struct v4l2_ifparm *p);
++ int (*priv_data_set) (void *);
++ u32 (*set_xclk) (struct v4l2_int_device *s, u32 xclkfreq);
++ u32 flags;
++};
++
++#endif /* __MT9P031_H__ */
+diff --git a/include/media/v4l2-chip-ident.h b/include/media/v4l2-chip-ident.h
+index 6cc107d..7599bf1 100644
+--- a/include/media/v4l2-chip-ident.h
++++ b/include/media/v4l2-chip-ident.h
+@@ -271,6 +271,7 @@ enum {
+ V4L2_IDENT_MT9T112 = 45022,
+ V4L2_IDENT_MT9V111 = 45031,
+ V4L2_IDENT_MT9V112 = 45032,
++ V4L2_IDENT_MT9P031 = 6145,
+
+ /* HV7131R CMOS sensor: just ident 46000 */
+ V4L2_IDENT_HV7131R = 46000,
+--
+1.6.6.1
+
diff --git a/recipes/linux/linux-omap-psp-2.6.32/cam/5m03/0002-board-omap3beagle-import-li5m03-driver-from-https-gi.patch b/recipes/linux/linux-omap-psp-2.6.32/cam/5m03/0002-board-omap3beagle-import-li5m03-driver-from-https-gi.patch
new file mode 100644
index 0000000000..2b45f1970b
--- /dev/null
+++ b/recipes/linux/linux-omap-psp-2.6.32/cam/5m03/0002-board-omap3beagle-import-li5m03-driver-from-https-gi.patch
@@ -0,0 +1,294 @@
+From 675ad06f53fbb0c7f398aaff8c3508196dfeb9bc Mon Sep 17 00:00:00 2001
+From: Koen Kooi <koen@dominion.thruhere.net>
+Date: Sun, 1 May 2011 16:41:57 +0200
+Subject: [PATCH 2/2] board-omap3beagle: import li5m03 driver from https://github.com/Aptina/BeagleBoard-xM/tree/master/Angstrom/MT9P031
+
+Properly hook it into the board file and some more updates
+
+Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
+---
+ arch/arm/mach-omap2/board-omap3beagle-camera.c | 186 +++++++++++++++++++++++-
+ arch/arm/mach-omap2/board-omap3beagle.c | 20 +++
+ 2 files changed, 198 insertions(+), 8 deletions(-)
+
+diff --git a/arch/arm/mach-omap2/board-omap3beagle-camera.c b/arch/arm/mach-omap2/board-omap3beagle-camera.c
+index 110c2c9..97f0e7a 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle-camera.c
++++ b/arch/arm/mach-omap2/board-omap3beagle-camera.c
+@@ -160,6 +160,8 @@ static int mt9v113_power_set(struct v4l2_int_device *s, enum v4l2_power power)
+ case V4L2_POWER_ON:
+
+ isp_configure_interface(vdev->cam->isp, &mt9v113_if_config);
++ /* Set RESET_BAR to 0 */
++ gpio_set_value(LEOPARD_RESET_GPIO, 0);
+
+ /* turn on VDD */
+ regulator_enable(cam_1v8_reg);
+@@ -168,9 +170,6 @@ static int mt9v113_power_set(struct v4l2_int_device *s, enum v4l2_power power)
+ regulator_enable(cam_2v8_reg);
+ mdelay(50);
+
+- /* Set RESET_BAR to 0 */
+- gpio_set_value(LEOPARD_RESET_GPIO, 0);
+-
+ /* Enable EXTCLK */
+ isp_set_xclk(vdev->cam->isp, MT9V113_CLK_MIN*2, CAM_USE_XCLKA);
+ /*
+@@ -294,7 +293,7 @@ static int mt9t112_set_prv_data(void *priv)
+ }
+
+ /**
+- * @brief mt9t112_power_set - Power-on or power-off TVP5146 device
++ * @brief mt9t112_power_set - Power-on or power-off MT9T112 device
+ *
+ * @param power - enum, Power on/off, resume/standby
+ *
+@@ -320,6 +319,8 @@ static int mt9t112_power_set(struct v4l2_int_device *s, enum v4l2_power power)
+ isp_configure_interface(vdev->cam->isp, &mt9t112_if_config);
+ #endif
+
++ /* Set RESET_BAR to 0 */
++ gpio_set_value(LEOPARD_RESET_GPIO, 0);
+
+ /* turn on VDD */
+ regulator_enable(cam_1v8_reg);
+@@ -331,11 +332,8 @@ static int mt9t112_power_set(struct v4l2_int_device *s, enum v4l2_power power)
+
+ mdelay(50);
+
+- /* Set RESET_BAR to 0 */
+- gpio_set_value(LEOPARD_RESET_GPIO, 0);
+-
+ /* Enable EXTCLK */
+- isp_set_xclk(vdev->cam->isp, 24000000, CAM_USE_XCLKA);
++ isp_set_xclk(vdev->cam->isp, 12000000, CAM_USE_XCLKA);
+
+ /*
+ * Wait at least 70 CLK cycles (w/EXTCLK = 24MHz):
+@@ -372,6 +370,178 @@ struct mt9t112_platform_data mt9t112_pdata = {
+
+ #endif /* #ifdef CONFIG_VIDEO_MT9T112 */
+
++#if defined(CONFIG_SOC_CAMERA_MT9P031) || defined(CONFIG_SOC_CAMERA_MT9P031_MODULE)
++#include <media/mt9p031.h>
++
++#define ISP_MT9P031_MCLK 216000000
++
++/* Arbitrary memory handling limit */
++#define MT9P031_BIGGEST_FRAME_BYTE_SIZE PAGE_ALIGN((2592 * 1944) * 2 * 4 )
++
++static struct isp_interface_config mt9p031_if_config = {
++ .ccdc_par_ser = ISP_PARLL,
++ .dataline_shift = 0x1,
++ .hsvs_syncdetect = ISPCTRL_SYNC_DETECT_VSRISE,
++ .strobe = 0x0,
++ .prestrobe = 0x0,
++ .shutter = 0x0,
++ .cam_mclk = ISP_MT9P031_MCLK,
++ .wenlog = ISPCCDC_CFG_WENLOG_AND,
++ .wait_hs_vs = 2,
++ .u.par.par_bridge = 0x0,
++ .u.par.par_clk_pol = 0x0,
++};
++
++static struct v4l2_ifparm mt9p031_ifparm_s = {
++ .if_type = V4L2_IF_TYPE_RAW,
++ .u = {
++ .raw = {
++ .frame_start_on_rising_vs = 1,
++ .bt_sync_correct = 0,
++ .swap = 0,
++ .latch_clk_inv = 0,
++ .nobt_hs_inv = 0, /* active high */
++ .nobt_vs_inv = 0, /* active high */
++ .clock_min = MT9P031_CLK_MIN,
++ .clock_max = MT9P031_CLK_MAX,
++ },
++ },
++};
++
++/**
++ * @brief mt9p031_ifparm - Returns the mt9p031 interface parameters
++ *
++ * @param p - pointer to v4l2_ifparm structure
++ *
++ * @return result of operation - 0 is success
++ */
++static int mt9p031_ifparm(struct v4l2_ifparm *p)
++{
++ if (p == NULL)
++ return -EINVAL;
++
++ *p = mt9p031_ifparm_s;
++ return 0;
++}
++
++#if defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
++static struct omap34xxcam_hw_config mt9p031_hwc = {
++ .dev_index = 1,
++ .dev_minor = -1,
++ .dev_type = OMAP34XXCAM_SLAVE_SENSOR,
++ .u.sensor.sensor_isp = 0,
++ .u.sensor.capture_mem = MT9P031_BIGGEST_FRAME_BYTE_SIZE,
++ .u.sensor.ival_default = { 1, 30 },
++};
++#endif
++
++/**
++ * @brief mt9p031_set_prv_data - Returns mt9p031 omap34xx driver private data
++ *
++ * @param priv - pointer to omap34xxcam_hw_config structure
++ *
++ * @return result of operation - 0 is success
++ */
++static int mt9p031_set_prv_data(void *priv)
++{
++#if defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
++ struct omap34xxcam_hw_config *hwc = priv;
++
++ if (priv == NULL)
++ return -EINVAL;
++
++ *hwc = mt9p031_hwc;
++ return 0;
++#else
++ return -EINVAL;
++#endif
++}
++
++/**
++ * @brief mt9p031_power_set - Power-on or power-off mt9p031 device
++ *
++ * @param power - enum, Power on/off, resume/standby
++ *
++ * @return result of operation - 0 is success
++ */
++static int mt9p031_power_set(struct v4l2_int_device *s, enum v4l2_power power)
++{
++ struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
++ switch (power) {
++ case V4L2_POWER_OFF:
++ case V4L2_POWER_STANDBY:
++ isp_set_xclk(vdev->cam->isp, 0, CAM_USE_XCLKA);
++
++ if (regulator_is_enabled(cam_1v8_reg))
++ regulator_disable(cam_1v8_reg);
++ if (regulator_is_enabled(cam_2v8_reg))
++ regulator_disable(cam_2v8_reg);
++ break;
++
++ case V4L2_POWER_ON:
++#if defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
++ isp_configure_interface(vdev->cam->isp, &mt9p031_if_config);
++#endif
++
++ /* Set RESET_BAR to 0 */
++ gpio_set_value(LEOPARD_RESET_GPIO, 0);
++
++ /* turn on VDD */
++ regulator_enable(cam_1v8_reg);
++
++ mdelay(1);
++
++ /* turn on VDD_IO */
++ regulator_enable(cam_2v8_reg);
++
++ mdelay(50);
++
++ /* Enable EXTCLK */
++ isp_set_xclk(vdev->cam->isp, 24000000, CAM_USE_XCLKA); //works for 36MHz too; try at lower freq
++
++ /*
++ * Wait at least 70 CLK cycles (w/EXTCLK = 24MHz):
++ * ((1000000 * 70) / 24000000) = aprox 2.91 us.
++ */
++
++ udelay(3);
++
++ /* Set RESET_BAR to 1 */
++ gpio_set_value(LEOPARD_RESET_GPIO, 1);
++
++ /*
++ * Wait at least 100 CLK cycles (w/EXTCLK = 24MHz):
++ * ((1000000 * 100) / 24000000) = aprox 4.16 us.
++ */
++
++ udelay(5);
++
++ break;
++
++ default:
++ return -ENODEV;
++ break;
++ }
++ return 0;
++}
++
++static u32 mt9p031_set_xclk(struct v4l2_int_device *s, u32 xclkfreq)
++{
++ struct omap34xxcam_videodev *vdev = s->u.slave->master->priv;
++ return isp_set_xclk(vdev->cam->isp, xclkfreq, 0);
++}
++
++
++struct mt9p031_platform_data mt9p031_pdata = {
++ .master = "omap34xxcam",
++ .power_set = mt9p031_power_set,
++ .set_xclk = mt9p031_set_xclk,
++ .priv_data_set = mt9p031_set_prv_data,
++ .ifparm = mt9p031_ifparm,
++};
++
++#endif /* #ifdef CONFIG_SOC_CAMERA_MT9P031 */
++
+ static int beagle_cam_probe(struct platform_device *pdev)
+ {
+ cam_1v8_reg = regulator_get(&pdev->dev, "cam_1v8");
+diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
+index 2677b41..e561431 100644
+--- a/arch/arm/mach-omap2/board-omap3beagle.c
++++ b/arch/arm/mach-omap2/board-omap3beagle.c
+@@ -83,6 +83,12 @@ extern struct mt9v113_platform_data mt9v113_pdata;
+ extern struct mt9t112_platform_data mt9t112_pdata;
+ #endif
+
++#if defined(CONFIG_SOC_CAMERA_MT9P031) || defined(CONFIG_SOC_CAMERA_MT9P031_MODULE)
++#include <media/v4l2-int-device.h>
++#include <media/mt9p031.h>
++extern struct mt9p031_platform_data mt9p031_pdata;
++#endif
++
+ #define GPMC_CS0_BASE 0x60
+ #define GPMC_CS_SIZE 0x30
+
+@@ -614,6 +620,15 @@ static struct i2c_board_info __initdata beagle_lbcm3m1_i2c2_boardinfo[] = {
+ #endif
+ };
+
++static struct i2c_board_info __initdata beagle_lbcm5m03_i2c2_boardinfo[] = {
++#if defined(CONFIG_SOC_CAMERA_MT9P031) || defined(CONFIG_SOC_CAMERA_MT9P031_MODULE)
++ {
++ I2C_BOARD_INFO("mt9p031", MT9P031_I2C_ADDR),
++ .platform_data = &mt9p031_pdata,
++ },
++#endif
++};
++
+ static int __init omap3_beagle_i2c_init(void)
+ {
+ omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo,
+@@ -636,6 +651,11 @@ static int __init omap3_beagle_i2c_init(void)
+ " registering i2c2 bus for lbcm3m1\n");
+ omap_register_i2c_bus(2, 400, beagle_lbcm3m1_i2c2_boardinfo,
+ ARRAY_SIZE(beagle_lbcm3m1_i2c2_boardinfo));
++ } else if (!strcmp(cameraboard_name, "lbcm5m03")) {
++ printk(KERN_INFO "Beagle cameraboard:"
++ " registering i2c2 bus for lbcm5m03\n");
++ omap_register_i2c_bus(2, 400, beagle_lbcm5m03_i2c2_boardinfo,
++ ARRAY_SIZE(beagle_lbcm5m03_i2c2_boardinfo));
+ } else {
+ omap_register_i2c_bus(2, 400, NULL, 0);
+ }
+--
+1.6.6.1
+
diff --git a/recipes/linux/linux-omap-psp_2.6.32.bb b/recipes/linux/linux-omap-psp_2.6.32.bb
index 3d0f42a8c5..1a3ea665c6 100644
--- a/recipes/linux/linux-omap-psp_2.6.32.bb
+++ b/recipes/linux/linux-omap-psp_2.6.32.bb
@@ -9,7 +9,7 @@ COMPATIBLE_MACHINE = "am3517-crane|beagleboard|omap3evm|am3517-evm|dm37x-evm|am3
SRCREV = "5fc29e7b2a76a64a739f857858ef0b98294aa155"
# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
-MACHINE_KERNEL_PR_append = "a+gitr${SRCREV}"
+MACHINE_KERNEL_PR_append = "b+gitr${SRCREV}"
SRC_URI = "git://arago-project.org/git/projects/linux-omap3.git;protocol=http;branch=master \
file://0001-Added-Crane-Board-support.patch \
@@ -133,6 +133,7 @@ SRC_URI = "git://arago-project.org/git/projects/linux-omap3.git;protocol=http;br
file://cam/0073-mt9v113-Fix-State-variable-handling.patch \
file://cam/0074-Move-sensor-rest-to-after-applying-power.patch \
file://cam/0075-omap3beagle-Add-camera-bootarg.patch \
+ file://cam/5m03/0001-mt9p031-import-driver-from-https-github.com-Aptina-B.patch \
file://0001-BeagleBoard-Adjust-USER-button-pin-for-xM.patch \
file://0001-PSP-3.0.1.6-kernel-source-patched-with-OCF-Linux.patch \
file://porches.patch \
@@ -149,6 +150,7 @@ SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \
file://beagleboard-xmc/0006-omap3-beaglexm-fix-power-on-of-DVI.patch \
file://beagleboard-xmc/0007-beagleboard-hack-in-support-from-xM-rev-C.patch \
file://beagleboard-xmc/0008-omap3-beagle-cleaned-up-board-revision-conditions.patch \
+ file://cam/5m03/0002-board-omap3beagle-import-li5m03-driver-from-https-gi.patch \
"
SRC_URI_append_omap3-touchbook = " \