#define SEN_OV7620 7
 #define SEN_OV7620AE 8
 #define SEN_OV7640 9
-#define SEN_OV7670 10
-#define SEN_OV76BE 11
-#define SEN_OV8610 12
+#define SEN_OV7648 10
+#define SEN_OV7670 11
+#define SEN_OV76BE 12
+#define SEN_OV8610 13
 
        u8 sensor_addr;
        int sensor_width;
                                break;
                        case 0x48:
                                PDEBUG(D_PROBE, "Sensor is an OV7648");
-                               sd->sensor = SEN_OV7640; /* FIXME */
+                               sd->sensor = SEN_OV7648;
                                break;
                        default:
                                PDEBUG(D_PROBE, "Unknown sensor: 0x76%x", low);
                                      (1 << OV7670_FREQ_IDX);
        }
        sd->quality = QUALITY_DEF;
-       if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
+       if (sd->sensor == SEN_OV7640 ||
+           sd->sensor == SEN_OV7648 ||
+           sd->sensor == SEN_OV7670)
                gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX;
        /* OV8610 Frequency filter control should work but needs testing */
        if (sd->sensor == SEN_OV8610)
                        return -EIO;
                break;
        case SEN_OV7640:
+       case SEN_OV7648:
                if (write_i2c_regvals(sd, norm_7640, ARRAY_SIZE(norm_7640)))
                        return -EIO;
                break;
        case SEN_OV7620:
        case SEN_OV7620AE:
        case SEN_OV7640:
+       case SEN_OV7648:
        case SEN_OV76BE:
                if (sd->gspca_dev.width == 320)
                        interlaced = 1;
                if (write_regvals(sd, mode_init_519,
                                  ARRAY_SIZE(mode_init_519)))
                        return -EIO;
-               if (sd->sensor == SEN_OV7640) {
+               if (sd->sensor == SEN_OV7640 ||
+                   sd->sensor == SEN_OV7648) {
                        /* Select 8-bit input mode */
                        reg_w_mask(sd, OV519_R20_DFR, 0x10, 0x10);
                }
        if (sd->sensor == SEN_OV7670 &&
            sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
                reg_w(sd, OV519_R12_X_OFFSETL, 0x04);
+       else if (sd->sensor == SEN_OV7648 &&
+           sd->gspca_dev.cam.cam_mode[sd->gspca_dev.curr_mode].priv)
+               reg_w(sd, OV519_R12_X_OFFSETL, 0x01);
        else
                reg_w(sd, OV519_R12_X_OFFSETL, 0x00);
        reg_w(sd, OV519_R13_X_OFFSETH,  0x00);
        sd->clockdiv = 0;
        switch (sd->sensor) {
        case SEN_OV7640:
+       case SEN_OV7648:
                switch (sd->frame_rate) {
                default:
 /*             case 30: */
                        i2c_w(sd, 0x35, qvga ? 0x1e : 0x9e);
                break;
        case SEN_OV7640:
+       case SEN_OV7648:
                i2c_w_mask(sd, 0x14, qvga ? 0x20 : 0x00, 0x20);
                i2c_w_mask(sd, 0x28, qvga ? 0x00 : 0x20, 0x20);
-/*             i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a); */
-/*             i2c_w(sd, 0x25, qvga ? 0x30 : 0x60); */
-/*             i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40); */
-/*             i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0); */
-/*             i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20); */
+               /* The following 5 lines where commented out before with a
+                  comment wondering if they did anything. This was because
+                  the old driver did only 640x480, at 320x240 these 5 writes
+                  *significantly* improve the image quality. */
+               i2c_w(sd, 0x24, qvga ? 0x20 : 0x3a);
+               i2c_w(sd, 0x25, qvga ? 0x30 : 0x60);
+               i2c_w_mask(sd, 0x2d, qvga ? 0x40 : 0x00, 0x40);
+               i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
+               i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
                i2c_w_mask(sd, 0x12, 0x04, 0x04); /* AWB: 1 */
                break;
        case SEN_OV7670:
                vwsbase = vwebase = 0x05;
                break;
        case SEN_OV7640:
+       case SEN_OV7648:
                hwsbase = 0x1a;
                hwebase = 0x1a;
                vwsbase = vwebase = 0x03;
        case SEN_OV6630:
        case SEN_OV66308AF:
        case SEN_OV7640:
+       case SEN_OV7648:
                i2c_w(sd, OV7610_REG_BRT, val);
                break;
        case SEN_OV7620:
                break;
            }
        case SEN_OV7640:
+       case SEN_OV7648:
                /* Use gain control instead. */
                i2c_w(sd, OV7610_REG_GAIN, val >> 2);
                break;
                i2c_w(sd, OV7610_REG_SAT, val);
                break;
        case SEN_OV7640:
+       case SEN_OV7648:
                i2c_w(sd, OV7610_REG_SAT, val & 0xf0);
                break;
        case SEN_OV7670:
 
 static void setautobrightness(struct sd *sd)
 {
-       if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670 ||
+       if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7648 ||
+           sd->sensor == SEN_OV7670 ||
            sd->sensor == SEN_OV2610 || sd->sensor == SEN_OV3610)
                return;