>From 82420673286f5b4ef2917ae87ba1656f3b53faad Mon Sep 17 00:00:00 2001
From: Sergio Aguirre <[email protected]>
Date: Tue, 6 Jan 2009 14:17:34 -0600
Subject: [PATCH] MT9P012: Changes to support QVGA at 120 fps

This enables MT9P012 sensor to stream video at 120 fps in
QVGA size only.

Signed-off-by: Sergio Aguirre <[email protected]>
---
 drivers/media/video/mt9p012.c |  147 ++++++++++++++++++++++++++++++++++++++---
 drivers/media/video/mt9p012.h |    3 +-
 2 files changed, 140 insertions(+), 10 deletions(-)
 mode change 100644 => 100755 drivers/media/video/mt9p012.c
 mode change 100644 => 100755 drivers/media/video/mt9p012.h

diff --git a/drivers/media/video/mt9p012.c b/drivers/media/video/mt9p012.c
old mode 100644
new mode 100755
index ee45881..7633086
--- a/drivers/media/video/mt9p012.c
+++ b/drivers/media/video/mt9p012.c
@@ -46,6 +46,7 @@
 
 #define I2C_ENTER_VIDEO_216_30FPS_LIST_SIZE 22
 #define I2C_ENTER_VIDEO_648_30FPS_LIST_SIZE 21
+#define I2C_ENTER_VIDEO_648_120FPS_LIST_SIZE 31
 #define I2C_ENTER_VIDEO_1296_30FPS_LIST_SIZE 21
 
 unsigned char initial_list_buf[][6] = {
@@ -776,6 +777,110 @@ struct i2c_msg enter_video_648_30fps[] = {
                                        &enter_video_648_30fps_buf[20][0]},
 };
 
+unsigned char enter_video_648_120fps_buf[][6] = {
+       /* hold */
+       {I2C_REG_GROUPED_PAR_HOLD, 0x00, 0x01, 0x00, 0x00},
+       {I2C_REG_VT_PIX_CLK_DIV, 0x00, 0x06, 0x00, 0x00},
+       {I2C_REG_VT_SYS_CLK_DIV, 0x00, 0x01, 0x00, 0x00},
+       {I2C_REG_PRE_PLL_CLK_DIV, 0x00, 0x02, 0x00, 0x00},
+       {I2C_REG_PLL_MULTIPLIER, 0x00, 0xc0, 0x00, 0x00},
+       {I2C_REG_OP_PIX_CLK_DIV, 0x00, 0x0a, 0x00, 0x00},
+       {I2C_REG_OP_SYS_CLK_DIV, 0x00, 0x01, 0x00, 0x00},
+       {I2C_REG_RESERVED_MFR_3064, 0x08, 0x05, 0x00, 0x00},
+       {I2C_REG_X_OUTPUT_SIZE, I2C_VIDEO_WIDTH_4X_BINN},
+       {I2C_REG_Y_OUTPUT_SIZE, I2C_VIDEO_HEIGHT_4X_BINN},
+       {I2C_REG_X_ADDR_START, 0x00, 0x08, 0x00, 0x00},
+       {I2C_REG_Y_ADDR_START, 0x00, 0x08, 0x00, 0x00},
+       {I2C_REG_X_ADDR_END, 0x0a, 0x01, 0x00, 0x00},
+       {I2C_REG_Y_ADDR_END, 0x07, 0x81, 0x00, 0x00},
+       {I2C_REG_READ_MODE, 0x00, 0xFC, 0x00, 0x00},
+       {I2C_REG_FINE_INT_TIME, 0x03, 0xf8, 0x00, 0x00},
+       {I2C_REG_LINE_LEN_PCK, 0x07, 0x24, 0x00, 0x00},
+       {I2C_REG_FRAME_LEN_LINES, 0x02, 0x3b, 0x00, 0x00},
+       {I2C_REG_SCALING_MODE, 0x00, 0x00, 0x00, 0x00},
+       {I2C_REG_SCALE_M, 0x00, 0x20, 0x00, 0x00},
+       {I2C_REG_COARSE_INT_TIME, 0x02, 0x38, 0x00, 0x00},
+       {I2C_REG_ANALOG_GAIN_GLOBAL, 0x00, 0x7D, 0x00, 0x00},
+       /* values for q...@120fps */
+       {0x30, 0x88, 0x6F, 0xF6, 0x00, 0x00},
+       {0x31, 0x62, 0x04, 0xCE, 0x00, 0x00},
+       {0x30, 0x8a, 0x64, 0x24, 0x00, 0x00},
+       {0x30, 0x92, 0x0a, 0x53, 0x00, 0x00},
+       {0x30, 0x94, 0x46, 0x56, 0x00, 0x00},
+       {0x30, 0x96, 0x56, 0x52, 0x00, 0x00},
+       {0x31, 0x54, 0x02, 0x82, 0x00, 0x00},
+       {0x31, 0x56, 0x03, 0x81, 0x00, 0x00},
+       /* update */
+       {I2C_REG_GROUPED_PAR_HOLD, 0x00, 0x00, 0x00, 0x00},
+};
+
+struct i2c_msg enter_video_648_120fps[] = {
+       /* hold */
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_8BIT,
+                                       &enter_video_648_120fps_buf[0][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[1][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[2][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[3][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[4][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[5][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[6][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[7][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[8][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[9][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[10][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[11][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[12][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[13][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[14][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[15][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[16][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[17][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[18][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[19][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[20][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[21][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[22][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[23][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[24][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[25][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[26][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[27][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[28][0]},
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_16BIT,
+                                       &enter_video_648_120fps_buf[29][0]},
+       /* update */
+       {MT9P012_I2C_ADDR, 0x00, I2C_MT9P012_8BIT,
+                                       &enter_video_648_120fps_buf[30][0]},
+};
+
 unsigned char enter_video_1296_30fps_buf[][6] = {
        /* hold */
        {I2C_REG_GROUPED_PAR_HOLD, 0x00, 0x01, 0x00, 0x00},
@@ -1073,6 +1178,10 @@ static struct mt9p012_pll_settings all_pll_settings[] = {
        /* PLL_216_30FPS */
        {.vt_pix_clk_div = 5, .vt_sys_clk_div = 2, .pre_pll_div = 3,
        .fine_int_tm = 1794,  .frame_lines = 1374, .line_len = 3712,
+       .min_pll = 96, .max_pll = 192},
+       /* PLL_648_120FPS */
+       {.vt_pix_clk_div = 6, .vt_sys_clk_div = 1, .pre_pll_div = 2,
+       .fine_int_tm = 1016, .frame_lines = 571, .line_len = 1828,
        .min_pll = 96, .max_pll = 192}
 };
 
@@ -1400,9 +1509,12 @@ mt9p012_calc_pll(enum image_size isize,
                        current_pll_video = PLL_1296_15FPS;
        } else if (isize > BIN4XSCALE) {
                sensor->scaler = 1;
-               if (sensor->fps > 15)
-                       current_pll_video = PLL_648_30FPS;
-               else
+               if (sensor->fps > 15) {
+                       if (sensor->fps == 120)
+                               current_pll_video = PLL_648_120FPS;
+                       else
+                               current_pll_video = PLL_648_30FPS;
+               } else
                        current_pll_video = PLL_648_15FPS;
        } else {
                sensor->scaler = 2;
@@ -1569,6 +1681,7 @@ static unsigned long mt9p012sensor_calc_xclk(struct 
i2c_client *c)
        struct mt9p012_sensor *sensor = i2c_get_clientdata(c);
        struct v4l2_fract *timeperframe = &sensor->timeperframe;
        struct v4l2_pix_format *pix = &sensor->pix;
+       int qvga_120 = 0;
 
        if ((timeperframe->numerator == 0)
        || (timeperframe->denominator == 0)) {
@@ -1578,15 +1691,18 @@ static unsigned long mt9p012sensor_calc_xclk(struct 
i2c_client *c)
        }
 
        sensor->fps = timeperframe->denominator/timeperframe->numerator;
+       if ((sensor->fps == 120) && (pix->width <= VIDEO_WIDTH_4X_BINN) &&
+                               (pix->width > VIDEO_WIDTH_4X_BINN_SCALED))
+               qvga_120 = 1;
        if (sensor->fps < MT9P012_MIN_FPS)
                sensor->fps = MT9P012_MIN_FPS;
-       else if (sensor->fps > MT9P012_MAX_FPS)
+       else if ((sensor->fps > MT9P012_MAX_FPS) && (!qvga_120))
                sensor->fps = MT9P012_MAX_FPS;
 
        timeperframe->numerator = 1;
        timeperframe->denominator = sensor->fps;
-
-       if ((pix->width <= VIDEO_WIDTH_4X_BINN) && (sensor->fps > 15))
+       if ((pix->width <= VIDEO_WIDTH_4X_BINN) && (sensor->fps > 15) &&
+                                                       (!qvga_120))
                xclk_current = MT9P012_XCLK_NOM_2;
        else
                xclk_current = MT9P012_XCLK_NOM_1;
@@ -1629,9 +1745,15 @@ static int mt9p012_configure(struct v4l2_int_device *s)
 
        /* configure image size and pixel format */
        if (pix->pixelformat == V4L2_PIX_FMT_SGRBG10) {
-               err = mt9p012_write_regs(client,
-                       mt9p012_reg_init[fps_index][isize].reg_list,
-                       mt9p012_reg_init[fps_index][isize].list_size);
+               if (sensor->fps == 120) {
+                       err = mt9p012_write_regs(client,
+                               enter_video_648_120fps,
+                               I2C_ENTER_VIDEO_648_120FPS_LIST_SIZE);
+               } else {
+                       err = mt9p012_write_regs(client,
+                               mt9p012_reg_init[fps_index][isize].reg_list,
+                               mt9p012_reg_init[fps_index][isize].list_size);
+               }
        } else if (pix->pixelformat == V4L2_PIX_FMT_PATT) {
                err = mt9p012_write_regs(client,
                        mt9p012_pattern_reg_init[0][0].reg_list,
@@ -2123,6 +2245,7 @@ const struct v4l2_fract mt9p012_frameintervals[] = {
        {  .numerator = 1, .denominator = 20 },
        {  .numerator = 1, .denominator = 25 },
        {  .numerator = 1, .denominator = 30 },
+       {  .numerator = 1, .denominator = 120 },
 };
 
 static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
@@ -2149,6 +2272,12 @@ static int ioctl_enum_frameintervals(struct 
v4l2_int_device *s,
                 */
                if (frmi->index != 0)
                        return -EINVAL;
+       } else if ((frmi->width == mt9p012_sizes[1].width) &&
+                               (frmi->height == mt9p012_sizes[1].height)) {
+               /* QVGA base size supports all framerates, including 120 fps!
+                */
+               if (frmi->index >= 6)
+                       return -EINVAL;
        } else {
                if (frmi->index >= 5)
                        return -EINVAL;
diff --git a/drivers/media/video/mt9p012.h b/drivers/media/video/mt9p012.h
old mode 100644
new mode 100755
index 4c74512..bf0c038
--- a/drivers/media/video/mt9p012.h
+++ b/drivers/media/video/mt9p012.h
@@ -289,7 +289,8 @@ enum mt9p012_pll_type {
   PLL_648_15FPS,
   PLL_648_30FPS,
   PLL_216_15FPS,
-  PLL_216_30FPS
+  PLL_216_30FPS,
+  PLL_648_120FPS
 };
 
 /* Used registers */
-- 
1.5.6.5

--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to