aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pwc
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2011-06-26 05:49:59 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-07-27 16:53:44 -0400
commit6eba93573d2dda3f627006101c0652faeeaffde6 (patch)
tree540ad9fe31cc22f7a043d3fb0fb172683b9963e5 /drivers/media/video/pwc
parent3b4d0ec79113e77b3fe90749ae00bfa015c73048 (diff)
[media] pwc: Move various initialization to driver load and / or stream start
Doing a bunch of initialization every time /dev/video is opened, and thus for example when the udev rules probe for capabilities makes no sense, do it at driver load, resp. stream start instead. This is a preparation patch for allowing multiple opens of the /dev/video node. 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.c28
-rw-r--r--drivers/media/video/pwc/pwc-dec1.c28
-rw-r--r--drivers/media/video/pwc/pwc-dec1.h8
-rw-r--r--drivers/media/video/pwc/pwc-dec23.c22
-rw-r--r--drivers/media/video/pwc/pwc-dec23.h10
-rw-r--r--drivers/media/video/pwc/pwc-if.c263
-rw-r--r--drivers/media/video/pwc/pwc.h1
7 files changed, 114 insertions, 246 deletions
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 69a1c6f37956..9d800c668073 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -261,8 +261,11 @@ static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
261 PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret); 261 PWC_DEBUG_MODULE("Failed to send video command... %d\n", ret);
262 return ret; 262 return ret;
263 } 263 }
264 if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420) 264 if (pEntry->compressed && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
265 pwc_dec1_init(pdev->type, pdev->release, buf, pdev->decompress_data); 265 ret = pwc_dec1_init(pdev, pdev->type, pdev->release, buf);
266 if (ret < 0)
267 return ret;
268 }
266 269
267 pdev->cmd_len = 3; 270 pdev->cmd_len = 3;
268 memcpy(pdev->cmd_buf, buf, 3); 271 memcpy(pdev->cmd_buf, buf, 3);
@@ -321,8 +324,11 @@ static int set_video_mode_Timon(struct pwc_device *pdev, int size, int frames, i
321 if (ret < 0) 324 if (ret < 0)
322 return ret; 325 return ret;
323 326
324 if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) 327 if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
325 pwc_dec23_init(pdev, pdev->type, buf); 328 ret = pwc_dec23_init(pdev, pdev->type, buf);
329 if (ret < 0)
330 return ret;
331 }
326 332
327 pdev->cmd_len = 13; 333 pdev->cmd_len = 13;
328 memcpy(pdev->cmd_buf, buf, 13); 334 memcpy(pdev->cmd_buf, buf, 13);
@@ -394,8 +400,11 @@ static int set_video_mode_Kiara(struct pwc_device *pdev, int size, int frames, i
394 if (ret < 0) 400 if (ret < 0)
395 return ret; 401 return ret;
396 402
397 if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) 403 if (pChoose->bandlength > 0 && pdev->pixfmt == V4L2_PIX_FMT_YUV420) {
398 pwc_dec23_init(pdev, pdev->type, buf); 404 ret = pwc_dec23_init(pdev, pdev->type, buf);
405 if (ret < 0)
406 return ret;
407 }
399 408
400 pdev->cmd_len = 12; 409 pdev->cmd_len = 12;
401 memcpy(pdev->cmd_buf, buf, 12); 410 memcpy(pdev->cmd_buf, buf, 12);
@@ -452,6 +461,7 @@ int pwc_set_video_mode(struct pwc_device *pdev, int width, int height, int frame
452 } 461 }
453 pdev->view.x = width; 462 pdev->view.x = width;
454 pdev->view.y = height; 463 pdev->view.y = height;
464 pdev->vcompression = compression;
455 pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size; 465 pdev->frame_total_size = pdev->frame_size + pdev->frame_header_size + pdev->frame_trailer_size;
456 pwc_set_image_buffer_size(pdev); 466 pwc_set_image_buffer_size(pdev);
457 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); 467 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);
@@ -1300,7 +1310,7 @@ static int pwc_mpt_get_status(struct pwc_device *pdev, struct pwc_mpt_status *st
1300 return 0; 1310 return 0;
1301} 1311}
1302 1312
1303 1313#ifdef CONFIG_USB_PWC_DEBUG
1304int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) 1314int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
1305{ 1315{
1306 unsigned char buf; 1316 unsigned char buf;
@@ -1323,7 +1333,7 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
1323 *sensor = buf; 1333 *sensor = buf;
1324 return 0; 1334 return 0;
1325} 1335}
1326 1336#endif
1327 1337
1328 /* End of Add-Ons */ 1338 /* End of Add-Ons */
1329 /* ************************************************* */ 1339 /* ************************************************* */
@@ -1387,8 +1397,6 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1387 ret = -EINVAL; 1397 ret = -EINVAL;
1388 else 1398 else
1389 ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot); 1399 ret = pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y, pdev->vframes, ARGR(qual), pdev->vsnapshot);
1390 if (ret >= 0)
1391 pdev->vcompression = ARGR(qual);
1392 break; 1400 break;
1393 } 1401 }
1394 1402
diff --git a/drivers/media/video/pwc/pwc-dec1.c b/drivers/media/video/pwc/pwc-dec1.c
index c29593f589eb..be0e02cb487f 100644
--- a/drivers/media/video/pwc/pwc-dec1.c
+++ b/drivers/media/video/pwc/pwc-dec1.c
@@ -22,29 +22,19 @@
22 along with this program; if not, write to the Free Software 22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24*/ 24*/
25
26
27
28#include "pwc-dec1.h" 25#include "pwc-dec1.h"
29 26
30 27int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer)
31void pwc_dec1_init(int type, int release, void *buffer, void *table)
32{ 28{
29 struct pwc_dec1_private *pdec;
33 30
34} 31 if (pwc->decompress_data == NULL) {
35 32 pdec = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
36void pwc_dec1_exit(void) 33 if (pdec == NULL)
37{ 34 return -ENOMEM;
35 pwc->decompress_data = pdec;
36 }
37 pdec = pwc->decompress_data;
38 38
39
40
41}
42
43int pwc_dec1_alloc(struct pwc_device *pwc)
44{
45 pwc->decompress_data = kmalloc(sizeof(struct pwc_dec1_private), GFP_KERNEL);
46 if (pwc->decompress_data == NULL)
47 return -ENOMEM;
48 return 0; 39 return 0;
49} 40}
50
diff --git a/drivers/media/video/pwc/pwc-dec1.h b/drivers/media/video/pwc/pwc-dec1.h
index 8b62ddcc5c7e..a57d8601080b 100644
--- a/drivers/media/video/pwc/pwc-dec1.h
+++ b/drivers/media/video/pwc/pwc-dec1.h
@@ -22,8 +22,6 @@
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23*/ 23*/
24 24
25
26
27#ifndef PWC_DEC1_H 25#ifndef PWC_DEC1_H
28#define PWC_DEC1_H 26#define PWC_DEC1_H
29 27
@@ -32,12 +30,8 @@
32struct pwc_dec1_private 30struct pwc_dec1_private
33{ 31{
34 int version; 32 int version;
35
36}; 33};
37 34
38int pwc_dec1_alloc(struct pwc_device *pwc); 35int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer);
39void pwc_dec1_init(int type, int release, void *buffer, void *private_data);
40void pwc_dec1_exit(void);
41 36
42#endif 37#endif
43
diff --git a/drivers/media/video/pwc/pwc-dec23.c b/drivers/media/video/pwc/pwc-dec23.c
index 0c801b8f3eca..06a4e877ba40 100644
--- a/drivers/media/video/pwc/pwc-dec23.c
+++ b/drivers/media/video/pwc/pwc-dec23.c
@@ -916,27 +916,5 @@ void pwc_dec23_decompress(const struct pwc_device *pwc,
916 pout_planar_v += pwc->view.x; 916 pout_planar_v += pwc->view.x;
917 917
918 } 918 }
919
920 } 919 }
921
922} 920}
923
924void pwc_dec23_exit(void)
925{
926 /* Do nothing */
927
928}
929
930/**
931 * Allocate a private structure used by lookup table.
932 * You must call kfree() to free the memory allocated.
933 */
934int pwc_dec23_alloc(struct pwc_device *pwc)
935{
936 pwc->decompress_data = kmalloc(sizeof(struct pwc_dec23_private), GFP_KERNEL);
937 if (pwc->decompress_data == NULL)
938 return -ENOMEM;
939 return 0;
940}
941
942/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff --git a/drivers/media/video/pwc/pwc-dec23.h b/drivers/media/video/pwc/pwc-dec23.h
index 1c55298ad153..a0ac4f3dff81 100644
--- a/drivers/media/video/pwc/pwc-dec23.h
+++ b/drivers/media/video/pwc/pwc-dec23.h
@@ -49,19 +49,9 @@ struct pwc_dec23_private
49 49
50}; 50};
51 51
52
53int pwc_dec23_alloc(struct pwc_device *pwc);
54int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd); 52int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd);
55void pwc_dec23_exit(void);
56void pwc_dec23_decompress(const struct pwc_device *pwc, 53void pwc_dec23_decompress(const struct pwc_device *pwc,
57 const void *src, 54 const void *src,
58 void *dst, 55 void *dst,
59 int flags); 56 int flags);
60
61
62
63#endif 57#endif
64
65
66/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
67
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index d2a1f3fc0468..b591b723f5a1 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -2,6 +2,7 @@
2 USB and Video4Linux interface part. 2 USB and Video4Linux interface part.
3 (C) 1999-2004 Nemosoft Unv. 3 (C) 1999-2004 Nemosoft Unv.
4 (C) 2004-2006 Luc Saillard (luc@saillard.org) 4 (C) 2004-2006 Luc Saillard (luc@saillard.org)
5 (C) 2011 Hans de Goede <hdegoede@redhat.com>
5 6
6 NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx 7 NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
7 driver and thus may have bugs that are not present in the original version. 8 driver and thus may have bugs that are not present in the original version.
@@ -128,7 +129,6 @@ static struct usb_driver pwc_driver = {
128#define MAX_DEV_HINTS 20 129#define MAX_DEV_HINTS 20
129#define MAX_ISOC_ERRORS 20 130#define MAX_ISOC_ERRORS 20
130 131
131static int default_size = PSZ_QCIF;
132static int default_fps = 10; 132static int default_fps = 10;
133#ifdef CONFIG_USB_PWC_DEBUG 133#ifdef CONFIG_USB_PWC_DEBUG
134 int pwc_trace = PWC_DEBUG_LEVEL; 134 int pwc_trace = PWC_DEBUG_LEVEL;
@@ -172,65 +172,6 @@ static struct video_device pwc_template = {
172/***************************************************************************/ 172/***************************************************************************/
173/* Private functions */ 173/* Private functions */
174 174
175static int pwc_allocate_buffers(struct pwc_device *pdev)
176{
177 int i, err;
178 void *kbuf;
179
180 PWC_DEBUG_MEMORY(">> pwc_allocate_buffers(pdev = 0x%p)\n", pdev);
181
182 /* Allocate Isochronuous pipe buffers */
183 for (i = 0; i < MAX_ISO_BUFS; i++) {
184 if (pdev->sbuf[i].data == NULL) {
185 kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
186 if (kbuf == NULL) {
187 PWC_ERROR("Failed to allocate iso buffer %d.\n", i);
188 return -ENOMEM;
189 }
190 PWC_DEBUG_MEMORY("Allocated iso buffer at %p.\n", kbuf);
191 pdev->sbuf[i].data = kbuf;
192 }
193 }
194
195 /* Allocate decompressor table space */
196 if (DEVICE_USE_CODEC1(pdev->type))
197 err = pwc_dec1_alloc(pdev);
198 else
199 err = pwc_dec23_alloc(pdev);
200
201 if (err) {
202 PWC_ERROR("Failed to allocate decompress table.\n");
203 return err;
204 }
205
206 PWC_DEBUG_MEMORY("<< pwc_allocate_buffers()\n");
207 return 0;
208}
209
210static void pwc_free_buffers(struct pwc_device *pdev)
211{
212 int i;
213
214 PWC_DEBUG_MEMORY("Entering free_buffers(%p).\n", pdev);
215
216 /* Release Iso-pipe buffers */
217 for (i = 0; i < MAX_ISO_BUFS; i++)
218 if (pdev->sbuf[i].data != NULL) {
219 PWC_DEBUG_MEMORY("Freeing ISO buffer at %p.\n", pdev->sbuf[i].data);
220 kfree(pdev->sbuf[i].data);
221 pdev->sbuf[i].data = NULL;
222 }
223
224 /* Intermediate decompression buffer & tables */
225 if (pdev->decompress_data != NULL) {
226 PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n", pdev->decompress_data);
227 kfree(pdev->decompress_data);
228 pdev->decompress_data = NULL;
229 }
230
231 PWC_DEBUG_MEMORY("Leaving free_buffers().\n");
232}
233
234struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev) 175struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev)
235{ 176{
236 unsigned long flags = 0; 177 unsigned long flags = 0;
@@ -435,12 +376,16 @@ static int pwc_isoc_init(struct pwc_device *pdev)
435 int i, j, ret; 376 int i, j, ret;
436 struct usb_interface *intf; 377 struct usb_interface *intf;
437 struct usb_host_interface *idesc = NULL; 378 struct usb_host_interface *idesc = NULL;
379 void *kbuf;
438 380
439 if (pdev->iso_init) 381 if (pdev->iso_init)
440 return 0; 382 return 0;
383
441 pdev->vsync = 0; 384 pdev->vsync = 0;
385 pdev->vlast_packet_size = 0;
442 pdev->fill_buf = NULL; 386 pdev->fill_buf = NULL;
443 pdev->vframe_count = 0; 387 pdev->vframe_count = 0;
388 pdev->visoc_errors = 0;
444 udev = pdev->udev; 389 udev = pdev->udev;
445 390
446 /* Get the current alternate interface, adjust packet size */ 391 /* Get the current alternate interface, adjust packet size */
@@ -471,24 +416,31 @@ static int pwc_isoc_init(struct pwc_device *pdev)
471 if (ret < 0) 416 if (ret < 0)
472 return ret; 417 return ret;
473 418
419 /* Allocate Isochronuous pipe buffers */
420 for (i = 0; i < MAX_ISO_BUFS; i++) {
421 kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL);
422 if (kbuf == NULL) {
423 PWC_ERROR("Failed to allocate iso buffer %d.\n", i);
424 pdev->iso_init = 1;
425 pwc_isoc_cleanup(pdev);
426 return -ENOMEM;
427 }
428 PWC_DEBUG_MEMORY("Allocated iso buffer at %p.\n", kbuf);
429 pdev->sbuf[i].data = kbuf;
430 }
431
432 /* Allocate Isochronuous urbs */
474 for (i = 0; i < MAX_ISO_BUFS; i++) { 433 for (i = 0; i < MAX_ISO_BUFS; i++) {
475 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); 434 urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL);
476 if (urb == NULL) { 435 if (urb == NULL) {
477 PWC_ERROR("Failed to allocate urb %d\n", i); 436 PWC_ERROR("Failed to allocate urb %d\n", i);
478 ret = -ENOMEM; 437 pdev->iso_init = 1;
479 break; 438 pwc_isoc_cleanup(pdev);
439 return -ENOMEM;
480 } 440 }
481 pdev->sbuf[i].urb = urb; 441 pdev->sbuf[i].urb = urb;
482 PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb); 442 PWC_DEBUG_MEMORY("Allocated URB at 0x%p\n", urb);
483 } 443 }
484 if (ret) {
485 /* De-allocate in reverse order */
486 while (i--) {
487 usb_free_urb(pdev->sbuf[i].urb);
488 pdev->sbuf[i].urb = NULL;
489 }
490 return ret;
491 }
492 444
493 /* init URB structure */ 445 /* init URB structure */
494 for (i = 0; i < MAX_ISO_BUFS; i++) { 446 for (i = 0; i < MAX_ISO_BUFS; i++) {
@@ -563,6 +515,8 @@ static void pwc_iso_free(struct pwc_device *pdev)
563 515
564static void pwc_isoc_cleanup(struct pwc_device *pdev) 516static void pwc_isoc_cleanup(struct pwc_device *pdev)
565{ 517{
518 int i;
519
566 PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n"); 520 PWC_DEBUG_OPEN(">> pwc_isoc_cleanup()\n");
567 521
568 if (pdev->iso_init == 0) 522 if (pdev->iso_init == 0)
@@ -572,6 +526,16 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
572 pwc_iso_free(pdev); 526 pwc_iso_free(pdev);
573 usb_set_interface(pdev->udev, 0, 0); 527 usb_set_interface(pdev->udev, 0, 0);
574 528
529 /* Release Iso-pipe buffers */
530 for (i = 0; i < MAX_ISO_BUFS; i++) {
531 if (pdev->sbuf[i].data != NULL) {
532 PWC_DEBUG_MEMORY("Freeing ISO buffer at %p.\n",
533 pdev->sbuf[i].data);
534 kfree(pdev->sbuf[i].data);
535 pdev->sbuf[i].data = NULL;
536 }
537 }
538
575 pdev->iso_init = 0; 539 pdev->iso_init = 0;
576 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n"); 540 PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
577} 541}
@@ -705,7 +669,6 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
705 669
706static int pwc_video_open(struct file *file) 670static int pwc_video_open(struct file *file)
707{ 671{
708 int i, ret;
709 struct video_device *vdev = video_devdata(file); 672 struct video_device *vdev = video_devdata(file);
710 struct pwc_device *pdev; 673 struct pwc_device *pdev;
711 674
@@ -720,68 +683,6 @@ static int pwc_video_open(struct file *file)
720 return -EBUSY; 683 return -EBUSY;
721 } 684 }
722 685
723 if (!pdev->usb_init) {
724 PWC_DEBUG_OPEN("Doing first time initialization.\n");
725 pdev->usb_init = 1;
726
727 /* Query sensor type */
728 ret = pwc_get_cmos_sensor(pdev, &i);
729 if (ret >= 0)
730 {
731 PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
732 pdev->vdev.name,
733 pwc_sensor_type_to_string(i), i);
734 }
735 }
736
737 /* Turn on camera and set LEDS on */
738 pwc_camera_power(pdev, 1);
739 pwc_set_leds(pdev, led_on, led_off);
740
741 /* So far, so good. Allocate memory. */
742 i = pwc_allocate_buffers(pdev);
743 if (i < 0) {
744 PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n");
745 pwc_free_buffers(pdev);
746 return i;
747 }
748
749 /* Reset buffers & parameters */
750 pdev->visoc_errors = 0;
751
752 /* Set some defaults */
753 pdev->vsnapshot = 0;
754
755 /* Set video size, first try the last used video size
756 (or the default one); if that fails try QCIF/10 or QSIF/10;
757 it that fails too, give up.
758 */
759 i = pwc_set_video_mode(pdev, pwc_image_sizes[pdev->vsize].x, pwc_image_sizes[pdev->vsize].y, pdev->vframes, pdev->vcompression, 0);
760 if (i) {
761 unsigned int default_resolution;
762 PWC_DEBUG_OPEN("First attempt at set_video_mode failed.\n");
763 if (pdev->type>= 730)
764 default_resolution = PSZ_QSIF;
765 else
766 default_resolution = PSZ_QCIF;
767
768 i = pwc_set_video_mode(pdev,
769 pwc_image_sizes[default_resolution].x,
770 pwc_image_sizes[default_resolution].y,
771 10,
772 pdev->vcompression,
773 0);
774 }
775 if (i) {
776 PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n");
777 pwc_free_buffers(pdev);
778 return i;
779 }
780
781 /* Initialize the webcam to sane value */
782 pwc_set_brightness(pdev, 0x7fff);
783 pwc_set_agc(pdev, 1, 0);
784
785 pdev->vopen++; 686 pdev->vopen++;
786 file->private_data = vdev; 687 file->private_data = vdev;
787 PWC_DEBUG_OPEN("<< video_open() returns 0.\n"); 688 PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
@@ -798,10 +699,17 @@ static void pwc_video_release(struct video_device *vfd)
798 if (device_hint[hint].pdev == pdev) 699 if (device_hint[hint].pdev == pdev)
799 device_hint[hint].pdev = NULL; 700 device_hint[hint].pdev = NULL;
800 701
702 /* Free intermediate decompression buffer & tables */
703 if (pdev->decompress_data != NULL) {
704 PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
705 pdev->decompress_data);
706 kfree(pdev->decompress_data);
707 pdev->decompress_data = NULL;
708 }
709
801 kfree(pdev); 710 kfree(pdev);
802} 711}
803 712
804/* Note that all cleanup is done in the reverse order as in _open */
805static int pwc_video_close(struct file *file) 713static int pwc_video_close(struct file *file)
806{ 714{
807 struct video_device *vdev = file->private_data; 715 struct video_device *vdev = file->private_data;
@@ -810,25 +718,10 @@ static int pwc_video_close(struct file *file)
810 PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); 718 PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
811 719
812 pdev = video_get_drvdata(vdev); 720 pdev = video_get_drvdata(vdev);
813 if (pdev->vopen == 0)
814 PWC_DEBUG_MODULE("video_close() called on closed device?\n");
815
816 if (DEVICE_USE_CODEC1(pdev->type))
817 pwc_dec1_exit();
818 else
819 pwc_dec23_exit();
820
821 vb2_queue_release(&pdev->vb_queue); 721 vb2_queue_release(&pdev->vb_queue);
822 pwc_free_buffers(pdev); 722 pdev->vopen--;
823
824 /* Turn off LEDS and power down camera, but only when not unplugged */
825 if (pdev->udev) {
826 pwc_set_leds(pdev, 0, 0);
827 pwc_camera_power(pdev, 0);
828 pdev->vopen--;
829 PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
830 }
831 723
724 PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
832 return 0; 725 return 0;
833} 726}
834 727
@@ -946,6 +839,16 @@ static int start_streaming(struct vb2_queue *vq)
946 if (!pdev->udev) 839 if (!pdev->udev)
947 return -ENODEV; 840 return -ENODEV;
948 841
842 /* Turn on camera and set LEDS on */
843 pwc_camera_power(pdev, 1);
844 if (pdev->power_save) {
845 /* Restore video mode */
846 pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y,
847 pdev->vframes, pdev->vcompression,
848 pdev->vsnapshot);
849 }
850 pwc_set_leds(pdev, led_on, led_off);
851
949 return pwc_isoc_init(pdev); 852 return pwc_isoc_init(pdev);
950} 853}
951 854
@@ -953,8 +856,11 @@ static int stop_streaming(struct vb2_queue *vq)
953{ 856{
954 struct pwc_device *pdev = vb2_get_drv_priv(vq); 857 struct pwc_device *pdev = vb2_get_drv_priv(vq);
955 858
956 if (pdev->udev) 859 if (pdev->udev) {
860 pwc_set_leds(pdev, 0, 0);
861 pwc_camera_power(pdev, 0);
957 pwc_isoc_cleanup(pdev); 862 pwc_isoc_cleanup(pdev);
863 }
958 pwc_cleanup_queued_bufs(pdev); 864 pwc_cleanup_queued_bufs(pdev);
959 865
960 return 0; 866 return 0;
@@ -1253,7 +1159,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1253 return -ENOMEM; 1159 return -ENOMEM;
1254 } 1160 }
1255 pdev->type = type_id; 1161 pdev->type = type_id;
1256 pdev->vsize = default_size;
1257 pdev->vframes = default_fps; 1162 pdev->vframes = default_fps;
1258 strcpy(pdev->serial, serial_number); 1163 strcpy(pdev->serial, serial_number);
1259 pdev->features = features; 1164 pdev->features = features;
@@ -1318,8 +1223,29 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1318 PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev); 1223 PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
1319 usb_set_intfdata(intf, pdev); 1224 usb_set_intfdata(intf, pdev);
1320 1225
1226#ifdef CONFIG_USB_PWC_DEBUG
1227 /* Query sensor type */
1228 if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
1229 PWC_DEBUG_OPEN("This %s camera is equipped with a %s (%d).\n",
1230 pdev->vdev.name,
1231 pwc_sensor_type_to_string(rc), rc);
1232 }
1233#endif
1234
1321 /* Set the leds off */ 1235 /* Set the leds off */
1322 pwc_set_leds(pdev, 0, 0); 1236 pwc_set_leds(pdev, 0, 0);
1237
1238 /* Setup intial videomode */
1239 rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y,
1240 pdev->vframes, pdev->vcompression, 0);
1241 if (rc)
1242 goto err_free_mem;
1243
1244 /* Initialize the webcam to sane values */
1245 pwc_set_brightness(pdev, 0x7fff);
1246 pwc_set_agc(pdev, 1, 0);
1247
1248 /* And powerdown the camera until streaming starts */
1323 pwc_camera_power(pdev, 0); 1249 pwc_camera_power(pdev, 0);
1324 1250
1325 rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr); 1251 rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
@@ -1402,7 +1328,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
1402 * Initialization code & module stuff 1328 * Initialization code & module stuff
1403 */ 1329 */
1404 1330
1405static char *size;
1406static int fps; 1331static int fps;
1407static int compression = -1; 1332static int compression = -1;
1408static int leds[2] = { -1, -1 }; 1333static int leds[2] = { -1, -1 };
@@ -1410,7 +1335,6 @@ static unsigned int leds_nargs;
1410static char *dev_hint[MAX_DEV_HINTS]; 1335static char *dev_hint[MAX_DEV_HINTS];
1411static unsigned int dev_hint_nargs; 1336static unsigned int dev_hint_nargs;
1412 1337
1413module_param(size, charp, 0444);
1414module_param(fps, int, 0444); 1338module_param(fps, int, 0444);
1415#ifdef CONFIG_USB_PWC_DEBUG 1339#ifdef CONFIG_USB_PWC_DEBUG
1416module_param_named(trace, pwc_trace, int, 0644); 1340module_param_named(trace, pwc_trace, int, 0644);
@@ -1420,7 +1344,6 @@ module_param(compression, int, 0444);
1420module_param_array(leds, int, &leds_nargs, 0444); 1344module_param_array(leds, int, &leds_nargs, 0444);
1421module_param_array(dev_hint, charp, &dev_hint_nargs, 0444); 1345module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
1422 1346
1423MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga");
1424MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); 1347MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
1425#ifdef CONFIG_USB_PWC_DEBUG 1348#ifdef CONFIG_USB_PWC_DEBUG
1426MODULE_PARM_DESC(trace, "For debugging purposes"); 1349MODULE_PARM_DESC(trace, "For debugging purposes");
@@ -1438,14 +1361,19 @@ MODULE_VERSION( PWC_VERSION );
1438 1361
1439static int __init usb_pwc_init(void) 1362static int __init usb_pwc_init(void)
1440{ 1363{
1441 int i, sz; 1364 int i;
1442 char *sizenames[PSZ_MAX] = { "sqcif", "qsif", "qcif", "sif", "cif", "vga" };
1443 1365
1366#ifdef CONFIG_USB_PWC_DEBUG
1444 PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n"); 1367 PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
1445 PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n"); 1368 PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
1446 PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n"); 1369 PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
1447 PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n"); 1370 PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
1448 1371
1372 if (pwc_trace >= 0) {
1373 PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
1374 }
1375#endif
1376
1449 if (fps) { 1377 if (fps) {
1450 if (fps < 4 || fps > 30) { 1378 if (fps < 4 || fps > 30) {
1451 PWC_ERROR("Framerate out of bounds (4-30).\n"); 1379 PWC_ERROR("Framerate out of bounds (4-30).\n");
@@ -1455,25 +1383,6 @@ static int __init usb_pwc_init(void)
1455 PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps); 1383 PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
1456 } 1384 }
1457 1385
1458 if (size) {
1459 /* string; try matching with array */
1460 for (sz = 0; sz < PSZ_MAX; sz++) {
1461 if (!strcmp(sizenames[sz], size)) { /* Found! */
1462 default_size = sz;
1463 break;
1464 }
1465 }
1466 if (sz == PSZ_MAX) {
1467 PWC_ERROR("Size not recognized; try size=[sqcif | qsif | qcif | sif | cif | vga].\n");
1468 return -EINVAL;
1469 }
1470 PWC_DEBUG_MODULE("Default image size set to %s [%dx%d].\n", sizenames[default_size], pwc_image_sizes[default_size].x, pwc_image_sizes[default_size].y);
1471 }
1472#ifdef CONFIG_USB_PWC_DEBUG
1473 if (pwc_trace >= 0) {
1474 PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
1475 }
1476#endif
1477 if (compression >= 0) { 1386 if (compression >= 0) {
1478 if (compression > 3) { 1387 if (compression > 3) {
1479 PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n"); 1388 PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 7013318997fd..8d82c6aac42c 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -158,7 +158,6 @@ struct pwc_device
158 int release; /* release number */ 158 int release; /* release number */
159 int features; /* feature bits */ 159 int features; /* feature bits */
160 char serial[30]; /* serial number (string) */ 160 char serial[30]; /* serial number (string) */
161 int usb_init; /* set when the cam has been initialized */
162 161
163 /*** Video data ***/ 162 /*** Video data ***/
164 int vopen; /* flag */ 163 int vopen; /* flag */