Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
[pandora-kernel.git] / drivers / media / video / gspca / m5602 / m5602_mt9m111.c
index fb700c2..7d3f9e3 100644 (file)
 
 #include "m5602_mt9m111.h"
 
+static struct v4l2_pix_format mt9m111_modes[] = {
+       {
+               640,
+               480,
+               V4L2_PIX_FMT_SBGGR8,
+               V4L2_FIELD_NONE,
+               .sizeimage = 640 * 480,
+               .bytesperline = 640,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0
+       }
+};
+
+const static struct ctrl mt9m111_ctrls[] = {
+       {
+               {
+                       .id             = V4L2_CID_VFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "vertical flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = mt9m111_set_vflip,
+               .get = mt9m111_get_vflip
+       }, {
+               {
+                       .id             = V4L2_CID_HFLIP,
+                       .type           = V4L2_CTRL_TYPE_BOOLEAN,
+                       .name           = "horizontal flip",
+                       .minimum        = 0,
+                       .maximum        = 1,
+                       .step           = 1,
+                       .default_value  = 0
+               },
+               .set = mt9m111_set_hflip,
+               .get = mt9m111_get_hflip
+       }, {
+               {
+                       .id             = V4L2_CID_GAIN,
+                       .type           = V4L2_CTRL_TYPE_INTEGER,
+                       .name           = "gain",
+                       .minimum        = 0,
+                       .maximum        = (INITIAL_MAX_GAIN - 1) * 2 * 2 * 2,
+                       .step           = 1,
+                       .default_value  = DEFAULT_GAIN,
+                       .flags          = V4L2_CTRL_FLAG_SLIDER
+               },
+               .set = mt9m111_set_gain,
+               .get = mt9m111_get_gain
+       }
+};
+
+
+static void mt9m111_dump_registers(struct sd *sd);
+
 int mt9m111_probe(struct sd *sd)
 {
        u8 data[2] = {0x00, 0x00};
@@ -44,12 +101,12 @@ int mt9m111_probe(struct sd *sd)
                } else {
                        data[0] = preinit_mt9m111[i][2];
                        data[1] = preinit_mt9m111[i][3];
-                       mt9m111_write_sensor(sd,
+                       m5602_write_sensor(sd,
                                preinit_mt9m111[i][1], data, 2);
                }
        }
 
-       if (mt9m111_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
+       if (m5602_read_sensor(sd, MT9M111_SC_CHIPVER, data, 2))
                return -ENODEV;
 
        if ((data[0] == 0x14) && (data[1] == 0x3a)) {
@@ -60,10 +117,10 @@ int mt9m111_probe(struct sd *sd)
        return -ENODEV;
 
 sensor_found:
-       sd->gspca_dev.cam.cam_mode = mt9m111.modes;
-       sd->gspca_dev.cam.nmodes = mt9m111.nmodes;
-       sd->desc->ctrls = mt9m111.ctrls;
-       sd->desc->nctrls = mt9m111.nctrls;
+       sd->gspca_dev.cam.cam_mode = mt9m111_modes;
+       sd->gspca_dev.cam.nmodes = ARRAY_SIZE(mt9m111_modes);
+       sd->desc->ctrls = mt9m111_ctrls;
+       sd->desc->nctrls = ARRAY_SIZE(mt9m111_ctrls);
        return 0;
 }
 
@@ -72,7 +129,7 @@ int mt9m111_init(struct sd *sd)
        int i, err = 0;
 
        /* Init the sensor */
-       for (i = 0; i < ARRAY_SIZE(init_mt9m111); i++) {
+       for (i = 0; i < ARRAY_SIZE(init_mt9m111) && !err; i++) {
                u8 data[2];
 
                if (init_mt9m111[i][0] == BRIDGE) {
@@ -82,7 +139,7 @@ int mt9m111_init(struct sd *sd)
                } else {
                        data[0] = init_mt9m111[i][2];
                        data[1] = init_mt9m111[i][3];
-                       err = mt9m111_write_sensor(sd,
+                       err = m5602_write_sensor(sd,
                                init_mt9m111[i][1], data, 2);
                }
        }
@@ -104,12 +161,12 @@ int mt9m111_get_vflip(struct gspca_dev *gspca_dev, __s32 *val)
        u8 data[2] = {0x00, 0x00};
        struct sd *sd = (struct sd *) gspca_dev;
 
-       err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+       err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
                                  data, 2);
        *val = data[0] & MT9M111_RMB_MIRROR_ROWS;
        PDEBUG(D_V4L2, "Read vertical flip %d", *val);
 
-       return (err < 0) ? err : 0;
+       return err;
 }
 
 int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -121,19 +178,18 @@ int mt9m111_set_vflip(struct gspca_dev *gspca_dev, __s32 val)
        PDEBUG(D_V4L2, "Set vertical flip to %d", val);
 
        /* Set the correct page map */
-       err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+       err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
        if (err < 0)
-               goto out;
+               return err;
 
-       err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+       err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
        if (err < 0)
-               goto out;
+               return err;
 
        data[0] = (data[0] & 0xfe) | val;
-       err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+       err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
                                   data, 2);
-out:
-       return (err < 0) ? err : 0;
+       return err;
 }
 
 int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
@@ -142,12 +198,12 @@ int mt9m111_get_hflip(struct gspca_dev *gspca_dev, __s32 *val)
        u8 data[2] = {0x00, 0x00};
        struct sd *sd = (struct sd *) gspca_dev;
 
-       err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+       err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
                                  data, 2);
        *val = data[0] & MT9M111_RMB_MIRROR_COLS;
        PDEBUG(D_V4L2, "Read horizontal flip %d", *val);
 
-       return (err < 0) ? err : 0;
+       return err;
 }
 
 int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
@@ -159,19 +215,18 @@ int mt9m111_set_hflip(struct gspca_dev *gspca_dev, __s32 val)
        PDEBUG(D_V4L2, "Set horizontal flip to %d", val);
 
        /* Set the correct page map */
-       err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+       err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
        if (err < 0)
-               goto out;
+               return err;
 
-       err = mt9m111_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
+       err = m5602_read_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B, data, 2);
        if (err < 0)
-               goto out;
+               return err;
 
        data[0] = (data[0] & 0xfd) | ((val << 1) & 0x02);
-       err = mt9m111_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
+       err = m5602_write_sensor(sd, MT9M111_SC_R_MODE_CONTEXT_B,
                                        data, 2);
-out:
-       return (err < 0) ? err : 0;
+       return err;
 }
 
 int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
@@ -180,7 +235,7 @@ int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
        u8 data[2] = {0x00, 0x00};
        struct sd *sd = (struct sd *) gspca_dev;
 
-       err = mt9m111_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
+       err = m5602_read_sensor(sd, MT9M111_SC_GLOBAL_GAIN, data, 2);
        tmp = ((data[1] << 8) | data[0]);
 
        *val = ((tmp & (1 << 10)) * 2) |
@@ -190,7 +245,7 @@ int mt9m111_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
 
        PDEBUG(D_V4L2, "Read gain %d", *val);
 
-       return (err < 0) ? err : 0;
+       return err;
 }
 
 int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
@@ -200,9 +255,9 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
        struct sd *sd = (struct sd *) gspca_dev;
 
        /* Set the correct page map */
-       err = mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
+       err = m5602_write_sensor(sd, MT9M111_PAGE_MAP, data, 2);
        if (err < 0)
-               goto out;
+               return err;
 
        if (val >= INITIAL_MAX_GAIN * 2 * 2 * 2)
                return -EINVAL;
@@ -225,90 +280,13 @@ int mt9m111_set_gain(struct gspca_dev *gspca_dev, __s32 val)
        PDEBUG(D_V4L2, "tmp=%d, data[1]=%d, data[0]=%d", tmp,
               data[1], data[0]);
 
-       err = mt9m111_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
+       err = m5602_write_sensor(sd, MT9M111_SC_GLOBAL_GAIN,
                                   data, 2);
-out:
-       return (err < 0) ? err : 0;
-}
-
-int mt9m111_read_sensor(struct sd *sd, const u8 address,
-                       u8 *i2c_data, const u8 len) {
-       int err, i;
-
-       do {
-               err = m5602_read_bridge(sd, M5602_XB_I2C_STATUS, i2c_data);
-       } while ((*i2c_data & I2C_BUSY) && !err);
-       if (err < 0)
-               goto out;
-
-       err = m5602_write_bridge(sd, M5602_XB_I2C_DEV_ADDR,
-                                sd->sensor->i2c_slave_id);
-       if (err < 0)
-               goto out;
-
-       err = m5602_write_bridge(sd, M5602_XB_I2C_REG_ADDR, address);
-       if (err < 0)
-               goto out;
 
-       err = m5602_write_bridge(sd, M5602_XB_I2C_CTRL, 0x1a);
-       if (err < 0)
-               goto out;
-
-       for (i = 0; i < len && !err; i++) {
-               err = m5602_read_bridge(sd, M5602_XB_I2C_DATA, &(i2c_data[i]));
-
-               PDEBUG(D_CONF, "Reading sensor register "
-                      "0x%x contains 0x%x ", address, *i2c_data);
-       }
-out:
-       return (err < 0) ? err : 0;
-}
-
-int mt9m111_write_sensor(struct sd *sd, const u8 address,
-                               u8 *i2c_data, const u8 len)
-{
-       int err, i;
-       u8 *p;
-       struct usb_device *udev = sd->gspca_dev.dev;
-       __u8 *buf = sd->gspca_dev.usb_buf;
-
-       /* No sensor with a data width larger
-          than 16 bits has yet been seen, nor with 0 :p*/
-       if (len > 2 || !len)
-               return -EINVAL;
-
-       memcpy(buf, sensor_urb_skeleton,
-              sizeof(sensor_urb_skeleton));
-
-       buf[11] = sd->sensor->i2c_slave_id;
-       buf[15] = address;
-
-       p = buf + 16;
-
-       /* Copy a four byte write sequence for each byte to be written to */
-       for (i = 0; i < len; i++) {
-               memcpy(p, sensor_urb_skeleton + 16, 4);
-               p[3] = i2c_data[i];
-               p += 4;
-               PDEBUG(D_CONF, "Writing sensor register 0x%x with 0x%x",
-                      address, i2c_data[i]);
-       }
-
-       /* Copy the tailer */
-       memcpy(p, sensor_urb_skeleton + 20, 4);
-
-       /* Set the total length */
-       p[3] = 0x10 + len;
-
-       err = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
-                             0x04, 0x40, 0x19,
-                             0x0000, buf,
-                             20 + len * 4, M5602_URB_MSG_TIMEOUT);
-
-       return (err < 0) ? err : 0;
+       return err;
 }
 
-void mt9m111_dump_registers(struct sd *sd)
+static void mt9m111_dump_registers(struct sd *sd)
 {
        u8 address, value[2] = {0x00, 0x00};
 
@@ -316,27 +294,27 @@ void mt9m111_dump_registers(struct sd *sd)
 
        info("Dumping the mt9m111 sensor core registers");
        value[1] = MT9M111_SENSOR_CORE;
-       mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+       m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
        for (address = 0; address < 0xff; address++) {
-               mt9m111_read_sensor(sd, address, value, 2);
+               m5602_read_sensor(sd, address, value, 2);
                info("register 0x%x contains 0x%x%x",
                     address, value[0], value[1]);
        }
 
        info("Dumping the mt9m111 color pipeline registers");
        value[1] = MT9M111_COLORPIPE;
-       mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+       m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
        for (address = 0; address < 0xff; address++) {
-               mt9m111_read_sensor(sd, address, value, 2);
+               m5602_read_sensor(sd, address, value, 2);
                info("register 0x%x contains 0x%x%x",
                     address, value[0], value[1]);
        }
 
        info("Dumping the mt9m111 camera control registers");
        value[1] = MT9M111_CAMERA_CONTROL;
-       mt9m111_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
+       m5602_write_sensor(sd, MT9M111_PAGE_MAP, value, 2);
        for (address = 0; address < 0xff; address++) {
-               mt9m111_read_sensor(sd, address, value, 2);
+               m5602_read_sensor(sd, address, value, 2);
                info("register 0x%x contains 0x%x%x",
                     address, value[0], value[1]);
        }