Re: [REVIEW PATCH 12/14] OMAP: CAM: Add Sensor Driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thursday 11 December 2008 21:38:25 Aguirre Rodriguez, Sergio Alberto wrote:
> >From 012e9767b91c3eb11eb1c803e775a50e6ea1412d Mon Sep 17 00:00:00 2001
> From: Sergio Aguirre <saaguirre@xxxxxx>
> Date: Thu, 11 Dec 2008 13:41:42 -0600
> Subject: [PATCH] OMAP: CAM: Add Sensor Driver
> 
> This adds the Micron MT9P012 sensor driver
> 
> Signed-off-by: Sergio Aguirre <saaguirre@xxxxxx>
> ---
>  drivers/media/video/Kconfig        |    8 +
>  drivers/media/video/Makefile       |    1 +
>  drivers/media/video/mt9p012.c      | 1730 ++++++++++++++++++++++++++++++++++++
>  drivers/media/video/mt9p012_regs.h |   74 ++
>  include/media/mt9p012.h            |  236 +++++
>  5 files changed, 2049 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/media/video/mt9p012.c
>  create mode 100644 drivers/media/video/mt9p012_regs.h
>  create mode 100644 include/media/mt9p012.h
> 
> diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
> index a20a83b..24957bc 100644
> --- a/drivers/media/video/Kconfig
> +++ b/drivers/media/video/Kconfig
> @@ -305,6 +305,14 @@ config VIDEO_TCM825X
>           This is a driver for the Toshiba TCM825x VGA camera sensor.
>           It is used for example in Nokia N800.
> 
> +config VIDEO_MT9P012
> +       tristate "Micron MT9P012 raw sensor driver (5MP)"
> +       depends on I2C && VIDEO_V4L2
> +       ---help---
> +         This is a Video4Linux2 sensor-level driver for the Micron
> +         MT9P012 camera.  It is currently working with the TI OMAP3
> +         camera controller.
> +
>  config VIDEO_SAA7110
>         tristate "Philips SAA7110 video decoder"
>         depends on VIDEO_V4L1 && I2C
> diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
> index a2f73cf..f73b65c 100644
> --- a/drivers/media/video/Makefile
> +++ b/drivers/media/video/Makefile
> @@ -100,6 +100,7 @@ obj-$(CONFIG_VIDEO_CAFE_CCIC) += cafe_ccic.o
>  obj-$(CONFIG_VIDEO_OV7670)     += ov7670.o
> 
>  obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
> +obj-$(CONFIG_VIDEO_MT9P012)    += mt9p012.o
> 
>  obj-$(CONFIG_VIDEO_OMAP3) += omap34xxcam.o isp/
> 
> diff --git a/drivers/media/video/mt9p012.c b/drivers/media/video/mt9p012.c
> new file mode 100644
> index 0000000..8aa5c58
> --- /dev/null
> +++ b/drivers/media/video/mt9p012.c
> @@ -0,0 +1,1730 @@
> +/*
> + * drivers/media/video/mt9p012.c
> + *
> + * mt9p012 sensor driver
> + *
> + * Copyright (C) 2008 Texas Instruments.
> + *
> + * Contributors:
> + *     Sameer Venkatraman <sameerv@xxxxxx>
> + *     Sergio Aguirre <saaguirre@xxxxxx>
> + *     Martinez Leonides
> + *
> + * Leverage OV9640.c
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#include <linux/i2c.h>
> +#include <linux/delay.h>
> +#include <media/v4l2-int-device.h>
> +
> +#include <media/mt9p012.h>
> +#include "mt9p012_regs.h"
> +
> +#define DRIVER_NAME  "mt9p012"
> +#define MOD_NAME "MT9P012: "
> +
> +/* Debug functions */
> +static int debug;
> +module_param(debug, bool, 0644);
> +MODULE_PARM_DESC(debug, "Debug level (0-1)");
> +
> +/**
> + * struct mt9p012_sensor - main structure for storage of sensor information
> + * @pdata: access functions and data for platform level information
> + * @v4l2_int_device: V4L2 device structure structure
> + * @i2c_client: iic client device structure
> + * @pix: V4L2 pixel format information structure
> + * @timeperframe: time per frame expressed as V4L fraction
> + * @scaler:
> + * @ver: mt9p012 chip version
> + * @fps: frames per second value
> + */
> +struct mt9p012_sensor {
> +       const struct mt9p012_platform_data *pdata;
> +       struct v4l2_int_device *v4l2_int_device;
> +       struct i2c_client *i2c_client;
> +       struct v4l2_pix_format pix;
> +       struct v4l2_fract timeperframe;
> +       int scaler;
> +       int ver;
> +       int fps;
> +       int state;
> +};
> +
> +static struct mt9p012_sensor mt9p012;

This should be dynamic. It's only a small amount of work, and then the
driver can support multiple sensors.

> +static struct i2c_driver mt9p012sensor_i2c_driver;
> +static unsigned long xclk_current = MT9P012_XCLK_NOM_1;
> +
> +/* list of image formats supported by mt9p012 sensor */
> +const static struct v4l2_fmtdesc mt9p012_formats[] = {
> +       {
> +               .description    = "Bayer10 (GrR/BGb)",
> +               .pixelformat    = V4L2_PIX_FMT_SGRBG10,
> +       }
> +};
> +
> +#define NUM_CAPTURE_FORMATS ARRAY_SIZE(mt9p012_formats)
> +
> +/* Enters soft standby, all settings are maintained */
> +const static struct mt9p012_reg stream_off_list[] = {
> +       {.length = MT9P012_8BIT, .reg = REG_MODE_SELECT, .val = 0x00},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0}
> +};
> +
> +/* Exits soft standby */
> +const static struct mt9p012_reg stream_on_list[] = {
> +       {.length = MT9P012_8BIT, .reg = REG_MODE_SELECT, .val = 0x01},
> +       /* Sensor datasheet says we need 1 ms to allow PLL lock */
> +       {.length = MT9P012_TOK_DELAY, .reg = 0x00, .val = 1},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0}
> +};
> +
> +/* Structure which will set the exposure time */
> +static struct mt9p012_reg set_exposure_time[] = {
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x01},
> +       /* less than frame_lines-1 */
> +       {.length = MT9P012_16BIT, .reg = REG_COARSE_INT_TIME, .val = 500},
> +        /* updating */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x00},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0}
> +};
> +
> +/* Structure to set analog gain */
> +static struct mt9p012_reg set_analog_gain[] = {
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x01},
> +       {.length = MT9P012_16BIT, .reg = REG_ANALOG_GAIN_GLOBAL,
> +               .val = MIN_GAIN},
> +        /* updating */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x00},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0},
> +};
> +
> +/*
> + * Common MT9P012 register initialization for all image sizes, pixel formats,
> + * and frame rates
> + */
> +const static struct mt9p012_reg mt9p012_common[] = {
> +       {MT9P012_8BIT, REG_SOFTWARE_RESET, 0x01},
> +       {MT9P012_TOK_DELAY, 0x00, 5}, /* Delay = 5ms, min 2400 xcks */
> +       {MT9P012_16BIT, REG_RESET_REGISTER, 0x10C8},
> +       {MT9P012_8BIT, REG_GROUPED_PAR_HOLD, 0x01}, /* hold */
> +       {MT9P012_16BIT, REG_ANALOG_GAIN_GREENR, 0x0020},
> +       {MT9P012_16BIT, REG_ANALOG_GAIN_RED, 0x0020},
> +       {MT9P012_16BIT, REG_ANALOG_GAIN_BLUE, 0x0020},
> +       {MT9P012_16BIT, REG_ANALOG_GAIN_GREENB, 0x0020},
> +       {MT9P012_16BIT, REG_DIGITAL_GAIN_GREENR, 0x0100},
> +       {MT9P012_16BIT, REG_DIGITAL_GAIN_RED, 0x0100},
> +       {MT9P012_16BIT, REG_DIGITAL_GAIN_BLUE, 0x0100},
> +       {MT9P012_16BIT, REG_DIGITAL_GAIN_GREENB, 0x0100},
> +       /* Recommended values for image quality, sensor Rev 1 */
> +       {MT9P012_16BIT, 0x3088, 0x6FFB},
> +       {MT9P012_16BIT, 0x308E, 0x2020},
> +       {MT9P012_16BIT, 0x309E, 0x4400},
> +       {MT9P012_16BIT, 0x30D4, 0x9080},
> +       {MT9P012_16BIT, 0x3126, 0x00FF},
> +       {MT9P012_16BIT, 0x3154, 0x1482},
> +       {MT9P012_16BIT, 0x3158, 0x97C7},
> +       {MT9P012_16BIT, 0x315A, 0x97C6},
> +       {MT9P012_16BIT, 0x3162, 0x074C},
> +       {MT9P012_16BIT, 0x3164, 0x0756},
> +       {MT9P012_16BIT, 0x3166, 0x0760},
> +       {MT9P012_16BIT, 0x316E, 0x8488},
> +       {MT9P012_16BIT, 0x3172, 0x0003},
> +       {MT9P012_16BIT, 0x30EA, 0x3F06},
> +       {MT9P012_8BIT, REG_GROUPED_PAR_HOLD, 0x00}, /* update all at once */
> +       {MT9P012_TOK_TERM, 0, 0}
> +
> +};
> +
> +/*
> + * mt9p012 register configuration for all combinations of pixel format and
> + * image size
> + */
> +       /* 4X BINNING+SCALING */
> +const static struct mt9p012_reg enter_video_216_15fps[] = {
> +       /* stream off */
> +       {.length = MT9P012_8BIT, .reg = REG_MODE_SELECT, .val = 0x00},
> +       {.length = MT9P012_TOK_DELAY, .reg = 0x00, .val = 100},
> +        /* hold */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x01},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_PIX_CLK_DIV, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_SYS_CLK_DIV, .val = 2},
> +       {.length = MT9P012_16BIT, .reg = REG_PRE_PLL_CLK_DIV, .val = 2},
> +       {.length = MT9P012_16BIT, .reg = REG_PLL_MULTIPLIER, .val = 126},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_PIX_CLK_DIV, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_SYS_CLK_DIV, .val = 2},
> +       {.length = MT9P012_16BIT, .reg = REG_RESERVED_MFR_3064,
> +               .val = 0x0805},
> +       {.length = MT9P012_16BIT, .reg = REG_X_OUTPUT_SIZE,
> +               .val = VIDEO_WIDTH_4X_BINN_SCALED},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_OUTPUT_SIZE,
> +               .val = VIDEO_HEIGHT_4X_BINN_SCALED},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_END, .val = 2593},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_END, .val = 1945},
> +       {.length = MT9P012_16BIT, .reg = REG_READ_MODE, .val = 0x04FC},
> +       {.length = MT9P012_16BIT, .reg = REG_FINE_INT_TIME, .val = 1794},
> +       {.length = MT9P012_16BIT, .reg = REG_FRAME_LEN_LINES, .val = 574},
> +       {.length = MT9P012_16BIT, .reg = REG_LINE_LEN_PCK, .val = 2712},
> +        /* 0x10/0x30 = 0.3333 */
> +       {.length = MT9P012_16BIT, .reg = REG_SCALE_M, .val = 0x0030},
> +       /* enable scaler */
> +       {.length = MT9P012_16BIT, .reg = REG_SCALING_MODE, .val = 0x0002},
> +       {.length = MT9P012_16BIT, .reg = REG_COARSE_INT_TIME,
> +               .val = COARSE_INT_TIME_216},
> +       /* update */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x00},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0}
> +       };
> +
> +       /* Video mode, 4x binning + scaling, range 16 - 30 fps */
> +const static struct mt9p012_reg enter_video_216_30fps[] = {
> +       /* stream off */
> +       {.length = MT9P012_8BIT, .reg = REG_MODE_SELECT, .val = 0x00},
> +       {.length = MT9P012_TOK_DELAY, .reg = 0x00, .val = 100},
> +       /* hold */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x01},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_PIX_CLK_DIV, .val = 5},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_SYS_CLK_DIV, .val = 2},
> +       {.length = MT9P012_16BIT, .reg = REG_PRE_PLL_CLK_DIV, .val = 3},
> +       {.length = MT9P012_16BIT, .reg = REG_PLL_MULTIPLIER, .val = 192},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_PIX_CLK_DIV, .val = 10},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_SYS_CLK_DIV, .val = 2},
> +       {.length = MT9P012_16BIT, .reg = REG_RESERVED_MFR_3064, .val = 0x0805},
> +       {.length = MT9P012_16BIT, .reg = REG_X_OUTPUT_SIZE,
> +               .val = VIDEO_WIDTH_4X_BINN},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_OUTPUT_SIZE,
> +               .val = VIDEO_HEIGHT_4X_BINN},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_END, .val = 2593},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_END, .val = 1945},
> +       {.length = MT9P012_16BIT, .reg = REG_READ_MODE, .val = 0x04FC},
> +       {.length = MT9P012_16BIT, .reg = REG_FINE_INT_TIME, .val = 1794},
> +       {.length = MT9P012_16BIT, .reg = REG_FRAME_LEN_LINES, .val = 1374},
> +       {.length = MT9P012_16BIT, .reg = REG_LINE_LEN_PCK, .val = 3712},
> +       /* 0x10/0x30 = 0.3333 */
> +       {.length = MT9P012_16BIT, .reg = REG_SCALE_M, .val = 0x0030},
> +       /* enable scaler */
> +       {.length = MT9P012_16BIT, .reg = REG_SCALING_MODE, .val = 0x0002},
> +       {.length = MT9P012_16BIT, .reg = REG_COARSE_INT_TIME,
> +               .val = COARSE_INT_TIME_216_30FPS},
> +       /* update */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x00},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0}
> +       };
> +
> +
> +       /*Video mode, 4x binning: 648 x 486, range 8 - 15 fps*/
> +const static struct mt9p012_reg enter_video_648_15fps[] = {
> +       /* stream off */
> +       {.length = MT9P012_8BIT, .reg = REG_MODE_SELECT, .val = 0x00},
> +       {.length = MT9P012_TOK_DELAY, .reg = 0x00, .val = 100},
> +       /* hold */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x01},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_PIX_CLK_DIV, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_SYS_CLK_DIV, .val = 2},
> +       {.length = MT9P012_16BIT, .reg = REG_PRE_PLL_CLK_DIV, .val = 2},
> +       {.length = MT9P012_16BIT, .reg = REG_PLL_MULTIPLIER, .val = 126},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_PIX_CLK_DIV, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_SYS_CLK_DIV, .val = 2},
> +       {.length = MT9P012_16BIT, .reg = REG_RESERVED_MFR_3064, .val = 0x0805},
> +       {.length = MT9P012_16BIT, .reg = REG_X_OUTPUT_SIZE,
> +               .val = VIDEO_WIDTH_4X_BINN},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_OUTPUT_SIZE,
> +               .val = VIDEO_HEIGHT_4X_BINN},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_END, .val = 2593},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_END, .val = 1945},
> +       {.length = MT9P012_16BIT, .reg = REG_READ_MODE, .val = 0x04FC},
> +       {.length = MT9P012_16BIT, .reg = REG_FINE_INT_TIME, .val = 1794},
> +       {.length = MT9P012_16BIT, .reg = REG_FRAME_LEN_LINES, .val = 574},
> +       {.length = MT9P012_16BIT, .reg = REG_LINE_LEN_PCK, .val = 2712},
> +       {.length = MT9P012_16BIT, .reg = REG_SCALING_MODE, .val = 0x0000},
> +       {.length = MT9P012_16BIT, .reg = REG_COARSE_INT_TIME,
> +               .val = COARSE_INT_TIME_648},
> +       /* update */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x00},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0}
> +};
> +
> +       /* Video mode, 4x binning: 648 x 486, range 16 - 30 fps */
> +const static struct mt9p012_reg enter_video_648_30fps[] = {
> +       /* stream off */
> +       {.length = MT9P012_8BIT, .reg = REG_MODE_SELECT, .val = 0x00},
> +       {.length = MT9P012_TOK_DELAY, .reg = 0x00, .val = 100},
> +       /* hold */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x01},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_PIX_CLK_DIV, .val = 5},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_SYS_CLK_DIV, .val = 2},
> +       {.length = MT9P012_16BIT, .reg = REG_PRE_PLL_CLK_DIV, .val = 3},
> +       {.length = MT9P012_16BIT, .reg = REG_PLL_MULTIPLIER, .val = 192},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_PIX_CLK_DIV, .val = 10},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_SYS_CLK_DIV, .val = 2},
> +       {.length = MT9P012_16BIT, .reg = REG_RESERVED_MFR_3064, .val = 0x0805},
> +       {.length = MT9P012_16BIT, .reg = REG_X_OUTPUT_SIZE,
> +               .val = VIDEO_WIDTH_4X_BINN},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_OUTPUT_SIZE,
> +               .val = VIDEO_HEIGHT_4X_BINN},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_END, .val = 2593},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_END, .val = 1945},
> +       {.length = MT9P012_16BIT, .reg = REG_READ_MODE, .val = 0x04FC},
> +       {.length = MT9P012_16BIT, .reg = REG_FINE_INT_TIME, .val = 1794},
> +       {.length = MT9P012_16BIT, .reg = REG_FRAME_LEN_LINES, .val = 1374},
> +       {.length = MT9P012_16BIT, .reg = REG_LINE_LEN_PCK, .val = 3712},
> +       {.length = MT9P012_16BIT, .reg = REG_SCALING_MODE, .val = 0x0000},
> +       {.length = MT9P012_16BIT, .reg = REG_COARSE_INT_TIME,
> +               .val = COARSE_INT_TIME_648_30FPS},
> +       /* update */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x00},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0}
> +};
> +
> +       /* Video mode, scaler off: 1296 x 972, range  11 - 21 fps*/
> +const static struct mt9p012_reg enter_video_1296_15fps[] = {
> +       /* stream off */
> +       {.length = MT9P012_8BIT, .reg = REG_MODE_SELECT, .val = 0x00},
> +       {.length = MT9P012_TOK_DELAY, .reg = 0x00, .val = 100},
> +       /* hold */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x01},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_PIX_CLK_DIV, .val = 5},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_SYS_CLK_DIV, .val = 2},
> +       {.length = MT9P012_16BIT, .reg = REG_PRE_PLL_CLK_DIV, .val = 3},
> +       {.length = MT9P012_16BIT, .reg = REG_PLL_MULTIPLIER, .val = 134},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_PIX_CLK_DIV, .val = 10},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_SYS_CLK_DIV, .val = 1},
> +       {.length = MT9P012_16BIT, .reg = REG_RESERVED_MFR_3064, .val = 0x0805},
> +       {.length = MT9P012_16BIT, .reg = REG_X_OUTPUT_SIZE,
> +               .val = VIDEO_WIDTH_2X_BINN},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_OUTPUT_SIZE,
> +               .val = VIDEO_HEIGHT_2X_BINN},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_END, .val = 2597},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_END, .val = 1949},
> +       {.length = MT9P012_16BIT, .reg = REG_READ_MODE, .val = 0x046C},
> +       {.length = MT9P012_16BIT, .reg = REG_FINE_INT_TIME, .val = 1794},
> +       {.length = MT9P012_16BIT, .reg = REG_FRAME_LEN_LINES, .val = 1061},
> +       {.length = MT9P012_16BIT, .reg = REG_LINE_LEN_PCK, .val = 3360},
> +       {.length = MT9P012_16BIT, .reg = REG_SCALING_MODE, .val = 0x0000},
> +       {.length = MT9P012_16BIT, .reg = REG_COARSE_INT_TIME,
> +               .val = COARSE_INT_TIME_1296},
> +       /* update */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x00},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0}
> +};
> +
> +       /* YUV (YCbCr) VGA */
> +const static struct mt9p012_reg enter_video_1296_30fps[] = {
> +       /* stream off */
> +       {.length = MT9P012_8BIT, .reg = REG_MODE_SELECT, .val = 0x00},
> +       {.length = MT9P012_TOK_DELAY, .reg = 0x00, .val = 100},
> +       /* hold */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x01},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_PIX_CLK_DIV, .val = 5},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_SYS_CLK_DIV, .val = 1},
> +       {.length = MT9P012_16BIT, .reg = REG_PRE_PLL_CLK_DIV, .val = 3},
> +       {.length = MT9P012_16BIT, .reg = REG_PLL_MULTIPLIER, .val = 134},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_PIX_CLK_DIV, .val = 10},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_SYS_CLK_DIV, .val = 1},
> +       {.length = MT9P012_16BIT, .reg = REG_RESERVED_MFR_3064, .val = 0x0805},
> +       {.length = MT9P012_16BIT, .reg = REG_X_OUTPUT_SIZE,
> +               .val = VIDEO_WIDTH_2X_BINN},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_OUTPUT_SIZE,
> +               .val = VIDEO_HEIGHT_2X_BINN},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_END, .val = 2597},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_END, .val = 1949},
> +       {.length = MT9P012_16BIT, .reg = REG_READ_MODE, .val = 0x046C},
> +       {.length = MT9P012_16BIT, .reg = REG_FINE_INT_TIME, .val = 1794},
> +       {.length = MT9P012_16BIT, .reg = REG_FRAME_LEN_LINES, .val = 1061},
> +       {.length = MT9P012_16BIT, .reg = REG_LINE_LEN_PCK, .val = 3360},
> +       {.length = MT9P012_16BIT, .reg = REG_SCALING_MODE, .val = 0x0000},
> +       {.length = MT9P012_16BIT, .reg = REG_COARSE_INT_TIME,
> +               .val = COARSE_INT_TIME_1296},
> +        /* update */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x00},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0}
> +};
> +
> +const static struct mt9p012_reg enter_image_mode_3MP_10fps[] = {
> +       /* stream off */
> +       {.length = MT9P012_8BIT, .reg = REG_MODE_SELECT, .val = 0x00},
> +       {.length = MT9P012_TOK_DELAY, .reg = 0x00, .val = 100},
> +       /* hold */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x01},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_PIX_CLK_DIV, .val = 4},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_SYS_CLK_DIV, .val = 1},
> +       {.length = MT9P012_16BIT, .reg = REG_PRE_PLL_CLK_DIV, .val = 5},
> +       /* 10 fps */
> +       {.length = MT9P012_16BIT, .reg = REG_PLL_MULTIPLIER, .val = 184},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_PIX_CLK_DIV, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_SYS_CLK_DIV, .val = 1},
> +       {.length = MT9P012_16BIT, .reg = REG_RESERVED_MFR_3064, .val = 0x0805},
> +       {.length = MT9P012_16BIT, .reg = REG_X_OUTPUT_SIZE,
> +               .val = IMAGE_WIDTH_MIN},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_OUTPUT_SIZE,
> +               .val = IMAGE_HEIGHT_MIN},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_END, .val = 2599},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_END, .val = 1951},
> +       {.length = MT9P012_16BIT, .reg = REG_READ_MODE, .val = 0x0024},
> +       {.length = MT9P012_16BIT, .reg = REG_FINE_INT_TIME, .val = 882},
> +       {.length = MT9P012_16BIT, .reg = REG_FRAME_LEN_LINES, .val = 2056},
> +       {.length = MT9P012_16BIT, .reg = REG_LINE_LEN_PCK, .val = 5372},
> +       /* 0x10/0x14 = 0.80 */
> +       {.length = MT9P012_16BIT, .reg = REG_SCALE_M, .val = 0x0014},
> +       /* enable scaler */
> +       {.length = MT9P012_16BIT, .reg = REG_SCALING_MODE, .val = 0x0002},
> +       {.length = MT9P012_16BIT, .reg = REG_TEST_PATTERN, .val = TST_PAT},
> +       {.length = MT9P012_16BIT, .reg = REG_COARSE_INT_TIME,
> +               .val = COARSE_INT_TIME_3MP},
> +       /* update */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x00},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0}
> +};
> +
> +/* Image mode, 5 MP @ 10 fps */
> +const static struct mt9p012_reg enter_image_mode_5MP_10fps[] = {
> +       /* stream off */
> +       {.length = MT9P012_8BIT, .reg = REG_MODE_SELECT, .val = 0x00},
> +       {.length = MT9P012_TOK_DELAY, .reg = 0x00, .val = 100},
> +       /* hold */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x01},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_PIX_CLK_DIV, .val = 4},
> +       {.length = MT9P012_16BIT, .reg = REG_VT_SYS_CLK_DIV, .val = 1},
> +       {.length = MT9P012_16BIT, .reg = REG_PRE_PLL_CLK_DIV, .val = 5},
> +       /* 10 fps */
> +       {.length = MT9P012_16BIT, .reg = REG_PLL_MULTIPLIER, .val = 184},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_PIX_CLK_DIV, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_OP_SYS_CLK_DIV, .val = 1},
> +       {.length = MT9P012_16BIT, .reg = REG_RESERVED_MFR_3064, .val = 0x0805},
> +       {.length = MT9P012_16BIT, .reg = REG_X_OUTPUT_SIZE,
> +               .val = IMAGE_WIDTH_MAX},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_OUTPUT_SIZE,
> +               .val = IMAGE_HEIGHT_MAX},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_START, .val = 8},
> +       {.length = MT9P012_16BIT, .reg = REG_X_ADDR_END, .val = 2599},
> +       {.length = MT9P012_16BIT, .reg = REG_Y_ADDR_END, .val = 1951},
> +       {.length = MT9P012_16BIT, .reg = REG_READ_MODE, .val = 0x0024},
> +       {.length = MT9P012_16BIT, .reg = REG_FINE_INT_TIME, .val = 882},
> +       {.length = MT9P012_16BIT, .reg = REG_FRAME_LEN_LINES, .val = 2056},
> +       {.length = MT9P012_16BIT, .reg = REG_LINE_LEN_PCK, .val = 5372},
> +       {.length = MT9P012_16BIT, .reg = REG_SCALE_M, .val = 0x0000},
> +       /* disable scaler */
> +       {.length = MT9P012_16BIT, .reg = REG_SCALING_MODE, .val = 0x0000},
> +       {.length = MT9P012_16BIT, .reg = REG_COARSE_INT_TIME,
> +               .val = COARSE_INT_TIME_5MP},
> +       /* update */
> +       {.length = MT9P012_8BIT, .reg = REG_GROUPED_PAR_HOLD, .val = 0x00},
> +       {.length = MT9P012_TOK_TERM, .reg = 0, .val = 0}
> +};
> +
> +static u32 min_exposure_time;
> +static u32 max_exposure_time;
> +static u32 pix_clk_freq;
> +
> +/* Structure to set frame rate */
> +static struct mt9p012_reg set_fps[2];

These statics might need to be moved to struct mt9p012_sensor as well.

> +
> +/**
> + * struct mt9p012_pll_settings - struct for storage of sensor pll values
> + * @vt_pix_clk_div: vertical pixel clock divider
> + * @vt_sys_clk_div: veritcal system clock divider
> + * @pre_pll_div: pre pll divider
> + * @fine_int_tm: fine resolution interval time
> + * @frame_lines: number of lines in frame
> + * @line_len: number of pixels in line
> + * @min_pll: minimum pll multiplier
> + * @max_pll: maximum pll multiplier
> + */
> +static struct mt9p012_pll_settings all_pll_settings[] = {

Make this const.

> +       /* PLL_5MP */
> +       {.vt_pix_clk_div = 4, .vt_sys_clk_div = 1, .pre_pll_div = 5,
> +       .fine_int_tm = 882, .frame_lines = 2056, .line_len = 5372,
> +       .min_pll = 160, .max_pll = 200},
> +       /* PLL_3MP */
> +       {.vt_pix_clk_div = 4, .vt_sys_clk_div = 1, .pre_pll_div = 5,
> +       .fine_int_tm = 882, .frame_lines = 2056, .line_len = 5372,
> +       .min_pll = 160, .max_pll = 200},
> +       /* PLL_1296_15FPS */
> +       {.vt_pix_clk_div = 5, .vt_sys_clk_div = 2, .pre_pll_div = 3,
> +       .fine_int_tm = 1794, .frame_lines = 1061, .line_len = 3360,
> +       .min_pll = 96, .max_pll = 190},
> +       /* PLL_1296_30FPS */
> +       {.vt_pix_clk_div = 5, .vt_sys_clk_div = 1, .pre_pll_div = 3,
> +       .fine_int_tm = 1794, .frame_lines = 1061, .line_len = 3360,
> +       .min_pll = 96, .max_pll = 150},
> +       /* PLL_648_15FPS */
> +       {.vt_pix_clk_div = 8, .vt_sys_clk_div = 2, .pre_pll_div = 2,
> +       .fine_int_tm = 1794, .frame_lines = 574, .line_len = 2712,
> +       .min_pll = 92, .max_pll = 128},
> +       /* PLL_648_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_216_15FPS */
> +       {.vt_pix_clk_div = 8, .vt_sys_clk_div = 2, .pre_pll_div = 2,
> +       .fine_int_tm = 1794,  .frame_lines = 574, .line_len = 2712,
> +       .min_pll = 92, .max_pll = 126},
> +       /* 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}
> +};
> +
> +static enum mt9p012_pll_type current_pll_video;
> +
> +const static struct mt9p012_reg *
> +       mt9p012_reg_init[NUM_FPS][NUM_IMAGE_SIZES] =
> +{
> +       {
> +               enter_video_216_15fps,
> +               enter_video_648_15fps,
> +               enter_video_1296_15fps,
> +               enter_image_mode_3MP_10fps,
> +               enter_image_mode_5MP_10fps
> +       },
> +       {
> +               enter_video_216_30fps,
> +               enter_video_648_30fps,
> +               enter_video_1296_30fps,
> +               enter_image_mode_3MP_10fps,
> +               enter_image_mode_5MP_10fps
> +       },
> +};
> +
> +/**
> + * 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;
> +} video_control[] = {
> +       {
> +               {
> +                       .id = V4L2_CID_EXPOSURE,
> +                       .type = V4L2_CTRL_TYPE_INTEGER,
> +                       .name = "Exposure",
> +                       .minimum = DEF_MIN_EXPOSURE,
> +                       .maximum = DEF_MAX_EXPOSURE,
> +                       .step = EXPOSURE_STEP,
> +                       .default_value = DEF_EXPOSURE,
> +               },
> +               .current_value = DEF_EXPOSURE,
> +       },
> +       {
> +               {
> +                       .id = V4L2_CID_GAIN,
> +                       .type = V4L2_CTRL_TYPE_INTEGER,
> +                       .name = "Analog Gain",

This should be 'Gain'. In the future strings like this will be set for
you, so it's good to use the standard string from the start.

> +                       .minimum = MIN_GAIN,
> +                       .maximum = MAX_GAIN,
> +                       .step = GAIN_STEP,
> +                       .default_value = DEF_GAIN,
> +               },
> +               .current_value = 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(video_control) - 1); i >= 0; i--)
> +               if (video_control[i].qc.id == id)
> +                       break;
> +       if (i < 0)
> +               i = -EINVAL;
> +       return i;
> +}
> +
> +/**
> + * mt9p012_read_reg - Read a value from a register in an mt9p012 sensor device
> + * @client: i2c driver client structure
> + * @data_length: length of data to be read
> + * @reg: register address / offset
> + * @val: stores the value that gets read
> + *
> + * Read a value from a register in an mt9p012 sensor device.
> + * The value is returned in 'val'.
> + * Returns zero if successful, or non-zero otherwise.
> + */
> +static int
> +mt9p012_read_reg(struct i2c_client *client, u16 data_length, u16 reg, u32 *val)
> +{
> +       int err;
> +       struct i2c_msg msg[1];
> +       unsigned char data[4];
> +
> +       if (!client->adapter)
> +               return -ENODEV;
> +       if (data_length != MT9P012_8BIT && data_length != MT9P012_16BIT
> +                                       && data_length != MT9P012_32BIT)
> +               return -EINVAL;
> +
> +       msg->addr = client->addr;
> +       msg->flags = 0;
> +       msg->len = 2;
> +       msg->buf = data;
> +
> +       /* high byte goes out first */
> +       data[0] = (u8) (reg >> 8);;
> +       data[1] = (u8) (reg & 0xff);
> +       err = i2c_transfer(client->adapter, msg, 1);
> +       if (err >= 0) {
> +               msg->len = data_length;
> +               msg->flags = I2C_M_RD;
> +               err = i2c_transfer(client->adapter, msg, 1);
> +       }
> +       if (err >= 0) {
> +               *val = 0;
> +               /* high byte comes first */
> +               if (data_length == MT9P012_8BIT)
> +                       *val = data[0];
> +               else if (data_length == MT9P012_16BIT)
> +                       *val = data[1] + (data[0] << 8);
> +               else
> +                       *val = data[3] + (data[2] << 8) +
> +                               (data[1] << 16) + (data[0] << 24);
> +               return 0;
> +       }
> +       dev_err(&client->dev, "read from offset 0x%x error %d", reg, err);
> +       return err;
> +}
> +/**
> + * mt9p012_write_reg - Write a value to a register in an mt9p012 sensor device
> + * @client: i2c driver client structure
> + * @data_length: length of data to be read
> + * @reg: register address / offset
> + * @val: value to be written to specified register
> + *
> + * Write a value to a register in an mt9p012 sensor device.
> + * Returns zero if successful, or non-zero otherwise.
> + */
> +static int
> +mt9p012_write_reg(struct i2c_client *client, u16 data_length, u16 reg, u32 val)
> +{
> +       int err;
> +       struct i2c_msg msg[1];
> +       unsigned char data[6];
> +       int retry = 0;
> +
> +       if (!client->adapter)
> +               return -ENODEV;
> +
> +       if (data_length != MT9P012_8BIT && data_length != MT9P012_16BIT
> +                                       && data_length != MT9P012_32BIT)
> +               return -EINVAL;
> +
> +again:
> +       msg->addr = client->addr;
> +       msg->flags = 0;
> +       msg->len = 2 + data_length;
> +       msg->buf = data;
> +
> +       /* high byte goes out first */
> +       data[0] = (u8) (reg >> 8);;
> +       data[1] = (u8) (reg & 0xff);
> +
> +       if (data_length == MT9P012_8BIT)
> +               data[2] = (u8) (val & 0xff);
> +       else if (data_length == MT9P012_16BIT) {
> +               data[2] = (u8) (val >> 8);
> +               data[3] = (u8) (val & 0xff);
> +       } else {
> +               data[2] = (u8) (val >> 24);
> +               data[3] = (u8) (val >> 16);
> +               data[4] = (u8) (val >> 8);
> +               data[5] = (u8) (val & 0xff);
> +       }
> +
> +       err = i2c_transfer(client->adapter, msg, 1);
> +       if (err >= 0)
> +               return 0;
> +
> +       v4l_dbg(1, debug, client, "wrote 0x%x to offset 0x%x error %d", val,
> +                                                       reg, err);
> +       if (retry <= I2C_RETRY_COUNT) {
> +               v4l_warn(client, "retry ... %d", retry);
> +               retry++;
> +               mdelay(20);
> +               goto again;
> +       }
> +       return err;
> +}
> +
> +/**
> + * mt9p012_write_regs - Initializes a list of MT9P012 registers
> + * @client: i2c driver client structure
> + * @reglist: list of registers to be written
> + *
> + * Initializes a list of MT9P012 registers. The list of registers is
> + * terminated by MT9P012_TOK_TERM.
> + */
> +static int
> +mt9p012_write_regs(struct i2c_client *client,
> +                       const struct mt9p012_reg reglist[])
> +{
> +       int err;
> +       const struct mt9p012_reg *next = reglist;
> +
> +       for (; next->length != MT9P012_TOK_TERM; next++) {
> +               if (next->length == MT9P012_TOK_DELAY) {
> +                       mdelay(next->val);
> +                       continue;
> +               }
> +
> +               err = mt9p012_write_reg(client, next->length,
> +                                               next->reg, next->val);
> +               if (err)
> +                       return err;
> +       }
> +       return 0;
> +}
> +
> +/**
> + * mt9p012_calc_pll - Calculate PLL settings based on input image size
> + * @isize: enum value corresponding to image size
> + * @xclk: xclk value (calculate by mt9p012sensor_calc_xclk())
> + * @sensor: pointer to sensor device information structure
> + *
> + * Calculates sensor PLL related settings (scaler, fps, pll_multiplier,
> + * pix_clk_freq, min_exposure_time, max_exposure_time) based on input
> + * image size.  It then applies the fps register settings based on
> + * these calculations.
> + */
> +static int
> +mt9p012_calc_pll(enum image_size isize,
> +               unsigned long xclk,
> +               struct mt9p012_sensor *sensor)
> +{
> +       int err = 0, row = 1, i = 0;
> +       unsigned int vt_pix_clk;
> +       unsigned int pll_multiplier;
> +       unsigned int exposure_factor, pix_clk_scaled;
> +       struct i2c_client *client = sensor->i2c_client;
> +       struct vcontrol *lvc;
> +
> +       /* Greater than 1296x972
> +       1. Scaler is 0
> +       2. fps is 10
> +       3. Apply image mode settings
> +       4. Turn Streaming ON.
> +       5. Exit
> +       */
> +       if (isize > BIN2X) {
> +               /* Burst Mode */
> +               sensor->scaler = 0;
> +               sensor->fps = 10;
> +               current_pll_video = PLL_5MP;
> +               return 0;
> +       }
> +
> +       /* Greater than 648X486 case
> +       1. Scaler is 0
> +       2. If fps>21 then choose PLL for 30
> +       3. If fps<21 then choose PLL for 15
> +
> +       Greater than 216X162 case
> +       1. Scaler is 1
> +       2. If fps>15 then choose PLL for 30
> +       3. If fps<15 then choose PLL for 15
> +
> +       Greater than 0 to 216x162
> +       1. Scaler is 2.
> +       2. If fps>15 then choose PLL for 30
> +       3. If fps<15 then choose PLL for 15
> +       */
> +
> +       if (isize > BIN4X) {
> +               sensor->scaler = 0;
> +               if (sensor->fps > 21)
> +                       current_pll_video = PLL_1296_30FPS;
> +               else
> +                       current_pll_video = PLL_1296_15FPS;
> +       } else if (isize > BIN4XSCALE) {
> +               sensor->scaler = 1;
> +               if (sensor->fps > 15)
> +                       current_pll_video = PLL_648_30FPS;
> +               else
> +                       current_pll_video = PLL_648_15FPS;
> +       } else {
> +               sensor->scaler = 2;
> +               if (sensor->fps > 15)
> +                       current_pll_video = PLL_216_30FPS;
> +               else
> +                       current_pll_video = PLL_216_15FPS;
> +       }
> +
> +       /* Row adjustment */
> +       if (sensor->scaler && (sensor->fps < 16))
> +               row = 2; /* Adjustment when using 4x binning and 12 MHz clk */
> +
> +       /* Calculate the PLL, set fps register */
> +       vt_pix_clk = sensor->fps *
> +               all_pll_settings[current_pll_video].frame_lines *
> +               all_pll_settings[current_pll_video].line_len;
> +
> +       pll_multiplier =
> +               (((vt_pix_clk
> +                  * all_pll_settings[current_pll_video].vt_pix_clk_div
> +                  * all_pll_settings[current_pll_video].vt_sys_clk_div
> +                  * row) / xclk)
> +                  * all_pll_settings[current_pll_video].pre_pll_div) + 1;
> +
> +       if (pll_multiplier < all_pll_settings[current_pll_video].min_pll)
> +               pll_multiplier = all_pll_settings[current_pll_video].min_pll;
> +       else if (pll_multiplier > all_pll_settings[current_pll_video].max_pll)
> +               pll_multiplier = all_pll_settings[current_pll_video].max_pll;
> +
> +       pix_clk_freq = (xclk /
> +                       (all_pll_settings[current_pll_video].pre_pll_div
> +                        * all_pll_settings[current_pll_video].vt_pix_clk_div
> +                        * all_pll_settings[current_pll_video].vt_sys_clk_div
> +                        * row)) * pll_multiplier;
> +       min_exposure_time = (all_pll_settings[current_pll_video].fine_int_tm
> +                            * 1000000 / pix_clk_freq) + 1;
> +       exposure_factor = (all_pll_settings[current_pll_video].frame_lines - 1)
> +                               * all_pll_settings[current_pll_video].line_len;
> +       exposure_factor += all_pll_settings[current_pll_video].fine_int_tm;
> +       exposure_factor *= 100;
> +       pix_clk_scaled = pix_clk_freq / 100;
> +       max_exposure_time = (exposure_factor / pix_clk_scaled) * 100;
> +
> +       /* Apply the fps settings */
> +       set_fps[0].length = MT9P012_16BIT;
> +       set_fps[0].reg = REG_PLL_MULTIPLIER;
> +       set_fps[0].val = pll_multiplier;
> +       set_fps[1].length = MT9P012_TOK_TERM;
> +       set_fps[1].reg = 0;
> +       set_fps[1].val = 0;
> +
> +       /* Update min/max for query control */
> +       i = find_vctrl(V4L2_CID_EXPOSURE);
> +       if (i >= 0) {
> +               lvc = &video_control[i];
> +               lvc->qc.minimum = min_exposure_time;
> +               lvc->qc.maximum = max_exposure_time;
> +       }
> +
> +       err = mt9p012_write_regs(client, set_fps);
> +       return err;
> +}
> +
> +/**
> + * mt9p012_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 image_size mt9p012_calc_size(unsigned int width,
> +                                                       unsigned int height)
> +{
> +       enum image_size isize;
> +       unsigned long pixels = width * height;
> +
> +       for (isize = BIN4XSCALE; isize <= FIVE_MP; isize++) {
> +               if (mt9p012_sizes[isize].height *
> +                                       mt9p012_sizes[isize].width >= pixels) {
> +                       /* To improve image quality in VGA */
> +                       if ((pixels > CIF_PIXELS) && (isize == BIN4X)) {
> +                               isize = BIN2X;
> +                       } else if ((pixels > QQVGA_PIXELS) &&
> +                                                       (isize == BIN4XSCALE)) {
> +                               isize = BIN4X;
> +                       }
> +                       return isize;
> +               }
> +       }
> +
> +       return FIVE_MP;
> +}
> +
> +/**
> + * mt9p012_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 image_size mt9p012_find_isize(unsigned int width)
> +{
> +       enum image_size isize;
> +
> +       for (isize = BIN4XSCALE; isize <= FIVE_MP; isize++) {
> +               if (mt9p012_sizes[isize].width >= width)
> +                       break;
> +       }
> +
> +       return isize;
> +}
> +/**
> + * mt9p012_find_fps_index - Find the best fps range match for a
> + *  requested frame rate
> + * @fps: desired frame rate
> + * @isize: enum value corresponding to image size
> + *
> + * Find the best match for a requested frame rate.  The best match
> + * is chosen between two fps ranges (11 - 15 and 16 - 30 fps) depending on
> + * the image size. For image sizes larger than BIN2X, frame rate is fixed
> + * at 10 fps.
> + */
> +static unsigned int mt9p012_find_fps_index(unsigned int fps,
> +                                                       enum image_size isize)
> +{
> +       unsigned int index = FPS_LOW_RANGE;
> +
> +       if (isize > BIN4X) {
> +               if (fps > 21)
> +                       index = FPS_HIGH_RANGE;
> +       } else {
> +               if (fps > 15)
> +                       index = FPS_HIGH_RANGE;
> +       }
> +
> +       return index;
> +}
> +
> +/**
> + * mt9p012sensor_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 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;
> +
> +       if ((timeperframe->numerator == 0)
> +       || (timeperframe->denominator == 0)) {
> +               /* supply a default nominal_timeperframe */
> +               timeperframe->numerator = 1;
> +               timeperframe->denominator = MT9P012_DEF_FPS;
> +       }
> +
> +       sensor->fps = timeperframe->denominator/timeperframe->numerator;
> +       if (sensor->fps < MT9P012_MIN_FPS)
> +               sensor->fps = MT9P012_MIN_FPS;
> +       else if (sensor->fps > MT9P012_MAX_FPS)
> +               sensor->fps = MT9P012_MAX_FPS;
> +
> +       timeperframe->numerator = 1;
> +       timeperframe->denominator = sensor->fps;
> +
> +       if ((pix->width <= VIDEO_WIDTH_4X_BINN) && (sensor->fps > 15))
> +               xclk_current = MT9P012_XCLK_NOM_2;
> +       else
> +               xclk_current = MT9P012_XCLK_NOM_1;
> +
> +       return xclk_current;
> +}
> +
> +/**
> + * mt9p012_configure - Configure the mt9p012 for the specified image mode
> + * @s: pointer to standard V4L2 device structure
> + *
> + * Configure the mt9p012 for a specified image size, pixel format, and frame
> + * period.  xclk is the frequency (in Hz) of the xclk input to the mt9p012.
> + * fper is the frame period (in seconds) expressed as a fraction.
> + * Returns zero if successful, or non-zero otherwise.
> + * The actual frame period is returned in fper.
> + */
> +static int mt9p012_configure(struct v4l2_int_device *s)
> +{
> +       struct mt9p012_sensor *sensor = s->priv;
> +       struct v4l2_pix_format *pix = &sensor->pix;
> +       struct i2c_client *client = sensor->i2c_client;
> +       enum image_size isize;
> +       unsigned int fps_index;
> +       int err;
> +
> +       isize = mt9p012_find_isize(pix->width);
> +
> +       /* common register initialization */
> +       err = mt9p012_write_regs(client, mt9p012_common);
> +       if (err)
> +               return err;
> +
> +       fps_index = mt9p012_find_fps_index(sensor->fps, isize);
> +
> +       /* configure image size and pixel format */
> +       err = mt9p012_write_regs(client, mt9p012_reg_init[fps_index][isize]);
> +       if (err)
> +               return err;
> +
> +       /* configure frame rate */
> +       err = mt9p012_calc_pll(isize, xclk_current, sensor);
> +       if (err)
> +               return err;
> +
> +       /* configure streaming ON */
> +       err = mt9p012_write_regs(client, stream_on_list);
> +
> +       return err;
> +}
> +
> +/**
> + * mt9p012_detect - Detect if an mt9p012 is present, and if so which revision
> + * @client: pointer to the i2c client driver structure
> + *
> + * Detect if an mt9p012 is present, and if so which revision.
> + * A device is considered to be detected if the manufacturer ID (MIDH and MIDL)
> + * and the product ID (PID) registers match the expected values.
> + * Any value of the version ID (VER) register is accepted.
> + * Here are the version numbers we know about:
> + *     0x48 --> mt9p012 Revision 1 or mt9p012 Revision 2
> + *     0x49 --> mt9p012 Revision 3
> + * Returns a negative error number if no device is detected, or the
> + * non-negative value of the version ID register if a device is detected.
> + */
> +static int
> +mt9p012_detect(struct i2c_client *client)
> +{
> +       u32 model_id, mfr_id, rev;
> +
> +       if (!client)
> +               return -ENODEV;
> +
> +       if (mt9p012_read_reg(client, MT9P012_16BIT, REG_MODEL_ID, &model_id))
> +               return -ENODEV;
> +       if (mt9p012_read_reg(client, MT9P012_8BIT, REG_MANUFACTURER_ID,
> +                               &mfr_id))
> +               return -ENODEV;
> +       if (mt9p012_read_reg(client, MT9P012_8BIT, REG_REVISION_NUMBER, &rev))
> +               return -ENODEV;
> +
> +       dev_info(&client->dev, "model id detected 0x%x mfr 0x%x\n", model_id,
> +                                                               mfr_id);
> +       if ((model_id != MT9P012_MOD_ID) || (mfr_id != MT9P012_MFR_ID)) {
> +               /* We didn't read the values we expected, so
> +                * this must not be an MT9P012.
> +                */
> +               dev_warn(&client->dev, "model id mismatch 0x%x mfr 0x%x\n",
> +                       model_id, mfr_id);
> +
> +               return -ENODEV;
> +       }
> +       return 0;
> +
> +}
> +
> +/**
> + * mt9p012sensor_set_exposure_time - sets exposure time per input value
> + * @exp_time: exposure time to be set on device
> + * @s: pointer to standard V4L2 device structure
> + * @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.
> + */
> +int
> +mt9p012sensor_set_exposure_time(u32 exp_time, struct v4l2_int_device *s,
> +                                               struct vcontrol *lvc)
> +{
> +       int err;
> +       struct mt9p012_sensor *sensor = s->priv;
> +       struct i2c_client *client = sensor->i2c_client;
> +       u32 coarse_int_time = 0;
> +
> +       if ((exp_time < min_exposure_time) ||
> +                       (exp_time > max_exposure_time)) {
> +               dev_err(&client->dev, "Exposure time not within the "
> +                       "legal range.\n");
> +               dev_err(&client->dev, "Min time %d us Max time %d us",
> +                       min_exposure_time, max_exposure_time);
> +               return -EINVAL;
> +       }
> +       coarse_int_time =
> +               ((((exp_time / 10) * (pix_clk_freq / 1000)) / 1000)
> +                  - (all_pll_settings[current_pll_video].fine_int_tm
> +                     / 10))
> +                  / (all_pll_settings[current_pll_video].line_len
> +                     / 10);

Unreadable, just append the trailing '/ 10' to the preceeding line. Or
split it up in multiple calculations.

> +
> +       dev_dbg(&client->dev, "coarse_int_time calculated = %d\n",
> +                                               coarse_int_time);
> +
> +       set_exposure_time[COARSE_INT_TIME_INDEX].val = coarse_int_time;
> +       err = mt9p012_write_regs(client, set_exposure_time);
> +
> +       if (err)
> +               dev_err(&client->dev, "Error setting exposure time %d\n",
> +                                                                       err);
> +       else
> +               lvc->current_value = exp_time;
> +
> +       return err;
> +}
> +
> +/**
> + * mt9p012sensor_set_gain - sets sensor analog gain per input value
> + * @gain: analog gain value to be set on device
> + * @s: pointer to standard V4L2 device structure
> + * @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
> +mt9p012sensor_set_gain(u16 gain, struct v4l2_int_device *s,
> +                                       struct vcontrol *lvc)
> +{
> +       int err;
> +       struct mt9p012_sensor *sensor = s->priv;
> +       struct i2c_client *client = sensor->i2c_client;
> +
> +       if ((gain < MIN_GAIN) || (gain > MAX_GAIN)) {
> +               dev_err(&client->dev, "Gain not within the legal range");
> +               return -EINVAL;
> +       }
> +       set_analog_gain[GAIN_INDEX].val = gain;
> +       err = mt9p012_write_regs(client, set_analog_gain);
> +       if (err) {
> +               dev_err(&client->dev, "Error setting gain.%d", err);
> +               return err;
> +       } else
> +               lvc->current_value = gain;
> +
> +       return err;
> +}
> +
> +/**
> + * 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)
> +{
> +       int i;
> +
> +       i = find_vctrl(qc->id);
> +       if (i == -EINVAL)
> +               qc->flags = V4L2_CTRL_FLAG_DISABLED;
> +
> +       if (i < 0)
> +               return -EINVAL;
> +
> +       *qc = video_control[i].qc;
> +       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)
> +{
> +       struct vcontrol *lvc;
> +       int i;
> +
> +       i = find_vctrl(vc->id);
> +       if (i < 0)
> +               return -EINVAL;
> +       lvc = &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;
> +}
> +
> +/**
> + * 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)
> +{
> +       int retval = -EINVAL;
> +       int i;
> +       struct vcontrol *lvc;
> +
> +       i = find_vctrl(vc->id);
> +       if (i < 0)
> +               return -EINVAL;
> +       lvc = &video_control[i];
> +
> +       switch (vc->id) {
> +       case V4L2_CID_EXPOSURE:
> +               retval = mt9p012sensor_set_exposure_time(vc->value, s, lvc);
> +               break;
> +       case V4L2_CID_GAIN:
> +               retval = mt9p012sensor_set_gain(vc->value, s, lvc);
> +               break;
> +       }
> +
> +       return retval;
> +}
> +
> +
> +/**
> + * ioctl_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 ioctl_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 >= NUM_CAPTURE_FORMATS)
> +                       return -EINVAL;
> +       break;
> +       default:
> +               return -EINVAL;
> +       }
> +
> +       fmt->flags = mt9p012_formats[index].flags;
> +       strlcpy(fmt->description, mt9p012_formats[index].description,
> +                                       sizeof(fmt->description));
> +       fmt->pixelformat = mt9p012_formats[index].pixelformat;
> +
> +       return 0;
> +}
> +
> +/**
> + * ioctl_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 ioctl_try_fmt_cap(struct v4l2_int_device *s,
> +                            struct v4l2_format *f)
> +{
> +       enum image_size isize;
> +       int ifmt;
> +       struct v4l2_pix_format *pix = &f->fmt.pix;
> +       struct mt9p012_sensor *sensor = s->priv;
> +       struct v4l2_pix_format *pix2 = &sensor->pix;
> +
> +       isize = mt9p012_calc_size(pix->width, pix->height);
> +
> +       pix->width = mt9p012_sizes[isize].width;
> +       pix->height = mt9p012_sizes[isize].height;
> +       for (ifmt = 0; ifmt < NUM_CAPTURE_FORMATS; ifmt++) {
> +               if (pix->pixelformat == mt9p012_formats[ifmt].pixelformat)
> +                       break;
> +       }
> +       if (ifmt == NUM_CAPTURE_FORMATS)
> +               ifmt = 0;
> +       pix->pixelformat = mt9p012_formats[ifmt].pixelformat;
> +       pix->field = V4L2_FIELD_NONE;
> +       pix->bytesperline = pix->width * 2;
> +       pix->sizeimage = pix->bytesperline * pix->height;
> +       pix->priv = 0;
> +       switch (pix->pixelformat) {
> +       case V4L2_PIX_FMT_YUYV:
> +       case V4L2_PIX_FMT_UYVY:
> +               pix->colorspace = V4L2_COLORSPACE_JPEG;
> +               break;
> +       case V4L2_PIX_FMT_RGB565:
> +       case V4L2_PIX_FMT_RGB565X:
> +       case V4L2_PIX_FMT_RGB555:
> +       case V4L2_PIX_FMT_SGRBG10:
> +       case V4L2_PIX_FMT_RGB555X:
> +       default:
> +               pix->colorspace = V4L2_COLORSPACE_SRGB;
> +               break;
> +       }
> +       *pix2 = *pix;
> +       return 0;
> +}
> +
> +/**
> + * ioctl_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 ioctl_s_fmt_cap(struct v4l2_int_device *s,
> +                               struct v4l2_format *f)
> +{
> +       struct mt9p012_sensor *sensor = s->priv;
> +       struct v4l2_pix_format *pix = &f->fmt.pix;
> +       int rval;
> +
> +       rval = ioctl_try_fmt_cap(s, f);
> +       if (rval)
> +               return rval;
> +       else
> +               sensor->pix = *pix;

Why not:

	if (rval == 0)
		sensor->pix = *pix;

Does the same as above, but in only 2 instead of 4 lines.

> +
> +       return rval;
> +}
> +
> +/**
> + * 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)
> +{
> +       struct mt9p012_sensor *sensor = s->priv;
> +       f->fmt.pix = sensor->pix;
> +
> +       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)
> +{
> +       struct mt9p012_sensor *sensor = 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 = sensor->timeperframe;
> +
> +       return 0;
> +}
> +
> +/**
> + * 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)
> +{
> +       struct mt9p012_sensor *sensor = s->priv;
> +       struct i2c_client *client = sensor->i2c_client;
> +       struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
> +
> +       sensor->timeperframe = *timeperframe;
> +       mt9p012sensor_calc_xclk(client);
> +       *timeperframe = sensor->timeperframe;
> +
> +       return 0;
> +}
> +
> +/**
> + * ioctl_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 ioctl_g_priv(struct v4l2_int_device *s, void *p)
> +{
> +       struct mt9p012_sensor *sensor = s->priv;
> +
> +       return sensor->pdata->priv_data_set(p);
> +}
> +
> +/**
> + * 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.
> + */
> +static int ioctl_s_power(struct v4l2_int_device *s, enum v4l2_power on)
> +{
> +       struct mt9p012_sensor *sensor = s->priv;
> +       struct i2c_client *c = sensor->i2c_client;
> +       int rval;
> +
> +       if ((on == V4L2_POWER_STANDBY) && (sensor->state == SENSOR_DETECTED))
> +               mt9p012_write_regs(c, stream_off_list);
> +
> +       if (on != V4L2_POWER_ON)
> +               sensor->pdata->set_xclk(0);
> +       else
> +               sensor->pdata->set_xclk(xclk_current);
> +
> +       rval = sensor->pdata->power_set(on);
> +       if (rval < 0) {
> +               dev_err(&c->dev, "Unable to set the power state: " DRIVER_NAME
> +                                                               " sensor\n");
> +               sensor->pdata->set_xclk(0);
> +               return rval;
> +       }
> +
> +       if ((on == V4L2_POWER_ON) && (sensor->state == SENSOR_DETECTED))
> +               mt9p012_configure(s);
> +
> +       if ((on == V4L2_POWER_ON) && (sensor->state == SENSOR_NOT_DETECTED)) {
> +               rval = mt9p012_detect(c);
> +               if (rval < 0) {
> +                       dev_err(&c->dev, "Unable to detect " DRIVER_NAME
> +                                                               " sensor\n");
> +                       sensor->state = SENSOR_NOT_DETECTED;
> +                       return rval;
> +               }
> +               sensor->state = SENSOR_DETECTED;
> +               sensor->ver = rval;
> +               pr_info(DRIVER_NAME " chip version 0x%02x detected\n",
> +                                                               sensor->ver);
> +       }
> +
> +       return 0;
> +}
> +
> +/**
> + * ioctl_init - V4L2 sensor interface handler for VIDIOC_INT_INIT
> + * @s: pointer to standard V4L2 device structure
> + *
> + * Initialize the sensor device (call mt9p012_configure())
> + */
> +static int ioctl_init(struct v4l2_int_device *s)
> +{
> +       return 0;
> +}
> +
> +/**
> + * ioctl_dev_exit - V4L2 sensor interface handler for vidioc_int_dev_exit_num
> + * @s: pointer to standard V4L2 device structure
> + *
> + * Delinitialise the dev. at slave detach.  The complement of ioctl_dev_init.
> + */
> +static int ioctl_dev_exit(struct v4l2_int_device *s)
> +{
> +       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.  Returns 0 if
> + * mt9p012 device could be found, otherwise returns appropriate error.
> + */
> +static int ioctl_dev_init(struct v4l2_int_device *s)
> +{
> +       return 0;
> +}
> +/**
> + * ioctl_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 ioctl_enum_framesizes(struct v4l2_int_device *s,
> +                                       struct v4l2_frmsizeenum *frms)
> +{
> +       int ifmt;
> +
> +       for (ifmt = 0; ifmt < NUM_CAPTURE_FORMATS; ifmt++) {
> +               if (frms->pixel_format == mt9p012_formats[ifmt].pixelformat)
> +                       break;
> +       }
> +       /* Is requested pixelformat not found on sensor? */
> +       if (ifmt == NUM_CAPTURE_FORMATS)
> +               return -EINVAL;
> +
> +       /* Do we already reached all discrete framesizes? */
> +       if (frms->index >= 5)
> +               return -EINVAL;
> +
> +       frms->type = V4L2_FRMSIZE_TYPE_DISCRETE;
> +       frms->discrete.width = mt9p012_sizes[frms->index].width;
> +       frms->discrete.height = mt9p012_sizes[frms->index].height;
> +
> +       return 0;
> +}
> +
> +const struct v4l2_fract mt9p012_frameintervals[] = {
> +       {  .numerator = 1, .denominator = 11 },
> +       {  .numerator = 1, .denominator = 15 },
> +       {  .numerator = 1, .denominator = 20 },
> +       {  .numerator = 1, .denominator = 25 },
> +       {  .numerator = 1, .denominator = 30 },
> +};
> +
> +static int ioctl_enum_frameintervals(struct v4l2_int_device *s,
> +                                       struct v4l2_frmivalenum *frmi)
> +{
> +       int ifmt;
> +
> +       for (ifmt = 0; ifmt < NUM_CAPTURE_FORMATS; ifmt++) {
> +               if (frmi->pixel_format == mt9p012_formats[ifmt].pixelformat)
> +                       break;
> +       }
> +       /* Is requested pixelformat not found on sensor? */
> +       if (ifmt == NUM_CAPTURE_FORMATS)
> +               return -EINVAL;
> +
> +       /* Do we already reached all discrete framesizes? */
> +
> +       if (((frmi->width == mt9p012_sizes[4].width) &&
> +                               (frmi->height == mt9p012_sizes[4].height)) ||
> +                               ((frmi->width == mt9p012_sizes[3].width) &&
> +                               (frmi->height == mt9p012_sizes[3].height))) {
> +               /* FIXME: The only frameinterval supported by 5MP and 3MP
> +                * capture sizes is 1/11 fps
> +                */
> +               if (frmi->index != 0)
> +                       return -EINVAL;
> +       } else {
> +               if (frmi->index >= 5)
> +                       return -EINVAL;
> +       }
> +
> +       frmi->type = V4L2_FRMSIZE_TYPE_DISCRETE;
> +       frmi->discrete.numerator =
> +                               mt9p012_frameintervals[frmi->index].numerator;
> +       frmi->discrete.denominator =
> +                               mt9p012_frameintervals[frmi->index].denominator;
> +
> +       return 0;
> +}
> +
> +static struct v4l2_int_ioctl_desc mt9p012_ioctl_desc[] = {
> +       { .num = vidioc_int_enum_framesizes_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_enum_framesizes },
> +       { .num = vidioc_int_enum_frameintervals_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_enum_frameintervals },
> +       { .num = vidioc_int_dev_init_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_dev_init },
> +       { .num = vidioc_int_dev_exit_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_dev_exit },
> +       { .num = vidioc_int_s_power_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_s_power },
> +       { .num = vidioc_int_g_priv_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_g_priv },
> +       { .num = vidioc_int_init_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_init },
> +       { .num = vidioc_int_enum_fmt_cap_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_enum_fmt_cap },
> +       { .num = vidioc_int_try_fmt_cap_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_try_fmt_cap },
> +       { .num = vidioc_int_g_fmt_cap_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_g_fmt_cap },
> +       { .num = vidioc_int_s_fmt_cap_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_s_fmt_cap },
> +       { .num = vidioc_int_g_parm_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_g_parm },
> +       { .num = vidioc_int_s_parm_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_s_parm },
> +       { .num = vidioc_int_queryctrl_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_queryctrl },
> +       { .num = vidioc_int_g_ctrl_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_g_ctrl },
> +       { .num = vidioc_int_s_ctrl_num,
> +         .func = (v4l2_int_ioctl_func *)ioctl_s_ctrl },
> +};
> +
> +static struct v4l2_int_slave mt9p012_slave = {
> +       .ioctls = mt9p012_ioctl_desc,
> +       .num_ioctls = ARRAY_SIZE(mt9p012_ioctl_desc),
> +};
> +
> +static struct v4l2_int_device mt9p012_int_device = {
> +       .module = THIS_MODULE,
> +       .name = DRIVER_NAME,
> +       .priv = &mt9p012,
> +       .type = v4l2_int_type_slave,
> +       .u = {
> +               .slave = &mt9p012_slave,
> +       },
> +};
> +
> +/**
> + * mt9p012_probe - sensor driver i2c probe handler
> + * @client: i2c driver client device structure
> + *
> + * Register sensor as an i2c client device and V4L2
> + * device.
> + */
> +static int
> +mt9p012_probe(struct i2c_client *client, const struct i2c_device_id *id)
> +{
> +       struct mt9p012_sensor *sensor = &mt9p012;
> +       int err;
> +
> +       if (i2c_get_clientdata(client))
> +               return -EBUSY;
> +
> +       sensor->pdata = client->dev.platform_data;
> +
> +       if (!sensor->pdata) {
> +               dev_err(&client->dev, "no platform data?\n");
> +               return -ENODEV;
> +       }
> +
> +       sensor->v4l2_int_device = &mt9p012_int_device;
> +       sensor->i2c_client = client;
> +
> +       i2c_set_clientdata(client, sensor);
> +
> +       /* Make the default capture format QCIF V4L2_PIX_FMT_SGRBG10 */
> +       sensor->pix.width = VIDEO_WIDTH_4X_BINN_SCALED;
> +       sensor->pix.height = VIDEO_WIDTH_4X_BINN_SCALED;
> +       sensor->pix.pixelformat = V4L2_PIX_FMT_SGRBG10;
> +
> +       err = v4l2_int_device_register(sensor->v4l2_int_device);
> +       if (err)
> +               i2c_set_clientdata(client, NULL);
> +
> +       return err;
> +}
> +
> +/**
> + * mt9p012_remove - sensor driver i2c remove handler
> + * @client: i2c driver client device structure
> + *
> + * Unregister sensor as an i2c client device and V4L2
> + * device.  Complement of mt9p012_probe().
> + */
> +static int __exit
> +mt9p012_remove(struct i2c_client *client)
> +{
> +       struct mt9p012_sensor *sensor = i2c_get_clientdata(client);
> +
> +       if (!client->adapter)
> +               return -ENODEV; /* our client isn't attached */
> +
> +       v4l2_int_device_unregister(sensor->v4l2_int_device);
> +       i2c_set_clientdata(client, NULL);
> +
> +       return 0;
> +}
> +
> +static const struct i2c_device_id mt9p012_id[] = {
> +       { DRIVER_NAME, 0 },
> +       { },
> +};
> +MODULE_DEVICE_TABLE(i2c, mt9p012_id);
> +
> +static struct i2c_driver mt9p012sensor_i2c_driver = {
> +       .driver = {
> +               .name = DRIVER_NAME,
> +               .owner = THIS_MODULE,
> +       },
> +       .probe = mt9p012_probe,
> +       .remove = __exit_p(mt9p012_remove),
> +       .id_table = mt9p012_id,
> +};
> +
> +static struct mt9p012_sensor mt9p012 = {
> +       .timeperframe = {
> +               .numerator = 1,
> +               .denominator = 15,
> +       },
> +       .state = SENSOR_NOT_DETECTED,
> +};
> +
> +/**
> + * mt9p012sensor_init - sensor driver module_init handler
> + *
> + * Registers driver as an i2c client driver.  Returns 0 on success,
> + * error code otherwise.
> + */
> +static int __init mt9p012sensor_init(void)
> +{
> +       return i2c_add_driver(&mt9p012sensor_i2c_driver);
> +}
> +module_init(mt9p012sensor_init);
> +
> +/**
> + * mt9p012sensor_cleanup - sensor driver module_exit handler
> + *
> + * Unregisters/deletes driver as an i2c client driver.
> + * Complement of mt9p012sensor_init.
> + */
> +static void __exit mt9p012sensor_cleanup(void)
> +{
> +       i2c_del_driver(&mt9p012sensor_i2c_driver);
> +}
> +module_exit(mt9p012sensor_cleanup);
> +
> +MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("mt9p012 camera sensor driver");
> diff --git a/drivers/media/video/mt9p012_regs.h b/drivers/media/video/mt9p012_regs.h
> new file mode 100644
> index 0000000..70f6ee7
> --- /dev/null
> +++ b/drivers/media/video/mt9p012_regs.h
> @@ -0,0 +1,74 @@
> +/*
> + * drivers/media/video/mt9p012_regs.h
> + *
> + * Register definitions for the MT9P012 camera sensor.
> + *
> + * Author:
> + *     Sameer Venkatraman <sameerv@xxxxxx>
> + *     Sergio Aguirre <saaguirre@xxxxxx>
> + *     Martinez Leonides
> + *
> + *
> + * Copyright (C) 2008 Texas Instruments.
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#define REG_MODEL_ID                   0x0000
> +#define REG_REVISION_NUMBER            0x0002
> +#define REG_MANUFACTURER_ID            0x0003
> +
> +#define REG_MODE_SELECT                        0x0100
> +#define REG_IMAGE_ORIENTATION          0x0101
> +#define REG_SOFTWARE_RESET             0x0103
> +#define REG_GROUPED_PAR_HOLD           0x0104
> +
> +#define REG_FINE_INT_TIME              0x0200
> +#define REG_COARSE_INT_TIME            0x0202
> +
> +#define REG_ANALOG_GAIN_GLOBAL         0x0204
> +#define REG_ANALOG_GAIN_GREENR         0x0206
> +#define REG_ANALOG_GAIN_RED            0x0208
> +#define REG_ANALOG_GAIN_BLUE           0x020A
> +#define REG_ANALOG_GAIN_GREENB         0x020C
> +#define REG_DIGITAL_GAIN_GREENR                0x020E
> +#define REG_DIGITAL_GAIN_RED           0x0210
> +#define REG_DIGITAL_GAIN_BLUE          0x0212
> +#define REG_DIGITAL_GAIN_GREENB                0x0214
> +
> +#define REG_VT_PIX_CLK_DIV             0x0300
> +#define REG_VT_SYS_CLK_DIV             0x0302
> +#define REG_PRE_PLL_CLK_DIV            0x0304
> +#define REG_PLL_MULTIPLIER             0x0306
> +#define REG_OP_PIX_CLK_DIV             0x0308
> +#define REG_OP_SYS_CLK_DIV             0x030A
> +
> +#define REG_FRAME_LEN_LINES            0x0340
> +#define REG_LINE_LEN_PCK               0x0342
> +
> +#define REG_X_ADDR_START               0x0344
> +#define REG_Y_ADDR_START               0x0346
> +#define REG_X_ADDR_END                 0x0348
> +#define REG_Y_ADDR_END                 0x034A
> +#define REG_X_OUTPUT_SIZE              0x034C
> +#define REG_Y_OUTPUT_SIZE              0x034E
> +#define REG_X_ODD_INC                  0x0382
> +#define REG_Y_ODD_INC                  0x0386
> +
> +#define REG_SCALING_MODE               0x0400
> +#define REG_SCALE_M                    0x0404
> +#define REG_SCALE_N                    0x0406
> +
> +#define REG_ROW_SPEED                  0x3016
> +#define REG_RESET_REGISTER             0x301A
> +#define REG_PIXEL_ORDER                        0x3024
> +#define REG_READ_MODE                  0x3040
> +
> +#define REG_DATAPATH_STATUS            0x306A
> +#define REG_DATAPATH_SELECT            0x306E
> +
> +#define REG_RESERVED_MFR_3064          0x3064
> +#define REG_TEST_PATTERN               0x3070
> +
> diff --git a/include/media/mt9p012.h b/include/media/mt9p012.h
> new file mode 100644
> index 0000000..848771d
> --- /dev/null
> +++ b/include/media/mt9p012.h
> @@ -0,0 +1,236 @@
> +/*
> + * drivers/media/video/mt9p012.h
> + *
> + * Register definitions for the MT9P012 camera sensor.
> + *
> + * Author:
> + *     Sameer Venkatraman <sameerv@xxxxxx>
> + *     Martinez Leonides
> + *
> + *
> + * Copyright (C) 2008 Texas Instruments.
> + *
> + * This file is licensed under the terms of the GNU General Public License
> + * version 2. This program is licensed "as is" without any warranty of any
> + * kind, whether express or implied.
> + */
> +
> +#ifndef MT9P012_H
> +#define MT9P012_H
> +
> +
> +#define MT9P012_I2C_ADDR               0x10
> +
> +/* The ID values we are looking for */
> +#define MT9P012_MOD_ID                 0x2800
> +#define MT9P012_MFR_ID                 0x0006
> +
> +/* MT9P012 has 8/16/32 registers */
> +#define MT9P012_8BIT                   1
> +#define MT9P012_16BIT                  2
> +#define MT9P012_32BIT                  4
> +
> +/* terminating token for reg list */
> +#define MT9P012_TOK_TERM               0xFF
> +
> +/* delay token for reg list */
> +#define MT9P012_TOK_DELAY              100
> +
> +/* Sensor specific GPIO signals */
> +#define MT9P012_RESET_GPIO     98
> +#define MT9P012_STANDBY_GPIO   58
> +
> +#define VAUX_2_8_V             0x09
> +#define VAUX_DEV_GRP_P1                0x20
> +#define VAUX_DEV_GRP_NONE      0x00
> +
> +#define DEBUG_BASE             0x08000000
> +#define REG_SDP3430_FPGA_GPIO_2 (0x50)
> +#define FPGA_SPR_GPIO1_3v3     (0x1 << 14)
> +#define FPGA_GPIO6_DIR_CTRL    (0x1 << 6)
> +
> +/* terminating list entry for reg */
> +#define MT9P012_REG_TERM               0xFF
> +/* terminating list entry for val */
> +#define MT9P012_VAL_TERM               0xFF
> +
> +#define MT9P012_CLKRC                  0x11
> +
> +#define MT9P012_GAIN                   0x00
> +
> +/*
> + * The nominal xclk input frequency of the MT9P012 is 12MHz, maximum
> + * frequency is 64MHz, and minimum frequency is 2MHz.
> + */
> +#define MT9P012_XCLK_MIN   2000000
> +#define MT9P012_XCLK_MAX   64000000
> +#define MT9P012_XCLK_NOM_1 12000000
> +#define MT9P012_XCLK_NOM_2 24000000
> +
> +#define MT9P012_USE_XCLKA      0
> +#define MT9P012_USE_XCLKB      1
> +
> +
> +/* FPS Capabilities */
> +#define MT9P012_MIN_FPS                11
> +#define MT9P012_DEF_FPS                15
> +#define MT9P012_MAX_FPS                30
> +
> +#define MT9P012_I2C_DELAY      3
> +#define I2C_RETRY_COUNT                5
> +
> +/* Still capture 5 MP */
> +#define IMAGE_WIDTH_MAX                2592
> +#define IMAGE_HEIGHT_MAX       1944
> +/* Still capture 3 MP and down to VGA, using ISP resizer */
> +#define IMAGE_WIDTH_MIN                2048
> +#define IMAGE_HEIGHT_MIN       1536
> +
> +
> +/* Video mode, for D1 NTSC, D1 PAL */
> +#define VIDEO_WIDTH_2X_BINN    1296
> +#define VIDEO_HEIGHT_2X_BINN   972
> +
> +/* Sensor Video mode size for VGA, CIF, QVGA in 4x binning mode */
> +#define VIDEO_WIDTH_4X_BINN    648
> +#define VIDEO_HEIGHT_4X_BINN   486
> +/* To improve image quality in VGA */
> +#define CIF_PIXELS             (352 * 288)
> +#define QQVGA_PIXELS           (160 * 120)
> +
> +/* Video mode, for QCIF, SQCIF */
> +#define VIDEO_WIDTH_4X_BINN_SCALED      216
> +#define VIDEO_HEIGHT_4X_BINN_SCALED     162
> +
> +/* Default coarse integration times to get a good exposure */
> +#define COARSE_INT_TIME_216             550
> +#define COARSE_INT_TIME_648             550
> +#define COARSE_INT_TIME_216_30FPS      1350
> +#define COARSE_INT_TIME_648_30FPS      1350
> +#define COARSE_INT_TIME_1296           1000
> +#define COARSE_INT_TIME_3MP            1700
> +#define COARSE_INT_TIME_5MP            1700
> +#define COARSE_INT_TIME_INDEX          1
> +#define TST_PAT                        0x0
> +
> +/* Analog gain values */
> +#define MIN_GAIN       0x08
> +#define MAX_GAIN       0x7F
> +#define DEF_GAIN       0x43
> +#define GAIN_STEP      0x1
> +
> +#define GAIN_INDEX     1
> +
> +/* Exposure time values */
> +#define DEF_MIN_EXPOSURE       0x08
> +#define DEF_MAX_EXPOSURE       0x7F
> +#define DEF_EXPOSURE           0x43
> +#define EXPOSURE_STEP          1
> +
> +#define SENSOR_DETECTED                1
> +#define SENSOR_NOT_DETECTED    0
> +
> +/**
> + * struct mt9p012_reg - mt9p012 register format
> + * @length: length of the register
> + * @reg: 16-bit offset to register
> + * @val: 8/16/32-bit register value
> + *
> + * Define a structure for MT9P012 register initialization values
> + */
> +struct mt9p012_reg {
> +       u16     length;
> +       u16     reg;
> +       u32     val;
> +};
> +
> +enum image_size {
> +       BIN4XSCALE,
> +       BIN4X,
> +       BIN2X,
> +       THREE_MP,
> +       FIVE_MP
> +};
> +
> +enum pixel_format {
> +       RAWBAYER10
> +};
> +
> +#define NUM_IMAGE_SIZES                5
> +#define NUM_PIXEL_FORMATS      1
> +#define NUM_FPS                        2       /* 2 ranges */
> +#define FPS_LOW_RANGE          0
> +#define FPS_HIGH_RANGE         1
> +
> +/**
> + * struct capture_size - image capture size information
> + * @width: image width in pixels
> + * @height: image height in pixels
> + */
> +struct capture_size {
> +       unsigned long width;
> +       unsigned long height;
> +};
> +
> +/**
> + * struct mt9p012_platform_data - platform data values and access functions
> + * @power_set: Power state access function, zero is off, non-zero is on.
> + * @default_regs: Default registers written after power-on or reset.
> + * @ifparm: Interface parameters access function
> + * @priv_data_set: device private data (pointer) access function
> + */
> +struct mt9p012_platform_data {
> +       int (*power_set)(enum v4l2_power power);
> +       u32 (*set_xclk)(u32 xclkfreq);
> +       int (*priv_data_set)(void *);
> +};
> +
> +/**
> + * struct mt9p012_pll_settings - struct for storage of sensor pll values
> + * @vt_pix_clk_div: vertical pixel clock divider
> + * @vt_sys_clk_div: veritcal system clock divider
> + * @pre_pll_div: pre pll divider
> + * @fine_int_tm: fine resolution interval time
> + * @frame_lines: number of lines in frame
> + * @line_len: number of pixels in line
> + * @min_pll: minimum pll multiplier
> + * @max_pll: maximum pll multiplier
> + */
> +struct mt9p012_pll_settings {
> +       u16     vt_pix_clk_div;
> +       u16     vt_sys_clk_div;
> +       u16     pre_pll_div;
> +
> +       u16     fine_int_tm;
> +       u16     frame_lines;
> +       u16     line_len;
> +
> +       u16     min_pll;
> +       u16     max_pll;
> +};
> +
> +/*
> + * Array of image sizes supported by MT9P012.  These must be ordered from
> + * smallest image size to largest.
> + */
> +const static struct capture_size mt9p012_sizes[] = {
> +       {  216, 162 },  /* 4X BINNING+SCALING */
> +       {  648, 486 },  /* 4X BINNING */
> +       { 1296, 972 },  /* 2X BINNING */
> +       { 2048, 1536},  /* 3 MP */
> +       { 2592, 1944},  /* 5 MP */
> +};

What's this array doing in this header? Should be in the source.

Please clean up this header: only defines and types used outside the sensor
driver should be here.

Regards,

	Hans

> +
> +/* PLL settings for MT9P012 */
> +enum mt9p012_pll_type {
> +  PLL_5MP = 0,
> +  PLL_3MP,
> +  PLL_1296_15FPS,
> +  PLL_1296_30FPS,
> +  PLL_648_15FPS,
> +  PLL_648_30FPS,
> +  PLL_216_15FPS,
> +  PLL_216_30FPS
> +};
> +
> +#endif /* ifndef MT9P012_H */
> --
> 1.5.6.5
> 
> 
> --
> video4linux-list mailing list
> Unsubscribe mailto:video4linux-list-request@xxxxxxxxxx?subject=unsubscribe
> https://www.redhat.com/mailman/listinfo/video4linux-list
> 
> 



-- 
Hans Verkuil - video4linux developer - sponsored by TANDBERG
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Arm (vger)]     [ARM Kernel]     [ARM MSM]     [Linux Tegra]     [Linux WPAN Networking]     [Linux Wireless Networking]     [Maemo Users]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite Trails]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux