Commit 3b4d0ec7 authored by Hans de Goede's avatar Hans de Goede Committed by Mauro Carvalho Chehab

[media] pwc: Make power-saving a per device option

  as vcinterface must be set before calling pwc_camera_power()
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 52a92547
...@@ -782,29 +782,32 @@ int pwc_get_shutter_speed(struct pwc_device *pdev, int *value) ...@@ -782,29 +782,32 @@ int pwc_get_shutter_speed(struct pwc_device *pdev, int *value)
return 0; return 0;
} }
/* POWER */ /* POWER */
void pwc_camera_power(struct pwc_device *pdev, int power)
int pwc_camera_power(struct pwc_device *pdev, int power)
{ {
char buf; char buf;
int r;
if (!pdev->power_save)
return;
if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6)) if (pdev->type < 675 || (pdev->type < 730 && pdev->release < 6))
return 0; /* Not supported by Nala or Timon < release 6 */ return; /* Not supported by Nala or Timon < release 6 */
if (power) if (power)
buf = 0x00; /* active */ buf = 0x00; /* active */
else else
buf = 0xFF; /* power save */ buf = 0xFF; /* power save */
return send_control_msg(pdev, r = send_control_msg(pdev,
SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER, SET_STATUS_CTL, SET_POWER_SAVE_MODE_FORMATTER,
&buf, sizeof(buf)); &buf, sizeof(buf));
}
if (r < 0)
PWC_ERROR("Failed to power %s camera (%d)\n",
power ? "on" : "off", r);
}
/* private calls */ /* private calls */
int pwc_restore_user(struct pwc_device *pdev) int pwc_restore_user(struct pwc_device *pdev)
{ {
return send_control_msg(pdev, return send_control_msg(pdev,
...@@ -1011,6 +1014,7 @@ static int pwc_get_wb_delay(struct pwc_device *pdev, int *value) ...@@ -1011,6 +1014,7 @@ static int pwc_get_wb_delay(struct pwc_device *pdev, int *value)
int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
{ {
unsigned char buf[2]; unsigned char buf[2];
int r;
if (pdev->type < 730) if (pdev->type < 730)
return 0; return 0;
...@@ -1028,8 +1032,12 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value) ...@@ -1028,8 +1032,12 @@ int pwc_set_leds(struct pwc_device *pdev, int on_value, int off_value)
buf[0] = on_value; buf[0] = on_value;
buf[1] = off_value; buf[1] = off_value;
return send_control_msg(pdev, r = send_control_msg(pdev,
SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf)); SET_STATUS_CTL, LED_FORMATTER, &buf, sizeof(buf));
if (r < 0)
PWC_ERROR("Failed to set LED on/off time (%d)\n", r);
return r;
} }
static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value) static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
......
...@@ -133,7 +133,7 @@ static int default_fps = 10; ...@@ -133,7 +133,7 @@ static int default_fps = 10;
#ifdef CONFIG_USB_PWC_DEBUG #ifdef CONFIG_USB_PWC_DEBUG
int pwc_trace = PWC_DEBUG_LEVEL; int pwc_trace = PWC_DEBUG_LEVEL;
#endif #endif
static int power_save; static int power_save = -1;
static int led_on = 100, led_off; /* defaults to LED that is on while in use */ static int led_on = 100, led_off; /* defaults to LED that is on while in use */
static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */ static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
static struct { static struct {
...@@ -720,7 +720,6 @@ static int pwc_video_open(struct file *file) ...@@ -720,7 +720,6 @@ static int pwc_video_open(struct file *file)
return -EBUSY; return -EBUSY;
} }
pwc_construct(pdev); /* set min/max sizes correct */
if (!pdev->usb_init) { if (!pdev->usb_init) {
PWC_DEBUG_OPEN("Doing first time initialization.\n"); PWC_DEBUG_OPEN("Doing first time initialization.\n");
pdev->usb_init = 1; pdev->usb_init = 1;
...@@ -735,16 +734,9 @@ static int pwc_video_open(struct file *file) ...@@ -735,16 +734,9 @@ static int pwc_video_open(struct file *file)
} }
} }
/* Turn on camera */ /* Turn on camera and set LEDS on */
if (power_save) { pwc_camera_power(pdev, 1);
i = pwc_camera_power(pdev, 1); pwc_set_leds(pdev, led_on, led_off);
if (i < 0)
PWC_DEBUG_OPEN("Failed to restore power to the camera! (%d)\n", i);
}
/* Set LED on/off time */
if (pwc_set_leds(pdev, led_on, led_off) < 0)
PWC_DEBUG_OPEN("Failed to set LED on/off time.\n");
/* So far, so good. Allocate memory. */ /* So far, so good. Allocate memory. */
i = pwc_allocate_buffers(pdev); i = pwc_allocate_buffers(pdev);
...@@ -756,7 +748,6 @@ static int pwc_video_open(struct file *file) ...@@ -756,7 +748,6 @@ static int pwc_video_open(struct file *file)
/* Reset buffers & parameters */ /* Reset buffers & parameters */
pdev->visoc_errors = 0; pdev->visoc_errors = 0;
pwc_construct(pdev); /* set min/max sizes correct */
/* Set some defaults */ /* Set some defaults */
pdev->vsnapshot = 0; pdev->vsnapshot = 0;
...@@ -815,7 +806,6 @@ static int pwc_video_close(struct file *file) ...@@ -815,7 +806,6 @@ static int pwc_video_close(struct file *file)
{ {
struct video_device *vdev = file->private_data; struct video_device *vdev = file->private_data;
struct pwc_device *pdev; struct pwc_device *pdev;
int i;
PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev); PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
...@@ -833,14 +823,8 @@ static int pwc_video_close(struct file *file) ...@@ -833,14 +823,8 @@ static int pwc_video_close(struct file *file)
/* Turn off LEDS and power down camera, but only when not unplugged */ /* Turn off LEDS and power down camera, but only when not unplugged */
if (pdev->udev) { if (pdev->udev) {
/* Turn LEDs off */ pwc_set_leds(pdev, 0, 0);
if (pwc_set_leds(pdev, 0, 0) < 0) pwc_camera_power(pdev, 0);
PWC_DEBUG_MODULE("Failed to set LED on/off time.\n");
if (power_save) {
i = pwc_camera_power(pdev, 0);
if (i < 0)
PWC_ERROR("Failed to power down camera (%d)\n", i);
}
pdev->vopen--; pdev->vopen--;
PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
} }
...@@ -1016,6 +1000,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -1016,6 +1000,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
int hint, rc; int hint, rc;
int features = 0; int features = 0;
int video_nr = -1; /* default: use next available device */ int video_nr = -1; /* default: use next available device */
int my_power_save = power_save;
char serial_number[30], *name; char serial_number[30], *name;
vendor_id = le16_to_cpu(udev->descriptor.idVendor); vendor_id = le16_to_cpu(udev->descriptor.idVendor);
...@@ -1133,7 +1118,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -1133,7 +1118,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n"); PWC_INFO("Logitech QuickCam Zoom (new model) USB webcam detected.\n");
name = "Logitech QuickCam Zoom"; name = "Logitech QuickCam Zoom";
type_id = 740; /* CCD sensor */ type_id = 740; /* CCD sensor */
power_save = 1; if (my_power_save == -1)
my_power_save = 1;
break; break;
case 0x08b5: case 0x08b5:
PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n"); PWC_INFO("Logitech QuickCam Orbit/Sphere USB webcam detected.\n");
...@@ -1250,6 +1236,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -1250,6 +1236,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
else else
return -ENODEV; /* Not any of the know types; but the list keeps growing. */ return -ENODEV; /* Not any of the know types; but the list keeps growing. */
if (my_power_save == -1)
my_power_save = 0;
memset(serial_number, 0, 30); memset(serial_number, 0, 30);
usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29); usb_string(udev, udev->descriptor.iSerialNumber, serial_number, 29);
PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number); PWC_DEBUG_PROBE("Device serial number is %s\n", serial_number);
...@@ -1278,6 +1267,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -1278,6 +1267,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pdev->angle_range.tilt_min = -3000; pdev->angle_range.tilt_min = -3000;
pdev->angle_range.tilt_max = 2500; pdev->angle_range.tilt_max = 2500;
} }
pwc_construct(pdev); /* set min/max sizes correct */
mutex_init(&pdev->modlock); mutex_init(&pdev->modlock);
spin_lock_init(&pdev->queued_bufs_lock); spin_lock_init(&pdev->queued_bufs_lock);
...@@ -1285,6 +1275,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id ...@@ -1285,6 +1275,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pdev->udev = udev; pdev->udev = udev;
pdev->vcompression = pwc_preferred_compression; pdev->vcompression = pwc_preferred_compression;
pdev->power_save = my_power_save;
/* Init videobuf2 queue structure */ /* Init videobuf2 queue structure */
memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue)); memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue));
...@@ -1424,7 +1415,7 @@ module_param(fps, int, 0444); ...@@ -1424,7 +1415,7 @@ module_param(fps, int, 0444);
#ifdef CONFIG_USB_PWC_DEBUG #ifdef CONFIG_USB_PWC_DEBUG
module_param_named(trace, pwc_trace, int, 0644); module_param_named(trace, pwc_trace, int, 0644);
#endif #endif
module_param(power_save, int, 0444); module_param(power_save, int, 0644);
module_param(compression, int, 0444); module_param(compression, int, 0444);
module_param_array(leds, int, &leds_nargs, 0444); module_param_array(leds, int, &leds_nargs, 0444);
module_param_array(dev_hint, charp, &dev_hint_nargs, 0444); module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
...@@ -1434,7 +1425,7 @@ MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful rang ...@@ -1434,7 +1425,7 @@ MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful rang
#ifdef CONFIG_USB_PWC_DEBUG #ifdef CONFIG_USB_PWC_DEBUG
MODULE_PARM_DESC(trace, "For debugging purposes"); MODULE_PARM_DESC(trace, "For debugging purposes");
#endif #endif
MODULE_PARM_DESC(power_save, "Turn power save feature in camera on or off"); MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)"); MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
MODULE_PARM_DESC(leds, "LED on,off time in milliseconds"); MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
MODULE_PARM_DESC(dev_hint, "Device node hints"); MODULE_PARM_DESC(dev_hint, "Device node hints");
...@@ -1491,8 +1482,6 @@ static int __init usb_pwc_init(void) ...@@ -1491,8 +1482,6 @@ static int __init usb_pwc_init(void)
pwc_preferred_compression = compression; pwc_preferred_compression = compression;
PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression); PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
} }
if (power_save)
PWC_DEBUG_MODULE("Enabling power save on open/close.\n");
if (leds[0] >= 0) if (leds[0] >= 0)
led_on = leds[0]; led_on = leds[0];
if (leds[1] >= 0) if (leds[1] >= 0)
......
...@@ -176,6 +176,7 @@ struct pwc_device ...@@ -176,6 +176,7 @@ struct pwc_device
char vsnapshot; /* snapshot mode */ char vsnapshot; /* snapshot mode */
char vsync; /* used by isoc handler */ char vsync; /* used by isoc handler */
char vmirror; /* for ToUCaM series */ char vmirror; /* for ToUCaM series */
char power_save; /* Do powersaving for this cam */
int cmd_len; int cmd_len;
unsigned char cmd_buf[13]; unsigned char cmd_buf[13];
...@@ -290,7 +291,7 @@ extern int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise); ...@@ -290,7 +291,7 @@ extern int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise);
extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise); extern int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise);
/* Power down or up the camera; not supported by all models */ /* Power down or up the camera; not supported by all models */
extern int pwc_camera_power(struct pwc_device *pdev, int power); extern void pwc_camera_power(struct pwc_device *pdev, int power);
/* Private ioctl()s; see pwc-ioctl.h */ /* Private ioctl()s; see pwc-ioctl.h */
extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg); extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment