aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pwc/pwc-if.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pwc/pwc-if.c')
-rw-r--r--drivers/media/video/pwc/pwc-if.c175
1 files changed, 16 insertions, 159 deletions
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 943d37ad0d33..122fbd0081eb 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -128,18 +128,11 @@ static struct usb_driver pwc_driver = {
128#define MAX_DEV_HINTS 20 128#define MAX_DEV_HINTS 20
129#define MAX_ISOC_ERRORS 20 129#define MAX_ISOC_ERRORS 20
130 130
131static int default_fps = 10;
132#ifdef CONFIG_USB_PWC_DEBUG 131#ifdef CONFIG_USB_PWC_DEBUG
133 int pwc_trace = PWC_DEBUG_LEVEL; 132 int pwc_trace = PWC_DEBUG_LEVEL;
134#endif 133#endif
135static int power_save = -1; 134static int power_save = -1;
136static int led_on = 100, led_off; /* defaults to LED that is on while in use */ 135static int leds[2] = { 100, 0 };
137static struct {
138 int type;
139 char serial_number[30];
140 int device_node;
141 struct pwc_device *pdev;
142} device_hint[MAX_DEV_HINTS];
143 136
144/***/ 137/***/
145 138
@@ -386,8 +379,8 @@ static int pwc_isoc_init(struct pwc_device *pdev)
386retry: 379retry:
387 /* We first try with low compression and then retry with a higher 380 /* We first try with low compression and then retry with a higher
388 compression setting if there is not enough bandwidth. */ 381 compression setting if there is not enough bandwidth. */
389 ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, 382 ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
390 pdev->vframes, &compression); 383 pdev->vframes, &compression, 1);
391 384
392 /* Get the current alternate interface, adjust packet size */ 385 /* Get the current alternate interface, adjust packet size */
393 intf = usb_ifnum_to_if(udev, 0); 386 intf = usb_ifnum_to_if(udev, 0);
@@ -597,23 +590,9 @@ leave:
597static void pwc_video_release(struct v4l2_device *v) 590static void pwc_video_release(struct v4l2_device *v)
598{ 591{
599 struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev); 592 struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
600 int hint;
601
602 /* search device_hint[] table if we occupy a slot, by any chance */
603 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
604 if (device_hint[hint].pdev == pdev)
605 device_hint[hint].pdev = NULL;
606
607 /* Free intermediate decompression buffer & tables */
608 if (pdev->decompress_data != NULL) {
609 PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
610 pdev->decompress_data);
611 kfree(pdev->decompress_data);
612 pdev->decompress_data = NULL;
613 }
614 593
615 v4l2_ctrl_handler_free(&pdev->ctrl_handler); 594 v4l2_ctrl_handler_free(&pdev->ctrl_handler);
616 595 kfree(pdev->ctrl_buf);
617 kfree(pdev); 596 kfree(pdev);
618} 597}
619 598
@@ -758,7 +737,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
758 737
759 /* Turn on camera and set LEDS on */ 738 /* Turn on camera and set LEDS on */
760 pwc_camera_power(pdev, 1); 739 pwc_camera_power(pdev, 1);
761 pwc_set_leds(pdev, led_on, led_off); 740 pwc_set_leds(pdev, leds[0], leds[1]);
762 741
763 r = pwc_isoc_init(pdev); 742 r = pwc_isoc_init(pdev);
764 if (r) { 743 if (r) {
@@ -813,10 +792,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
813 struct usb_device *udev = interface_to_usbdev(intf); 792 struct usb_device *udev = interface_to_usbdev(intf);
814 struct pwc_device *pdev = NULL; 793 struct pwc_device *pdev = NULL;
815 int vendor_id, product_id, type_id; 794 int vendor_id, product_id, type_id;
816 int hint, rc; 795 int rc;
817 int features = 0; 796 int features = 0;
818 int compression = 0; 797 int compression = 0;
819 int video_nr = -1; /* default: use next available device */
820 int my_power_save = power_save; 798 int my_power_save = power_save;
821 char serial_number[30], *name; 799 char serial_number[30], *name;
822 800
@@ -1076,7 +1054,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1076 return -ENOMEM; 1054 return -ENOMEM;
1077 } 1055 }
1078 pdev->type = type_id; 1056 pdev->type = type_id;
1079 pdev->vframes = default_fps;
1080 pdev->features = features; 1057 pdev->features = features;
1081 pwc_construct(pdev); /* set min/max sizes correct */ 1058 pwc_construct(pdev); /* set min/max sizes correct */
1082 1059
@@ -1107,24 +1084,14 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1107 pdev->release = le16_to_cpu(udev->descriptor.bcdDevice); 1084 pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
1108 PWC_DEBUG_PROBE("Release: %04x\n", pdev->release); 1085 PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
1109 1086
1110 /* Now search device_hint[] table for a match, so we can hint a node number. */ 1087 /* Allocate USB command buffers */
1111 for (hint = 0; hint < MAX_DEV_HINTS; hint++) { 1088 pdev->ctrl_buf = kmalloc(sizeof(pdev->cmd_buf), GFP_KERNEL);
1112 if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) && 1089 if (!pdev->ctrl_buf) {
1113 (device_hint[hint].pdev == NULL)) { 1090 PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
1114 /* so far, so good... try serial number */ 1091 rc = -ENOMEM;
1115 if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) { 1092 goto err_free_mem;
1116 /* match! */
1117 video_nr = device_hint[hint].device_node;
1118 PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
1119 break;
1120 }
1121 }
1122 } 1093 }
1123 1094
1124 /* occupy slot */
1125 if (hint < MAX_DEV_HINTS)
1126 device_hint[hint].pdev = pdev;
1127
1128#ifdef CONFIG_USB_PWC_DEBUG 1095#ifdef CONFIG_USB_PWC_DEBUG
1129 /* Query sensor type */ 1096 /* Query sensor type */
1130 if (pwc_get_cmos_sensor(pdev, &rc) >= 0) { 1097 if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
@@ -1138,8 +1105,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1138 pwc_set_leds(pdev, 0, 0); 1105 pwc_set_leds(pdev, 0, 0);
1139 1106
1140 /* Setup intial videomode */ 1107 /* Setup intial videomode */
1141 rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT, pdev->vframes, 1108 rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
1142 &compression); 1109 V4L2_PIX_FMT_YUV420, 30, &compression, 1);
1143 if (rc) 1110 if (rc)
1144 goto err_free_mem; 1111 goto err_free_mem;
1145 1112
@@ -1164,7 +1131,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1164 pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler; 1131 pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
1165 pdev->vdev.v4l2_dev = &pdev->v4l2_dev; 1132 pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
1166 1133
1167 rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr); 1134 rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1);
1168 if (rc < 0) { 1135 if (rc < 0) {
1169 PWC_ERROR("Failed to register as video device (%d).\n", rc); 1136 PWC_ERROR("Failed to register as video device (%d).\n", rc);
1170 goto err_unregister_v4l2_dev; 1137 goto err_unregister_v4l2_dev;
@@ -1207,8 +1174,7 @@ err_unregister_v4l2_dev:
1207err_free_controls: 1174err_free_controls:
1208 v4l2_ctrl_handler_free(&pdev->ctrl_handler); 1175 v4l2_ctrl_handler_free(&pdev->ctrl_handler);
1209err_free_mem: 1176err_free_mem:
1210 if (hint < MAX_DEV_HINTS) 1177 kfree(pdev->ctrl_buf);
1211 device_hint[hint].pdev = NULL;
1212 kfree(pdev); 1178 kfree(pdev);
1213 return rc; 1179 return rc;
1214} 1180}
@@ -1243,27 +1209,19 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
1243 * Initialization code & module stuff 1209 * Initialization code & module stuff
1244 */ 1210 */
1245 1211
1246static int fps;
1247static int leds[2] = { -1, -1 };
1248static unsigned int leds_nargs; 1212static unsigned int leds_nargs;
1249static char *dev_hint[MAX_DEV_HINTS];
1250static unsigned int dev_hint_nargs;
1251 1213
1252module_param(fps, int, 0444);
1253#ifdef CONFIG_USB_PWC_DEBUG 1214#ifdef CONFIG_USB_PWC_DEBUG
1254module_param_named(trace, pwc_trace, int, 0644); 1215module_param_named(trace, pwc_trace, int, 0644);
1255#endif 1216#endif
1256module_param(power_save, int, 0644); 1217module_param(power_save, int, 0644);
1257module_param_array(leds, int, &leds_nargs, 0444); 1218module_param_array(leds, int, &leds_nargs, 0444);
1258module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
1259 1219
1260MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
1261#ifdef CONFIG_USB_PWC_DEBUG 1220#ifdef CONFIG_USB_PWC_DEBUG
1262MODULE_PARM_DESC(trace, "For debugging purposes"); 1221MODULE_PARM_DESC(trace, "For debugging purposes");
1263#endif 1222#endif
1264MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off"); 1223MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
1265MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); 1224MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
1266MODULE_PARM_DESC(dev_hint, "Device node hints");
1267 1225
1268MODULE_DESCRIPTION("Philips & OEM USB webcam driver"); 1226MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
1269MODULE_AUTHOR("Luc Saillard <luc@saillard.org>"); 1227MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
@@ -1273,114 +1231,13 @@ MODULE_VERSION( PWC_VERSION );
1273 1231
1274static int __init usb_pwc_init(void) 1232static int __init usb_pwc_init(void)
1275{ 1233{
1276 int i;
1277
1278#ifdef CONFIG_USB_PWC_DEBUG
1279 PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
1280 PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
1281 PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
1282 PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
1283
1284 if (pwc_trace >= 0) {
1285 PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
1286 }
1287#endif
1288
1289 if (fps) {
1290 if (fps < 4 || fps > 30) {
1291 PWC_ERROR("Framerate out of bounds (4-30).\n");
1292 return -EINVAL;
1293 }
1294 default_fps = fps;
1295 PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
1296 }
1297
1298 if (leds[0] >= 0)
1299 led_on = leds[0];
1300 if (leds[1] >= 0)
1301 led_off = leds[1];
1302
1303 /* Big device node whoopla. Basically, it allows you to assign a
1304 device node (/dev/videoX) to a camera, based on its type
1305 & serial number. The format is [type[.serialnumber]:]node.
1306
1307 Any camera that isn't matched by these rules gets the next
1308 available free device node.
1309 */
1310 for (i = 0; i < MAX_DEV_HINTS; i++) {
1311 char *s, *colon, *dot;
1312
1313 /* This loop also initializes the array */
1314 device_hint[i].pdev = NULL;
1315 s = dev_hint[i];
1316 if (s != NULL && *s != '\0') {
1317 device_hint[i].type = -1; /* wildcard */
1318 strcpy(device_hint[i].serial_number, "*");
1319
1320 /* parse string: chop at ':' & '/' */
1321 colon = dot = s;
1322 while (*colon != '\0' && *colon != ':')
1323 colon++;
1324 while (*dot != '\0' && *dot != '.')
1325 dot++;
1326 /* Few sanity checks */
1327 if (*dot != '\0' && dot > colon) {
1328 PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
1329 return -EINVAL;
1330 }
1331
1332 if (*colon == '\0') {
1333 /* No colon */
1334 if (*dot != '\0') {
1335 PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
1336 return -EINVAL;
1337 }
1338 else {
1339 /* No type or serial number specified, just a number. */
1340 device_hint[i].device_node =
1341 simple_strtol(s, NULL, 10);
1342 }
1343 }
1344 else {
1345 /* There's a colon, so we have at least a type and a device node */
1346 device_hint[i].type =
1347 simple_strtol(s, NULL, 10);
1348 device_hint[i].device_node =
1349 simple_strtol(colon + 1, NULL, 10);
1350 if (*dot != '\0') {
1351 /* There's a serial number as well */
1352 int k;
1353
1354 dot++;
1355 k = 0;
1356 while (*dot != ':' && k < 29) {
1357 device_hint[i].serial_number[k++] = *dot;
1358 dot++;
1359 }
1360 device_hint[i].serial_number[k] = '\0';
1361 }
1362 }
1363 PWC_TRACE("device_hint[%d]:\n", i);
1364 PWC_TRACE(" type : %d\n", device_hint[i].type);
1365 PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number);
1366 PWC_TRACE(" node : %d\n", device_hint[i].device_node);
1367 }
1368 else
1369 device_hint[i].type = 0; /* not filled */
1370 } /* ..for MAX_DEV_HINTS */
1371
1372 PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
1373 return usb_register(&pwc_driver); 1234 return usb_register(&pwc_driver);
1374} 1235}
1375 1236
1376static void __exit usb_pwc_exit(void) 1237static void __exit usb_pwc_exit(void)
1377{ 1238{
1378 PWC_DEBUG_MODULE("Deregistering driver.\n");
1379 usb_deregister(&pwc_driver); 1239 usb_deregister(&pwc_driver);
1380 PWC_INFO("Philips webcam module removed.\n");
1381} 1240}
1382 1241
1383module_init(usb_pwc_init); 1242module_init(usb_pwc_init);
1384module_exit(usb_pwc_exit); 1243module_exit(usb_pwc_exit);
1385
1386/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */