diff options
Diffstat (limited to 'drivers/media/video/gspca/stv06xx/stv06xx_st6422.c')
-rw-r--r-- | drivers/media/video/gspca/stv06xx/stv06xx_st6422.c | 291 |
1 files changed, 120 insertions, 171 deletions
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c index 3af53264a364..8a456de4970a 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx_st6422.c @@ -28,6 +28,20 @@ #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; } |