V4L/DVB (13422): gspca - ov534: ov772x changes from Richard Kaswy.
[safe/jmp/linux-2.6] / drivers / media / video / gspca / conex.c
index b0294c9..eca0035 100644 (file)
@@ -25,9 +25,6 @@
 #define CONEX_CAM 1            /* special JPEG header */
 #include "jpeg.h"
 
-#define DRIVER_VERSION_NUMBER  KERNEL_VERSION(2, 1, 0)
-static const char version[] = "2.1.0";
-
 MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
 MODULE_DESCRIPTION("GSPCA USB Conexant Camera Driver");
 MODULE_LICENSE("GPL");
@@ -39,8 +36,12 @@ struct sd {
        unsigned char brightness;
        unsigned char contrast;
        unsigned char colors;
+       u8 quality;
+#define QUALITY_MIN 30
+#define QUALITY_MAX 60
+#define QUALITY_DEF 40
 
-       unsigned char qindex;
+       u8 *jpeg_hdr;
 };
 
 /* V4L2 controls supported by the driver */
@@ -52,7 +53,6 @@ static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val);
 
 static struct ctrl sd_ctrls[] = {
-#define SD_BRIGHTNESS 0
        {
            {
                .id      = V4L2_CID_BRIGHTNESS,
@@ -61,12 +61,12 @@ static struct ctrl sd_ctrls[] = {
                .minimum = 0,
                .maximum = 255,
                .step    = 1,
-               .default_value = 0xd4,
+#define BRIGHTNESS_DEF 0xd4
+               .default_value = BRIGHTNESS_DEF,
            },
            .set = sd_setbrightness,
            .get = sd_getbrightness,
        },
-#define SD_CONTRAST 1
        {
            {
                .id      = V4L2_CID_CONTRAST,
@@ -75,12 +75,12 @@ static struct ctrl sd_ctrls[] = {
                .minimum = 0x0a,
                .maximum = 0x1f,
                .step    = 1,
-               .default_value = 0x0c,
+#define CONTRAST_DEF 0x0c
+               .default_value = CONTRAST_DEF,
            },
            .set = sd_setcontrast,
            .get = sd_getcontrast,
        },
-#define SD_COLOR 2
        {
            {
                .id      = V4L2_CID_SATURATION,
@@ -89,46 +89,98 @@ static struct ctrl sd_ctrls[] = {
                .minimum = 0,
                .maximum = 7,
                .step    = 1,
-               .default_value = 3,
+#define COLOR_DEF 3
+               .default_value = COLOR_DEF,
            },
            .set = sd_setcolors,
            .get = sd_getcolors,
        },
 };
 
-static struct cam_mode vga_mode[] = {
-       {V4L2_PIX_FMT_JPEG, 176, 144, 3},
-       {V4L2_PIX_FMT_JPEG, 320, 240, 2},
-       {V4L2_PIX_FMT_JPEG, 352, 288, 1},
-       {V4L2_PIX_FMT_JPEG, 640, 480, 0},
+static const struct v4l2_pix_format vga_mode[] = {
+       {176, 144, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 3},
+       {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 2},
+       {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 1},
+       {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+               .bytesperline = 640,
+               .sizeimage = 640 * 480 * 3 / 8 + 590,
+               .colorspace = V4L2_COLORSPACE_JPEG,
+               .priv = 0},
 };
 
-static void reg_r(struct usb_device *dev,
-                          __u16 index,
-                          __u8 *buffer, __u16 length)
+/* the read bytes are found in gspca_dev->usb_buf */
+static void reg_r(struct gspca_dev *gspca_dev,
+                 __u16 index,
+                 __u16 len)
 {
+       struct usb_device *dev = gspca_dev->dev;
+
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               err("reg_r: buffer overflow");
+               return;
+       }
+#endif
        usb_control_msg(dev,
                        usb_rcvctrlpipe(dev, 0),
                        0,
                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                        0,
-                       index, buffer, length,
+                       index, gspca_dev->usb_buf, len,
                        500);
-       PDEBUG(D_USBI, "reg read i:%02x -> %02x", index, *buffer);
+       PDEBUG(D_USBI, "reg read [%02x] -> %02x ..",
+                       index, gspca_dev->usb_buf[0]);
+}
+
+/* the bytes to write are in gspca_dev->usb_buf */
+static void reg_w_val(struct gspca_dev *gspca_dev,
+                       __u16 index,
+                       __u8 val)
+{
+       struct usb_device *dev = gspca_dev->dev;
+
+       gspca_dev->usb_buf[0] = val;
+       usb_control_msg(dev,
+                       usb_sndctrlpipe(dev, 0),
+                       0,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0,
+                       index, gspca_dev->usb_buf, 1, 500);
 }
 
-static void reg_w(struct usb_device *dev,
+static void reg_w(struct gspca_dev *gspca_dev,
                  __u16 index,
-                 const __u8 *buffer, __u16 length)
+                 const __u8 *buffer,
+                 __u16 len)
 {
-       PDEBUG(D_USBO, "reg write i:%02x = %02x", index, *buffer);
+       struct usb_device *dev = gspca_dev->dev;
+
+#ifdef GSPCA_DEBUG
+       if (len > USB_BUF_SZ) {
+               err("reg_w: buffer overflow");
+               return;
+       }
+       PDEBUG(D_USBO, "reg write [%02x] = %02x..", index, *buffer);
+#endif
+       memcpy(gspca_dev->usb_buf, buffer, len);
        usb_control_msg(dev,
                        usb_sndctrlpipe(dev, 0),
                        0,
                        USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                        0,
-                       index, (__u8 *) buffer, length,
-                       500);
+                       index, gspca_dev->usb_buf, len, 500);
 }
 
 static const __u8 cx_sensor_init[][4] = {
@@ -208,20 +260,17 @@ static const __u8 cx11646_fw1[][3] = {
 };
 static void cx11646_fw(struct gspca_dev*gspca_dev)
 {
-       __u8 val;
        int i = 0;
 
-       val = 0x02;
-       reg_w(gspca_dev->dev, 0x006a, &val, 1);
+       reg_w_val(gspca_dev, 0x006a, 0x02);
        while (cx11646_fw1[i][1]) {
-               reg_w(gspca_dev->dev, 0x006b, cx11646_fw1[i], 3);
+               reg_w(gspca_dev, 0x006b, cx11646_fw1[i], 3);
                i++;
        }
-       val = 0x00;
-       reg_w(gspca_dev->dev, 0x006a, &val, 1);
+       reg_w_val(gspca_dev, 0x006a, 0x00);
 }
 
-static __u8 cxsensor[] = {
+static const __u8 cxsensor[] = {
        0x88, 0x12, 0x70, 0x01,
        0x88, 0x0d, 0x02, 0x01,
        0x88, 0x0f, 0x00, 0x01,
@@ -236,68 +285,63 @@ static __u8 cxsensor[] = {
        0x00
 };
 
-static __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
-static __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
-static __u8 reg10[] = { 0xb1, 0xb1 };
-static __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e };     /* 640 */
-static __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
+static const __u8 reg20[] = { 0x10, 0x42, 0x81, 0x19, 0xd3, 0xff, 0xa7, 0xff };
+static const __u8 reg28[] = { 0x87, 0x00, 0x87, 0x00, 0x8f, 0xff, 0xea, 0xff };
+static const __u8 reg10[] = { 0xb1, 0xb1 };
+static const __u8 reg71a[] = { 0x08, 0x18, 0x0a, 0x1e };       /* 640 */
+static const __u8 reg71b[] = { 0x04, 0x0c, 0x05, 0x0f };
        /* 352{0x04,0x0a,0x06,0x12}; //352{0x05,0x0e,0x06,0x11}; //352 */
-static __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
+static const __u8 reg71c[] = { 0x02, 0x07, 0x03, 0x09 };
                                        /* 320{0x04,0x0c,0x05,0x0f}; //320 */
-static __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 };     /* 176 */
-static __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
+static const __u8 reg71d[] = { 0x02, 0x07, 0x03, 0x09 };       /* 176 */
+static const __u8 reg7b[] = { 0x00, 0xff, 0x00, 0xff, 0x00, 0xff };
 
 static void cx_sensor(struct gspca_dev*gspca_dev)
 {
-       __u8 val = 0;
        int i = 0;
-       __u8 bufread[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-       int length = 0;
-       __u8 *ptsensor = cxsensor;
+       int length;
+       const __u8 *ptsensor = cxsensor;
 
-       reg_w(gspca_dev->dev, 0x0020, reg20, 8);
-       reg_w(gspca_dev->dev, 0x0028, reg28, 8);
-       reg_w(gspca_dev->dev, 0x0010, reg10, 8);
-       val = 0x03;
-       reg_w(gspca_dev->dev, 0x0092, &val, 1);
+       reg_w(gspca_dev, 0x0020, reg20, 8);
+       reg_w(gspca_dev, 0x0028, reg28, 8);
+       reg_w(gspca_dev, 0x0010, reg10, 8);
+       reg_w_val(gspca_dev, 0x0092, 0x03);
 
-       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
+       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
        case 0:
-               reg_w(gspca_dev->dev, 0x0071, reg71a, 4);
+               reg_w(gspca_dev, 0x0071, reg71a, 4);
                break;
        case 1:
-               reg_w(gspca_dev->dev, 0x0071, reg71b, 4);
+               reg_w(gspca_dev, 0x0071, reg71b, 4);
                break;
        default:
-/* case 2: */
-               reg_w(gspca_dev->dev, 0x0071, reg71c, 4);
+/*     case 2: */
+               reg_w(gspca_dev, 0x0071, reg71c, 4);
                break;
        case 3:
-               reg_w(gspca_dev->dev, 0x0071, reg71d, 4);
+               reg_w(gspca_dev, 0x0071, reg71d, 4);
                break;
        }
-       reg_w(gspca_dev->dev, 0x007b, reg7b, 6);
-       val = 0x00;
-       reg_w(gspca_dev->dev, 0x00f8, &val, 1);
-       reg_w(gspca_dev->dev, 0x0010, reg10, 8);
-       val = 0x41;
-       reg_w(gspca_dev->dev, 0x0098, &val, 1);
+       reg_w(gspca_dev, 0x007b, reg7b, 6);
+       reg_w_val(gspca_dev, 0x00f8, 0x00);
+       reg_w(gspca_dev, 0x0010, reg10, 8);
+       reg_w_val(gspca_dev, 0x0098, 0x41);
        for (i = 0; i < 11; i++) {
                if (i == 3 || i == 5 || i == 8)
                        length = 8;
                else
                        length = 4;
-               reg_w(gspca_dev->dev, 0x00e5, ptsensor, length);
+               reg_w(gspca_dev, 0x00e5, ptsensor, length);
                if (length == 4)
-                       reg_r(gspca_dev->dev, 0x00e8, &val, 1);
+                       reg_r(gspca_dev, 0x00e8, 1);
                else
-                       reg_r(gspca_dev->dev, 0x00e8, bufread, length);
+                       reg_r(gspca_dev, 0x00e8, length);
                ptsensor += length;
        }
-       reg_r(gspca_dev->dev, 0x00e7, bufread, 8);
+       reg_r(gspca_dev, 0x00e7, 8);
 }
 
-static __u8 cx_inits_176[] = {
+static const __u8 cx_inits_176[] = {
        0x33, 0x81, 0xB0, 0x00, 0x90, 0x00, 0x0A, 0x03, /* 176x144 */
        0x00, 0x03, 0x03, 0x03, 0x1B, 0x05, 0x30, 0x03,
        0x65, 0x15, 0x18, 0x25, 0x03, 0x25, 0x08, 0x30,
@@ -306,7 +350,7 @@ static __u8 cx_inits_176[] = {
        0xF7, 0xFF, 0x88, 0xFF, 0x66, 0x02, 0x28, 0x02,
        0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
-static __u8 cx_inits_320[] = {
+static const __u8 cx_inits_320[] = {
        0x7f, 0x7f, 0x40, 0x01, 0xf0, 0x00, 0x02, 0x01,
        0x00, 0x01, 0x01, 0x01, 0x10, 0x00, 0x02, 0x01,
        0x65, 0x45, 0xfa, 0x4c, 0x2c, 0xdf, 0xb9, 0x81,
@@ -315,7 +359,7 @@ static __u8 cx_inits_320[] = {
        0xf5, 0xff, 0x6d, 0xff, 0xf6, 0x01, 0x43, 0x02,
        0xd3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
-static __u8 cx_inits_352[] = {
+static const __u8 cx_inits_352[] = {
        0x2e, 0x7c, 0x60, 0x01, 0x20, 0x01, 0x05, 0x03,
        0x00, 0x06, 0x03, 0x06, 0x1b, 0x10, 0x05, 0x3b,
        0x30, 0x25, 0x18, 0x25, 0x08, 0x30, 0x03, 0x25,
@@ -324,7 +368,7 @@ static __u8 cx_inits_352[] = {
        0xf5, 0xff, 0x6b, 0xff, 0xee, 0x01, 0x43, 0x02,
        0xe4, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
-static __u8 cx_inits_640[] = {
+static const __u8 cx_inits_640[] = {
        0x7e, 0x7e, 0x80, 0x02, 0xe0, 0x01, 0x01, 0x01,
        0x00, 0x02, 0x01, 0x02, 0x10, 0x30, 0x01, 0x01,
        0x65, 0x45, 0xf7, 0x52, 0x2c, 0xdf, 0xb9, 0x81,
@@ -334,15 +378,14 @@ static __u8 cx_inits_640[] = {
        0x77, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
-static int cx11646_initsize(struct gspca_dev *gspca_dev)
+static void cx11646_initsize(struct gspca_dev *gspca_dev)
 {
-       __u8 *cxinit;
-       __u8 val;
+       const __u8 *cxinit;
        static const __u8 reg12[] = { 0x08, 0x05, 0x07, 0x04, 0x24 };
        static const __u8 reg17[] =
                        { 0x0a, 0x00, 0xf2, 0x01, 0x0f, 0x00, 0x97, 0x02 };
 
-       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
+       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
        case 0:
                cxinit = cx_inits_640;
                break;
@@ -357,38 +400,32 @@ static int cx11646_initsize(struct gspca_dev *gspca_dev)
                cxinit = cx_inits_176;
                break;
        }
-       val = 0x01;
-       reg_w(gspca_dev->dev, 0x009a, &val, 1);
-       val = 0x10;
-       reg_w(gspca_dev->dev, 0x0010, &val, 1);
-       reg_w(gspca_dev->dev, 0x0012, reg12, 5);
-       reg_w(gspca_dev->dev, 0x0017, reg17, 8);
-       val = 0x00;
-       reg_w(gspca_dev->dev, 0x00c0, &val, 1);
-       val = 0x04;
-       reg_w(gspca_dev->dev, 0x00c1, &val, 1);
-       val = 0x04;
-       reg_w(gspca_dev->dev, 0x00c2, &val, 1);
-
-       reg_w(gspca_dev->dev, 0x0061, cxinit, 8);
+       reg_w_val(gspca_dev, 0x009a, 0x01);
+       reg_w_val(gspca_dev, 0x0010, 0x10);
+       reg_w(gspca_dev, 0x0012, reg12, 5);
+       reg_w(gspca_dev, 0x0017, reg17, 8);
+       reg_w_val(gspca_dev, 0x00c0, 0x00);
+       reg_w_val(gspca_dev, 0x00c1, 0x04);
+       reg_w_val(gspca_dev, 0x00c2, 0x04);
+
+       reg_w(gspca_dev, 0x0061, cxinit, 8);
        cxinit += 8;
-       reg_w(gspca_dev->dev, 0x00ca, cxinit, 8);
+       reg_w(gspca_dev, 0x00ca, cxinit, 8);
        cxinit += 8;
-       reg_w(gspca_dev->dev, 0x00d2, cxinit, 8);
+       reg_w(gspca_dev, 0x00d2, cxinit, 8);
        cxinit += 8;
-       reg_w(gspca_dev->dev, 0x00da, cxinit, 6);
+       reg_w(gspca_dev, 0x00da, cxinit, 6);
        cxinit += 8;
-       reg_w(gspca_dev->dev, 0x0041, cxinit, 8);
+       reg_w(gspca_dev, 0x0041, cxinit, 8);
        cxinit += 8;
-       reg_w(gspca_dev->dev, 0x0049, cxinit, 8);
+       reg_w(gspca_dev, 0x0049, cxinit, 8);
        cxinit += 8;
-       reg_w(gspca_dev->dev, 0x0051, cxinit, 2);
+       reg_w(gspca_dev, 0x0051, cxinit, 2);
 
-       reg_r(gspca_dev->dev, 0x0010, &val, 1);
-       return val;
+       reg_r(gspca_dev, 0x0010, 1);
 }
 
-static __u8 cx_jpeg_init[][8] = {
+static const __u8 cx_jpeg_init[][8] = {
        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x15},       /* 1 */
        {0x0f, 0x10, 0x12, 0x10, 0x0d, 0x15, 0x12, 0x11},
        {0x12, 0x18, 0x16, 0x15, 0x19, 0x20, 0x35, 0x22},
@@ -471,7 +508,7 @@ static __u8 cx_jpeg_init[][8] = {
 };
 
 
-static __u8 cxjpeg_640[][8] = {
+static const __u8 cxjpeg_640[][8] = {
        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x10},       /* 1 */
        {0x0b, 0x0c, 0x0e, 0x0c, 0x0a, 0x10, 0x0e, 0x0d},
        {0x0e, 0x12, 0x11, 0x10, 0x13, 0x18, 0x28, 0x1a},
@@ -500,7 +537,7 @@ static __u8 cxjpeg_640[][8] = {
        {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
        {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}        /* 27 */
 };
-static __u8 cxjpeg_352[][8] = {
+static const __u8 cxjpeg_352[][8] = {
        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
        {0x09, 0x09, 0x0b, 0x09, 0x08, 0x0D, 0x0b, 0x0a},
        {0x0b, 0x0e, 0x0d, 0x0d, 0x0f, 0x13, 0x1f, 0x14},
@@ -529,7 +566,7 @@ static __u8 cxjpeg_352[][8] = {
        {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
        {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 };
-static __u8 cxjpeg_320[][8] = {
+static const __u8 cxjpeg_320[][8] = {
        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x05},
        {0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04, 0x04},
        {0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08},
@@ -558,7 +595,7 @@ static __u8 cxjpeg_320[][8] = {
        {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
        {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}        /* 27 */
 };
-static __u8 cxjpeg_176[][8] = {
+static const __u8 cxjpeg_176[][8] = {
        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x0d},
        {0x09, 0x09, 0x0B, 0x09, 0x08, 0x0D, 0x0B, 0x0A},
        {0x0B, 0x0E, 0x0D, 0x0D, 0x0F, 0x13, 0x1F, 0x14},
@@ -587,7 +624,8 @@ static __u8 cxjpeg_176[][8] = {
        {0x00, 0x01, 0x11, 0x02, 0x11, 0x00, 0x3F, 0x00},
        {0xFF, 0xD9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
 };
-static __u8 cxjpeg_qtable[][8] = {     /* 640 take with the zcx30x part */
+/* 640 take with the zcx30x part */
+static const __u8 cxjpeg_qtable[][8] = {
        {0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x08},
        {0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07, 0x07},
        {0x07, 0x09, 0x09, 0x08, 0x0a, 0x0c, 0x14, 0x0a},
@@ -611,59 +649,50 @@ static __u8 cxjpeg_qtable[][8] = {        /* 640 take with the zcx30x part */
 
 static void cx11646_jpegInit(struct gspca_dev*gspca_dev)
 {
-       __u8 val;
        int i;
        int length;
 
-       val = 0x01;
-       reg_w(gspca_dev->dev, 0x00c0, &val, 1);
-       val = 0x00;
-       reg_w(gspca_dev->dev, 0x00c3, &val, 1);
-       val = 0x00;
-       reg_w(gspca_dev->dev, 0x00c0, &val, 1);
-       reg_r(gspca_dev->dev, 0x0001, &val, 1);
+       reg_w_val(gspca_dev, 0x00c0, 0x01);
+       reg_w_val(gspca_dev, 0x00c3, 0x00);
+       reg_w_val(gspca_dev, 0x00c0, 0x00);
+       reg_r(gspca_dev, 0x0001, 1);
        length = 8;
        for (i = 0; i < 79; i++) {
                if (i == 78)
                        length = 6;
-               reg_w(gspca_dev->dev, 0x0008, cx_jpeg_init[i], length);
+               reg_w(gspca_dev, 0x0008, cx_jpeg_init[i], length);
        }
-       reg_r(gspca_dev->dev, 0x0002, &val, 1);
-       val = 0x14;
-       reg_w(gspca_dev->dev, 0x0055, &val, 1);
+       reg_r(gspca_dev, 0x0002, 1);
+       reg_w_val(gspca_dev, 0x0055, 0x14);
 }
 
-static __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
-static __u8 regE5_8[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
-static __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
-static __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
-static __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
-static __u8 reg51[] = { 0x77, 0x03 };
-static __u8 reg70 = 0x03;
+static const __u8 reg12[] = { 0x0a, 0x05, 0x07, 0x04, 0x19 };
+static const __u8 regE5_8[] =
+               { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
+static const __u8 regE5a[] = { 0x88, 0x0a, 0x0c, 0x01 };
+static const __u8 regE5b[] = { 0x88, 0x0b, 0x12, 0x01 };
+static const __u8 regE5c[] = { 0x88, 0x05, 0x01, 0x01 };
+static const __u8 reg51[] = { 0x77, 0x03 };
+#define reg70 0x03
 
 static void cx11646_jpeg(struct gspca_dev*gspca_dev)
 {
-       __u8 val;
        int i;
-       int length = 8;
-       __u8 Reg55 = 0x14;
-       __u8 bufread[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-       int retry = 50;
+       int length;
+       __u8 Reg55;
+       int retry;
 
-       val = 0x01;
-       reg_w(gspca_dev->dev, 0x00c0, &val, 1);
-       val = 0x00;
-       reg_w(gspca_dev->dev, 0x00c3, &val, 1);
-       val = 0x00;
-       reg_w(gspca_dev->dev, 0x00c0, &val, 1);
-       reg_r(gspca_dev->dev, 0x0001, &val, 1);
-       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode) {
+       reg_w_val(gspca_dev, 0x00c0, 0x01);
+       reg_w_val(gspca_dev, 0x00c3, 0x00);
+       reg_w_val(gspca_dev, 0x00c0, 0x00);
+       reg_r(gspca_dev, 0x0001, 1);
+       length = 8;
+       switch (gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv) {
        case 0:
                for (i = 0; i < 27; i++) {
                        if (i == 26)
                                length = 2;
-                       reg_w(gspca_dev->dev, 0x0008,
-                                       cxjpeg_640[i], length);
+                       reg_w(gspca_dev, 0x0008, cxjpeg_640[i], length);
                }
                Reg55 = 0x28;
                break;
@@ -671,8 +700,7 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev)
                for (i = 0; i < 27; i++) {
                        if (i == 26)
                                length = 2;
-                       reg_w(gspca_dev->dev, 0x0008,
-                                       cxjpeg_352[i], length);
+                       reg_w(gspca_dev, 0x0008, cxjpeg_352[i], length);
                }
                Reg55 = 0x16;
                break;
@@ -681,8 +709,7 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev)
                for (i = 0; i < 27; i++) {
                        if (i == 26)
                                length = 2;
-                       reg_w(gspca_dev->dev, 0x0008,
-                                       cxjpeg_320[i], length);
+                       reg_w(gspca_dev, 0x0008, cxjpeg_320[i], length);
                }
                Reg55 = 0x14;
                break;
@@ -690,125 +717,98 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev)
                for (i = 0; i < 27; i++) {
                        if (i == 26)
                                length = 2;
-                       reg_w(gspca_dev->dev, 0x0008,
-                                       cxjpeg_176[i], length);
+                       reg_w(gspca_dev, 0x0008, cxjpeg_176[i], length);
                }
                Reg55 = 0x0B;
                break;
        }
 
-       reg_r(gspca_dev->dev, 0x0002, &val, 1);
-       val = Reg55;
-       reg_w(gspca_dev->dev, 0x0055, &val, 1);
-       reg_r(gspca_dev->dev, 0x0002, &val, 1);
-       reg_w(gspca_dev->dev, 0x0010, reg10, 2);
-       val = 0x02;
-       reg_w(gspca_dev->dev, 0x0054, &val, 1);
-       val = 0x01;
-       reg_w(gspca_dev->dev, 0x0054, &val, 1);
-       val = 0x94;
-       reg_w(gspca_dev->dev, 0x0000, &val, 1);
-       val = 0xc0;
-       reg_w(gspca_dev->dev, 0x0053, &val, 1);
-       val = 0xe1;
-       reg_w(gspca_dev->dev, 0x00fc, &val, 1);
-       val = 0x00;
-       reg_w(gspca_dev->dev, 0x0000, &val, 1);
+       reg_r(gspca_dev, 0x0002, 1);
+       reg_w_val(gspca_dev, 0x0055, Reg55);
+       reg_r(gspca_dev, 0x0002, 1);
+       reg_w(gspca_dev, 0x0010, reg10, 2);
+       reg_w_val(gspca_dev, 0x0054, 0x02);
+       reg_w_val(gspca_dev, 0x0054, 0x01);
+       reg_w_val(gspca_dev, 0x0000, 0x94);
+       reg_w_val(gspca_dev, 0x0053, 0xc0);
+       reg_w_val(gspca_dev, 0x00fc, 0xe1);
+       reg_w_val(gspca_dev, 0x0000, 0x00);
        /* wait for completion */
-       while (retry--) {
-               reg_r(gspca_dev->dev, 0x0002, &val, 1);
+       retry = 50;
+       do {
+               reg_r(gspca_dev, 0x0002, 1);
                                                        /* 0x07 until 0x00 */
-               if (val == 0x00)
+               if (gspca_dev->usb_buf[0] == 0x00)
                        break;
-               val = 0x00;
-               reg_w(gspca_dev->dev, 0x0053, &val, 1);
-       }
+               reg_w_val(gspca_dev, 0x0053, 0x00);
+       } while (--retry);
        if (retry == 0)
                PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
        /* send the qtable now */
-       reg_r(gspca_dev->dev, 0x0001, &val, 1);         /* -> 0x18 */
+       reg_r(gspca_dev, 0x0001, 1);            /* -> 0x18 */
        length = 8;
        for (i = 0; i < 18; i++) {
                if (i == 17)
                        length = 2;
-               reg_w(gspca_dev->dev, 0x0008,
-                               cxjpeg_qtable[i], length);
+               reg_w(gspca_dev, 0x0008, cxjpeg_qtable[i], length);
 
        }
-       reg_r(gspca_dev->dev, 0x0002, &val, 1); /* 0x00 */
-       reg_r(gspca_dev->dev, 0x0053, &val, 1); /* 0x00 */
-       val = 0x02;
-       reg_w(gspca_dev->dev, 0x0054, &val, 1);
-       val = 0x01;
-       reg_w(gspca_dev->dev, 0x0054, &val, 1);
-       val = 0x94;
-       reg_w(gspca_dev->dev, 0x0000, &val, 1);
-       val = 0xc0;
-       reg_w(gspca_dev->dev, 0x0053, &val, 1);
-
-       reg_r(gspca_dev->dev, 0x0038, &val, 1); /* 0x40 */
-       reg_r(gspca_dev->dev, 0x0038, &val, 1); /* 0x40 */
-       reg_r(gspca_dev->dev, 0x001f, &val, 1); /* 0x38 */
-       reg_w(gspca_dev->dev, 0x0012, reg12, 5);
-       reg_w(gspca_dev->dev, 0x00e5, regE5_8, 8);
-       reg_r(gspca_dev->dev, 0x00e8, bufread, 8);
-       reg_w(gspca_dev->dev, 0x00e5, regE5a, 4);
-       reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
-       val = 0x01;
-       reg_w(gspca_dev->dev, 0x009a, &val, 1);
-       reg_w(gspca_dev->dev, 0x00e5, regE5b, 4);
-       reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
-       reg_w(gspca_dev->dev, 0x00e5, regE5c, 4);
-       reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
-
-       reg_w(gspca_dev->dev, 0x0051, reg51, 2);
-       reg_w(gspca_dev->dev, 0x0010, reg10, 2);
-       reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
+       reg_r(gspca_dev, 0x0002, 1);    /* 0x00 */
+       reg_r(gspca_dev, 0x0053, 1);    /* 0x00 */
+       reg_w_val(gspca_dev, 0x0054, 0x02);
+       reg_w_val(gspca_dev, 0x0054, 0x01);
+       reg_w_val(gspca_dev, 0x0000, 0x94);
+       reg_w_val(gspca_dev, 0x0053, 0xc0);
+
+       reg_r(gspca_dev, 0x0038, 1);            /* 0x40 */
+       reg_r(gspca_dev, 0x0038, 1);            /* 0x40 */
+       reg_r(gspca_dev, 0x001f, 1);            /* 0x38 */
+       reg_w(gspca_dev, 0x0012, reg12, 5);
+       reg_w(gspca_dev, 0x00e5, regE5_8, 8);
+       reg_r(gspca_dev, 0x00e8, 8);
+       reg_w(gspca_dev, 0x00e5, regE5a, 4);
+       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
+       reg_w_val(gspca_dev, 0x009a, 0x01);
+       reg_w(gspca_dev, 0x00e5, regE5b, 4);
+       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
+       reg_w(gspca_dev, 0x00e5, regE5c, 4);
+       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
+
+       reg_w(gspca_dev, 0x0051, reg51, 2);
+       reg_w(gspca_dev, 0x0010, reg10, 2);
+       reg_w_val(gspca_dev, 0x0070, reg70);
 }
 
 static void cx11646_init1(struct gspca_dev *gspca_dev)
 {
-       __u8 val;
        int i = 0;
 
-       val = 0;
-       reg_w(gspca_dev->dev, 0x0010, &val, 1);
-       reg_w(gspca_dev->dev, 0x0053, &val, 1);
-       reg_w(gspca_dev->dev, 0x0052, &val, 1);
-       val = 0x2f;
-       reg_w(gspca_dev->dev, 0x009b, &val, 1);
-       val = 0x10;
-       reg_w(gspca_dev->dev, 0x009c, &val, 1);
-       reg_r(gspca_dev->dev, 0x0098, &val, 1);
-       val = 0x40;
-       reg_w(gspca_dev->dev, 0x0098, &val, 1);
-       reg_r(gspca_dev->dev, 0x0099, &val, 1);
-       val = 0x07;
-       reg_w(gspca_dev->dev, 0x0099, &val, 1);
-       val = 0x40;
-       reg_w(gspca_dev->dev, 0x0039, &val, 1);
-       val = 0xff;
-       reg_w(gspca_dev->dev, 0x003c, &val, 1);
-       val = 0x1f;
-       reg_w(gspca_dev->dev, 0x003f, &val, 1);
-       val = 0x40;
-       reg_w(gspca_dev->dev, 0x003d, &val, 1);
-/* val= 0x60; */
-/* reg_w(gspca_dev->dev,0x00,0x00,0x003d,&val,1); */
-       reg_r(gspca_dev->dev, 0x0099, &val, 1);                 /* ->0x07 */
+       reg_w_val(gspca_dev, 0x0010, 0x00);
+       reg_w_val(gspca_dev, 0x0053, 0x00);
+       reg_w_val(gspca_dev, 0x0052, 0x00);
+       reg_w_val(gspca_dev, 0x009b, 0x2f);
+       reg_w_val(gspca_dev, 0x009c, 0x10);
+       reg_r(gspca_dev, 0x0098, 1);
+       reg_w_val(gspca_dev, 0x0098, 0x40);
+       reg_r(gspca_dev, 0x0099, 1);
+       reg_w_val(gspca_dev, 0x0099, 0x07);
+       reg_w_val(gspca_dev, 0x0039, 0x40);
+       reg_w_val(gspca_dev, 0x003c, 0xff);
+       reg_w_val(gspca_dev, 0x003f, 0x1f);
+       reg_w_val(gspca_dev, 0x003d, 0x40);
+/*     reg_w_val(gspca_dev, 0x003d, 0x60); */
+       reg_r(gspca_dev, 0x0099, 1);                    /* ->0x07 */
 
        while (cx_sensor_init[i][0]) {
-               reg_w(gspca_dev->dev, 0x00e5, cx_sensor_init[i], 1);
-               reg_r(gspca_dev->dev, 0x00e8, &val, 1);         /* -> 0x00 */
+               reg_w_val(gspca_dev, 0x00e5, cx_sensor_init[i][0]);
+               reg_r(gspca_dev, 0x00e8, 1);            /* -> 0x00 */
                if (i == 1) {
-                       val = 1;
-                       reg_w(gspca_dev->dev, 0x00ed, &val, 1);
-                       reg_r(gspca_dev->dev, 0x00ed, &val, 1); /* -> 0x01 */
+                       reg_w_val(gspca_dev, 0x00ed, 0x01);
+                       reg_r(gspca_dev, 0x00ed, 1);    /* -> 0x01 */
                }
                i++;
        }
-       val = 0x00;
-       reg_w(gspca_dev->dev, 0x00c3, &val, 1);
+       reg_w_val(gspca_dev, 0x00c3, 0x00);
 }
 
 /* this function is called at probe time */
@@ -819,20 +819,18 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct cam *cam;
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
-       cam->epaddr = 0x01;
        cam->cam_mode = vga_mode;
-       cam->nmodes = sizeof vga_mode / sizeof vga_mode[0];
+       cam->nmodes = ARRAY_SIZE(vga_mode);
 
-       sd->qindex = 0;                 /* set the quantization table */
-       sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
-       sd->contrast = sd_ctrls[SD_CONTRAST].qctrl.default_value;
-       sd->colors = sd_ctrls[SD_COLOR].qctrl.default_value;
+       sd->brightness = BRIGHTNESS_DEF;
+       sd->contrast = CONTRAST_DEF;
+       sd->colors = COLOR_DEF;
+       sd->quality = QUALITY_DEF;
        return 0;
 }
 
-/* this function is called at open time */
-static int sd_open(struct gspca_dev *gspca_dev)
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
 {
        cx11646_init1(gspca_dev);
        cx11646_initsize(gspca_dev);
@@ -842,55 +840,60 @@ static int sd_open(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       /* create the JPEG header */
+       sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
+       if (!sd->jpeg_hdr)
+               return -ENOMEM;
+       jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
+                       0x22);          /* JPEG 411 */
+       jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+
        cx11646_initsize(gspca_dev);
        cx11646_fw(gspca_dev);
        cx_sensor(gspca_dev);
        cx11646_jpeg(gspca_dev);
+       return 0;
 }
 
-static void sd_stopN(struct gspca_dev *gspca_dev)
-{
-}
-
+/* called on streamoff with alt 0 and on disconnect */
 static void sd_stop0(struct gspca_dev *gspca_dev)
 {
+       struct sd *sd = (struct sd *) gspca_dev;
        int retry = 50;
-       __u8 val;
 
-       val = 0;
-       reg_w(gspca_dev->dev, 0x0000, &val, 1);
-       reg_r(gspca_dev->dev, 0x0002, &val, 1);
-       val = 0;
-       reg_w(gspca_dev->dev, 0x0053, &val, 1);
+       kfree(sd->jpeg_hdr);
+
+       if (!gspca_dev->present)
+               return;
+       reg_w_val(gspca_dev, 0x0000, 0x00);
+       reg_r(gspca_dev, 0x0002, 1);
+       reg_w_val(gspca_dev, 0x0053, 0x00);
 
        while (retry--) {
-/*             reg_r (gspca_dev->dev,0x00,0x00,0x0002,&val,1);*/
-               reg_r(gspca_dev->dev, 0x0053, &val, 1);
-               if (val == 0)
+/*             reg_r(gspca_dev, 0x0002, 1);*/
+               reg_r(gspca_dev, 0x0053, 1);
+               if (gspca_dev->usb_buf[0] == 0)
                        break;
        }
-       val = 0;
-       reg_w(gspca_dev->dev, 0x0000, &val, 1);
-       reg_r(gspca_dev->dev, 0x0002, &val, 1);
-
-       val = 0;
-       reg_w(gspca_dev->dev, 0x0010, &val, 1);
-       reg_r(gspca_dev->dev, 0x0033, &val, 1);
-       val = 0xe0;
-       reg_w(gspca_dev->dev, 0x00fc, &val, 1);
-}
+       reg_w_val(gspca_dev, 0x0000, 0x00);
+       reg_r(gspca_dev, 0x0002, 1);
 
-static void sd_close(struct gspca_dev *gspca_dev)
-{
+       reg_w_val(gspca_dev, 0x0010, 0x00);
+       reg_r(gspca_dev, 0x0033, 1);
+       reg_w_val(gspca_dev, 0x00fc, 0xe0);
 }
 
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
-                       unsigned char *data,            /* isoc packet */
+                       __u8 *data,                     /* isoc packet */
                        int len)                        /* iso packet length */
 {
+       struct sd *sd = (struct sd *) gspca_dev;
+
        if (data[0] == 0xff && data[1] == 0xd8) {
 
                /* start of frame */
@@ -898,9 +901,8 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                                        data, 0);
 
                /* put the JPEG header in the new frame */
-               jpeg_put_header(gspca_dev, frame,
-                               ((struct sd *) gspca_dev)->qindex,
-                               0x22);
+               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                       sd->jpeg_hdr, JPEG_HDR_SZ);
                data += 2;
                len -= 2;
        }
@@ -911,41 +913,40 @@ static void setbrightness(struct gspca_dev*gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        __u8 regE5cbx[] = { 0x88, 0x00, 0xd4, 0x01, 0x88, 0x01, 0x01, 0x01 };
-       __u8 reg51c[] = { 0x77, 0x03 };
+       __u8 reg51c[2];
        __u8 bright;
        __u8 colors;
-       __u8 val;
-       __u8 bufread[8];
 
        bright = sd->brightness;
-       colors = sd->colors;
        regE5cbx[2] = bright;
+       reg_w(gspca_dev, 0x00e5, regE5cbx, 8);
+       reg_r(gspca_dev, 0x00e8, 8);
+       reg_w(gspca_dev, 0x00e5, regE5c, 4);
+       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
+
+       colors = sd->colors;
+       reg51c[0] = 0x77;
        reg51c[1] = colors;
-       reg_w(gspca_dev->dev, 0x00e5, regE5cbx, 8);
-       reg_r(gspca_dev->dev, 0x00e8, bufread, 8);
-       reg_w(gspca_dev->dev, 0x00e5, regE5c, 4);
-       reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
-
-       reg_w(gspca_dev->dev, 0x0051, reg51c, 2);
-       reg_w(gspca_dev->dev, 0x0010, reg10, 2);
-       reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
+       reg_w(gspca_dev, 0x0051, reg51c, 2);
+       reg_w(gspca_dev, 0x0010, reg10, 2);
+       reg_w_val(gspca_dev, 0x0070, reg70);
 }
 
 static void setcontrast(struct gspca_dev*gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
        __u8 regE5acx[] = { 0x88, 0x0a, 0x0c, 0x01 };   /* seem MSB */
-       /* __u8 regE5bcx[]={0x88,0x0b,0x12,0x01}; // LSB */
-       __u8 reg51c[] = { 0x77, 0x03 };
-       __u8 val;
+/*     __u8 regE5bcx[] = { 0x88, 0x0b, 0x12, 0x01};     * LSB */
+       __u8 reg51c[2];
 
-       reg51c[1] = sd->colors;
        regE5acx[2] = sd->contrast;
-       reg_w(gspca_dev->dev, 0x00e5, regE5acx, 4);
-       reg_r(gspca_dev->dev, 0x00e8, &val, 1); /* 0x00 */
-       reg_w(gspca_dev->dev, 0x0051, reg51c, 2);
-       reg_w(gspca_dev->dev, 0x0010, reg10, 2);
-       reg_w(gspca_dev->dev, 0x0070, &reg70, 1);
+       reg_w(gspca_dev, 0x00e5, regE5acx, 4);
+       reg_r(gspca_dev, 0x00e8, 1);            /* 0x00 */
+       reg51c[0] = 0x77;
+       reg51c[1] = sd->colors;
+       reg_w(gspca_dev, 0x0051, reg51c, 2);
+       reg_w(gspca_dev, 0x0010, reg10, 2);
+       reg_w_val(gspca_dev, 0x0070, reg70);
 }
 
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
@@ -1004,24 +1005,51 @@ static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val)
        return 0;
 }
 
+static int sd_set_jcomp(struct gspca_dev *gspca_dev,
+                       struct v4l2_jpegcompression *jcomp)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       if (jcomp->quality < QUALITY_MIN)
+               sd->quality = QUALITY_MIN;
+       else if (jcomp->quality > QUALITY_MAX)
+               sd->quality = QUALITY_MAX;
+       else
+               sd->quality = jcomp->quality;
+       if (gspca_dev->streaming)
+               jpeg_set_qual(sd->jpeg_hdr, sd->quality);
+       return 0;
+}
+
+static int sd_get_jcomp(struct gspca_dev *gspca_dev,
+                       struct v4l2_jpegcompression *jcomp)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       memset(jcomp, 0, sizeof *jcomp);
+       jcomp->quality = sd->quality;
+       jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT
+                       | V4L2_JPEG_MARKER_DQT;
+       return 0;
+}
+
 /* sub-driver description */
 static struct sd_desc sd_desc = {
        .name = MODULE_NAME,
        .ctrls = sd_ctrls,
        .nctrls = ARRAY_SIZE(sd_ctrls),
        .config = sd_config,
-       .open = sd_open,
+       .init = sd_init,
        .start = sd_start,
-       .stopN = sd_stopN,
        .stop0 = sd_stop0,
-       .close = sd_close,
        .pkt_scan = sd_pkt_scan,
+       .get_jcomp = sd_get_jcomp,
+       .set_jcomp = sd_set_jcomp,
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
 static __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x0572, 0x0041), DVNM("Creative Notebook cx11646")},
+       {USB_DEVICE(0x0572, 0x0041)},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -1039,14 +1067,20 @@ static struct usb_driver sd_driver = {
        .id_table = device_table,
        .probe = sd_probe,
        .disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+       .suspend = gspca_suspend,
+       .resume = gspca_resume,
+#endif
 };
 
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-       if (usb_register(&sd_driver) < 0)
-               return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       int ret;
+       ret = usb_register(&sd_driver);
+       if (ret < 0)
+               return ret;
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)