]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/media/video/gspca/stv06xx/stv06xx_st6422.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / media / video / gspca / stv06xx / stv06xx_st6422.c
index 3af53264a36446db7aeea51df862c959ba7397bb..8a456de4970ab2a82cb7c5ecd920cc71c35205ce 100644 (file)
 
 #include "stv06xx_st6422.h"
 
+/* controls */
+enum e_ctrl {
+       BRIGHTNESS,
+       CONTRAST,
+       GAIN,
+       EXPOSURE,
+       NCTRLS          /* number of controls */
+};
+
+/* sensor settings */
+struct st6422_settings {
+       struct gspca_ctrl ctrls[NCTRLS];
+};
+
 static struct v4l2_pix_format st6422_mode[] = {
        /* Note we actually get 124 lines of data, of which we skip the 4st
           4 as they are garbage */
@@ -57,9 +71,14 @@ static struct v4l2_pix_format st6422_mode[] = {
        },
 };
 
-static const struct ctrl st6422_ctrl[] = {
-#define BRIGHTNESS_IDX 0
-       {
+/* V4L2 controls supported by the driver */
+static void st6422_set_brightness(struct gspca_dev *gspca_dev);
+static void st6422_set_contrast(struct gspca_dev *gspca_dev);
+static void st6422_set_gain(struct gspca_dev *gspca_dev);
+static void st6422_set_exposure(struct gspca_dev *gspca_dev);
+
+static const struct ctrl st6422_ctrl[NCTRLS] = {
+[BRIGHTNESS] = {
                {
                        .id             = V4L2_CID_BRIGHTNESS,
                        .type           = V4L2_CTRL_TYPE_INTEGER,
@@ -69,11 +88,9 @@ static const struct ctrl st6422_ctrl[] = {
                        .step           = 1,
                        .default_value  = 3
                },
-               .set = st6422_set_brightness,
-               .get = st6422_get_brightness
+               .set_control = st6422_set_brightness
        },
-#define CONTRAST_IDX 1
-       {
+[CONTRAST] = {
                {
                        .id             = V4L2_CID_CONTRAST,
                        .type           = V4L2_CTRL_TYPE_INTEGER,
@@ -83,11 +100,9 @@ static const struct ctrl st6422_ctrl[] = {
                        .step           = 1,
                        .default_value  = 11
                },
-               .set = st6422_set_contrast,
-               .get = st6422_get_contrast
+               .set_control = st6422_set_contrast
        },
-#define GAIN_IDX 2
-       {
+[GAIN] = {
                {
                        .id             = V4L2_CID_GAIN,
                        .type           = V4L2_CTRL_TYPE_INTEGER,
@@ -97,49 +112,43 @@ static const struct ctrl st6422_ctrl[] = {
                        .step           = 1,
                        .default_value  = 64
                },
-               .set = st6422_set_gain,
-               .get = st6422_get_gain
+               .set_control = st6422_set_gain
        },
-#define EXPOSURE_IDX 3
-       {
+[EXPOSURE] = {
                {
                        .id             = V4L2_CID_EXPOSURE,
                        .type           = V4L2_CTRL_TYPE_INTEGER,
                        .name           = "Exposure",
                        .minimum        = 0,
-                       .maximum        = 1023,
+#define EXPOSURE_MAX 1023
+                       .maximum        = EXPOSURE_MAX,
                        .step           = 1,
                        .default_value  = 256
                },
-               .set = st6422_set_exposure,
-               .get = st6422_get_exposure
+               .set_control = st6422_set_exposure
        },
 };
 
 static int st6422_probe(struct sd *sd)
 {
-       int i;
-       s32 *sensor_settings;
+       struct st6422_settings *sensor_settings;
 
        if (sd->bridge != BRIDGE_ST6422)
                return -ENODEV;
 
        info("st6422 sensor detected");
 
-       sensor_settings = kmalloc(ARRAY_SIZE(st6422_ctrl) * sizeof(s32),
-                                 GFP_KERNEL);
+       sensor_settings = kmalloc(sizeof *sensor_settings, GFP_KERNEL);
        if (!sensor_settings)
                return -ENOMEM;
 
        sd->gspca_dev.cam.cam_mode = st6422_mode;
        sd->gspca_dev.cam.nmodes = ARRAY_SIZE(st6422_mode);
+       sd->gspca_dev.cam.ctrls = sensor_settings->ctrls;
        sd->desc.ctrls = st6422_ctrl;
        sd->desc.nctrls = ARRAY_SIZE(st6422_ctrl);
        sd->sensor_priv = sensor_settings;
 
-       for (i = 0; i < sd->desc.nctrls; i++)
-               sensor_settings[i] = st6422_ctrl[i].qctrl.default_value;
-
        return 0;
 }
 
@@ -151,11 +160,11 @@ static int st6422_init(struct sd *sd)
                { STV_ISO_ENABLE, 0x00 }, /* disable capture */
                { 0x1436, 0x00 },
                { 0x1432, 0x03 },       /* 0x00-0x1F brightness */
-               { 0x143a, 0xF9 },       /* 0x00-0x0F contrast */
+               { 0x143a, 0xf9 },       /* 0x00-0x0F contrast */
                { 0x0509, 0x38 },       /* R */
                { 0x050a, 0x38 },       /* G */
                { 0x050b, 0x38 },       /* B */
-               { 0x050c, 0x2A },
+               { 0x050c, 0x2a },
                { 0x050d, 0x01 },
 
 
@@ -213,7 +222,6 @@ static int st6422_init(struct sd *sd)
                { 0x150e, 0x8e },
                { 0x150f, 0x37 },
                { 0x15c0, 0x00 },
-               { 0x15c1, 1023 }, /* 160x120, ISOC_PACKET_SIZE */
                { 0x15c3, 0x08 },       /* 0x04/0x14 ... test pictures ??? */
 
 
@@ -235,91 +243,92 @@ static void st6422_disconnect(struct sd *sd)
        kfree(sd->sensor_priv);
 }
 
-static int st6422_start(struct sd *sd)
+static int setbrightness(struct sd *sd)
 {
-       int err, packet_size;
-       struct cam *cam = &sd->gspca_dev.cam;
-       s32 *sensor_settings = sd->sensor_priv;
-       struct usb_host_interface *alt;
-       struct usb_interface *intf;
-
-       intf = usb_ifnum_to_if(sd->gspca_dev.dev, sd->gspca_dev.iface);
-       alt = usb_altnum_to_altsetting(intf, sd->gspca_dev.alt);
-       if (!alt) {
-               err("Couldn't get altsetting");
-               return -EIO;
-       }
+       struct st6422_settings *sensor_settings = sd->sensor_priv;
 
-       packet_size = le16_to_cpu(alt->endpoint[0].desc.wMaxPacketSize);
-       err = stv06xx_write_bridge(sd, 0x15c1, packet_size);
-       if (err < 0)
-               return err;
+       /* val goes from 0 -> 31 */
+       return stv06xx_write_bridge(sd, 0x1432,
+                       sensor_settings->ctrls[BRIGHTNESS].val);
+}
 
-       if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
-               err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
-       else
-               err = stv06xx_write_bridge(sd, 0x1505, 0x02);
-       if (err < 0)
-               return err;
+static int setcontrast(struct sd *sd)
+{
+       struct st6422_settings *sensor_settings = sd->sensor_priv;
+
+       /* Val goes from 0 -> 15 */
+       return stv06xx_write_bridge(sd, 0x143a,
+                       sensor_settings->ctrls[CONTRAST].val | 0xf0);
+}
+
+static int setgain(struct sd *sd)
+{
+       struct st6422_settings *sensor_settings = sd->sensor_priv;
+       u8 gain;
+       int err;
+
+       gain = sensor_settings->ctrls[GAIN].val;
 
-       err = st6422_set_brightness(&sd->gspca_dev,
-                                   sensor_settings[BRIGHTNESS_IDX]);
+       /* Set red, green, blue, gain */
+       err = stv06xx_write_bridge(sd, 0x0509, gain);
        if (err < 0)
                return err;
 
-       err = st6422_set_contrast(&sd->gspca_dev,
-                                 sensor_settings[CONTRAST_IDX]);
+       err = stv06xx_write_bridge(sd, 0x050a, gain);
        if (err < 0)
                return err;
 
-       err = st6422_set_exposure(&sd->gspca_dev,
-                                 sensor_settings[EXPOSURE_IDX]);
+       err = stv06xx_write_bridge(sd, 0x050b, gain);
        if (err < 0)
                return err;
 
-       err = st6422_set_gain(&sd->gspca_dev,
-                             sensor_settings[GAIN_IDX]);
+       /* 2 mystery writes */
+       err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
        if (err < 0)
                return err;
 
-       PDEBUG(D_STREAM, "Starting stream");
-
-       return 0;
+       return stv06xx_write_bridge(sd, 0x050d, 0x01);
 }
 
-static int st6422_stop(struct sd *sd)
+static int setexposure(struct sd *sd)
 {
-       PDEBUG(D_STREAM, "Halting stream");
-
-       return 0;
-}
-
-static int st6422_get_brightness(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[BRIGHTNESS_IDX];
+       struct st6422_settings *sensor_settings = sd->sensor_priv;
+       u16 expo;
+       int err;
 
-       PDEBUG(D_V4L2, "Read brightness %d", *val);
+       expo = sensor_settings->ctrls[EXPOSURE].val;
+       err = stv06xx_write_bridge(sd, 0x143d, expo & 0xff);
+       if (err < 0)
+               return err;
 
-       return 0;
+       return stv06xx_write_bridge(sd, 0x143e, expo >> 8);
 }
 
-static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
+static int st6422_start(struct sd *sd)
 {
        int err;
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
+       struct cam *cam = &sd->gspca_dev.cam;
 
-       sensor_settings[BRIGHTNESS_IDX] = val;
+       if (cam->cam_mode[sd->gspca_dev.curr_mode].priv)
+               err = stv06xx_write_bridge(sd, 0x1505, 0x0f);
+       else
+               err = stv06xx_write_bridge(sd, 0x1505, 0x02);
+       if (err < 0)
+               return err;
 
-       if (!gspca_dev->streaming)
-               return 0;
+       err = setbrightness(sd);
+       if (err < 0)
+               return err;
 
-       /* val goes from 0 -> 31 */
-       PDEBUG(D_V4L2, "Set brightness to %d", val);
-       err = stv06xx_write_bridge(sd, 0x1432, val);
+       err = setcontrast(sd);
+       if (err < 0)
+               return err;
+
+       err = setexposure(sd);
+       if (err < 0)
+               return err;
+
+       err = setgain(sd);
        if (err < 0)
                return err;
 
@@ -328,125 +337,65 @@ static int st6422_set_brightness(struct gspca_dev *gspca_dev, __s32 val)
        return (err < 0) ? err : 0;
 }
 
-static int st6422_get_contrast(struct gspca_dev *gspca_dev, __s32 *val)
+static int st6422_stop(struct sd *sd)
 {
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[CONTRAST_IDX];
-
-       PDEBUG(D_V4L2, "Read contrast %d", *val);
+       PDEBUG(D_STREAM, "Halting stream");
 
        return 0;
 }
 
-static int st6422_set_contrast(struct gspca_dev *gspca_dev, __s32 val)
+static void st6422_set_brightness(struct gspca_dev *gspca_dev)
 {
        int err;
        struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       sensor_settings[CONTRAST_IDX] = val;
 
-       if (!gspca_dev->streaming)
-               return 0;
-
-       /* Val goes from 0 -> 15 */
-       PDEBUG(D_V4L2, "Set contrast to %d\n", val);
-       err = stv06xx_write_bridge(sd, 0x143a, 0xf0 | val);
-       if (err < 0)
-               return err;
+       err = setbrightness(sd);
 
        /* commit settings */
-       err = stv06xx_write_bridge(sd, 0x143f, 0x01);
-       return (err < 0) ? err : 0;
-}
-
-static int st6422_get_gain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       *val = sensor_settings[GAIN_IDX];
-
-       PDEBUG(D_V4L2, "Read gain %d", *val);
+       if (err >= 0)
+               err = stv06xx_write_bridge(sd, 0x143f, 0x01);
 
-       return 0;
+       gspca_dev->usb_err = err;
 }
 
-static int st6422_set_gain(struct gspca_dev *gspca_dev, __s32 val)
+static void st6422_set_contrast(struct gspca_dev *gspca_dev)
 {
        int err;
        struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       sensor_settings[GAIN_IDX] = val;
-
-       if (!gspca_dev->streaming)
-               return 0;
-
-       PDEBUG(D_V4L2, "Set gain to %d", val);
 
-       /* Set red, green, blue, gain */
-       err = stv06xx_write_bridge(sd, 0x0509, val);
-       if (err < 0)
-               return err;
-
-       err = stv06xx_write_bridge(sd, 0x050a, val);
-       if (err < 0)
-               return err;
-
-       err = stv06xx_write_bridge(sd, 0x050b, val);
-       if (err < 0)
-               return err;
-
-       /* 2 mystery writes */
-       err = stv06xx_write_bridge(sd, 0x050c, 0x2a);
-       if (err < 0)
-               return err;
-
-       err = stv06xx_write_bridge(sd, 0x050d, 0x01);
-       if (err < 0)
-               return err;
+       err = setcontrast(sd);
 
        /* commit settings */
-       err = stv06xx_write_bridge(sd, 0x143f, 0x01);
-       return (err < 0) ? err : 0;
+       if (err >= 0)
+               err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+
+       gspca_dev->usb_err = err;
 }
 
-static int st6422_get_exposure(struct gspca_dev *gspca_dev, __s32 *val)
+static void st6422_set_gain(struct gspca_dev *gspca_dev)
 {
+       int err;
        struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
 
-       *val = sensor_settings[EXPOSURE_IDX];
+       err = setgain(sd);
 
-       PDEBUG(D_V4L2, "Read exposure %d", *val);
+       /* commit settings */
+       if (err >= 0)
+               err = stv06xx_write_bridge(sd, 0x143f, 0x01);
 
-       return 0;
+       gspca_dev->usb_err = err;
 }
 
-static int st6422_set_exposure(struct gspca_dev *gspca_dev, __s32 val)
+static void st6422_set_exposure(struct gspca_dev *gspca_dev)
 {
        int err;
        struct sd *sd = (struct sd *) gspca_dev;
-       s32 *sensor_settings = sd->sensor_priv;
-
-       sensor_settings[EXPOSURE_IDX] = val;
 
-       if (!gspca_dev->streaming)
-               return 0;
-
-       PDEBUG(D_V4L2, "Set exposure to %d\n", val);
-       err = stv06xx_write_bridge(sd, 0x143d, val & 0xff);
-       if (err < 0)
-               return err;
-
-       err = stv06xx_write_bridge(sd, 0x143e, val >> 8);
-       if (err < 0)
-               return err;
+       err = setexposure(sd);
 
        /* commit settings */
-       err = stv06xx_write_bridge(sd, 0x143f, 0x01);
-       return (err < 0) ? err : 0;
+       if (err >= 0)
+               err = stv06xx_write_bridge(sd, 0x143f, 0x01);
+
+       gspca_dev->usb_err = err;
 }