V4L/DVB (9877): gspca - ov534: Add framerate support.
[safe/jmp/linux-2.6] / drivers / media / video / gspca / spca508.c
index 2ccd877..63ec902 100644 (file)
@@ -22,9 +22,6 @@
 
 #include "gspca.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/SPCA508 USB Camera Driver");
 MODULE_LICENSE("GPL");
@@ -33,10 +30,6 @@ MODULE_LICENSE("GPL");
 struct sd {
        struct gspca_dev gspca_dev;             /* !! must be the first item */
 
-       int buflen;
-       unsigned char tmpbuf[352 * 288 * 3 / 2]; /* YUVY per line */
-       unsigned char tmpbuf2[352 * 288 * 2];   /* YUYV */
-
        unsigned char brightness;
 
        char subtype;
@@ -53,27 +46,43 @@ static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val);
 static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val);
 
 static struct ctrl sd_ctrls[] = {
-#define SD_BRIGHTNESS 0
        {
            {
                .id      = V4L2_CID_BRIGHTNESS,
                .type    = V4L2_CTRL_TYPE_INTEGER,
                .name    = "Brightness",
                .minimum = 0,
-               .maximum = 0xff,
+               .maximum = 255,
                .step    = 1,
-               .default_value = 0x80,
+#define BRIGHTNESS_DEF 128
+               .default_value = BRIGHTNESS_DEF,
            },
            .set = sd_setbrightness,
            .get = sd_getbrightness,
        },
 };
 
-static struct cam_mode sif_mode[] = {
-       {V4L2_PIX_FMT_YUYV, 160, 120, 3},
-       {V4L2_PIX_FMT_YUYV, 176, 144, 2},
-       {V4L2_PIX_FMT_YUYV, 320, 240, 1},
-       {V4L2_PIX_FMT_YUYV, 352, 288, 0},
+static struct v4l2_pix_format sif_mode[] = {
+       {160, 120, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+               .bytesperline = 160,
+               .sizeimage = 160 * 120 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 3},
+       {176, 144, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+               .bytesperline = 176,
+               .sizeimage = 176 * 144 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 2},
+       {320, 240, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+               .bytesperline = 320,
+               .sizeimage = 320 * 240 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 1},
+       {352, 288, V4L2_PIX_FMT_SPCA508, V4L2_FIELD_NONE,
+               .bytesperline = 352,
+               .sizeimage = 352 * 288 * 3 / 2,
+               .colorspace = V4L2_COLORSPACE_SRGB,
+               .priv = 0},
 };
 
 /* Frame packet header offsets for the spca508 */
@@ -92,7 +101,7 @@ static struct cam_mode sif_mode[] = {
  * Initialization data: this is the first set-up data written to the
  * device (before the open data).
  */
-static __u16 spca508_init_data[][3] =
+static const __u16 spca508_init_data[][3] =
 #define IGN(x)                 /* nothing */
 {
        /*  line   URB      value, index */
@@ -577,14 +586,14 @@ static __u16 spca508_init_data[][3] =
        /* Video drop enable, ISO streaming disable */
        /* 53252  2165 */
             /* UNKNOWN DIRECTION (URB_FUNCTION_SELECT_INTERFACE: (ALT=0) ) */
-       {0, 0}
+       {}
 };
 
 
 /*
  * Initialization data for Intel EasyPC Camera CS110
  */
-static __u16 spca508cs110_init_data[][3] = {
+static const __u16 spca508cs110_init_data[][3] = {
        {0x0000, 0x870b}, /* Reset CTL3 */
        {0x0003, 0x8111}, /* Soft Reset compression, memory, TG & CDSP */
        {0x0000, 0x8111}, /* Normal operation on reset */
@@ -668,7 +677,7 @@ static __u16 spca508cs110_init_data[][3] = {
        {}
 };
 
-static __u16 spca508_sightcam_init_data[][3] = {
+static const __u16 spca508_sightcam_init_data[][3] = {
 /* This line seems to setup the frame/canvas */
        /*368  */ {0x000f, 0x8402},
 
@@ -748,11 +757,10 @@ static __u16 spca508_sightcam_init_data[][3] = {
        /*542  */ {0x0040, 0x8652},
        /*543  */ {0x004c, 0x8653},
        /*544  */ {0x0040, 0x8654},
-
-       {0, 0}
+       {}
 };
 
-static __u16 spca508_sightcam2_init_data[][3] = {
+static const __u16 spca508_sightcam2_init_data[][3] = {
 /* 35 */ {0x0020, 0x8112},
 
 /* 36 */ {0x000f, 0x8402},
@@ -1099,7 +1107,7 @@ static __u16 spca508_sightcam2_init_data[][3] = {
 /*
  * Initialization data for Creative Webcam Vista
  */
-static __u16 spca508_vista_init_data[][3] = {
+static const __u16 spca508_vista_init_data[][3] = {
        {0x0008, 0x8200},       /* Clear register */
        {0x0000, 0x870b},       /* Reset CTL3 */
        {0x0020, 0x8112},       /* Video Drop packet enable */
@@ -1418,30 +1426,30 @@ static int reg_write(struct usb_device *dev,
 
 /* read 1 byte */
 /* returns: negative is error, pos or zero is data */
-static int reg_read(struct usb_device *dev,
+static int reg_read(struct gspca_dev *gspca_dev,
                        __u16 index)    /* wIndex */
 {
        int ret;
-       __u8 data;
 
-       ret = usb_control_msg(dev,
-                       usb_rcvctrlpipe(dev, 0),
+       ret = usb_control_msg(gspca_dev->dev,
+                       usb_rcvctrlpipe(gspca_dev->dev, 0),
                        0,                      /* register */
                        USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-                       (__u16) 0,              /* value */
+                       0,              /* value */
                        index,
-                       &data, 1,
+                       gspca_dev->usb_buf, 1,
                        500);                   /* timeout */
-       PDEBUG(D_USBI, "reg read i:%04x --> %02x", index, data);
+       PDEBUG(D_USBI, "reg read i:%04x --> %02x",
+               index, gspca_dev->usb_buf[0]);
        if (ret < 0) {
                PDEBUG(D_ERR|D_USBI, "reg_read err %d", ret);
                return ret;
        }
-       return data;
+       return gspca_dev->usb_buf[0];
 }
 
 static int write_vector(struct gspca_dev *gspca_dev,
-                               __u16 data[][3])
+                       const __u16 data[][3])
 {
        struct usb_device *dev = gspca_dev->dev;
        int ret, i = 0;
@@ -1460,81 +1468,31 @@ static int sd_config(struct gspca_dev *gspca_dev,
                        const struct usb_device_id *id)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       struct usb_device *dev = gspca_dev->dev;
        struct cam *cam;
-       __u16 vendor;
-       __u16 product;
        int data1, data2;
 
-       vendor = id->idVendor;
-       product = id->idProduct;
-       switch (vendor) {
-       case 0x041e:            /* Creative cameras */
-/*             switch (product) { */
-/*             case 0x4018: */
-                       sd->subtype = CreativeVista;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0461:            /* MicroInnovation */
-/*             switch (product) { */
-/*             case 0x0815: */
-                       sd->subtype = MicroInnovationIC200;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0733:    /* Rebadged ViewQuest (Intel) and ViewQuest cameras */
-/*             switch (product) { */
-/*             case 0x110: */
-                       sd->subtype = ViewQuestVQ110;
-/*                     break; */
-/*             } */
-               break;
-       case 0x0130:            /* Clone webcam */
-       case 0x0af9:            /* Hama cameras */
-               switch (product) {
-               case 0x0130:
-               case 0x0010:
-                       sd->subtype = HamaUSBSightcam;
-                       break;
-               case 0x0011:
-                       sd->subtype = HamaUSBSightcam2;
-                       break;
-               }
-               break;
-       case 0x8086:            /* Intel */
-/*             switch (product) { */
-/*             case 0x0110: */
-                       sd->subtype = IntelEasyPCCamera;
-/*                     break; */
-/*             } */
-               break;
-       }
+       /* Read from global register the USB product and vendor IDs, just to
+        * prove that we can communicate with the device.  This works, which
+        * confirms at we are communicating properly and that the device
+        * is a 508. */
+       data1 = reg_read(gspca_dev, 0x8104);
+       data2 = reg_read(gspca_dev, 0x8105);
+       PDEBUG(D_PROBE, "Webcam Vendor ID: 0x%02x%02x", data2, data1);
 
-       /* Read from global register the USB product and vendor IDs, just to */
-       /* prove that we can communicate with the device.  This works, which */
-       /* confirms at we are communicating properly and that the device */
-       /* is a 508. */
-       data1 = reg_read(dev, 0x8104);
-       data2 = reg_read(dev, 0x8105);
-       PDEBUG(D_PROBE,
-               "Read from GLOBAL: USB Vendor ID 0x%02x%02x", data2, data1);
+       data1 = reg_read(gspca_dev, 0x8106);
+       data2 = reg_read(gspca_dev, 0x8107);
+       PDEBUG(D_PROBE, "Webcam Product ID: 0x%02x%02x", data2, data1);
 
-       data1 = reg_read(dev, 0x8106);
-       data2 = reg_read(dev, 0x8107);
-       PDEBUG(D_PROBE,
-               "Read from GLOBAL: USB Product ID 0x%02x%02x", data2, data1);
-
-       data1 = reg_read(dev, 0x8621);
-       PDEBUG(D_PROBE,
-               "Read from GLOBAL: Window 1 average luminance %d", data1);
+       data1 = reg_read(gspca_dev, 0x8621);
+       PDEBUG(D_PROBE, "Window 1 average luminance: %d", data1);
 
        cam = &gspca_dev->cam;
-       cam->dev_name = (char *) id->driver_info;
        cam->epaddr = 0x01;
        cam->cam_mode = sif_mode;
-       cam->nmodes = sizeof sif_mode / sizeof sif_mode[0];
-       sd->brightness = sd_ctrls[SD_BRIGHTNESS].qctrl.default_value;
+       cam->nmodes = ARRAY_SIZE(sif_mode);
+
+       sd->subtype = id->driver_info;
+       sd->brightness = BRIGHTNESS_DEF;
 
        switch (sd->subtype) {
        case ViewQuestVQ110:
@@ -1563,18 +1521,18 @@ static int sd_config(struct gspca_dev *gspca_dev,
        return 0;                       /* success */
 }
 
-/* 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)
 {
 /*     write_vector(gspca_dev, spca508_open_data); */
        return 0;
 }
 
-static void sd_start(struct gspca_dev *gspca_dev)
+static int sd_start(struct gspca_dev *gspca_dev)
 {
        int mode;
 
-       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].mode;
+       mode = gspca_dev->cam.cam_mode[(int) gspca_dev->curr_mode].priv;
        reg_write(gspca_dev->dev, 0x8500, mode);
        switch (mode) {
        case 0:
@@ -1588,6 +1546,7 @@ static void sd_start(struct gspca_dev *gspca_dev)
                break;
        }
        reg_write(gspca_dev->dev, 0x8112, 0x10 | 0x20);
+       return 0;
 }
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
@@ -1596,86 +1555,30 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
        reg_write(gspca_dev->dev, 0x8112, 0x20);
 }
 
-static void sd_stop0(struct gspca_dev *gspca_dev)
-{
-}
-
-/* this function is called at close time */
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
-/* convert YUVY per line to YUYV (YUV 4:2:2) */
-static void yuvy_decode(unsigned char *out,
-                       unsigned char *in,
-                       int width,
-                       int height)
-{
-       unsigned char *Ui, *Vi, *yi, *yi1;
-       unsigned char *out1;
-       int i, j;
-
-       yi = in;
-       for (i = height / 2; --i >= 0; ) {
-               out1 = out + width * 2;         /* next line */
-               Ui = yi + width;
-               Vi = Ui + width / 2;
-               yi1 = Vi + width / 2;
-               for (j = width / 2; --j >= 0; ) {
-                       *out++ = 128 + *yi++;
-                       *out++ = 128 + *Ui;
-                       *out++ = 128 + *yi++;
-                       *out++ = 128 + *Vi;
-
-                       *out1++ = 128 + *yi1++;
-                       *out1++ = 128 + *Ui++;
-                       *out1++ = 128 + *yi1++;
-                       *out1++ = 128 + *Vi++;
-               }
-               yi += width * 2;
-               out = out1;
-       }
-}
-
 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;
-
        switch (data[0]) {
        case 0:                         /* start of frame */
-               if (gspca_dev->last_packet_type == FIRST_PACKET) {
-                       yuvy_decode(sd->tmpbuf2, sd->tmpbuf,
-                                       gspca_dev->width,
-                                       gspca_dev->height);
-                       frame = gspca_frame_add(gspca_dev,
-                                               LAST_PACKET,
-                                               frame,
-                                               sd->tmpbuf2,
-                                               gspca_dev->width
-                                                       * gspca_dev->height
-                                                       * 2);
-               }
-               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
-                               data, 0);
+               frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
+                                       data, 0);
                data += SPCA508_OFFSET_DATA;
                len -= SPCA508_OFFSET_DATA;
-               if (len > 0)
-                       memcpy(sd->tmpbuf, data, len);
-               else
-                       len = 0;
-               sd->buflen = len;
-               return;
+               gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
+                               data, len);
+               break;
        case 0xff:                      /* drop */
 /*             gspca_dev->last_packet_type = DISCARD_PACKET; */
-               return;
+               break;
+       default:
+               data += 1;
+               len -= 1;
+               gspca_frame_add(gspca_dev, INTER_PACKET, frame,
+                               data, len);
+               break;
        }
-       data += 1;
-       len -= 1;
-       memcpy(&sd->tmpbuf[sd->buflen], data, len);
-       sd->buflen += len;
 }
 
 static void setbrightness(struct gspca_dev *gspca_dev)
@@ -1683,7 +1586,7 @@ static void setbrightness(struct gspca_dev *gspca_dev)
        struct sd *sd = (struct sd *) gspca_dev;
        __u8 brightness = sd->brightness;
 
-/* MX seem contrast */
+       /* MX seem contrast */
        reg_write(gspca_dev->dev, 0x8651, brightness);
        reg_write(gspca_dev->dev, 0x8652, brightness);
        reg_write(gspca_dev->dev, 0x8653, brightness);
@@ -1694,7 +1597,7 @@ static void getbrightness(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-       sd->brightness = reg_read(gspca_dev->dev, 0x8651);
+       sd->brightness = reg_read(gspca_dev, 0x8651);
 }
 
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
@@ -1717,30 +1620,26 @@ static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val)
 }
 
 /* sub-driver description */
-static struct sd_desc sd_desc = {
+static const 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,
 };
 
 /* -- module initialisation -- */
-#define DVNM(name) .driver_info = (kernel_ulong_t) name
-static __devinitdata struct usb_device_id device_table[] = {
-       {USB_DEVICE(0x041e, 0x4018), DVNM("Creative Webcam Vista (PD1100)")},
-       {USB_DEVICE(0x0461, 0x0815), DVNM("Micro Innovation IC200")},
-       {USB_DEVICE(0x0733, 0x0110), DVNM("ViewQuest VQ110")},
-       {USB_DEVICE(0x0af9, 0x0010), DVNM("Hama USB Sightcam 100")},
-       {USB_DEVICE(0x0af9, 0x0011), DVNM("Hama USB Sightcam 100")},
-       {USB_DEVICE(0x8086, 0x0110), DVNM("Intel Easy PC Camera")},
-       {USB_DEVICE(0x0130, 0x0130),
-               DVNM("Clone Digital Webcam 11043 (spca508a)")},
+static const __devinitdata struct usb_device_id device_table[] = {
+       {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam},
+       {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista},
+       {USB_DEVICE(0x0461, 0x0815), .driver_info = MicroInnovationIC200},
+       {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110},
+       {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam},
+       {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2},
+       {USB_DEVICE(0x8086, 0x0110), .driver_info = IntelEasyPCCamera},
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
@@ -1758,6 +1657,10 @@ 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 -- */
@@ -1765,7 +1668,7 @@ static int __init sd_mod_init(void)
 {
        if (usb_register(&sd_driver) < 0)
                return -1;
-       PDEBUG(D_PROBE, "v%s registered", version);
+       PDEBUG(D_PROBE, "registered");
        return 0;
 }
 static void __exit sd_mod_exit(void)