diff options
author | Hans de Goede <hdegoede@redhat.com> | 2011-06-26 05:49:59 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-07-27 16:53:44 -0400 |
commit | 6eba93573d2dda3f627006101c0652faeeaffde6 (patch) | |
tree | 540ad9fe31cc22f7a043d3fb0fb172683b9963e5 /drivers/media/video/pwc | |
parent | 3b4d0ec79113e77b3fe90749ae00bfa015c73048 (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.c | 28 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-dec1.c | 28 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-dec1.h | 8 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-dec23.c | 22 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-dec23.h | 10 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc-if.c | 263 | ||||
-rw-r--r-- | drivers/media/video/pwc/pwc.h | 1 |
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 | |
1304 | int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor) | 1314 | int 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 | 27 | int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer) | |
31 | void 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); | |
36 | void 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 | |||
43 | int 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 @@ | |||
32 | struct pwc_dec1_private | 30 | struct pwc_dec1_private |
33 | { | 31 | { |
34 | int version; | 32 | int version; |
35 | |||
36 | }; | 33 | }; |
37 | 34 | ||
38 | int pwc_dec1_alloc(struct pwc_device *pwc); | 35 | int pwc_dec1_init(struct pwc_device *pwc, int type, int release, void *buffer); |
39 | void pwc_dec1_init(int type, int release, void *buffer, void *private_data); | ||
40 | void 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 | |||
924 | void 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 | */ | ||
934 | int 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 | |||
53 | int pwc_dec23_alloc(struct pwc_device *pwc); | ||
54 | int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd); | 52 | int pwc_dec23_init(struct pwc_device *pwc, int type, unsigned char *cmd); |
55 | void pwc_dec23_exit(void); | ||
56 | void pwc_dec23_decompress(const struct pwc_device *pwc, | 53 | void 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 | ||
131 | static int default_size = PSZ_QCIF; | ||
132 | static int default_fps = 10; | 132 | static 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 | ||
175 | static 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 | |||
210 | static 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 | |||
234 | struct pwc_frame_buf *pwc_get_next_fill_buf(struct pwc_device *pdev) | 175 | struct 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 | ||
564 | static void pwc_isoc_cleanup(struct pwc_device *pdev) | 516 | static 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 | ||
706 | static int pwc_video_open(struct file *file) | 670 | static 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 */ | ||
805 | static int pwc_video_close(struct file *file) | 713 | static 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 | ||
1405 | static char *size; | ||
1406 | static int fps; | 1331 | static int fps; |
1407 | static int compression = -1; | 1332 | static int compression = -1; |
1408 | static int leds[2] = { -1, -1 }; | 1333 | static int leds[2] = { -1, -1 }; |
@@ -1410,7 +1335,6 @@ static unsigned int leds_nargs; | |||
1410 | static char *dev_hint[MAX_DEV_HINTS]; | 1335 | static char *dev_hint[MAX_DEV_HINTS]; |
1411 | static unsigned int dev_hint_nargs; | 1336 | static unsigned int dev_hint_nargs; |
1412 | 1337 | ||
1413 | module_param(size, charp, 0444); | ||
1414 | module_param(fps, int, 0444); | 1338 | module_param(fps, int, 0444); |
1415 | #ifdef CONFIG_USB_PWC_DEBUG | 1339 | #ifdef CONFIG_USB_PWC_DEBUG |
1416 | module_param_named(trace, pwc_trace, int, 0644); | 1340 | module_param_named(trace, pwc_trace, int, 0644); |
@@ -1420,7 +1344,6 @@ module_param(compression, int, 0444); | |||
1420 | module_param_array(leds, int, &leds_nargs, 0444); | 1344 | module_param_array(leds, int, &leds_nargs, 0444); |
1421 | module_param_array(dev_hint, charp, &dev_hint_nargs, 0444); | 1345 | module_param_array(dev_hint, charp, &dev_hint_nargs, 0444); |
1422 | 1346 | ||
1423 | MODULE_PARM_DESC(size, "Initial image size. One of sqcif, qsif, qcif, sif, cif, vga"); | ||
1424 | MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30"); | 1347 | MODULE_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 |
1426 | MODULE_PARM_DESC(trace, "For debugging purposes"); | 1349 | MODULE_PARM_DESC(trace, "For debugging purposes"); |
@@ -1438,14 +1361,19 @@ MODULE_VERSION( PWC_VERSION ); | |||
1438 | 1361 | ||
1439 | static int __init usb_pwc_init(void) | 1362 | static 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 */ |