include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / media / video / gspca / sn9c20x.c
index a74c36f..38a6e15 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/freezer.h>
 #include <linux/usb/input.h>
 #include <linux/input.h>
+#include <linux/slab.h>
 #endif
 
 #include "gspca.h"
@@ -94,6 +95,16 @@ struct sd {
 #endif
 };
 
+struct i2c_reg_u8 {
+       u8 reg;
+       u8 val;
+};
+
+struct i2c_reg_u16 {
+       u8 reg;
+       u16 val;
+};
+
 static int sd_setbrightness(struct gspca_dev *gspca_dev, s32 val);
 static int sd_getbrightness(struct gspca_dev *gspca_dev, s32 *val);
 static int sd_setcontrast(struct gspca_dev *gspca_dev, s32 val);
@@ -119,7 +130,7 @@ static int sd_getexposure(struct gspca_dev *gspca_dev, s32 *val);
 static int sd_setautoexposure(struct gspca_dev *gspca_dev, s32 val);
 static int sd_getautoexposure(struct gspca_dev *gspca_dev, s32 *val);
 
-static struct ctrl sd_ctrls[] = {
+static const struct ctrl sd_ctrls[] = {
        {
 #define BRIGHTNESS_IDX 0
            {
@@ -403,7 +414,7 @@ static const struct v4l2_pix_format sxga_mode[] = {
                .priv = 3 | MODE_RAW | MODE_SXGA},
 };
 
-static const int hsv_red_x[] = {
+static const s16 hsv_red_x[] = {
        41,  44,  46,  48,  50,  52,  54,  56,
        58,  60,  62,  64,  66,  68,  70,  72,
        74,  76,  78,  80,  81,  83,  85,  87,
@@ -451,7 +462,7 @@ static const int hsv_red_x[] = {
        24,  26,  28,  30,  33,  35,  37,  39, 41
 };
 
-static const int hsv_red_y[] = {
+static const s16 hsv_red_y[] = {
        82,  80,  78,  76,  74,  73,  71,  69,
        67,  65,  63,  61,  58,  56,  54,  52,
        50,  48,  46,  44,  41,  39,  37,  35,
@@ -499,7 +510,7 @@ static const int hsv_red_y[] = {
        96, 94, 92, 91, 89, 87, 85, 84, 82
 };
 
-static const int hsv_green_x[] = {
+static const s16 hsv_green_x[] = {
        -124, -124, -125, -125, -125, -125, -125, -125,
        -125, -126, -126, -125, -125, -125, -125, -125,
        -125, -124, -124, -124, -123, -123, -122, -122,
@@ -547,7 +558,7 @@ static const int hsv_green_x[] = {
        -120, -120, -121, -122, -122, -123, -123, -124, -124
 };
 
-static const int hsv_green_y[] = {
+static const s16 hsv_green_y[] = {
        -100, -99, -98, -97, -95, -94, -93, -91,
        -90, -89, -87, -86, -84, -83, -81, -80,
        -78, -76, -75, -73, -71, -70, -68, -66,
@@ -595,7 +606,7 @@ static const int hsv_green_y[] = {
        -109, -108, -107, -106, -105, -104, -103, -102, -100
 };
 
-static const int hsv_blue_x[] = {
+static const s16 hsv_blue_x[] = {
        112, 113, 114, 114, 115, 116, 117, 117,
        118, 118, 119, 119, 120, 120, 120, 121,
        121, 121, 122, 122, 122, 122, 122, 122,
@@ -643,7 +654,7 @@ static const int hsv_blue_x[] = {
        104, 105, 106, 107, 108, 109, 110, 111, 112
 };
 
-static const int hsv_blue_y[] = {
+static const s16 hsv_blue_y[] = {
        -11, -13, -15, -17, -19, -21, -23, -25,
        -27, -29, -31, -33, -35, -37, -39, -41,
        -43, -45, -46, -48, -50, -52, -54, -55,
@@ -792,7 +803,7 @@ static u8 hv7131r_gain[] = {
        0x78 /* 8x */
 };
 
-static u8 soi968_init[][2] = {
+static struct i2c_reg_u8 soi968_init[] = {
        {0x12, 0x80}, {0x0c, 0x00}, {0x0f, 0x1f},
        {0x11, 0x80}, {0x38, 0x52}, {0x1e, 0x00},
        {0x33, 0x08}, {0x35, 0x8c}, {0x36, 0x0c},
@@ -806,7 +817,7 @@ static u8 soi968_init[][2] = {
        {0x00, 0x00}, {0x01, 0x80}, {0x02, 0x80},
 };
 
-static u8 ov7660_init[][2] = {
+static struct i2c_reg_u8 ov7660_init[] = {
        {0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
        {0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
        {0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
@@ -815,7 +826,7 @@ static u8 ov7660_init[][2] = {
        {0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
 };
 
-static u8 ov7670_init[][2] = {
+static struct i2c_reg_u8 ov7670_init[] = {
        {0x12, 0x80}, {0x11, 0x80}, {0x3a, 0x04}, {0x12, 0x01},
        {0x32, 0xb6}, {0x03, 0x0a}, {0x0c, 0x00}, {0x3e, 0x00},
        {0x70, 0x3a}, {0x71, 0x35}, {0x72, 0x11}, {0x73, 0xf0},
@@ -872,7 +883,7 @@ static u8 ov7670_init[][2] = {
        {0x93, 0x00},
 };
 
-static u8 ov9650_init[][2] = {
+static struct i2c_reg_u8 ov9650_init[] = {
        {0x12, 0x80}, {0x00, 0x00}, {0x01, 0x78},
        {0x02, 0x78}, {0x03, 0x36}, {0x04, 0x03},
        {0x05, 0x00}, {0x06, 0x00}, {0x08, 0x00},
@@ -902,7 +913,7 @@ static u8 ov9650_init[][2] = {
        {0xaa, 0x92}, {0xab, 0x0a},
 };
 
-static u8 ov9655_init[][2] = {
+static struct i2c_reg_u8 ov9655_init[] = {
        {0x12, 0x80}, {0x12, 0x01}, {0x0d, 0x00}, {0x0e, 0x61},
        {0x11, 0x80}, {0x13, 0xba}, {0x14, 0x2e}, {0x16, 0x24},
        {0x1e, 0x04}, {0x1e, 0x04}, {0x1e, 0x04}, {0x27, 0x08},
@@ -939,7 +950,7 @@ static u8 ov9655_init[][2] = {
        {0x00, 0x03}, {0x00, 0x0a}, {0x00, 0x10}, {0x00, 0x13},
 };
 
-static u16 mt9v112_init[][2] = {
+static struct i2c_reg_u16 mt9v112_init[] = {
        {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0020},
        {0x34, 0xc019}, {0x0a, 0x0011}, {0x0b, 0x000b},
        {0x20, 0x0703}, {0x35, 0x2022}, {0xf0, 0x0001},
@@ -958,7 +969,7 @@ static u16 mt9v112_init[][2] = {
        {0x2c, 0x00ae}, {0x2d, 0x00ae}, {0x2e, 0x00ae},
 };
 
-static u16 mt9v111_init[][2] = {
+static struct i2c_reg_u16 mt9v111_init[] = {
        {0x01, 0x0004}, {0x0d, 0x0001}, {0x0d, 0x0000},
        {0x01, 0x0001}, {0x02, 0x0016}, {0x03, 0x01e1},
        {0x04, 0x0281}, {0x05, 0x0004}, {0x07, 0x3002},
@@ -985,7 +996,7 @@ static u16 mt9v111_init[][2] = {
        {0x0e, 0x0008}, {0x06, 0x002d}, {0x05, 0x0004},
 };
 
-static u16 mt9v011_init[][2] = {
+static struct i2c_reg_u16 mt9v011_init[] = {
        {0x07, 0x0002}, {0x0d, 0x0001}, {0x0d, 0x0000},
        {0x01, 0x0008}, {0x02, 0x0016}, {0x03, 0x01e1},
        {0x04, 0x0281}, {0x05, 0x0083}, {0x06, 0x0006},
@@ -1012,7 +1023,7 @@ static u16 mt9v011_init[][2] = {
        {0x06, 0x0029}, {0x05, 0x0009},
 };
 
-static u16 mt9m001_init[][2] = {
+static struct i2c_reg_u16 mt9m001_init[] = {
        {0x0d, 0x0001}, {0x0d, 0x0000}, {0x01, 0x000e},
        {0x02, 0x0014}, {0x03, 0x03c1}, {0x04, 0x0501},
        {0x05, 0x0083}, {0x06, 0x0006}, {0x0d, 0x0002},
@@ -1025,14 +1036,14 @@ static u16 mt9m001_init[][2] = {
        {0x2e, 0x0029}, {0x07, 0x0002},
 };
 
-static u16 mt9m111_init[][2] = {
-       {0xf0, 0x0000}, {0x0d, 0x0008}, {0x0d, 0x0009},
-       {0x0d, 0x0008}, {0xf0, 0x0001}, {0x3a, 0x4300},
-       {0x9b, 0x4300}, {0xa1, 0x0280}, {0xa4, 0x0200},
-       {0x06, 0x308e}, {0xf0, 0x0000},
+static struct i2c_reg_u16 mt9m111_init[] = {
+       {0xf0, 0x0000}, {0x0d, 0x0021}, {0x0d, 0x0008},
+       {0xf0, 0x0001}, {0x3a, 0x4300}, {0x9b, 0x4300},
+       {0x06, 0x708e}, {0xf0, 0x0002}, {0x2e, 0x0a1e},
+       {0xf0, 0x0000},
 };
 
-static u8 hv7131r_init[][2] = {
+static struct i2c_reg_u8 hv7131r_init[] = {
        {0x02, 0x08}, {0x02, 0x00}, {0x01, 0x08},
        {0x02, 0x00}, {0x20, 0x00}, {0x21, 0xd0},
        {0x22, 0x00}, {0x23, 0x09}, {0x01, 0x08},
@@ -1043,7 +1054,7 @@ static u8 hv7131r_init[][2] = {
        {0x23, 0x09}, {0x01, 0x08},
 };
 
-int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
+static int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
 {
        struct usb_device *dev = gspca_dev->dev;
        int result;
@@ -1062,7 +1073,8 @@ int reg_r(struct gspca_dev *gspca_dev, u16 reg, u16 length)
        return 0;
 }
 
-int reg_w(struct gspca_dev *gspca_dev, u16 reg, const u8 *buffer, int length)
+static int reg_w(struct gspca_dev *gspca_dev, u16 reg,
+                const u8 *buffer, int length)
 {
        struct usb_device *dev = gspca_dev->dev;
        int result;
@@ -1082,13 +1094,13 @@ int reg_w(struct gspca_dev *gspca_dev, u16 reg, const u8 *buffer, int length)
        return 0;
 }
 
-int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
+static int reg_w1(struct gspca_dev *gspca_dev, u16 reg, const u8 value)
 {
        u8 data[1] = {value};
        return reg_w(gspca_dev, reg, data, 1);
 }
 
-int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
+static int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
 {
        int i;
        reg_w(gspca_dev, 0x10c0, buffer, 8);
@@ -1104,7 +1116,7 @@ int i2c_w(struct gspca_dev *gspca_dev, const u8 *buffer)
        return -EIO;
 }
 
-int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
+static int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
@@ -1126,7 +1138,7 @@ int i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val)
        return i2c_w(gspca_dev, row);
 }
 
-int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
+static int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        u8 row[8];
@@ -1147,7 +1159,7 @@ int i2c_w2(struct gspca_dev *gspca_dev, u8 reg, u16 val)
        return i2c_w(gspca_dev, row);
 }
 
-int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
+static int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        u8 row[8];
@@ -1172,7 +1184,7 @@ int i2c_r1(struct gspca_dev *gspca_dev, u8 reg, u8 *val)
        return 0;
 }
 
-int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
+static int i2c_r2(struct gspca_dev *gspca_dev, u8 reg, u16 *val)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        u8 row[8];
@@ -1203,8 +1215,8 @@ static int ov9650_init_sensor(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
 
        for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
-               if (i2c_w1(gspca_dev, ov9650_init[i][0],
-                               ov9650_init[i][1]) < 0) {
+               if (i2c_w1(gspca_dev, ov9650_init[i].reg,
+                               ov9650_init[i].val) < 0) {
                        err("OV9650 sensor initialization failed");
                        return -ENODEV;
                }
@@ -1220,8 +1232,8 @@ static int ov9655_init_sensor(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
 
        for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
-               if (i2c_w1(gspca_dev, ov9655_init[i][0],
-                               ov9655_init[i][1]) < 0) {
+               if (i2c_w1(gspca_dev, ov9655_init[i].reg,
+                               ov9655_init[i].val) < 0) {
                        err("OV9655 sensor initialization failed");
                        return -ENODEV;
                }
@@ -1239,8 +1251,8 @@ static int soi968_init_sensor(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
 
        for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
-               if (i2c_w1(gspca_dev, soi968_init[i][0],
-                               soi968_init[i][1]) < 0) {
+               if (i2c_w1(gspca_dev, soi968_init[i].reg,
+                               soi968_init[i].val) < 0) {
                        err("SOI968 sensor initialization failed");
                        return -ENODEV;
                }
@@ -1258,8 +1270,8 @@ static int ov7660_init_sensor(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
 
        for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
-               if (i2c_w1(gspca_dev, ov7660_init[i][0],
-                               ov7660_init[i][1]) < 0) {
+               if (i2c_w1(gspca_dev, ov7660_init[i].reg,
+                               ov7660_init[i].val) < 0) {
                        err("OV7660 sensor initialization failed");
                        return -ENODEV;
                }
@@ -1277,8 +1289,8 @@ static int ov7670_init_sensor(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
 
        for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
-               if (i2c_w1(gspca_dev, ov7670_init[i][0],
-                               ov7670_init[i][1]) < 0) {
+               if (i2c_w1(gspca_dev, ov7670_init[i].reg,
+                               ov7670_init[i].val) < 0) {
                        err("OV7670 sensor initialization failed");
                        return -ENODEV;
                }
@@ -1301,8 +1313,8 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
        ret = i2c_r2(gspca_dev, 0xff, &value);
        if ((ret == 0) && (value == 0x8243)) {
                for (i = 0; i < ARRAY_SIZE(mt9v011_init); i++) {
-                       if (i2c_w2(gspca_dev, mt9v011_init[i][0],
-                                       mt9v011_init[i][1]) < 0) {
+                       if (i2c_w2(gspca_dev, mt9v011_init[i].reg,
+                                       mt9v011_init[i].val) < 0) {
                                err("MT9V011 sensor initialization failed");
                                return -ENODEV;
                        }
@@ -1319,8 +1331,8 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
        ret = i2c_r2(gspca_dev, 0xff, &value);
        if ((ret == 0) && (value == 0x823a)) {
                for (i = 0; i < ARRAY_SIZE(mt9v111_init); i++) {
-                       if (i2c_w2(gspca_dev, mt9v111_init[i][0],
-                                       mt9v111_init[i][1]) < 0) {
+                       if (i2c_w2(gspca_dev, mt9v111_init[i].reg,
+                                       mt9v111_init[i].val) < 0) {
                                err("MT9V111 sensor initialization failed");
                                return -ENODEV;
                        }
@@ -1341,8 +1353,8 @@ static int mt9v_init_sensor(struct gspca_dev *gspca_dev)
        ret = i2c_r2(gspca_dev, 0x00, &value);
        if ((ret == 0) && (value == 0x1229)) {
                for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
-                       if (i2c_w2(gspca_dev, mt9v112_init[i][0],
-                                       mt9v112_init[i][1]) < 0) {
+                       if (i2c_w2(gspca_dev, mt9v112_init[i].reg,
+                                       mt9v112_init[i].val) < 0) {
                                err("MT9V112 sensor initialization failed");
                                return -ENODEV;
                        }
@@ -1362,12 +1374,13 @@ static int mt9m111_init_sensor(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
        int i;
        for (i = 0; i < ARRAY_SIZE(mt9m111_init); i++) {
-               if (i2c_w2(gspca_dev, mt9m111_init[i][0],
-                               mt9m111_init[i][1]) < 0) {
+               if (i2c_w2(gspca_dev, mt9m111_init[i].reg,
+                               mt9m111_init[i].val) < 0) {
                        err("MT9M111 sensor initialization failed");
                        return -ENODEV;
                }
        }
+       gspca_dev->ctrl_dis = (1 << EXPOSURE_IDX) | (1 << AUTOGAIN_IDX) | (1 << GAIN_IDX);
        sd->hstart = 0;
        sd->vstart = 2;
        return 0;
@@ -1378,8 +1391,8 @@ static int mt9m001_init_sensor(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
        int i;
        for (i = 0; i < ARRAY_SIZE(mt9m001_init); i++) {
-               if (i2c_w2(gspca_dev, mt9m001_init[i][0],
-                               mt9m001_init[i][1]) < 0) {
+               if (i2c_w2(gspca_dev, mt9m001_init[i].reg,
+                               mt9m001_init[i].val) < 0) {
                        err("MT9M001 sensor initialization failed");
                        return -ENODEV;
                }
@@ -1397,8 +1410,8 @@ static int hv7131r_init_sensor(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
 
        for (i = 0; i < ARRAY_SIZE(hv7131r_init); i++) {
-               if (i2c_w1(gspca_dev, hv7131r_init[i][0],
-                               hv7131r_init[i][1]) < 0) {
+               if (i2c_w1(gspca_dev, hv7131r_init[i].reg,
+                               hv7131r_init[i].val) < 0) {
                        err("HV7131R Sensor initialization failed");
                        return -ENODEV;
                }
@@ -1464,8 +1477,9 @@ static int sn9c20x_input_init(struct gspca_dev *gspca_dev)
        if (input_register_device(sd->input_dev))
                return -EINVAL;
 
-       sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%d",
-                                    gspca_dev->vdev.minor);
+       sd->input_task = kthread_run(input_kthread, gspca_dev, "sn9c20x/%s-%s",
+                                    gspca_dev->dev->bus->bus_name,
+                                    gspca_dev->dev->devpath);
 
        if (IS_ERR(sd->input_task))
                return -EINVAL;
@@ -1493,36 +1507,36 @@ static int set_cmatrix(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
        s32 hue_coord, hue_index = 180 + sd->hue;
        u8 cmatrix[21];
-       memset(cmatrix, 0, 21);
 
+       memset(cmatrix, 0, sizeof cmatrix);
        cmatrix[2] = (sd->contrast * 0x25 / 0x100) + 0x26;
        cmatrix[0] = 0x13 + (cmatrix[2] - 0x26) * 0x13 / 0x25;
        cmatrix[4] = 0x07 + (cmatrix[2] - 0x26) * 0x07 / 0x25;
        cmatrix[18] = sd->brightness - 0x80;
 
        hue_coord = (hsv_red_x[hue_index] * sd->saturation) >> 8;
-       cmatrix[6] = (unsigned char)(hue_coord & 0xff);
-       cmatrix[7] = (unsigned char)((hue_coord >> 8) & 0x0f);
+       cmatrix[6] = hue_coord;
+       cmatrix[7] = (hue_coord >> 8) & 0x0f;
 
        hue_coord = (hsv_red_y[hue_index] * sd->saturation) >> 8;
-       cmatrix[8] = (unsigned char)(hue_coord & 0xff);
-       cmatrix[9] = (unsigned char)((hue_coord >> 8) & 0x0f);
+       cmatrix[8] = hue_coord;
+       cmatrix[9] = (hue_coord >> 8) & 0x0f;
 
        hue_coord = (hsv_green_x[hue_index] * sd->saturation) >> 8;
-       cmatrix[10] = (unsigned char)(hue_coord & 0xff);
-       cmatrix[11] = (unsigned char)((hue_coord >> 8) & 0x0f);
+       cmatrix[10] = hue_coord;
+       cmatrix[11] = (hue_coord >> 8) & 0x0f;
 
        hue_coord = (hsv_green_y[hue_index] * sd->saturation) >> 8;
-       cmatrix[12] = (unsigned char)(hue_coord & 0xff);
-       cmatrix[13] = (unsigned char)((hue_coord >> 8) & 0x0f);
+       cmatrix[12] = hue_coord;
+       cmatrix[13] = (hue_coord >> 8) & 0x0f;
 
        hue_coord = (hsv_blue_x[hue_index] * sd->saturation) >> 8;
-       cmatrix[14] = (unsigned char)(hue_coord & 0xff);
-       cmatrix[15] = (unsigned char)((hue_coord >> 8) & 0x0f);
+       cmatrix[14] = hue_coord;
+       cmatrix[15] = (hue_coord >> 8) & 0x0f;
 
        hue_coord = (hsv_blue_y[hue_index] * sd->saturation) >> 8;
-       cmatrix[16] = (unsigned char)(hue_coord & 0xff);
-       cmatrix[17] = (unsigned char)((hue_coord >> 8) & 0x0f);
+       cmatrix[16] = hue_coord;
+       cmatrix[17] = (hue_coord >> 8) & 0x0f;
 
        return reg_w(gspca_dev, 0x10e1, cmatrix, 21);
 }
@@ -1630,7 +1644,6 @@ static int set_exposure(struct gspca_dev *gspca_dev)
                exp[4] = sd->exposure >> 8;
                break;
        case SENSOR_MT9M001:
-       case SENSOR_MT9M111:
        case SENSOR_MT9V112:
        case SENSOR_MT9V111:
        case SENSOR_MT9V011:
@@ -1674,7 +1687,6 @@ static int set_gain(struct gspca_dev *gspca_dev)
                gain[4] = micron1_gain[sd->gain] & 0xff;
                break;
        case SENSOR_MT9V112:
-       case SENSOR_MT9M111:
                gain[0] |= (3 << 4);
                gain[2] = 0x2f;
                gain[3] = micron1_gain[sd->gain] >> 8;
@@ -1995,13 +2007,16 @@ static int sd_config(struct gspca_dev *gspca_dev,
        sd->i2c_addr = id->driver_info & 0xff;
 
        switch (sd->sensor) {
+       case SENSOR_MT9M111:
        case SENSOR_OV9650:
+       case SENSOR_SOI968:
                cam->cam_mode = sxga_mode;
                cam->nmodes = ARRAY_SIZE(sxga_mode);
                break;
        default:
                cam->cam_mode = vga_mode;
                cam->nmodes = ARRAY_SIZE(vga_mode);
+               break;
        }
 
        sd->old_step = 0;
@@ -2111,6 +2126,25 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
        struct sd *sd = (struct sd *) gspca_dev;
        u8 value;
        switch (sd->sensor) {
+       case SENSOR_SOI968:
+               if (mode & MODE_SXGA) {
+                       i2c_w1(gspca_dev, 0x17, 0x1d);
+                       i2c_w1(gspca_dev, 0x18, 0xbd);
+                       i2c_w1(gspca_dev, 0x19, 0x01);
+                       i2c_w1(gspca_dev, 0x1a, 0x81);
+                       i2c_w1(gspca_dev, 0x12, 0x00);
+                       sd->hstart = 140;
+                       sd->vstart = 19;
+               } else {
+                       i2c_w1(gspca_dev, 0x17, 0x13);
+                       i2c_w1(gspca_dev, 0x18, 0x63);
+                       i2c_w1(gspca_dev, 0x19, 0x01);
+                       i2c_w1(gspca_dev, 0x1a, 0x79);
+                       i2c_w1(gspca_dev, 0x12, 0x40);
+                       sd->hstart = 60;
+                       sd->vstart = 11;
+               }
+               break;
        case SENSOR_OV9650:
                if (mode & MODE_SXGA) {
                        i2c_w1(gspca_dev, 0x17, 0x1b);
@@ -2128,12 +2162,22 @@ static void configure_sensor_output(struct gspca_dev *gspca_dev, int mode)
                        i2c_w1(gspca_dev, 0x12, (value & 0x7) | 0x40);
                }
                break;
+       case SENSOR_MT9M111:
+               if (mode & MODE_SXGA) {
+                       i2c_w2(gspca_dev, 0xf0, 0x0002);
+                       i2c_w2(gspca_dev, 0xc8, 0x970b);
+                       i2c_w2(gspca_dev, 0xf0, 0x0000);
+               } else {
+                       i2c_w2(gspca_dev, 0xf0, 0x0002);
+                       i2c_w2(gspca_dev, 0xc8, 0x8000);
+                       i2c_w2(gspca_dev, 0xf0, 0x0000);
+               }
+               break;
        }
 }
 
 #define HW_WIN(mode, hstart, vstart) \
-((const u8 []){hstart & 0xff, hstart >> 8, \
-vstart & 0xff, vstart >> 8, \
+((const u8 []){hstart, 0, vstart, 0, \
 (mode & MODE_SXGA ? 1280 >> 4 : 640 >> 4), \
 (mode & MODE_SXGA ? 1024 >> 3 : 480 >> 3)})
 
@@ -2277,7 +2321,7 @@ static void do_autogain(struct gspca_dev *gspca_dev, u16 avg_lum)
                }
        }
        if (avg_lum > MAX_AVG_LUM) {
-               if (sd->gain - 1 >= 0) {
+               if (sd->gain > 0) {
                        sd->gain--;
                        set_gain(gspca_dev);
                }
@@ -2300,13 +2344,12 @@ static void sd_dqcallback(struct gspca_dev *gspca_dev)
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
-                       struct gspca_frame *frame,      /* target */
                        u8 *data,                       /* isoc packet */
                        int len)                        /* iso packet length */
 {
        struct sd *sd = (struct sd *) gspca_dev;
        int avg_lum;
-       static unsigned char frame_header[] =
+       static u8 frame_header[] =
                {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
        if (len == 64 && memcmp(data, frame_header, 6) == 0) {
                avg_lum = ((data[35] >> 2) & 3) |
@@ -2336,22 +2379,22 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                avg_lum >>= 9;
                atomic_set(&sd->avg_lum, avg_lum);
                gspca_frame_add(gspca_dev, LAST_PACKET,
-                               frame, data, len);
+                               data, len);
                return;
        }
        if (gspca_dev->last_packet_type == LAST_PACKET) {
                if (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv
                                & MODE_JPEG) {
-                       gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
                                sd->jpeg_hdr, JPEG_HDR_SZ);
-                       gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+                       gspca_frame_add(gspca_dev, INTER_PACKET,
                                data, len);
                } else {
-                       gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                       gspca_frame_add(gspca_dev, FIRST_PACKET,
                                data, len);
                }
        } else {
-               gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
+               gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
        }
 }