V4L/DVB (13422): gspca - ov534: ov772x changes from Richard Kaswy.
[safe/jmp/linux-2.6] / drivers / media / video / gspca / conex.c
index 739ef55..eca0035 100644 (file)
@@ -36,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 */
@@ -93,7 +97,7 @@ static struct ctrl sd_ctrls[] = {
        },
 };
 
-static struct v4l2_pix_format vga_mode[] = {
+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,
@@ -124,7 +128,7 @@ static void reg_r(struct gspca_dev *gspca_dev,
        struct usb_device *dev = gspca_dev->dev;
 
 #ifdef GSPCA_DEBUG
-       if (len > sizeof gspca_dev->usb_buf) {
+       if (len > USB_BUF_SZ) {
                err("reg_r: buffer overflow");
                return;
        }
@@ -164,7 +168,7 @@ static void reg_w(struct gspca_dev *gspca_dev,
        struct usb_device *dev = gspca_dev->dev;
 
 #ifdef GSPCA_DEBUG
-       if (len > sizeof gspca_dev->usb_buf) {
+       if (len > USB_BUF_SZ) {
                err("reg_w: buffer overflow");
                return;
        }
@@ -731,13 +735,13 @@ static void cx11646_jpeg(struct gspca_dev*gspca_dev)
        reg_w_val(gspca_dev, 0x0000, 0x00);
        /* wait for completion */
        retry = 50;
-       while (retry--) {
+       do {
                reg_r(gspca_dev, 0x0002, 1);
                                                        /* 0x07 until 0x00 */
                if (gspca_dev->usb_buf[0] == 0x00)
                        break;
                reg_w_val(gspca_dev, 0x0053, 0x00);
-       }
+       } while (--retry);
        if (retry == 0)
                PDEBUG(D_ERR, "Damned Errors sending jpeg Table");
        /* send the qtable now */
@@ -815,19 +819,18 @@ static int sd_config(struct gspca_dev *gspca_dev,
        struct cam *cam;
 
        cam = &gspca_dev->cam;
-       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 */
        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);
@@ -837,22 +840,35 @@ 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;
 
+       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);
@@ -871,15 +887,13 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
        reg_w_val(gspca_dev, 0x00fc, 0xe0);
 }
 
-static void sd_close(struct gspca_dev *gspca_dev)
-{
-}
-
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
                        struct gspca_frame *frame,      /* target */
                        __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 */
@@ -887,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;
        }
@@ -992,18 +1005,46 @@ 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 -- */
@@ -1035,8 +1076,10 @@ static struct usb_driver sd_driver = {
 /* -- module insert / remove -- */
 static int __init sd_mod_init(void)
 {
-       if (usb_register(&sd_driver) < 0)
-               return -1;
+       int ret;
+       ret = usb_register(&sd_driver);
+       if (ret < 0)
+               return ret;
        PDEBUG(D_PROBE, "registered");
        return 0;
 }