We had some problems with sensor probing and decided to use a new procdure.

Here is my second try to solve that.

The first two paches are not vital but I didn't want to rebase.

It currently breaks the module since I have no idea how to assign the correct formats and resolutions. I also remeber Brian had developed a new system for to make YUV422 work. Maybe we can include this right now.

Let's get this over done.

GWater
From 805eb0cd70a4fb7e3fd9d624f4c5a918b9ea133a Mon Sep 17 00:00:00 2001
From: GWater <[EMAIL PROTECTED]>
Date: Sat, 15 Nov 2008 14:09:12 +0100
Subject: [PATCH] Add YUV422-output for MT9V111 sensors

Signed-off-by: GWater <[EMAIL PROTECTED]>
---
 micron.c |   42 +++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 41 insertions(+), 1 deletions(-)

diff --git a/micron.c b/micron.c
index cc70fec..d263cbe 100644
--- a/micron.c
+++ b/micron.c
@@ -71,7 +71,13 @@ struct microdia_video_format mt9v111_fmts[] = {
                .pix_fmt = V4L2_PIX_FMT_SBGGR8,
                .desc = "Bayer 8bit (BGGR)",
                .depth = 8,
-               .set_format = sn9c20x_set_raw
+               .set_format = mt9v111_set_raw
+       },
+       {
+               .pix_fmt = V4L2_PIX_FMT_YUYV,
+               .desc = "YUV 4:2:2",
+               .depth = 16,
+               .set_format = mt9v111_set_yuv422
        },
        {
                .pix_fmt = V4L2_PIX_FMT_JPEG,
@@ -597,6 +603,40 @@ int mt9v111_probe(struct usb_microdia *dev)
        return -EINVAL;
 }
 
+int mt9v111_set_raw(struct usb_microdia *dev)
+{
+       __u16 buf;
+
+       mt9v111_select_address_space(dev, MT9V111_ADDRESSSPACE_IFP);
+
+       sn9c20x_read_i2c_data16(dev, 1, 0x08, &buf);
+       buf = (buf & 0xef7f) + 0x1080;
+       sn9c20x_write_i2c_data16(dev, 1, 0x08, &buf);
+
+       sn9c20x_set_raw(dev);
+
+       return 0;
+}
+
+int mt9v111_set_yuv422(struct usb_microdia *dev)
+{
+       __u16 buf;
+
+       mt9v111_select_address_space(dev, MT9V111_ADDRESSSPACE_IFP);
+
+       sn9c20x_read_i2c_data16(dev, 1, 0x08, &buf);
+       buf &= 0xef7f;
+       sn9c20x_write_i2c_data16(dev, 1, 0x08, &buf);
+
+       sn9c20x_read_i2c_data16(dev, 1, 0x3a, &buf);
+       buf &= 0xffde;
+       sn9c20x_write_i2c_data16(dev, 1, 0x3a, &buf);
+
+       sn9c20x_set_raw(dev);
+
+       return 0;
+}
+
 /**
  * @brief Initialize mt9m111 sensors
  *
-- 
1.5.6.5

From ebaf7d2cba2738962877eb961916a71db3577aa7 Mon Sep 17 00:00:00 2001
From: GWater <[EMAIL PROTECTED]>
Date: Fri, 14 Nov 2008 19:14:27 +0100
Subject: [PATCH] Add sensor MT9V112 used in 6270 devices

        The sensor supports YUV442 and 10-bit Bayer output.
        JPEG is available via sn9c20x.
        However YUV422 output is disabled until we get it to work.

Signed-off-by: GWater <[EMAIL PROTECTED]>
---
 microdia-dev.c |    6 ++++
 microdia.h     |    1 +
 micron.c       |   72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 micron.h       |    2 +
 4 files changed, 79 insertions(+), 2 deletions(-)

diff --git a/microdia-dev.c b/microdia-dev.c
index f3cdf4d..a233ab9 100644
--- a/microdia-dev.c
+++ b/microdia-dev.c
@@ -88,6 +88,12 @@ struct sensor_info sensors[] = {
                .address = 0x5d,
                .probe = mt9m001_probe
        },
+       {
+               .id = MT9V112_SENSOR,
+               .name = "MT9V112",
+               .address = 0x5d,
+               .probe = mt9v112_probe
+       },
 };
 
 /**
diff --git a/microdia.h b/microdia.h
index 09f3e9f..6f18e09 100644
--- a/microdia.h
+++ b/microdia.h
@@ -311,6 +311,7 @@ enum microdia_sensors {
        MT9V111_SENSOR          = 7,
        MT9V011_SENSOR          = 8,
        MT9M001_SENSOR          = 9,
+       MT9V112_SENSOR          = 10,
 };
 
 
diff --git a/micron.c b/micron.c
index d263cbe..57c113f 100644
--- a/micron.c
+++ b/micron.c
@@ -52,12 +52,12 @@ struct microdia_video_format mt9m111_fmts[] = {
                .depth = 8,
                .set_format = mt9m111_set_raw
        },
-       {
+       /*{
                .pix_fmt = V4L2_PIX_FMT_YUYV,
                .desc = "YUV 4:2:2",
                .depth = 16,
                .set_format = mt9m111_set_yuv422
-       },
+       },*/
        {
                .pix_fmt = V4L2_PIX_FMT_JPEG,
                .desc = "JPEG (YUV 4:2:2)",
@@ -425,6 +425,74 @@ static __u8 mt9m001_init[][3] = {
        {0x2e, 0x00, 0x24}, {0x07, 0x00, 0x02},
 };
 
+static __u8 mt9v112_init[][3] = {
+       {0x0d, 0x00, 0x21}, {0x0d, 0x00, 0x20}, {0xf0, 0x00, 0x00},
+       {0x34, 0xc0, 0x19}, {0x0a, 0x00, 0x11}, {0x0b, 0x00, 0x0b},
+       {0x20, 0x07, 0x03}, {0x35, 0x20, 0x22}, {0xf0, 0x00, 0x01},
+       {0x05, 0x00, 0x00}, {0x06, 0x34, 0x0c}, {0x3b, 0x04, 0x2a},
+       {0x3c, 0x04, 0x00}, {0xf0, 0x00, 0x02}, {0x2e, 0x0c, 0x58},
+       {0x5b, 0x00, 0x01}, {0xc8, 0x9f, 0x0b}, {0xf0, 0x00, 0x01},
+       {0x9b, 0x53, 0x00}, {0xf0, 0x00, 0x00}, {0x2b, 0x00, 0x20},
+       {0x2c, 0x00, 0x2a}, {0x2d, 0x00, 0x32}, {0x2e, 0x00, 0x20},
+       {0x09, 0x01, 0xdc}, {0x01, 0x00, 0x0c}, {0x02, 0x00, 0x20},
+       {0x03, 0x01, 0xe0}, {0x04, 0x02, 0x80}, {0x06, 0x00, 0x0c},
+       {0x05, 0x00, 0x98}, {0x20, 0x07, 0x03}, {0x09, 0x01, 0xf2},
+       {0x2b, 0x00, 0xa0}, {0x2c, 0x00, 0xa0}, {0x2d, 0x00, 0xa0},
+       {0x2e, 0x00, 0xa0}, {0x01, 0x00, 0x0c}, {0x02, 0x00, 0x20},
+       {0x03, 0x01, 0xe0}, {0x04, 0x02, 0x80}, {0x06, 0x00, 0x0c},
+       {0x05, 0x00, 0x98}, {0x09, 0x01, 0xc1}, {0x2b, 0x00, 0xae},
+       {0x2c, 0x00, 0xae}, {0x2d, 0x00, 0xae}, {0x2e, 0x00, 0xae},
+};
+
+/**
+ * @brief Initialize mt9v112 sensors
+ *
+ * @param dev Pointer to device structure
+ *
+ * @return 0 or negative error code
+ *
+ */
+int  mt9v112_initialize(struct usb_microdia *dev)
+{
+       int i;
+       int ret = 0;
+       __u8 value[2], reg;
+       for (i = 0; i < ARRAY_SIZE(mt9v112_init); i++) {
+               reg = mt9v011_init[i][0];
+               value[0] = mt9v112_init[i][1];
+               value[1] = mt9v112_init[i][2];
+               ret = sn9c20x_write_i2c_data(dev, 2, reg, value);
+               if (ret < 0) {
+                       UDIA_WARNING("Sensor Init Error (%d). "
+                               "line %d\n", ret, i);
+                       break;
+               }
+       }
+
+       return ret;
+}
+
+int mt9v112_probe(struct usb_microdia *dev)
+{
+       int ret;
+       __u8 buf[2];
+       ret = sn9c20x_read_i2c_data(dev, 2, 0x00, buf);
+       if (ret == 0) {
+               if (buf[0] != 0x12)
+                       return -EINVAL;
+               if (buf[1] == 0x29) {
+                       mt9v112_initialize(dev);
+                       dev->camera.modes = micron_resolutions;
+                       dev->camera.nmodes = ARRAY_SIZE(micron_resolutions);
+                       dev->camera.fmts = mt9m111_fmts;
+                       dev->camera.nfmts = ARRAY_SIZE(mt9m111_fmts);
+                       return MT9V112_SENSOR;
+               }
+       }
+
+       return -EINVAL;
+}
+
 /**
  * @brief Initialize mt9v011 sensors
  *
diff --git a/micron.h b/micron.h
index 4e2ee99..1955e5e 100644
--- a/micron.h
+++ b/micron.h
@@ -121,4 +121,6 @@ int mt9m111_set_yuv422(struct usb_microdia *dev);
 
 int mt9m001_probe(struct usb_microdia *dev);
 
+int mt9v112_probe(struct usb_microdia *dev);
+
 #endif
-- 
1.5.6.5

From 0a2f7fd94cd882d78980e388434214df8620cd0e Mon Sep 17 00:00:00 2001
From: GWater <[EMAIL PROTECTED]>
Date: Sat, 22 Nov 2008 13:39:43 +0100
Subject: [PATCH] New system regarding sensor assignment

        Sensors are now assigned using the dev_microdia_assign_sensor() 
function.

        Initilization is seperated from that and probing has been removed.

        FIXME:
        - No support for 6270 and 62b0. These need probing.
        - Resolutions and Formats are not geing assigned.
          Therefore this patch temporarily breaks video capture.

Signed-off-by: GWater <[EMAIL PROTECTED]>
---
 microdia-dev.c |  135 +++++++++++++++++++++++++++++++++++--------------------
 microdia.h     |   29 +++++++-----
 micron.c       |   54 ----------------------
 micron.h       |    5 +-
 omnivision.c   |  122 ++++++++++++++++++++------------------------------
 omnivision.h   |    3 +-
 sn9c20x.c      |   57 ++++++++++--------------
 7 files changed, 178 insertions(+), 227 deletions(-)

diff --git a/microdia-dev.c b/microdia-dev.c
index a233ab9..f915272 100644
--- a/microdia-dev.c
+++ b/microdia-dev.c
@@ -38,64 +38,127 @@ struct sensor_info sensors[] = {
                .id = OV9650_SENSOR,
                .name = "OV9650",
                .address = 0x30,
-               .probe = ov_probe
+               .initialize = ov_initialize,
+               .set_hvflip = ov965x_set_hvflip,
+               .set_exposure = ov965x_set_exposure,
+               .set_auto_exposure = ov965x_set_autoexposure,
+               .flip_detect = ov965x_flip_detect,
        },
        {
                .id = OV9655_SENSOR,
                .name = "OV9655",
                .address = 0x30,
-               .probe = ov_probe
+               .initialize = ov_initialize,
        },
        {
                .id = SOI968_SENSOR,
                .name = "SOI968",
                .address = 0x30,
-               .probe = ov_probe
+               .initialize = ov_initialize,
+               .set_exposure = soi968_set_exposure,
+               .set_auto_exposure = ov965x_set_autoexposure,
        },
        {
                .id = OV7660_SENSOR,
                .name = "OV7660",
                .address = 0x21,
-               .probe = ov_probe
+               .initialize = ov_initialize,
+               .set_exposure = ov7660_set_exposure,
+               .set_auto_exposure = ov7660_set_autoexposure,
        },
        {
                .id = OV7670_SENSOR,
                .name = "OV7670",
                .address = 0x21,
-               .probe = ov_probe
-       },
-       {
-               .id = MT9M111_SENSOR,
-               .name = "MT9M111",
-               .address = 0x5d,
-               .probe = mt9m111_probe
+               .initialize = ov_initialize,
+               .flip_detect = ov7670_flip_detect,
        },
        {
                .id = MT9V111_SENSOR,
                .name = "MT9V111",
                .address = 0x5c,
-               .probe = mt9v111_probe
+               .initialize = mt9v111_initialize,
+               .set_hvflip = mt9v111_set_hvflip,
+               .set_exposure = mt9v111_set_exposure,
+               .set_auto_exposure = mt9v111_set_autoexposure,
+       },
+       {
+               .id = MT9M111_SENSOR,
+               .name = "MT9M111",
+               .address = 0x5d,
+               .initialize = mt9m111_initialize,
        },
        {
                .id = MT9V011_SENSOR,
                .name = "MT9V011",
                .address = 0x5d,
-               .probe = mt9v011_probe
+               .initialize = mt9v011_initialize,
+               .set_hvflip = mt9v011_set_hvflip,
+               .set_exposure = mt9v011_set_exposure,
        },
        {
                .id = MT9M001_SENSOR,
                .name = "MT9M001",
                .address = 0x5d,
-               .probe = mt9m001_probe
+               .initialize = mt9m001_initialize,
        },
        {
                .id = MT9V112_SENSOR,
                .name = "MT9V112",
                .address = 0x5d,
-               .probe = mt9v112_probe
+               .initialize = mt9v112_initialize,
        },
 };
 
+static __u16 known_cams[][2] = {
+       {0x6240, MT9M001_SENSOR},
+       {0x6242, MT9M111_SENSOR},
+       {0x6248, OV9655_SENSOR},
+       {0x624e, SOI968_SENSOR},
+       {0x624f, OV9650_SENSOR},
+       {0x6253, OV9650_SENSOR},
+       {0x6260, OV7670_SENSOR},
+       {0x627b, OV7660_SENSOR},
+       {0x627f, OV9650_SENSOR},
+       {0x6288, OV9655_SENSOR},
+       {0x628e, SOI968_SENSOR},
+       {0x62a0, OV7670_SENSOR},
+       {0x62b3, OV9655_SENSOR},
+       {0x62bb, OV7660_SENSOR},
+};
+
+int dev_microdia_assign_sensor(struct usb_microdia *dev)
+{
+       int i, j;
+       __u16 pid = le16_to_cpu(dev->udev->descriptor.idProduct);
+
+       /* FIXME: For 6270 and 62b0 perform probe */
+
+       for (i = 0; i < ARRAY_SIZE(known_cams); i++) {
+               if (pid == known_cams[i][0]) {
+                       for (j = 0; j < ARRAY_SIZE(sensors); j++) {
+                               if (known_cams[i][1] == sensors[j].id) {
+                                       dev->camera.sensor = &sensors[j];
+                                       return 0;
+                               }
+                       }
+               }
+       }
+
+       UDIA_ERROR("Could not assign sensor: "
+               "Please report to [email protected] .\n");
+
+       return -EINVAL;
+}
+
+int dev_microdia_initialize_sensor(struct usb_microdia *dev)
+{
+       int ret = -ENODEV;
+       if (dev && dev->camera.sensor->initialize)
+               ret = dev->camera.sensor->initialize(dev);
+       return ret;
+}
+
 /**
  * @brief Wrapper function for camera-setting functions
  *
@@ -175,8 +238,8 @@ int dev_microdia_camera_set_gamma(struct usb_microdia *dev)
  */
 int dev_microdia_camera_set_exposure(struct usb_microdia *dev)
 {
-       if (dev && dev->camera.set_exposure != NULL)
-               return dev->camera.set_exposure(dev);
+       if (dev && dev->camera.sensor->set_exposure != NULL)
+               return dev->camera.sensor->set_exposure(dev);
 
        return 0;
 }
@@ -192,8 +255,8 @@ int dev_microdia_camera_set_exposure(struct usb_microdia 
*dev)
 int dev_microdia_camera_set_hvflip(struct usb_microdia *dev)
 {
        int ret = -ENODEV;
-       if (dev && dev->camera.set_hvflip)
-               ret = dev->camera.set_hvflip(dev);
+       if (dev && dev->camera.sensor->set_hvflip)
+               ret = dev->camera.sensor->set_hvflip(dev);
 
        return ret;
 }
@@ -243,8 +306,8 @@ int dev_microdia_camera_set_rgb_gain(struct usb_microdia 
*dev)
 int dev_microdia_camera_set_auto_exposure(struct usb_microdia *dev)
 {
        int ret = -ENODEV;
-       if (dev && dev->camera.set_auto_exposure)
-               ret = dev->camera.set_auto_exposure(dev);
+       if (dev && dev->camera.sensor->set_auto_exposure)
+               ret = dev->camera.sensor->set_auto_exposure(dev);
 
        return ret;
 }
@@ -260,39 +323,13 @@ int dev_microdia_camera_set_auto_exposure(struct 
usb_microdia *dev)
 int dev_microdia_camera_set_auto_whitebalance(struct usb_microdia *dev)
 {
        int ret = -ENODEV;
-       if (dev && dev->camera.set_auto_whitebalance)
-               ret = dev->camera.set_auto_whitebalance(dev);
+       if (dev && dev->camera.sensor->set_auto_whitebalance)
+               ret = dev->camera.sensor->set_auto_whitebalance(dev);
 
        return ret;
 }
 
 /**
- * @brief function to probe sensor attached to bridge
- *
- * @param dev pointer to device structure
- *
- * @returns 0 or negative error value
- *
- * This function will probe the bridge for the proper sensor
- */
-int dev_microdia_probe_sensor(struct usb_microdia *dev)
-{
-       int i, ret;
-       dev->camera.sensor_flags = SN9C20X_I2C_2WIRE;
-
-       for (i = 0; i < ARRAY_SIZE(sensors); i++) {
-               dev->camera.sensor_slave_address = sensors[i].address;
-               ret = sensors[i].probe(dev);
-               if (ret == sensors[i].id) {
-                       UDIA_INFO("Detected sensor: %s\n", sensors[i].name);
-                       return ret;
-               }
-       }
-
-       return UNKNOWN_SENSOR;
-}
-
-/**
  * @brief Wrapper function for device-specific initialization functions
  *
  * @param dev Pointer to device structure
diff --git a/microdia.h b/microdia.h
index 6f18e09..bf05203 100644
--- a/microdia.h
+++ b/microdia.h
@@ -336,17 +336,20 @@ struct sensor_info {
        __u8 id;
        __u8 *name;
        __u8 address;
-       int (*probe) (struct usb_microdia *dev);
+
+/* sensor specific functions */
+       int (*initialize) (struct usb_microdia *dev);
+       int (*set_exposure) (struct usb_microdia *dev);
+       int (*set_auto_exposure) (struct usb_microdia *dev);
+       int (*set_auto_whitebalance) (struct usb_microdia *dev);
+       int (*flip_detect) (struct usb_microdia *dev);
+       int (*set_hvflip) (struct usb_microdia *dev);
 };
 
 extern struct sensor_info sensors[];
 
 struct microdia_camera {
 
-       __u8 sensor_slave_address;
-       __u8 sensor_flags;
-       __u8 sensor;
-
 /* supported resolutions */
        __u8 nmodes;
        struct microdia_video_resolution *modes;
@@ -354,22 +357,21 @@ struct microdia_camera {
        __u8 nfmts;
        struct microdia_video_format *fmts;
 
+/* image sensor */
+       struct sensor_info *sensor;
+
+/* SCCB/I2C interface */
+       __u8 i2c_flags;
+
 /* bridge functions */
-       int (*initialize) (struct usb_microdia *dev);
        int (*enable_video) (struct usb_microdia *dev, int enable);
 
 /* image quality functions */
-
        int (*set_contrast) (struct usb_microdia *dev);
        int (*set_brightness) (struct usb_microdia *dev);
        int (*set_gamma) (struct usb_microdia *dev);
-       int (*set_exposure) (struct usb_microdia *dev);
-       int (*flip_detect) (struct usb_microdia *dev);
-       int (*set_hvflip) (struct usb_microdia *dev);
        int (*set_sharpness) (struct usb_microdia *dev);
        int (*set_rgb_gain) (struct usb_microdia *dev);
-       int (*set_auto_exposure) (struct usb_microdia *dev);
-       int (*set_auto_whitebalance) (struct usb_microdia *dev);
 };
 
 /**
@@ -425,7 +427,8 @@ void usb_microdia_delete(struct kref *);
 
 
 int dev_microdia_initialize_device(struct usb_microdia *, __u32 flags);
-int dev_microdia_probe_sensor(struct usb_microdia *);
+int dev_microdia_assign_sensor(struct usb_microdia *dev);
+int dev_microdia_initialize_sensor(struct usb_microdia *dev);
 int dev_microdia_enable_video(struct usb_microdia *, int);
 int dev_microdia_camera_settings(struct usb_microdia *);
 int dev_microdia_camera_set_contrast(struct usb_microdia *);
diff --git a/micron.c b/micron.c
index 57c113f..512bd80 100644
--- a/micron.c
+++ b/micron.c
@@ -481,7 +481,6 @@ int mt9v112_probe(struct usb_microdia *dev)
                if (buf[0] != 0x12)
                        return -EINVAL;
                if (buf[1] == 0x29) {
-                       mt9v112_initialize(dev);
                        dev->camera.modes = micron_resolutions;
                        dev->camera.nmodes = ARRAY_SIZE(micron_resolutions);
                        dev->camera.fmts = mt9m111_fmts;
@@ -565,9 +564,6 @@ int mt9v011_probe(struct usb_microdia *dev)
                if (buf[0] != 0x82)
                        return -EINVAL;
                if (buf[1] == 0x43) {
-                       mt9v011_initialize(dev);
-                       dev->camera.set_hvflip = mt9v011_set_hvflip;
-                       dev->camera.set_exposure = mt9v011_set_exposure;
                        dev->camera.modes = micron_resolutions;
                        dev->camera.nmodes = ARRAY_SIZE(micron_resolutions);
                        dev->camera.fmts = mt9x0xx_fmts;
@@ -654,10 +650,6 @@ int mt9v111_probe(struct usb_microdia *dev)
                if (buf[0] != 0x82)
                        return -EINVAL;
                if (buf[1] == 0x3a) {
-                       mt9v111_initialize(dev);
-                       dev->camera.set_hvflip = mt9v111_set_hvflip;
-                       dev->camera.set_exposure = mt9v111_set_exposure;
-                       dev->camera.set_auto_exposure = 
mt9v111_set_autoexposure;
                        dev->camera.modes = micron_resolutions;
                        dev->camera.nmodes = ARRAY_SIZE(micron_resolutions);
                        dev->camera.fmts = mt9v111_fmts;
@@ -734,27 +726,6 @@ int mt9m001_initialize(struct usb_microdia *dev)
        return ret;
 }
 
-int mt9m001_probe(struct usb_microdia *dev)
-{
-       int ret;
-       __u8 buf[2];
-       ret = sn9c20x_read_i2c_data(dev, 2, 0x00, buf);
-       if (ret == 0) {
-               if (buf[0] != 0x84)
-                       return -EINVAL;
-               if (buf[1] == 0x31) {
-                       mt9m001_initialize(dev);
-                       dev->camera.modes = micron_resolutions;
-                       dev->camera.nmodes = ARRAY_SIZE(micron_resolutions);
-                       dev->camera.fmts = mt9x0xx_fmts;
-                       dev->camera.nfmts = ARRAY_SIZE(mt9x0xx_fmts);
-                       return MT9M001_SENSOR;
-               }
-       }
-
-       return -EINVAL;
-}
-
 /**
  * @brief Initialize mt9m111 sensors
  *
@@ -788,31 +759,6 @@ int mt9m111_initialize(struct usb_microdia *dev)
        return ret;
 }
 
-int mt9m111_probe(struct usb_microdia *dev)
-{
-       int ret;
-       __u8 buf[2] = {0x00, 0x00};
-
-       /* Select address-space: Sensor */
-       sn9c20x_write_i2c_data(dev, 2, 0xf0, buf);
-
-       ret = sn9c20x_read_i2c_data(dev, 2, 0x00, buf);
-       if (ret == 0) {
-               if (buf[0] != 0x14)
-                       return -EINVAL;
-               if (buf[1] == 0x3a) {
-                       mt9m111_initialize(dev);
-                       dev->camera.modes = mt9m111_resolutions;
-                       dev->camera.nmodes = ARRAY_SIZE(mt9m111_resolutions);
-                       dev->camera.fmts = mt9m111_fmts;
-                       dev->camera.nfmts = ARRAY_SIZE(mt9m111_fmts);
-                       return MT9M111_SENSOR;
-               }
-       }
-
-       return -EINVAL;
-}
-
 int mt9m111_set_raw(struct usb_microdia *dev)
 {
        __u16 buf;
diff --git a/micron.h b/micron.h
index 1955e5e..8d693f5 100644
--- a/micron.h
+++ b/micron.h
@@ -115,12 +115,13 @@ int mt9v011_set_hvflip(struct usb_microdia *dev);
 int mt9v011_initialize(struct usb_microdia *dev);
 int mt9v011_probe(struct usb_microdia *dev);
 
-int mt9m111_probe(struct usb_microdia *dev);
 int mt9m111_set_raw(struct usb_microdia *dev);
 int mt9m111_set_yuv422(struct usb_microdia *dev);
+int mt9m111_initialize(struct usb_microdia *dev);
 
-int mt9m001_probe(struct usb_microdia *dev);
+int mt9m001_initialize(struct usb_microdia *dev);
 
 int mt9v112_probe(struct usb_microdia *dev);
+int mt9v112_initialize(struct usb_microdia *dev);
 
 #endif
diff --git a/omnivision.c b/omnivision.c
index 36eb280..defcd5a 100644
--- a/omnivision.c
+++ b/omnivision.c
@@ -598,96 +598,70 @@ struct microdia_video_resolution ov7660_resolutions[] = {
        },
 };
 
-int ov_probe(struct usb_microdia *dev)
-{
-       int ret;
-       __u8 buf[2];
-       ret = sn9c20x_read_i2c_data(dev, 2, 0x0a, buf);
-       if (ret == 0) {
-               if (buf[0] != 0x76 && buf[0] != 0x96)
-                       return -EINVAL;
-               if (buf[1] == 0x60) {
-                       ov_initialize(dev, ov7660_init, 
ARRAY_SIZE(ov7660_init));
-                       dev->camera.set_exposure = ov7660_set_exposure;
-                       dev->camera.set_auto_exposure = ov7660_set_autoexposure;
-                       dev->camera.modes = ov7660_resolutions;
-                       dev->camera.nmodes = ARRAY_SIZE(ov7660_resolutions);
-                       dev->camera.fmts = ov_fmts;
-                       dev->camera.nfmts = ARRAY_SIZE(ov_fmts);
-                       return OV7660_SENSOR;
-               }
-               if (buf[1] == 0x70) {
-                       ov_initialize(dev, ov7670_init, 
ARRAY_SIZE(ov7670_init));
-                       dev->camera.flip_detect = ov7670_flip_detect;
-                       dev->camera.modes = ov7670_resolutions;
-                       dev->camera.nmodes = ARRAY_SIZE(ov7670_resolutions);
-                       dev->camera.fmts = ov_fmts;
-                       dev->camera.nfmts = ARRAY_SIZE(ov_fmts);
-                       return OV7670_SENSOR;
-               }
-               if (buf[1] == 0x52) {
-                       ov_initialize(dev, ov9650_init, 
ARRAY_SIZE(ov9650_init));
-                       dev->camera.set_hvflip = ov965x_set_hvflip;
-                       dev->camera.set_exposure = ov965x_set_exposure;
-                       dev->camera.set_auto_exposure = ov965x_set_autoexposure;
-                       dev->camera.flip_detect = ov965x_flip_detect;
-                       dev->camera.modes = ov965x_resolutions;
-                       dev->camera.nmodes = ARRAY_SIZE(ov965x_resolutions);
-                       dev->camera.fmts = ov_fmts;
-                       dev->camera.nfmts = ARRAY_SIZE(ov_fmts);
-                       return OV9650_SENSOR;
-               }
-               if (buf[1] == 0x56 || buf[1] == 0x57) {
-                       ov_initialize(dev, ov9655_init, 
ARRAY_SIZE(ov9655_init));
-                       dev->camera.modes = ov7670_resolutions;
-                       dev->camera.nmodes = ARRAY_SIZE(ov7670_resolutions);
-                       dev->camera.fmts = ov_fmts;
-                       dev->camera.nfmts = ARRAY_SIZE(ov_fmts);
-                       return OV9655_SENSOR;
-               }
-               if (buf[1] == 0x28) {
-                       ov_initialize(dev, soi968_init, 
ARRAY_SIZE(soi968_init));
-                       dev->camera.set_exposure = soi968_set_exposure;
-                       dev->camera.set_auto_exposure = ov965x_set_autoexposure;
-                       dev->camera.modes = soi968_resolutions;
-                       dev->camera.nmodes = ARRAY_SIZE(soi968_resolutions);
-                       dev->camera.fmts = ov_fmts;
-                       dev->camera.nfmts = ARRAY_SIZE(ov_fmts);
-                       return SOI968_SENSOR;
-               }
-       }
-
-       return -EINVAL;
-}
-
 /**
  * @brief Initialize ov sensors
  *
  * @param dev Pointer to device structure
- * @param ov_init Data array for initialization
- * @param array_size size of ov_init
  *
  * @return 0 or negative error code
  *
  */
-int ov_initialize(struct usb_microdia *dev, __u8 ov_init[][2], int array_size)
+int ov_initialize(struct usb_microdia *dev)
 {
        int i;
        int ret = 0;
-       __u8 value, reg;
-
-       for (i = 0; i < array_size; i++) {
-               reg = ov_init[i][0];
-               value = ov_init[i][1];
-               ret = sn9c20x_write_i2c_data(dev, 1, reg, &value);
-               if (ret < 0) {
-                       UDIA_INFO("Sensor Init Error (%d). line %d\n", ret, i);
-                       break;
-               }
+
+       switch (dev->camera.sensor->id) {
+               case SOI968_SENSOR:
+                       for (i = 0; i < ARRAY_SIZE(soi968_init); i++) {
+                               ret = sn9c20x_write_i2c_data(dev, 1,
+                                       soi968_init[i][0], &soi968_init[i][1]);
+                               if (ret < 0)
+                                       goto err;
+                       }
+               break;
+               case OV9650_SENSOR:
+                       for (i = 0; i < ARRAY_SIZE(ov9650_init); i++) {
+                               ret = sn9c20x_write_i2c_data(dev, 1,
+                                       ov9650_init[i][0], &ov9650_init[i][1]);
+                               if (ret < 0)
+                                       goto err;
+                       }
+               break;
+               case OV9655_SENSOR:
+                       for (i = 0; i < ARRAY_SIZE(ov9655_init); i++) {
+                               ret = sn9c20x_write_i2c_data(dev, 1,
+                                       ov9655_init[i][0], &ov9655_init[i][1]);
+                               if (ret < 0)
+                                       goto err;
+                       }
+               break;
+               case OV7670_SENSOR:
+                       for (i = 0; i < ARRAY_SIZE(ov7670_init); i++) {
+                               ret = sn9c20x_write_i2c_data(dev, 1,
+                                       ov7670_init[i][0], &ov7670_init[i][1]);
+                               if (ret < 0)
+                                       goto err;
+                       }
+               break;
+               case OV7660_SENSOR:
+                       for (i = 0; i < ARRAY_SIZE(ov7660_init); i++) {
+                               ret = sn9c20x_write_i2c_data(dev, 1,
+                                       ov7660_init[i][0], &ov7660_init[i][1]);
+                               if (ret < 0)
+                                       goto err;
+                       }
+               break;
+
+               default:
+                       return -EINVAL;
        }
 
        return ret;
 
+err:
+       UDIA_ERROR("Sensor Init failed (%d)! - line %d\n", ret, i);
+       return ret;
 }
 
 /**
diff --git a/omnivision.h b/omnivision.h
index e08092a..1403a18 100644
--- a/omnivision.h
+++ b/omnivision.h
@@ -547,7 +547,6 @@ int ov965x_set_exposure(struct usb_microdia *);
 int ov965x_set_autoexposure(struct usb_microdia *dev);
 int ov965x_flip_detect(struct usb_microdia *dev);
 
-int ov_probe(struct usb_microdia *dev);
-int ov_initialize(struct usb_microdia *dev, __u8 ov_init[][2], int array_size);
+int ov_initialize(struct usb_microdia *dev);
 
 #endif
diff --git a/sn9c20x.c b/sn9c20x.c
index a26ae01..bde5b9b 100644
--- a/sn9c20x.c
+++ b/sn9c20x.c
@@ -44,7 +44,7 @@
  */
 int sn9c20x_initialize(struct usb_microdia *dev)
 {
-       int ret, i, sensor;
+       int ret, i;
 
        __u16 reg;
        __u8 value;
@@ -99,15 +99,6 @@ int sn9c20x_initialize(struct usb_microdia *dev)
                {0x11bf, 0x00},
        };
 
-       __u8 lens_gain[48] = {
-               0x10, 0x21, 0x34, 0x40, 0x47, 0x4f, 0x57, 0x5f,
-               0x64, 0x68, 0x6d, 0x73, 0x79, 0x80, 0x89, 0x97,
-               0x0d, 0x1c, 0x2a, 0x33, 0x38, 0x3d, 0x44, 0x4a,
-               0x4e, 0x52, 0x56, 0x5b, 0x61, 0x68, 0x6f, 0x7a,
-               0x0d, 0x1a, 0x2a, 0x31, 0x36, 0x3b, 0x41, 0x47,
-               0x4a, 0x4e, 0x53, 0x58, 0x5d, 0x64, 0x6b, 0x76
-       };
-
        __u8 qtable1[64] = {
                0x0d, 0x08, 0x08, 0x0d, 0x08, 0x08, 0x0d, 0x0d,
                0x0d, 0x0d, 0x11, 0x0d, 0x0d, 0x11, 0x15, 0x21,
@@ -160,21 +151,19 @@ int sn9c20x_initialize(struct usb_microdia *dev)
        dev->camera.set_sharpness = sn9c20x_set_sharpness;
        dev->camera.set_rgb_gain = sn9c20x_set_rgb_gain;
 
-       sensor = dev_microdia_probe_sensor(dev);
-       if (sensor == UNKNOWN_SENSOR) {
-               UDIA_ERROR("Failed to detect sensor.\n");
-               ret = -ENODEV;
+       ret = dev_microdia_assign_sensor(dev);
+       if (ret < 0)
                goto err;
-       }
-       dev->camera.sensor = sensor;
-
-       if (!(sensor == OV9650_SENSOR || sensor == OV9655_SENSOR))
-               memset(lens_gain, 0x00, 48);
 
-       ret = usb_microdia_control_write(dev, 0x11c0, lens_gain, 48);
+       ret = dev_microdia_initialize_sensor(dev);
        if (ret < 0)
                goto err;
 
+       /** FIXME: Assign sensor-specific reslutions and formats
+        * Brian developed a new system for that with his YUV422
+        * patch for OV sensors.
+        */
+
        return 0;
 
 err:
@@ -231,7 +220,7 @@ int sn9c20x_set_LEDs(struct usb_microdia *dev, int enable)
        int ret;
        __u8 led[2];
 
-       int sensor = dev->camera.sensor;
+       int sensor = dev->camera.sensor->id;
 
        if (enable) {
                switch (sensor) {
@@ -303,8 +292,10 @@ int sn9c20x_i2c_initialize(struct usb_microdia *dev)
        __u8 buf[9];
        int ret;
 
-       buf[0] = dev->camera.sensor_flags;
-       buf[1] = dev->camera.sensor_slave_address;
+       dev->camera.i2c_flags = SN9C20X_I2C_2WIRE;
+
+       buf[0] = dev->camera.i2c_flags;
+       buf[1] = dev->camera.sensor->address;
        buf[2] = 0x00;
        buf[3] = 0x00;
        buf[4] = 0x00;
@@ -383,9 +374,9 @@ int sn9c20x_read_i2c_data(struct usb_microdia *dev, __u8 
nbytes,
        memset(row, 0, 5);
        /* now we issue the same command but with the read bit set
         * and no slave register address */
-       dev->camera.sensor_flags |= SN9C20X_I2C_READ;
+       dev->camera.i2c_flags |= SN9C20X_I2C_READ;
        ret = sn9c20x_write_i2c_data(dev, nbytes - 1, 0, row);
-       dev->camera.sensor_flags &= ~SN9C20X_I2C_READ;
+       dev->camera.i2c_flags &= ~SN9C20X_I2C_READ;
        if (ret < 0)
                return ret;
 
@@ -455,8 +446,8 @@ int sn9c20x_write_i2c_data(struct usb_microdia *dev, __u8 
nbytes,
 
        /* from the point of view of the bridge, the length
         * includes the address */
-       row[0] = dev->camera.sensor_flags | ((nbytes + 1) << 4);
-       row[1] = dev->camera.sensor_slave_address;
+       row[0] = dev->camera.i2c_flags | ((nbytes + 1) << 4);
+       row[1] = dev->camera.sensor->address;
        row[2] = address;
        row[7] = 0x10; /* I think this means we want an ack */
 
@@ -464,19 +455,19 @@ int sn9c20x_write_i2c_data(struct usb_microdia *dev, __u8 
nbytes,
                row[i + 3] = i < nbytes ? data[i] : 0;
 
        UDIA_DEBUG("I2C %s %02x: %02x %02x %02x %02x %02x %02x %02x %02x\n",
-               (dev->camera.sensor_flags & SN9C20X_I2C_READ ? wasread : 
waswrite), address,
+               (dev->camera.i2c_flags & SN9C20X_I2C_READ ? wasread : 
waswrite), address,
                row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7]);
 
        ret = usb_microdia_control_write(dev, 0x10c0, row, 8);
        if (ret >= 0)
                ret = sn9c20x_i2c_ack_wait(dev,
-                       dev->camera.sensor_flags & SN9C20X_I2C_400KHZ,
+                       dev->camera.i2c_flags & SN9C20X_I2C_400KHZ,
                        &slave_error);
 
        if (slave_error) {
                UDIA_ERROR("I2C slave 0x%02x returned error during %s address 
0x%02x\n",
-                       dev->camera.sensor_slave_address,
-                       (dev->camera.sensor_flags & SN9C20X_I2C_READ ? wasread 
: waswrite),
+                       dev->camera.sensor->address,
+                       (dev->camera.i2c_flags & SN9C20X_I2C_READ ? wasread : 
waswrite),
                        address);
                return -1000;
                /* there should be no interference with USB errors */
@@ -485,8 +476,8 @@ int sn9c20x_write_i2c_data(struct usb_microdia *dev, __u8 
nbytes,
        if (ret < 0) {
                /* we got no ack */
                UDIA_ERROR("No ack from I2C slave 0x%02x for %s address 
0x%02x\n",
-                       dev->camera.sensor_slave_address,
-                       (dev->camera.sensor_flags & SN9C20X_I2C_READ ? wasread 
: waswrite),
+                       dev->camera.sensor->address,
+                       (dev->camera.i2c_flags & SN9C20X_I2C_READ ? wasread : 
waswrite),
                        address);
                return ret;
        }
-- 
1.5.6.5

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to