[media] gspca - ov519: Re-initialize the webcam at resume time
[pandora-kernel.git] / drivers / media / video / gspca / ov519.c
index 2484e52..08f07c3 100644 (file)
@@ -513,6 +513,7 @@ static const struct v4l2_pix_format ovfx2_ov3610_mode[] = {
 /* OV519 System Controller register numbers */
 #define OV519_R51_RESET1               0x51
 #define OV519_R54_EN_CLK1              0x54
+#define OV519_R57_SNAPSHOT             0x57
 
 #define OV519_GPIO_DATA_OUT0           0x71
 #define OV519_GPIO_IO_CTRL0            0x72
@@ -2325,6 +2326,8 @@ static inline void ov51x_stop(struct sd *sd)
                break;
        case BRIDGE_OV519:
                reg_w(sd, OV519_R51_RESET1, 0x0f);
+               reg_w(sd, OV519_R51_RESET1, 0x00);
+               reg_w(sd, 0x22, 0x00);          /* FRAR */
                break;
        case BRIDGE_OVFX2:
                reg_w_mask(sd, 0x0f, 0x00, 0x02);
@@ -2356,7 +2359,9 @@ static inline void ov51x_restart(struct sd *sd)
                reg_w(sd, R51x_SYS_RESET, 0x00);
                break;
        case BRIDGE_OV519:
+               reg_w(sd, OV519_R51_RESET1, 0x0f);
                reg_w(sd, OV519_R51_RESET1, 0x00);
+               reg_w(sd, 0x22, 0x1d);          /* FRAR */
                break;
        case BRIDGE_OVFX2:
                reg_w_mask(sd, 0x0f, 0x02, 0x02);
@@ -2943,28 +2948,64 @@ static int sd_config(struct gspca_dev *gspca_dev,
        switch (sd->bridge) {
        case BRIDGE_OV511:
        case BRIDGE_OV511PLUS:
-               ov511_configure(gspca_dev);
+               cam->cam_mode = ov511_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
                break;
        case BRIDGE_OV518:
        case BRIDGE_OV518PLUS:
-               ov518_configure(gspca_dev);
+               cam->cam_mode = ov518_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
                break;
        case BRIDGE_OV519:
-               ov519_configure(sd);
+               cam->cam_mode = ov519_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
+               sd->invert_led = !sd->invert_led;
                break;
        case BRIDGE_OVFX2:
-               ovfx2_configure(sd);
+               cam->cam_mode = ov519_vga_mode;
+               cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
                cam->bulk_size = OVFX2_BULK_SIZE;
                cam->bulk_nurbs = MAX_NURBS;
                cam->bulk = 1;
                break;
        case BRIDGE_W9968CF:
-               w9968cf_configure(sd);
+               cam->cam_mode = w9968cf_vga_mode;
+               cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
                cam->reverse_alts = 1;
                break;
        }
 
-       ov51x_led_control(sd, 0);       /* turn LED off */
+       gspca_dev->cam.ctrls = sd->ctrls;
+       sd->quality = QUALITY_DEF;
+
+       return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+       struct cam *cam = &gspca_dev->cam;
+
+       switch (sd->bridge) {
+       case BRIDGE_OV511:
+       case BRIDGE_OV511PLUS:
+               ov511_configure(gspca_dev);
+               break;
+       case BRIDGE_OV518:
+       case BRIDGE_OV518PLUS:
+               ov518_configure(gspca_dev);
+               break;
+       case BRIDGE_OV519:
+               ov519_configure(sd);
+               break;
+       case BRIDGE_OVFX2:
+               ovfx2_configure(sd);
+               break;
+       case BRIDGE_W9968CF:
+               w9968cf_configure(sd);
+               break;
+       }
 
        /* The OV519 must be more aggressive about sensor detection since
         * I2C write will never fail if the sensor is not present. We have
@@ -2994,32 +3035,25 @@ static int sd_config(struct gspca_dev *gspca_dev,
        if (sd->sensor < 0)
                goto error;
 
+       ov51x_led_control(sd, 0);       /* turn LED off */
+
        switch (sd->bridge) {
        case BRIDGE_OV511:
        case BRIDGE_OV511PLUS:
-               if (!sd->sif) {
-                       cam->cam_mode = ov511_vga_mode;
-                       cam->nmodes = ARRAY_SIZE(ov511_vga_mode);
-               } else {
+               if (sd->sif) {
                        cam->cam_mode = ov511_sif_mode;
                        cam->nmodes = ARRAY_SIZE(ov511_sif_mode);
                }
                break;
        case BRIDGE_OV518:
        case BRIDGE_OV518PLUS:
-               if (!sd->sif) {
-                       cam->cam_mode = ov518_vga_mode;
-                       cam->nmodes = ARRAY_SIZE(ov518_vga_mode);
-               } else {
+               if (sd->sif) {
                        cam->cam_mode = ov518_sif_mode;
                        cam->nmodes = ARRAY_SIZE(ov518_sif_mode);
                }
                break;
        case BRIDGE_OV519:
-               if (!sd->sif) {
-                       cam->cam_mode = ov519_vga_mode;
-                       cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
-               } else {
+               if (sd->sif) {
                        cam->cam_mode = ov519_sif_mode;
                        cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
                }
@@ -3031,40 +3065,22 @@ static int sd_config(struct gspca_dev *gspca_dev,
                } else if (sd->sensor == SEN_OV3610) {
                        cam->cam_mode = ovfx2_ov3610_mode;
                        cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode);
-               } else if (!sd->sif) {
-                       cam->cam_mode = ov519_vga_mode;
-                       cam->nmodes = ARRAY_SIZE(ov519_vga_mode);
-               } else {
+               } else if (sd->sif) {
                        cam->cam_mode = ov519_sif_mode;
                        cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
                }
                break;
        case BRIDGE_W9968CF:
-               cam->cam_mode = w9968cf_vga_mode;
-               cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
                if (sd->sif)
-                       cam->nmodes--;
+                       cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode) - 1;
 
                /* w9968cf needs initialisation once the sensor is known */
                w9968cf_init(sd);
                break;
        }
-       gspca_dev->cam.ctrls = sd->ctrls;
-       sd->quality = QUALITY_DEF;
 
        gspca_dev->ctrl_dis = ctrl_dis[sd->sensor];
 
-       return gspca_dev->usb_err;
-error:
-       PDEBUG(D_ERR, "OV519 Config failed");
-       return -EINVAL;
-}
-
-/* this function is called at probe and resume time */
-static int sd_init(struct gspca_dev *gspca_dev)
-{
-       struct sd *sd = (struct sd *) gspca_dev;
-
        /* initialize the sensor */
        switch (sd->sensor) {
        case SEN_OV2610:
@@ -3112,6 +3128,9 @@ static int sd_init(struct gspca_dev *gspca_dev)
                break;
        }
        return gspca_dev->usb_err;
+error:
+       PDEBUG(D_ERR, "OV519 Config failed");
+       return -EINVAL;
 }
 
 /* Set up the OV511/OV511+ with the given image parameters.
@@ -3668,13 +3687,13 @@ static void sethvflip(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
 
        if (sd->gspca_dev.streaming)
-               ov51x_stop(sd);
+               reg_w(sd, OV519_R51_RESET1, 0x0f);      /* block stream */
        i2c_w_mask(sd, OV7670_R1E_MVFP,
                OV7670_MVFP_MIRROR * sd->ctrls[HFLIP].val
                        | OV7670_MVFP_VFLIP * sd->ctrls[VFLIP].val,
                OV7670_MVFP_MIRROR | OV7670_MVFP_VFLIP);
        if (sd->gspca_dev.streaming)
-               ov51x_restart(sd);
+               reg_w(sd, OV519_R51_RESET1, 0x00);      /* restart stream */
 }
 
 static void set_ov_sensor_window(struct sd *sd)
@@ -3860,6 +3879,8 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
                sd->snapshot_pressed = 0;
        }
 #endif
+       if (sd->bridge == BRIDGE_OV519)
+               reg_w(sd, OV519_R57_SNAPSHOT, 0x23);
 }
 
 static void ov51x_handle_button(struct gspca_dev *gspca_dev, u8 state)