diff options
author | Hans de Goede <hdegoede@redhat.com> | 2012-01-04 14:58:44 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2012-01-06 07:46:46 -0500 |
commit | 795e6eb3262d3b7247ce450835eea6df6571d103 (patch) | |
tree | 558c161d69a04a172f54c1edd38c44b2553bf10e /drivers/media/video/pwc | |
parent | a08d2c727153dc6cea1d5d54a43fd7d69c1467c3 (diff) |
[media] pwc: Remove software emulation of arbritary resolutions
The pwc driver claims to support any resolution between 160x120
and 640x480, but emulates this by simply drawing a black border
around the image. Userspace can draw its own black border if it
really wants one.
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/pwc')
-rw-r--r-- | drivers/media/video/pwc/pwc-ctrl.c | 69 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-dec23.c | 29 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-if.c | 10 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-misc.c | 87 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-uncompress.c | 38 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-v4l.c | 52 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc.h | 19 |
7 files changed, 92 insertions, 212 deletions
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c index 684b7c50eea..6b9c97fff27 100644 --- a/drivers/media/video/pwc/pwc-ctrl.c +++ b/drivers/media/video/pwc/pwc-ctrl.c | |||
@@ -102,8 +102,6 @@ static struct Nala_table_entry Nala_table[PSZ_MAX][PWC_FPS_MAX_NALA] = | |||
102 | #include "pwc-nala.h" | 102 | #include "pwc-nala.h" |
103 | }; | 103 | }; |
104 | 104 | ||
105 | static void pwc_set_image_buffer_size(struct pwc_device *pdev); | ||
106 | |||
107 | /****************************************************************************/ | 105 | /****************************************************************************/ |
108 | 106 | ||
109 | static int _send_control_msg(struct pwc_device *pdev, | 107 | static int _send_control_msg(struct pwc_device *pdev, |
@@ -221,8 +219,9 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) | |||
221 | /* Set various parameters */ | 219 | /* Set various parameters */ |
222 | pdev->vframes = frames; | 220 | pdev->vframes = frames; |
223 | pdev->valternate = pEntry->alternate; | 221 | pdev->valternate = pEntry->alternate; |
224 | pdev->image = pwc_image_sizes[size]; | 222 | pdev->width = pwc_image_sizes[size][0]; |
225 | pdev->frame_size = (pdev->image.x * pdev->image.y * 3) / 2; | 223 | pdev->height = pwc_image_sizes[size][1]; |
224 | pdev->frame_size = (pdev->width * pdev->height * 3) / 2; | ||
226 | if (pEntry->compressed) { | 225 | if (pEntry->compressed) { |
227 | if (pdev->release < 5) { /* 4 fold compression */ | 226 | if (pdev->release < 5) { /* 4 fold compression */ |
228 | pdev->vbandlength = 528; | 227 | pdev->vbandlength = 528; |
@@ -282,12 +281,13 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, | |||
282 | /* Set various parameters */ | 281 | /* Set various parameters */ |
283 | pdev->vframes = frames; | 282 | pdev->vframes = frames; |
284 | pdev->valternate = pChoose->alternate; | 283 | pdev->valternate = pChoose->alternate; |
285 | pdev->image = pwc_image_sizes[size]; | 284 | pdev->width = pwc_image_sizes[size][0]; |
285 | pdev->height = pwc_image_sizes[size][1]; | ||
286 | pdev->vbandlength = pChoose->bandlength; | 286 | pdev->vbandlength = pChoose->bandlength; |
287 | if (pChoose->bandlength > 0) | 287 | if (pChoose->bandlength > 0) |
288 | pdev->frame_size = (pChoose->bandlength * pdev->image.y) / 4; | 288 | pdev->frame_size = (pChoose->bandlength * pdev->height) / 4; |
289 | else | 289 | else |
290 | pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; | 290 | pdev->frame_size = (pdev->width * pdev->height * 12) / 8; |
291 | return 0; | 291 | return 0; |
292 | } | 292 | } |
293 | 293 | ||
@@ -339,37 +339,25 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, | |||
339 | /* All set and go */ | 339 | /* All set and go */ |
340 | pdev->vframes = frames; | 340 | pdev->vframes = frames; |
341 | pdev->valternate = pChoose->alternate; | 341 | pdev->valternate = pChoose->alternate; |
342 | pdev->image = pwc_image_sizes[size]; | 342 | pdev->width = pwc_image_sizes[size][0]; |
343 | pdev->height = pwc_image_sizes[size][1]; | ||
343 | pdev->vbandlength = pChoose->bandlength; | 344 | pdev->vbandlength = pChoose->bandlength; |
344 | if (pdev->vbandlength > 0) | 345 | if (pdev->vbandlength > 0) |
345 | pdev->frame_size = (pdev->vbandlength * pdev->image.y) / 4; | 346 | pdev->frame_size = (pdev->vbandlength * pdev->height) / 4; |
346 | else | 347 | else |
347 | pdev->frame_size = (pdev->image.x * pdev->image.y * 12) / 8; | 348 | pdev->frame_size = (pdev->width * pdev->height * 12) / 8; |
348 | PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n", | 349 | PWC_TRACE("frame_size=%d, vframes=%d, vsize=%d, vbandlength=%d\n", |
349 | pdev->frame_size, pdev->vframes, size, pdev->vbandlength); | 350 | pdev->frame_size, pdev->vframes, size, pdev->vbandlength); |
350 | return 0; | 351 | return 0; |
351 | } | 352 | } |
352 | 353 | ||
353 | |||
354 | |||
355 | /** | ||
356 | @pdev: device structure | ||
357 | @width: viewport width | ||
358 | @height: viewport height | ||
359 | @frame: framerate, in fps | ||
360 | @compression: preferred compression ratio | ||
361 | */ | ||
362 | int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, | 354 | int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, |
363 | int frames, int compression) | 355 | int frames, int compression) |
364 | { | 356 | { |
365 | int ret, size; | 357 | int ret, size; |
366 | 358 | ||
367 | PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt); | 359 | PWC_DEBUG_FLOW("set_video_mode(%dx%d @ %d, pixfmt %08x).\n", width, height, frames, pdev->pixfmt); |
368 | size = pwc_decode_size(pdev, width, height); | 360 | size = pwc_get_size(pdev, width, height); |
369 | if (size < 0) { | ||
370 | PWC_DEBUG_MODULE("Could not find suitable size.\n"); | ||
371 | return -ERANGE; | ||
372 | } | ||
373 | PWC_TRACE("decode_size = %d.\n", size); | 361 | PWC_TRACE("decode_size = %d.\n", size); |
374 | 362 | ||
375 | if (DEVICE_USE_CODEC1(pdev->type)) { | 363 | if (DEVICE_USE_CODEC1(pdev->type)) { |
@@ -385,12 +373,9 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, | |||
385 | PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); | 373 | PWC_ERROR("Failed to set video mode %s@%d fps; return code = %d\n", size2name[size], frames, ret); |
386 | return ret; | 374 | return ret; |
387 | } | 375 | } |
388 | pdev->view.x = width; | ||
389 | pdev->view.y = height; | ||
390 | pdev->vcompression = compression; | 376 | pdev->vcompression = compression; |
391 | pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; | 377 | pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; |
392 | pwc_set_image_buffer_size(pdev); | 378 | PWC_DEBUG_SIZE("Set resolution to %dx%d\n", pdev->width, pdev->height); |
393 | PWC_DEBUG_SIZE("Set viewport to %dx%d, image size is %dx%d.\n", width, height, pwc_image_sizes[size].x, pwc_image_sizes[size].y); | ||
394 | return 0; | 379 | return 0; |
395 | } | 380 | } |
396 | 381 | ||
@@ -447,34 +432,6 @@ unsigned int pwc_get_fps(struct pwc_device *pdev, unsigned int index, unsigned i | |||
447 | return ret; | 432 | return ret; |
448 | } | 433 | } |
449 | 434 | ||
450 | static void pwc_set_image_buffer_size(struct pwc_device *pdev) | ||
451 | { | ||
452 | int factor = 0; | ||
453 | |||
454 | /* for V4L2_PIX_FMT_YUV420 */ | ||
455 | switch (pdev->pixfmt) { | ||
456 | case V4L2_PIX_FMT_YUV420: | ||
457 | factor = 6; | ||
458 | break; | ||
459 | case V4L2_PIX_FMT_PWC1: | ||
460 | case V4L2_PIX_FMT_PWC2: | ||
461 | factor = 6; /* can be uncompressed YUV420P */ | ||
462 | break; | ||
463 | } | ||
464 | |||
465 | /* Set sizes in bytes */ | ||
466 | pdev->image.size = pdev->image.x * pdev->image.y * factor / 4; | ||
467 | pdev->view.size = pdev->view.x * pdev->view.y * factor / 4; | ||
468 | |||
469 | /* Align offset, or you'll get some very weird results in | ||
470 | YUV420 mode... x must be multiple of 4 (to get the Y's in | ||
471 | place), and y even (or you'll mixup U & V). This is less of a | ||
472 | problem for YUV420P. | ||
473 | */ | ||
474 | pdev->offset.x = ((pdev->view.x - pdev->image.x) / 2) & 0xFFFC; | ||
475 | pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE; | ||
476 | } | ||
477 | |||
478 | int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) | 435 | int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data) |
479 | { | 436 | { |
480 | int ret; | 437 | int ret; |
diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c index e531f85460c..2c6709112b2 100644 --- a/drivers/media/video/pwc/pwc-dec23.c +++ b/drivers/media/video/pwc/pwc-dec23.c | |||
@@ -656,10 +656,6 @@ static void DecompressBand23(struct pwc_dec23_private *pdec, | |||
656 | * | 656 | * |
657 | * Uncompress a pwc23 buffer. | 657 | * Uncompress a pwc23 buffer. |
658 | * | 658 | * |
659 | * pwc.view: size of the image wanted | ||
660 | * pwc.image: size of the image returned by the camera | ||
661 | * pwc.offset: (x,y) to displayer image in the view | ||
662 | * | ||
663 | * src: raw data | 659 | * src: raw data |
664 | * dst: image output | 660 | * dst: image output |
665 | */ | 661 | */ |
@@ -667,7 +663,7 @@ void pwc_dec23_decompress(const struct pwc_device *pwc, | |||
667 | const void *src, | 663 | const void *src, |
668 | void *dst) | 664 | void *dst) |
669 | { | 665 | { |
670 | int bandlines_left, stride, bytes_per_block; | 666 | int bandlines_left, bytes_per_block; |
671 | struct pwc_dec23_private *pdec = pwc->decompress_data; | 667 | struct pwc_dec23_private *pdec = pwc->decompress_data; |
672 | 668 | ||
673 | /* YUV420P image format */ | 669 | /* YUV420P image format */ |
@@ -678,28 +674,23 @@ void pwc_dec23_decompress(const struct pwc_device *pwc, | |||
678 | 674 | ||
679 | mutex_lock(&pdec->lock); | 675 | mutex_lock(&pdec->lock); |
680 | 676 | ||
681 | bandlines_left = pwc->image.y / 4; | 677 | bandlines_left = pwc->height / 4; |
682 | bytes_per_block = pwc->view.x * 4; | 678 | bytes_per_block = pwc->width * 4; |
683 | plane_size = pwc->view.x * pwc->view.y; | 679 | plane_size = pwc->height * pwc->width; |
684 | |||
685 | /* offset in Y plane */ | ||
686 | stride = pwc->view.x * pwc->offset.y; | ||
687 | pout_planar_y = dst + stride + pwc->offset.x; | ||
688 | 680 | ||
689 | /* offsets in U/V planes */ | 681 | pout_planar_y = dst; |
690 | stride = (pwc->view.x * pwc->offset.y) / 4 + pwc->offset.x / 2; | 682 | pout_planar_u = dst + plane_size; |
691 | pout_planar_u = dst + plane_size + stride; | 683 | pout_planar_v = dst + plane_size + plane_size / 4; |
692 | pout_planar_v = dst + plane_size + plane_size / 4 + stride; | ||
693 | 684 | ||
694 | while (bandlines_left--) { | 685 | while (bandlines_left--) { |
695 | DecompressBand23(pwc->decompress_data, | 686 | DecompressBand23(pwc->decompress_data, |
696 | src, | 687 | src, |
697 | pout_planar_y, pout_planar_u, pout_planar_v, | 688 | pout_planar_y, pout_planar_u, pout_planar_v, |
698 | pwc->image.x, pwc->view.x); | 689 | pwc->width, pwc->width); |
699 | src += pwc->vbandlength; | 690 | src += pwc->vbandlength; |
700 | pout_planar_y += bytes_per_block; | 691 | pout_planar_y += bytes_per_block; |
701 | pout_planar_u += pwc->view.x; | 692 | pout_planar_u += pwc->width; |
702 | pout_planar_v += pwc->view.x; | 693 | pout_planar_v += pwc->width; |
703 | } | 694 | } |
704 | mutex_unlock(&pdec->lock); | 695 | mutex_unlock(&pdec->lock); |
705 | } | 696 | } |
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c index 963b4a55ec7..be4406a7c80 100644 --- a/drivers/media/video/pwc/pwc-if.c +++ b/drivers/media/video/pwc/pwc-if.c | |||
@@ -656,6 +656,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | |||
656 | unsigned int sizes[], void *alloc_ctxs[]) | 656 | unsigned int sizes[], void *alloc_ctxs[]) |
657 | { | 657 | { |
658 | struct pwc_device *pdev = vb2_get_drv_priv(vq); | 658 | struct pwc_device *pdev = vb2_get_drv_priv(vq); |
659 | int size; | ||
659 | 660 | ||
660 | if (*nbuffers < MIN_FRAMES) | 661 | if (*nbuffers < MIN_FRAMES) |
661 | *nbuffers = MIN_FRAMES; | 662 | *nbuffers = MIN_FRAMES; |
@@ -664,7 +665,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt, | |||
664 | 665 | ||
665 | *nplanes = 1; | 666 | *nplanes = 1; |
666 | 667 | ||
667 | sizes[0] = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2); | 668 | size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT); |
669 | sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] * | ||
670 | pwc_image_sizes[size][1] * 3 / 2); | ||
668 | 671 | ||
669 | return 0; | 672 | return 0; |
670 | } | 673 | } |
@@ -742,7 +745,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) | |||
742 | pwc_camera_power(pdev, 1); | 745 | pwc_camera_power(pdev, 1); |
743 | if (pdev->power_save) { | 746 | if (pdev->power_save) { |
744 | /* Restore video mode */ | 747 | /* Restore video mode */ |
745 | pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, | 748 | pwc_set_video_mode(pdev, pdev->width, pdev->height, |
746 | pdev->vframes, pdev->vcompression); | 749 | pdev->vframes, pdev->vcompression); |
747 | } | 750 | } |
748 | pwc_set_leds(pdev, led_on, led_off); | 751 | pwc_set_leds(pdev, led_on, led_off); |
@@ -1056,7 +1059,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1056 | } | 1059 | } |
1057 | pdev->type = type_id; | 1060 | pdev->type = type_id; |
1058 | pdev->vframes = default_fps; | 1061 | pdev->vframes = default_fps; |
1059 | strcpy(pdev->serial, serial_number); | ||
1060 | pdev->features = features; | 1062 | pdev->features = features; |
1061 | pwc_construct(pdev); /* set min/max sizes correct */ | 1063 | pwc_construct(pdev); /* set min/max sizes correct */ |
1062 | 1064 | ||
@@ -1119,7 +1121,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id | |||
1119 | pwc_set_leds(pdev, 0, 0); | 1121 | pwc_set_leds(pdev, 0, 0); |
1120 | 1122 | ||
1121 | /* Setup intial videomode */ | 1123 | /* Setup intial videomode */ |
1122 | rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y, | 1124 | rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, |
1123 | pdev->vframes, pdev->vcompression); | 1125 | pdev->vframes, pdev->vcompression); |
1124 | if (rc) | 1126 | if (rc) |
1125 | goto err_free_mem; | 1127 | goto err_free_mem; |
diff --git a/drivers/media/video/pwc/pwc-misc.c b/drivers/media/video/pwc/pwc-misc.c index 0b031336eab..23a55b5814f 100644 --- a/drivers/media/video/pwc/pwc-misc.c +++ b/drivers/media/video/pwc/pwc-misc.c | |||
@@ -27,67 +27,47 @@ | |||
27 | 27 | ||
28 | #include "pwc.h" | 28 | #include "pwc.h" |
29 | 29 | ||
30 | const struct pwc_coord pwc_image_sizes[PSZ_MAX] = | 30 | const int pwc_image_sizes[PSZ_MAX][2] = |
31 | { | 31 | { |
32 | { 128, 96, 0 }, /* sqcif */ | 32 | { 128, 96 }, /* sqcif */ |
33 | { 160, 120, 0 }, /* qsif */ | 33 | { 160, 120 }, /* qsif */ |
34 | { 176, 144, 0 }, /* qcif */ | 34 | { 176, 144 }, /* qcif */ |
35 | { 320, 240, 0 }, /* sif */ | 35 | { 320, 240 }, /* sif */ |
36 | { 352, 288, 0 }, /* cif */ | 36 | { 352, 288 }, /* cif */ |
37 | { 640, 480, 0 }, /* vga */ | 37 | { 640, 480 }, /* vga */ |
38 | }; | 38 | }; |
39 | 39 | ||
40 | /* x,y -> PSZ_ */ | 40 | /* x,y -> PSZ_ */ |
41 | int pwc_decode_size(struct pwc_device *pdev, int width, int height) | 41 | int pwc_get_size(struct pwc_device *pdev, int width, int height) |
42 | { | 42 | { |
43 | int i, find; | 43 | int i; |
44 | |||
45 | /* Make sure we don't go beyond our max size. | ||
46 | NB: we have different limits for RAW and normal modes. In case | ||
47 | you don't have the decompressor loaded or use RAW mode, | ||
48 | the maximum viewable size is smaller. | ||
49 | */ | ||
50 | if (pdev->pixfmt != V4L2_PIX_FMT_YUV420) | ||
51 | { | ||
52 | if (width > pdev->abs_max.x || height > pdev->abs_max.y) | ||
53 | { | ||
54 | PWC_DEBUG_SIZE("VIDEO_PALETTE_RAW: going beyond abs_max.\n"); | ||
55 | return -1; | ||
56 | } | ||
57 | } | ||
58 | else | ||
59 | { | ||
60 | if (width > pdev->view_max.x || height > pdev->view_max.y) | ||
61 | { | ||
62 | PWC_DEBUG_SIZE("VIDEO_PALETTE_not RAW: going beyond view_max.\n"); | ||
63 | return -1; | ||
64 | } | ||
65 | } | ||
66 | 44 | ||
67 | /* Find the largest size supported by the camera that fits into the | 45 | /* Find the largest size supported by the camera that fits into the |
68 | requested size. | 46 | requested size. */ |
69 | */ | 47 | for (i = PSZ_MAX - 1; i >= 0; i--) { |
70 | find = -1; | 48 | if (!(pdev->image_mask & (1 << i))) |
49 | continue; | ||
50 | |||
51 | if (pwc_image_sizes[i][0] <= width && | ||
52 | pwc_image_sizes[i][1] <= height) | ||
53 | return i; | ||
54 | } | ||
55 | |||
56 | /* No mode found, return the smallest mode we have */ | ||
71 | for (i = 0; i < PSZ_MAX; i++) { | 57 | for (i = 0; i < PSZ_MAX; i++) { |
72 | if (pdev->image_mask & (1 << i)) { | 58 | if (pdev->image_mask & (1 << i)) |
73 | if (pwc_image_sizes[i].x <= width && pwc_image_sizes[i].y <= height) | 59 | return i; |
74 | find = i; | ||
75 | } | ||
76 | } | 60 | } |
77 | return find; | 61 | |
62 | /* Never reached there always is atleast one supported mode */ | ||
63 | return 0; | ||
78 | } | 64 | } |
79 | 65 | ||
80 | /* initialize variables depending on type and decompressor*/ | 66 | /* initialize variables depending on type and decompressor */ |
81 | void pwc_construct(struct pwc_device *pdev) | 67 | void pwc_construct(struct pwc_device *pdev) |
82 | { | 68 | { |
83 | if (DEVICE_USE_CODEC1(pdev->type)) { | 69 | if (DEVICE_USE_CODEC1(pdev->type)) { |
84 | 70 | ||
85 | pdev->view_min.x = 128; | ||
86 | pdev->view_min.y = 96; | ||
87 | pdev->view_max.x = 352; | ||
88 | pdev->view_max.y = 288; | ||
89 | pdev->abs_max.x = 352; | ||
90 | pdev->abs_max.y = 288; | ||
91 | pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF; | 71 | pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QCIF | 1 << PSZ_CIF; |
92 | pdev->vcinterface = 2; | 72 | pdev->vcinterface = 2; |
93 | pdev->vendpoint = 4; | 73 | pdev->vendpoint = 4; |
@@ -96,13 +76,7 @@ void pwc_construct(struct pwc_device *pdev) | |||
96 | 76 | ||
97 | } else if (DEVICE_USE_CODEC3(pdev->type)) { | 77 | } else if (DEVICE_USE_CODEC3(pdev->type)) { |
98 | 78 | ||
99 | pdev->view_min.x = 160; | ||
100 | pdev->view_min.y = 120; | ||
101 | pdev->view_max.x = 640; | ||
102 | pdev->view_max.y = 480; | ||
103 | pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; | 79 | pdev->image_mask = 1 << PSZ_QSIF | 1 << PSZ_SIF | 1 << PSZ_VGA; |
104 | pdev->abs_max.x = 640; | ||
105 | pdev->abs_max.y = 480; | ||
106 | pdev->vcinterface = 3; | 80 | pdev->vcinterface = 3; |
107 | pdev->vendpoint = 5; | 81 | pdev->vendpoint = 5; |
108 | pdev->frame_header_size = TOUCAM_HEADER_SIZE; | 82 | pdev->frame_header_size = TOUCAM_HEADER_SIZE; |
@@ -110,20 +84,11 @@ void pwc_construct(struct pwc_device *pdev) | |||
110 | 84 | ||
111 | } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ { | 85 | } else /* if (DEVICE_USE_CODEC2(pdev->type)) */ { |
112 | 86 | ||
113 | pdev->view_min.x = 128; | ||
114 | pdev->view_min.y = 96; | ||
115 | /* Anthill bug #38: PWC always reports max size, even without PWCX */ | ||
116 | pdev->view_max.x = 640; | ||
117 | pdev->view_max.y = 480; | ||
118 | pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA; | 87 | pdev->image_mask = 1 << PSZ_SQCIF | 1 << PSZ_QSIF | 1 << PSZ_QCIF | 1 << PSZ_SIF | 1 << PSZ_CIF | 1 << PSZ_VGA; |
119 | pdev->abs_max.x = 640; | ||
120 | pdev->abs_max.y = 480; | ||
121 | pdev->vcinterface = 3; | 88 | pdev->vcinterface = 3; |
122 | pdev->vendpoint = 4; | 89 | pdev->vendpoint = 4; |
123 | pdev->frame_header_size = 0; | 90 | pdev->frame_header_size = 0; |
124 | pdev->frame_trailer_size = 0; | 91 | pdev->frame_trailer_size = 0; |
125 | } | 92 | } |
126 | pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */ | 93 | pdev->pixfmt = V4L2_PIX_FMT_YUV420; /* default */ |
127 | pdev->view_min.size = pdev->view_min.x * pdev->view_min.y; | ||
128 | pdev->view_max.size = pdev->view_max.x * pdev->view_max.y; | ||
129 | } | 94 | } |
diff --git a/drivers/media/video/pwc/pwc-uncompress.c b/drivers/media/video/pwc/pwc-uncompress.c index e55b568cbf3..b65903fbcf0 100644 --- a/drivers/media/video/pwc/pwc-uncompress.c +++ b/drivers/media/video/pwc/pwc-uncompress.c | |||
@@ -35,7 +35,7 @@ | |||
35 | 35 | ||
36 | int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) | 36 | int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) |
37 | { | 37 | { |
38 | int n, line, col, stride; | 38 | int n, line, col; |
39 | void *yuv, *image; | 39 | void *yuv, *image; |
40 | u16 *src; | 40 | u16 *src; |
41 | u16 *dsty, *dstu, *dstv; | 41 | u16 *dsty, *dstu, *dstv; |
@@ -60,35 +60,23 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) | |||
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
63 | vb2_set_plane_payload(&fbuf->vb, 0, pdev->view.size); | 63 | vb2_set_plane_payload(&fbuf->vb, 0, |
64 | pdev->width * pdev->height * 3 / 2); | ||
64 | 65 | ||
65 | if (pdev->vbandlength == 0) { | 66 | if (pdev->vbandlength == 0) { |
66 | /* Uncompressed mode. | 67 | /* Uncompressed mode. |
67 | * We copy the data into the output buffer, using the viewport | ||
68 | * size (which may be larger than the image size). | ||
69 | * Unfortunately we have to do a bit of byte stuffing to get | ||
70 | * the desired output format/size. | ||
71 | * | 68 | * |
72 | * We do some byte shuffling here to go from the | 69 | * We do some byte shuffling here to go from the |
73 | * native format to YUV420P. | 70 | * native format to YUV420P. |
74 | */ | 71 | */ |
75 | src = (u16 *)yuv; | 72 | src = (u16 *)yuv; |
76 | n = pdev->view.x * pdev->view.y; | 73 | n = pdev->width * pdev->height; |
74 | dsty = (u16 *)(image); | ||
75 | dstu = (u16 *)(image + n); | ||
76 | dstv = (u16 *)(image + n + n / 4); | ||
77 | 77 | ||
78 | /* offset in Y plane */ | 78 | for (line = 0; line < pdev->height; line++) { |
79 | stride = pdev->view.x * pdev->offset.y + pdev->offset.x; | 79 | for (col = 0; col < pdev->width; col += 4) { |
80 | dsty = (u16 *)(image + stride); | ||
81 | |||
82 | /* offsets in U/V planes */ | ||
83 | stride = pdev->view.x * pdev->offset.y / 4 + pdev->offset.x / 2; | ||
84 | dstu = (u16 *)(image + n + stride); | ||
85 | dstv = (u16 *)(image + n + n / 4 + stride); | ||
86 | |||
87 | /* increment after each line */ | ||
88 | stride = (pdev->view.x - pdev->image.x) / 2; /* u16 is 2 bytes */ | ||
89 | |||
90 | for (line = 0; line < pdev->image.y; line++) { | ||
91 | for (col = 0; col < pdev->image.x; col += 4) { | ||
92 | *dsty++ = *src++; | 80 | *dsty++ = *src++; |
93 | *dsty++ = *src++; | 81 | *dsty++ = *src++; |
94 | if (line & 1) | 82 | if (line & 1) |
@@ -96,11 +84,6 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) | |||
96 | else | 84 | else |
97 | *dstu++ = *src++; | 85 | *dstu++ = *src++; |
98 | } | 86 | } |
99 | dsty += stride; | ||
100 | if (line & 1) | ||
101 | dstv += (stride >> 1); | ||
102 | else | ||
103 | dstu += (stride >> 1); | ||
104 | } | 87 | } |
105 | 88 | ||
106 | return 0; | 89 | return 0; |
@@ -122,6 +105,3 @@ int pwc_decompress(struct pwc_device *pdev, struct pwc_frame_buf *fbuf) | |||
122 | } | 105 | } |
123 | return 0; | 106 | return 0; |
124 | } | 107 | } |
125 | |||
126 | |||
127 | /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */ | ||
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c index 87457b53f49..097ec582ee6 100644 --- a/drivers/media/video/pwc/pwc-v4l.c +++ b/drivers/media/video/pwc/pwc-v4l.c | |||
@@ -398,8 +398,8 @@ int pwc_init_controls(struct pwc_device *pdev) | |||
398 | static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f) | 398 | static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_format *f) |
399 | { | 399 | { |
400 | memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); | 400 | memset(&f->fmt.pix, 0, sizeof(struct v4l2_pix_format)); |
401 | f->fmt.pix.width = pdev->view.x; | 401 | f->fmt.pix.width = pdev->width; |
402 | f->fmt.pix.height = pdev->view.y; | 402 | f->fmt.pix.height = pdev->height; |
403 | f->fmt.pix.field = V4L2_FIELD_NONE; | 403 | f->fmt.pix.field = V4L2_FIELD_NONE; |
404 | if (pdev->pixfmt == V4L2_PIX_FMT_YUV420) { | 404 | if (pdev->pixfmt == V4L2_PIX_FMT_YUV420) { |
405 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; | 405 | f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420; |
@@ -429,6 +429,8 @@ static void pwc_vidioc_fill_fmt(const struct pwc_device *pdev, struct v4l2_forma | |||
429 | /* ioctl(VIDIOC_TRY_FMT) */ | 429 | /* ioctl(VIDIOC_TRY_FMT) */ |
430 | static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) | 430 | static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) |
431 | { | 431 | { |
432 | int size; | ||
433 | |||
432 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { | 434 | if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { |
433 | PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); | 435 | PWC_DEBUG_IOCTL("Bad video type must be V4L2_BUF_TYPE_VIDEO_CAPTURE\n"); |
434 | return -EINVAL; | 436 | return -EINVAL; |
@@ -455,15 +457,9 @@ static int pwc_vidioc_try_fmt(struct pwc_device *pdev, struct v4l2_format *f) | |||
455 | 457 | ||
456 | } | 458 | } |
457 | 459 | ||
458 | if (f->fmt.pix.width > pdev->view_max.x) | 460 | size = pwc_get_size(pdev, f->fmt.pix.width, f->fmt.pix.height); |
459 | f->fmt.pix.width = pdev->view_max.x; | 461 | f->fmt.pix.width = pwc_image_sizes[size][0]; |
460 | else if (f->fmt.pix.width < pdev->view_min.x) | 462 | f->fmt.pix.height = pwc_image_sizes[size][1]; |
461 | f->fmt.pix.width = pdev->view_min.x; | ||
462 | |||
463 | if (f->fmt.pix.height > pdev->view_max.y) | ||
464 | f->fmt.pix.height = pdev->view_max.y; | ||
465 | else if (f->fmt.pix.height < pdev->view_min.y) | ||
466 | f->fmt.pix.height = pdev->view_min.y; | ||
467 | 463 | ||
468 | return 0; | 464 | return 0; |
469 | } | 465 | } |
@@ -972,7 +968,7 @@ static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f) | |||
972 | 968 | ||
973 | mutex_lock(&pdev->udevlock); /* To avoid race with s_fmt */ | 969 | mutex_lock(&pdev->udevlock); /* To avoid race with s_fmt */ |
974 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n", | 970 | PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n", |
975 | pdev->image.x, pdev->image.y); | 971 | pdev->width, pdev->height); |
976 | pwc_vidioc_fill_fmt(pdev, f); | 972 | pwc_vidioc_fill_fmt(pdev, f); |
977 | mutex_unlock(&pdev->udevlock); | 973 | mutex_unlock(&pdev->udevlock); |
978 | return 0; | 974 | return 0; |
@@ -1061,25 +1057,21 @@ static int pwc_enum_framesizes(struct file *file, void *fh, | |||
1061 | struct pwc_device *pdev = video_drvdata(file); | 1057 | struct pwc_device *pdev = video_drvdata(file); |
1062 | unsigned int i = 0, index = fsize->index; | 1058 | unsigned int i = 0, index = fsize->index; |
1063 | 1059 | ||
1064 | if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) { | 1060 | if (fsize->pixel_format == V4L2_PIX_FMT_YUV420 || |
1061 | (fsize->pixel_format == V4L2_PIX_FMT_PWC1 && | ||
1062 | DEVICE_USE_CODEC1(pdev->type)) || | ||
1063 | (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && | ||
1064 | DEVICE_USE_CODEC23(pdev->type))) { | ||
1065 | for (i = 0; i < PSZ_MAX; i++) { | 1065 | for (i = 0; i < PSZ_MAX; i++) { |
1066 | if (pdev->image_mask & (1UL << i)) { | 1066 | if (!(pdev->image_mask & (1UL << i))) |
1067 | if (!index--) { | 1067 | continue; |
1068 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; | 1068 | if (!index--) { |
1069 | fsize->discrete.width = pwc_image_sizes[i].x; | 1069 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; |
1070 | fsize->discrete.height = pwc_image_sizes[i].y; | 1070 | fsize->discrete.width = pwc_image_sizes[i][0]; |
1071 | return 0; | 1071 | fsize->discrete.height = pwc_image_sizes[i][1]; |
1072 | } | 1072 | return 0; |
1073 | } | 1073 | } |
1074 | } | 1074 | } |
1075 | } else if (fsize->index == 0 && | ||
1076 | ((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) || | ||
1077 | (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) { | ||
1078 | |||
1079 | fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE; | ||
1080 | fsize->discrete.width = pdev->abs_max.x; | ||
1081 | fsize->discrete.height = pdev->abs_max.y; | ||
1082 | return 0; | ||
1083 | } | 1075 | } |
1084 | return -EINVAL; | 1076 | return -EINVAL; |
1085 | } | 1077 | } |
@@ -1092,8 +1084,8 @@ static int pwc_enum_frameintervals(struct file *file, void *fh, | |||
1092 | unsigned int i; | 1084 | unsigned int i; |
1093 | 1085 | ||
1094 | for (i = 0; i < PSZ_MAX; i++) { | 1086 | for (i = 0; i < PSZ_MAX; i++) { |
1095 | if (pwc_image_sizes[i].x == fival->width && | 1087 | if (pwc_image_sizes[i][0] == fival->width && |
1096 | pwc_image_sizes[i].y == fival->height) { | 1088 | pwc_image_sizes[i][1] == fival->height) { |
1097 | size = i; | 1089 | size = i; |
1098 | break; | 1090 | break; |
1099 | } | 1091 | } |
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h index 19c692c186f..5d013851ed2 100644 --- a/drivers/media/video/pwc/pwc.h +++ b/drivers/media/video/pwc/pwc.h | |||
@@ -107,6 +107,9 @@ | |||
107 | #define FEATURE_CODEC1 0x0002 | 107 | #define FEATURE_CODEC1 0x0002 |
108 | #define FEATURE_CODEC2 0x0004 | 108 | #define FEATURE_CODEC2 0x0004 |
109 | 109 | ||
110 | #define MAX_WIDTH 640 | ||
111 | #define MAX_HEIGHT 480 | ||
112 | |||
110 | /* Ignore errors in the first N frames, to allow for startup delays */ | 113 | /* Ignore errors in the first N frames, to allow for startup delays */ |
111 | #define FRAME_LOWMARK 5 | 114 | #define FRAME_LOWMARK 5 |
112 | 115 | ||
@@ -205,12 +208,6 @@ struct pwc_raw_frame { | |||
205 | __u8 rawframe[0]; /* frame_size = H / 4 * vbandlength */ | 208 | __u8 rawframe[0]; /* frame_size = H / 4 * vbandlength */ |
206 | } __packed; | 209 | } __packed; |
207 | 210 | ||
208 | /* structure for transferring x & y coordinates */ | ||
209 | struct pwc_coord { | ||
210 | int x, y; /* guess what */ | ||
211 | int size; /* size, or offset */ | ||
212 | }; | ||
213 | |||
214 | /* intermediate buffers with raw data from the USB cam */ | 211 | /* intermediate buffers with raw data from the USB cam */ |
215 | struct pwc_frame_buf | 212 | struct pwc_frame_buf |
216 | { | 213 | { |
@@ -233,7 +230,6 @@ struct pwc_device | |||
233 | int type; | 230 | int type; |
234 | int release; /* release number */ | 231 | int release; /* release number */ |
235 | int features; /* feature bits */ | 232 | int features; /* feature bits */ |
236 | char serial[30]; /* serial number (string) */ | ||
237 | 233 | ||
238 | /*** Video data ***/ | 234 | /*** Video data ***/ |
239 | struct file *capt_file; /* file doing video capture */ | 235 | struct file *capt_file; /* file doing video capture */ |
@@ -286,10 +282,7 @@ struct pwc_device | |||
286 | * a gray or black border. view_min <= image <= view <= view_max; | 282 | * a gray or black border. view_min <= image <= view <= view_max; |
287 | */ | 283 | */ |
288 | int image_mask; /* supported sizes */ | 284 | int image_mask; /* supported sizes */ |
289 | struct pwc_coord view_min, view_max; /* minimum and maximum view */ | 285 | int width, height; /* current resolution */ |
290 | struct pwc_coord abs_max; /* maximum supported size */ | ||
291 | struct pwc_coord image, view; /* image and viewport size */ | ||
292 | struct pwc_coord offset; /* offset of the viewport */ | ||
293 | 286 | ||
294 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV | 287 | #ifdef CONFIG_USB_PWC_INPUT_EVDEV |
295 | struct input_dev *button_dev; /* webcam snapshot button input */ | 288 | struct input_dev *button_dev; /* webcam snapshot button input */ |
@@ -364,9 +357,9 @@ int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file); | |||
364 | 357 | ||
365 | /** Functions in pwc-misc.c */ | 358 | /** Functions in pwc-misc.c */ |
366 | /* sizes in pixels */ | 359 | /* sizes in pixels */ |
367 | extern const struct pwc_coord pwc_image_sizes[PSZ_MAX]; | 360 | extern const int pwc_image_sizes[PSZ_MAX][2]; |
368 | 361 | ||
369 | int pwc_decode_size(struct pwc_device *pdev, int width, int height); | 362 | int pwc_get_size(struct pwc_device *pdev, int width, int height); |
370 | void pwc_construct(struct pwc_device *pdev); | 363 | void pwc_construct(struct pwc_device *pdev); |
371 | 364 | ||
372 | /** Functions in pwc-ctrl.c */ | 365 | /** Functions in pwc-ctrl.c */ |