aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2009-10-19 05:08:01 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-12-05 15:40:46 -0500
commit79b359025d57969decb465973f7c0ea195009007 (patch)
tree651bc699116aa3607412cb85208bca091ebd9386
parent8394bcf3fc0293aa5cd07e2a1a3c6bf4e1a5b835 (diff)
V4L/DVB (13181): gspca w9968cf: Add support for JPEG compression
gspca w9968cf: Add support for JPEG compression, this enables much higher framerates at 320x240 / 352x288 and also allows for 640x480 mode for cams which can do this. The w9968cf uses planar JPEG, which libv4l until now did not support, so this requires atleast version 0.6.3 of libv4l. And something important I forgot to mention in my earlier w9968cf commits: Many thanks to Hans Verkuil for giving me a w9968cf based cam, which has allowed me to develop the gspca w9968cf support. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/Kconfig6
-rw-r--r--drivers/media/video/gspca/ov519.c68
-rw-r--r--drivers/media/video/gspca/w996Xcf.c143
3 files changed, 146 insertions, 71 deletions
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index c69f858c9278..7ecae636e6ad 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -956,7 +956,8 @@ config VIDEO_OVCAMCHIP
956 ---help--- 956 ---help---
957 This driver is DEPRECATED please use the gspca ov519 module 957 This driver is DEPRECATED please use the gspca ov519 module
958 instead. Note that for the ov511 / ov518 support of the gspca module 958 instead. Note that for the ov511 / ov518 support of the gspca module
959 you need atleast version 0.6.0 of libv4l. 959 you need atleast version 0.6.0 of libv4l and for the w9968cf
960 atleast version 0.6.3 of libv4l.
960 961
961 Support for the OmniVision OV6xxx and OV7xxx series of camera chips. 962 Support for the OmniVision OV6xxx and OV7xxx series of camera chips.
962 This driver is intended to be used with the ov511 and w9968cf USB 963 This driver is intended to be used with the ov511 and w9968cf USB
@@ -970,7 +971,8 @@ config USB_W9968CF
970 depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP 971 depends on VIDEO_V4L1 && I2C && VIDEO_OVCAMCHIP
971 ---help--- 972 ---help---
972 This driver is DEPRECATED please use the gspca ov519 module 973 This driver is DEPRECATED please use the gspca ov519 module
973 instead. 974 instead. Note that for the w9968cf support of the gspca module
975 you need atleast version 0.6.3 of libv4l.
974 976
975 Say Y here if you want support for cameras based on OV681 or 977 Say Y here if you want support for cameras based on OV681 or
976 Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips. 978 Winbond W9967CF/W9968CF JPEG USB Dual Mode Camera Chips.
diff --git a/drivers/media/video/gspca/ov519.c b/drivers/media/video/gspca/ov519.c
index ef88e244df17..a63cb75aa7f1 100644
--- a/drivers/media/video/gspca/ov519.c
+++ b/drivers/media/video/gspca/ov519.c
@@ -80,6 +80,10 @@ struct sd {
80 __u8 vflip; 80 __u8 vflip;
81 __u8 autobrightness; 81 __u8 autobrightness;
82 __u8 freq; 82 __u8 freq;
83 __u8 quality;
84#define QUALITY_MIN 50
85#define QUALITY_MAX 70
86#define QUALITY_DEF 50
83 87
84 __u8 stopped; /* Streaming is temporarily paused */ 88 __u8 stopped; /* Streaming is temporarily paused */
85 89
@@ -104,6 +108,8 @@ struct sd {
104 int sensor_width; 108 int sensor_width;
105 int sensor_height; 109 int sensor_height;
106 int sensor_reg_cache[256]; 110 int sensor_reg_cache[256];
111
112 u8 *jpeg_hdr;
107}; 113};
108 114
109/* Note this is a bit of a hack, but the w9968cf driver needs the code for all 115/* Note this is a bit of a hack, but the w9968cf driver needs the code for all
@@ -2303,8 +2309,6 @@ static int i2c_w_mask(struct sd *sd,
2303 * registers while the camera is streaming */ 2309 * registers while the camera is streaming */
2304static inline int ov51x_stop(struct sd *sd) 2310static inline int ov51x_stop(struct sd *sd)
2305{ 2311{
2306 int ret;
2307
2308 PDEBUG(D_STREAM, "stopping"); 2312 PDEBUG(D_STREAM, "stopping");
2309 sd->stopped = 1; 2313 sd->stopped = 1;
2310 switch (sd->bridge) { 2314 switch (sd->bridge) {
@@ -2319,10 +2323,7 @@ static inline int ov51x_stop(struct sd *sd)
2319 case BRIDGE_OVFX2: 2323 case BRIDGE_OVFX2:
2320 return reg_w_mask(sd, 0x0f, 0x00, 0x02); 2324 return reg_w_mask(sd, 0x0f, 0x00, 0x02);
2321 case BRIDGE_W9968CF: 2325 case BRIDGE_W9968CF:
2322 ret = reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */ 2326 return reg_w(sd, 0x3c, 0x0a05); /* stop USB transfer */
2323 ret += reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */
2324 ret += reg_w(sd, 0x16, 0x0000); /* stop video capture */
2325 return ret;
2326 } 2327 }
2327 2328
2328 return 0; 2329 return 0;
@@ -3088,8 +3089,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
3088 case BRIDGE_W9968CF: 3089 case BRIDGE_W9968CF:
3089 cam->cam_mode = w9968cf_vga_mode; 3090 cam->cam_mode = w9968cf_vga_mode;
3090 cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode); 3091 cam->nmodes = ARRAY_SIZE(w9968cf_vga_mode);
3091 /* if (sd->sif) 3092 if (sd->sif)
3092 cam->nmodes--; */ 3093 cam->nmodes--;
3093 3094
3094 /* w9968cf needs initialisation once the sensor is known */ 3095 /* w9968cf needs initialisation once the sensor is known */
3095 if (w9968cf_init(sd) < 0) 3096 if (w9968cf_init(sd) < 0)
@@ -3113,6 +3114,7 @@ static int sd_config(struct gspca_dev *gspca_dev,
3113 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) | 3114 gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX) |
3114 (1 << OV7670_FREQ_IDX); 3115 (1 << OV7670_FREQ_IDX);
3115 } 3116 }
3117 sd->quality = QUALITY_DEF;
3116 if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670) 3118 if (sd->sensor == SEN_OV7640 || sd->sensor == SEN_OV7670)
3117 gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX; 3119 gspca_dev->ctrl_dis |= 1 << AUTOBRIGHT_IDX;
3118 /* OV8610 Frequency filter control should work but needs testing */ 3120 /* OV8610 Frequency filter control should work but needs testing */
@@ -3909,6 +3911,14 @@ static void sd_stopN(struct gspca_dev *gspca_dev)
3909 ov51x_led_control(sd, 0); 3911 ov51x_led_control(sd, 0);
3910} 3912}
3911 3913
3914static void sd_stop0(struct gspca_dev *gspca_dev)
3915{
3916 struct sd *sd = (struct sd *) gspca_dev;
3917
3918 if (sd->bridge == BRIDGE_W9968CF)
3919 w9968cf_stop0(sd);
3920}
3921
3912static void ov511_pkt_scan(struct gspca_dev *gspca_dev, 3922static void ov511_pkt_scan(struct gspca_dev *gspca_dev,
3913 struct gspca_frame *frame, /* target */ 3923 struct gspca_frame *frame, /* target */
3914 __u8 *in, /* isoc packet */ 3924 __u8 *in, /* isoc packet */
@@ -4421,6 +4431,45 @@ static int sd_querymenu(struct gspca_dev *gspca_dev,
4421 return -EINVAL; 4431 return -EINVAL;
4422} 4432}
4423 4433
4434static int sd_get_jcomp(struct gspca_dev *gspca_dev,
4435 struct v4l2_jpegcompression *jcomp)
4436{
4437 struct sd *sd = (struct sd *) gspca_dev;
4438
4439 if (sd->bridge != BRIDGE_W9968CF)
4440 return -EINVAL;
4441
4442 memset(jcomp, 0, sizeof *jcomp);
4443 jcomp->quality = sd->quality;
4444 jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | V4L2_JPEG_MARKER_DQT |
4445 V4L2_JPEG_MARKER_DRI;
4446 return 0;
4447}
4448
4449static int sd_set_jcomp(struct gspca_dev *gspca_dev,
4450 struct v4l2_jpegcompression *jcomp)
4451{
4452 struct sd *sd = (struct sd *) gspca_dev;
4453
4454 if (sd->bridge != BRIDGE_W9968CF)
4455 return -EINVAL;
4456
4457 if (gspca_dev->streaming)
4458 return -EBUSY;
4459
4460 if (jcomp->quality < QUALITY_MIN)
4461 sd->quality = QUALITY_MIN;
4462 else if (jcomp->quality > QUALITY_MAX)
4463 sd->quality = QUALITY_MAX;
4464 else
4465 sd->quality = jcomp->quality;
4466
4467 /* Return resulting jcomp params to app */
4468 sd_get_jcomp(gspca_dev, jcomp);
4469
4470 return 0;
4471}
4472
4424/* sub-driver description */ 4473/* sub-driver description */
4425static const struct sd_desc sd_desc = { 4474static const struct sd_desc sd_desc = {
4426 .name = MODULE_NAME, 4475 .name = MODULE_NAME,
@@ -4430,8 +4479,11 @@ static const struct sd_desc sd_desc = {
4430 .init = sd_init, 4479 .init = sd_init,
4431 .start = sd_start, 4480 .start = sd_start,
4432 .stopN = sd_stopN, 4481 .stopN = sd_stopN,
4482 .stop0 = sd_stop0,
4433 .pkt_scan = sd_pkt_scan, 4483 .pkt_scan = sd_pkt_scan,
4434 .querymenu = sd_querymenu, 4484 .querymenu = sd_querymenu,
4485 .get_jcomp = sd_get_jcomp,
4486 .set_jcomp = sd_set_jcomp,
4435}; 4487};
4436 4488
4437/* -- module initialisation -- */ 4489/* -- module initialisation -- */
diff --git a/drivers/media/video/gspca/w996Xcf.c b/drivers/media/video/gspca/w996Xcf.c
index 3bdc6b405e27..7378f0495082 100644
--- a/drivers/media/video/gspca/w996Xcf.c
+++ b/drivers/media/video/gspca/w996Xcf.c
@@ -31,57 +31,14 @@
31 the sensor drivers to v4l2 sub drivers, and properly split of this 31 the sensor drivers to v4l2 sub drivers, and properly split of this
32 driver from ov519.c */ 32 driver from ov519.c */
33 33
34#define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */ 34/* The CONEX_CAM define for jpeg.h needs renaming, now its used here too */
35#define CONEX_CAM
36#include "jpeg.h"
35 37
36/* FIXME make this runtime configurable */ 38#define W9968CF_I2C_BUS_DELAY 4 /* delay in us for I2C bit r/w operations */
37/* Comment/uncomment this for high/low quality of compressed video */
38#define W9968CF_DEC_FAST_LOWQUALITY_VIDEO
39
40#ifdef W9968CF_DEC_FAST_LOWQUALITY_VIDEO
41static const unsigned char Y_QUANTABLE[64] = {
42 16, 11, 10, 16, 24, 40, 51, 61,
43 12, 12, 14, 19, 26, 58, 60, 55,
44 14, 13, 16, 24, 40, 57, 69, 56,
45 14, 17, 22, 29, 51, 87, 80, 62,
46 18, 22, 37, 56, 68, 109, 103, 77,
47 24, 35, 55, 64, 81, 104, 113, 92,
48 49, 64, 78, 87, 103, 121, 120, 101,
49 72, 92, 95, 98, 112, 100, 103, 99
50};
51 39
52static const unsigned char UV_QUANTABLE[64] = { 40#define Y_QUANTABLE (sd->jpeg_hdr + JPEG_QT0_OFFSET)
53 17, 18, 24, 47, 99, 99, 99, 99, 41#define UV_QUANTABLE (sd->jpeg_hdr + JPEG_QT1_OFFSET)
54 18, 21, 26, 66, 99, 99, 99, 99,
55 24, 26, 56, 99, 99, 99, 99, 99,
56 47, 66, 99, 99, 99, 99, 99, 99,
57 99, 99, 99, 99, 99, 99, 99, 99,
58 99, 99, 99, 99, 99, 99, 99, 99,
59 99, 99, 99, 99, 99, 99, 99, 99,
60 99, 99, 99, 99, 99, 99, 99, 99
61};
62#else
63static const unsigned char Y_QUANTABLE[64] = {
64 8, 5, 5, 8, 12, 20, 25, 30,
65 6, 6, 7, 9, 13, 29, 30, 27,
66 7, 6, 8, 12, 20, 28, 34, 28,
67 7, 8, 11, 14, 25, 43, 40, 31,
68 9, 11, 18, 28, 34, 54, 51, 38,
69 12, 17, 27, 32, 40, 52, 56, 46,
70 24, 32, 39, 43, 51, 60, 60, 50,
71 36, 46, 47, 49, 56, 50, 51, 49
72};
73
74static const unsigned char UV_QUANTABLE[64] = {
75 8, 9, 12, 23, 49, 49, 49, 49,
76 9, 10, 13, 33, 49, 49, 49, 49,
77 12, 13, 28, 49, 49, 49, 49, 49,
78 23, 33, 49, 49, 49, 49, 49, 49,
79 49, 49, 49, 49, 49, 49, 49, 49,
80 49, 49, 49, 49, 49, 49, 49, 49,
81 49, 49, 49, 49, 49, 49, 49, 49,
82 49, 49, 49, 49, 49, 49, 49, 49
83};
84#endif
85 42
86static const struct v4l2_pix_format w9968cf_vga_mode[] = { 43static const struct v4l2_pix_format w9968cf_vga_mode[] = {
87 {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, 44 {160, 120, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE,
@@ -92,18 +49,18 @@ static const struct v4l2_pix_format w9968cf_vga_mode[] = {
92 .bytesperline = 176 * 2, 49 .bytesperline = 176 * 2,
93 .sizeimage = 176 * 144 * 2, 50 .sizeimage = 176 * 144 * 2,
94 .colorspace = V4L2_COLORSPACE_JPEG}, 51 .colorspace = V4L2_COLORSPACE_JPEG},
95 {320, 240, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, 52 {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
96 .bytesperline = 320 * 2, 53 .bytesperline = 320 * 2,
97 .sizeimage = 320 * 240 * 2, 54 .sizeimage = 320 * 240 * 2,
98 .colorspace = V4L2_COLORSPACE_JPEG}, 55 .colorspace = V4L2_COLORSPACE_JPEG},
99 {352, 288, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, 56 {352, 288, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
100 .bytesperline = 352 * 2, 57 .bytesperline = 352 * 2,
101 .sizeimage = 352 * 288 * 2, 58 .sizeimage = 352 * 288 * 2,
102 .colorspace = V4L2_COLORSPACE_JPEG}, 59 .colorspace = V4L2_COLORSPACE_JPEG},
103/* {640, 480, V4L2_PIX_FMT_UYVY, V4L2_FIELD_NONE, 60 {640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
104 .bytesperline = 640 * 2, 61 .bytesperline = 640 * 2,
105 .sizeimage = 640 * 480 * 2, 62 .sizeimage = 640 * 480 * 2,
106 .colorspace = V4L2_COLORSPACE_JPEG}, */ 63 .colorspace = V4L2_COLORSPACE_JPEG},
107}; 64};
108 65
109static int reg_w(struct sd *sd, __u16 index, __u16 value); 66static int reg_w(struct sd *sd, __u16 index, __u16 value);
@@ -534,17 +491,35 @@ static int w9968cf_mode_init_regs(struct sd *sd)
534 ret += reg_w(sd, 0x31, sd->gspca_dev.height); 491 ret += reg_w(sd, 0x31, sd->gspca_dev.height);
535 492
536 /* Y & UV frame buffer strides (in WORD) */ 493 /* Y & UV frame buffer strides (in WORD) */
494 if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
495 V4L2_PIX_FMT_JPEG) {
496 ret += reg_w(sd, 0x2c, sd->gspca_dev.width/2);
497 ret += reg_w(sd, 0x2d, sd->gspca_dev.width/4);
498 } else
537 ret += reg_w(sd, 0x2c, sd->gspca_dev.width); 499 ret += reg_w(sd, 0x2c, sd->gspca_dev.width);
538 500
539 ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */ 501 ret += reg_w(sd, 0x00, 0xbf17); /* reset everything */
540 ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */ 502 ret += reg_w(sd, 0x00, 0xbf10); /* normal operation */
541 503
542 /* Transfer size */ 504 /* Transfer size in WORDS (for UYVY format only) */
543 /* FIXME JPEG * 4 ?? */
544 val = sd->gspca_dev.width * sd->gspca_dev.height; 505 val = sd->gspca_dev.width * sd->gspca_dev.height;
545 ret += reg_w(sd, 0x3d, val & 0xffff); /* low bits */ 506 ret += reg_w(sd, 0x3d, val & 0xffff); /* low bits */
546 ret += reg_w(sd, 0x3e, val >> 16); /* high bits */ 507 ret += reg_w(sd, 0x3e, val >> 16); /* high bits */
547 508
509 if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
510 V4L2_PIX_FMT_JPEG) {
511 /* We may get called multiple times (usb isoc bw negotiat.) */
512 if (!sd->jpeg_hdr)
513 sd->jpeg_hdr = kmalloc(JPEG_HDR_SZ, GFP_KERNEL);
514 if (!sd->jpeg_hdr)
515 return -ENOMEM;
516
517 jpeg_define(sd->jpeg_hdr, sd->gspca_dev.height,
518 sd->gspca_dev.width, 0x22); /* JPEG 420 */
519 jpeg_set_qual(sd->jpeg_hdr, sd->quality);
520 ret += w9968cf_upload_quantizationtables(sd);
521 }
522
548 /* Video Capture Control Register */ 523 /* Video Capture Control Register */
549 if (sd->sensor == SEN_OV7620) { 524 if (sd->sensor == SEN_OV7620) {
550 /* Seems to work around a bug in the image sensor */ 525 /* Seems to work around a bug in the image sensor */
@@ -557,6 +532,15 @@ static int w9968cf_mode_init_regs(struct sd *sd)
557 532
558 val = (vs_polarity << 12) | (hs_polarity << 11); 533 val = (vs_polarity << 12) | (hs_polarity << 11);
559 534
535 /* NOTE: We may not have enough memory to do double buffering while
536 doing compression (amount of memory differs per model cam).
537 So we use the second image buffer also as jpeg stream buffer
538 (see w9968cf_init), and disable double buffering. */
539 if (w9968cf_vga_mode[sd->gspca_dev.curr_mode].pixelformat ==
540 V4L2_PIX_FMT_JPEG) {
541 /* val |= 0x0002; YUV422P */
542 val |= 0x0003; /* YUV420P */
543 } else
560 val |= 0x0080; /* Enable HW double buffering */ 544 val |= 0x0080; /* Enable HW double buffering */
561 545
562 /* val |= 0x0020; enable clamping */ 546 /* val |= 0x0020; enable clamping */
@@ -572,18 +556,55 @@ static int w9968cf_mode_init_regs(struct sd *sd)
572 return ret; 556 return ret;
573} 557}
574 558
559static void w9968cf_stop0(struct sd *sd)
560{
561 if (sd->gspca_dev.present) {
562 reg_w(sd, 0x39, 0x0000); /* disable JPEG encoder */
563 reg_w(sd, 0x16, 0x0000); /* stop video capture */
564 }
565
566 kfree(sd->jpeg_hdr);
567 sd->jpeg_hdr = NULL;
568}
569
570/* The w9968cf docs say that a 0 sized packet means EOF (and also SOF
571 for the next frame). This seems to simply not be true when operating
572 in JPEG mode, in this case there may be empty packets within the
573 frame. So in JPEG mode use the JPEG SOI marker to detect SOF.
574
575 Note to make things even more interesting the w9968cf sends *PLANAR* jpeg,
576 to be precise it sends: SOI, SOF, DRI, SOS, Y-data, SOS, U-data, SOS,
577 V-data, EOI. */
575static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, 578static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev,
576 struct gspca_frame *frame, /* target */ 579 struct gspca_frame *frame, /* target */
577 __u8 *data, /* isoc packet */ 580 __u8 *data, /* isoc packet */
578 int len) /* iso packet length */ 581 int len) /* iso packet length */
579{ 582{
580 /* An empty packet signals EOF */ 583 struct sd *sd = (struct sd *) gspca_dev;
581 if (gspca_dev->empty_packet) { 584
582 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame, 585 if (w9968cf_vga_mode[gspca_dev->curr_mode].pixelformat ==
586 V4L2_PIX_FMT_JPEG) {
587 if (len >= 2 &&
588 data[0] == 0xff &&
589 data[1] == 0xd8) {
590 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
583 NULL, 0); 591 NULL, 0);
584 gspca_frame_add(gspca_dev, FIRST_PACKET, frame, 592 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
585 NULL, 0); 593 sd->jpeg_hdr, JPEG_HDR_SZ);
586 gspca_dev->empty_packet = 0; 594 /* Strip the ff d8, our own header (which adds
595 huffman and quantization tables) already has this */
596 len -= 2;
597 data += 2;
598 }
599 } else {
600 /* In UYVY mode an empty packet signals EOF */
601 if (gspca_dev->empty_packet) {
602 frame = gspca_frame_add(gspca_dev, LAST_PACKET, frame,
603 NULL, 0);
604 gspca_frame_add(gspca_dev, FIRST_PACKET, frame,
605 NULL, 0);
606 gspca_dev->empty_packet = 0;
607 }
587 } 608 }
588 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len); 609 gspca_frame_add(gspca_dev, INTER_PACKET, frame, data, len);
589} 610}