diff options
-rw-r--r-- | drivers/media/video/Kconfig | 6 | ||||
-rw-r--r-- | drivers/media/video/gspca/ov519.c | 68 | ||||
-rw-r--r-- | drivers/media/video/gspca/w996Xcf.c | 143 |
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 */ |
2304 | static inline int ov51x_stop(struct sd *sd) | 2310 | static 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 | ||
3914 | static 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 | |||
3912 | static void ov511_pkt_scan(struct gspca_dev *gspca_dev, | 3922 | static 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 | ||
4434 | static 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 | |||
4449 | static 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 */ |
4425 | static const struct sd_desc sd_desc = { | 4474 | static 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 | ||
41 | static 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 | ||
52 | static 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 | ||
63 | static 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 | |||
74 | static 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 | ||
86 | static const struct v4l2_pix_format w9968cf_vga_mode[] = { | 43 | static 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 | ||
109 | static int reg_w(struct sd *sd, __u16 index, __u16 value); | 66 | static 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 | ||
559 | static 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. */ | ||
575 | static void w9968cf_pkt_scan(struct gspca_dev *gspca_dev, | 578 | static 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 | } |