diff options
author | Jaime Velasco Juan <jsagarribay@gmail.com> | 2008-01-27 10:24:59 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-02-18 09:14:58 -0500 |
commit | 1fdd61c0228a32b9a5e10593b225851d8920595b (patch) | |
tree | 61a2134e8a05f10fe51b0904d361a4b1eafc6e37 /drivers/media | |
parent | 1112fb68ae9c838294d38e1f209fedbc0dbf11d5 (diff) |
V4L/DVB (7089): V4L: stkwebcam: Power management support
Signed-off-by: Jaime Velasco Juan <jsagarribay@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/stk-webcam.c | 92 | ||||
-rw-r--r-- | drivers/media/video/stk-webcam.h | 1 |
2 files changed, 73 insertions, 20 deletions
diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index ba4fe934ee9e..f84e8d511763 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c | |||
@@ -682,6 +682,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) | |||
682 | return -ENXIO; | 682 | return -ENXIO; |
683 | fp->private_data = vdev; | 683 | fp->private_data = vdev; |
684 | kref_get(&dev->kref); | 684 | kref_get(&dev->kref); |
685 | usb_autopm_get_interface(dev->interface); | ||
685 | 686 | ||
686 | return 0; | 687 | return 0; |
687 | } | 688 | } |
@@ -703,6 +704,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) | |||
703 | } | 704 | } |
704 | 705 | ||
705 | if (dev->owner != fp) { | 706 | if (dev->owner != fp) { |
707 | usb_autopm_put_interface(dev->interface); | ||
706 | kref_put(&dev->kref, stk_camera_cleanup); | 708 | kref_put(&dev->kref, stk_camera_cleanup); |
707 | return 0; | 709 | return 0; |
708 | } | 710 | } |
@@ -713,6 +715,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) | |||
713 | 715 | ||
714 | dev->owner = NULL; | 716 | dev->owner = NULL; |
715 | 717 | ||
718 | usb_autopm_put_interface(dev->interface); | ||
716 | kref_put(&dev->kref, stk_camera_cleanup); | 719 | kref_put(&dev->kref, stk_camera_cleanup); |
717 | 720 | ||
718 | return 0; | 721 | return 0; |
@@ -1085,6 +1088,42 @@ static int stk_vidioc_try_fmt_cap(struct file *filp, | |||
1085 | return 0; | 1088 | return 0; |
1086 | } | 1089 | } |
1087 | 1090 | ||
1091 | static int stk_setup_format(struct stk_camera *dev) | ||
1092 | { | ||
1093 | int i = 0; | ||
1094 | int depth; | ||
1095 | if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8) | ||
1096 | depth = 1; | ||
1097 | else | ||
1098 | depth = 2; | ||
1099 | while (stk_sizes[i].m != dev->vsettings.mode | ||
1100 | && i < ARRAY_SIZE(stk_sizes)) | ||
1101 | i++; | ||
1102 | if (i == ARRAY_SIZE(stk_sizes)) { | ||
1103 | STK_ERROR("Something is broken in %s\n", __FUNCTION__); | ||
1104 | return -EFAULT; | ||
1105 | } | ||
1106 | /* This registers controls some timings, not sure of what. */ | ||
1107 | stk_camera_write_reg(dev, 0x001b, 0x0e); | ||
1108 | if (dev->vsettings.mode == MODE_SXGA) | ||
1109 | stk_camera_write_reg(dev, 0x001c, 0x0e); | ||
1110 | else | ||
1111 | stk_camera_write_reg(dev, 0x001c, 0x46); | ||
1112 | /* | ||
1113 | * Registers 0x0115 0x0114 are the size of each line (bytes), | ||
1114 | * regs 0x0117 0x0116 are the heigth of the image. | ||
1115 | */ | ||
1116 | stk_camera_write_reg(dev, 0x0115, | ||
1117 | ((stk_sizes[i].w * depth) >> 8) & 0xff); | ||
1118 | stk_camera_write_reg(dev, 0x0114, | ||
1119 | (stk_sizes[i].w * depth) & 0xff); | ||
1120 | stk_camera_write_reg(dev, 0x0117, | ||
1121 | (stk_sizes[i].h >> 8) & 0xff); | ||
1122 | stk_camera_write_reg(dev, 0x0116, | ||
1123 | stk_sizes[i].h & 0xff); | ||
1124 | return stk_sensor_configure(dev); | ||
1125 | } | ||
1126 | |||
1088 | static int stk_vidioc_s_fmt_cap(struct file *filp, | 1127 | static int stk_vidioc_s_fmt_cap(struct file *filp, |
1089 | void *priv, struct v4l2_format *fmtd) | 1128 | void *priv, struct v4l2_format *fmtd) |
1090 | { | 1129 | { |
@@ -1099,10 +1138,10 @@ static int stk_vidioc_s_fmt_cap(struct file *filp, | |||
1099 | return -EBUSY; | 1138 | return -EBUSY; |
1100 | if (dev->owner && dev->owner != filp) | 1139 | if (dev->owner && dev->owner != filp) |
1101 | return -EBUSY; | 1140 | return -EBUSY; |
1102 | dev->owner = filp; | ||
1103 | ret = stk_vidioc_try_fmt_cap(filp, priv, fmtd); | 1141 | ret = stk_vidioc_try_fmt_cap(filp, priv, fmtd); |
1104 | if (ret) | 1142 | if (ret) |
1105 | return ret; | 1143 | return ret; |
1144 | dev->owner = filp; | ||
1106 | 1145 | ||
1107 | dev->vsettings.palette = fmtd->fmt.pix.pixelformat; | 1146 | dev->vsettings.palette = fmtd->fmt.pix.pixelformat; |
1108 | stk_free_buffers(dev); | 1147 | stk_free_buffers(dev); |
@@ -1110,25 +1149,7 @@ static int stk_vidioc_s_fmt_cap(struct file *filp, | |||
1110 | dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m; | 1149 | dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m; |
1111 | 1150 | ||
1112 | stk_initialise(dev); | 1151 | stk_initialise(dev); |
1113 | /* This registers controls some timings, not sure of what. */ | 1152 | return stk_setup_format(dev); |
1114 | stk_camera_write_reg(dev, 0x001b, 0x0e); | ||
1115 | if (dev->vsettings.mode == MODE_SXGA) | ||
1116 | stk_camera_write_reg(dev, 0x001c, 0x0e); | ||
1117 | else | ||
1118 | stk_camera_write_reg(dev, 0x001c, 0x46); | ||
1119 | /* | ||
1120 | * Registers 0x0115 0x0114 are the size of each line (bytes), | ||
1121 | * regs 0x0117 0x0116 are the heigth of the image. | ||
1122 | */ | ||
1123 | stk_camera_write_reg(dev, 0x0115, | ||
1124 | (fmtd->fmt.pix.bytesperline >> 8) & 0xff); | ||
1125 | stk_camera_write_reg(dev, 0x0114, | ||
1126 | fmtd->fmt.pix.bytesperline & 0xff); | ||
1127 | stk_camera_write_reg(dev, 0x0117, | ||
1128 | (fmtd->fmt.pix.height >> 8) & 0xff); | ||
1129 | stk_camera_write_reg(dev, 0x0116, | ||
1130 | fmtd->fmt.pix.height & 0xff); | ||
1131 | return stk_sensor_configure(dev); | ||
1132 | } | 1153 | } |
1133 | 1154 | ||
1134 | static int stk_vidioc_reqbufs(struct file *filp, | 1155 | static int stk_vidioc_reqbufs(struct file *filp, |
@@ -1422,6 +1443,7 @@ static int stk_camera_probe(struct usb_interface *interface, | |||
1422 | } | 1443 | } |
1423 | 1444 | ||
1424 | stk_create_sysfs_files(&dev->vdev); | 1445 | stk_create_sysfs_files(&dev->vdev); |
1446 | usb_autopm_enable(dev->interface); | ||
1425 | 1447 | ||
1426 | return 0; | 1448 | return 0; |
1427 | } | 1449 | } |
@@ -1439,11 +1461,41 @@ static void stk_camera_disconnect(struct usb_interface *interface) | |||
1439 | kref_put(&dev->kref, stk_camera_cleanup); | 1461 | kref_put(&dev->kref, stk_camera_cleanup); |
1440 | } | 1462 | } |
1441 | 1463 | ||
1464 | #ifdef CONFIG_PM | ||
1465 | int stk_camera_suspend(struct usb_interface *intf, pm_message_t message) | ||
1466 | { | ||
1467 | struct stk_camera *dev = usb_get_intfdata(intf); | ||
1468 | if (is_streaming(dev)) { | ||
1469 | stk_stop_stream(dev); | ||
1470 | /* yes, this is ugly */ | ||
1471 | set_streaming(dev); | ||
1472 | } | ||
1473 | return 0; | ||
1474 | } | ||
1475 | |||
1476 | int stk_camera_resume(struct usb_interface *intf) | ||
1477 | { | ||
1478 | struct stk_camera *dev = usb_get_intfdata(intf); | ||
1479 | if (!is_initialised(dev)) | ||
1480 | return 0; | ||
1481 | unset_initialised(dev); | ||
1482 | stk_initialise(dev); | ||
1483 | stk_setup_format(dev); | ||
1484 | if (is_streaming(dev)) | ||
1485 | stk_start_stream(dev); | ||
1486 | return 0; | ||
1487 | } | ||
1488 | #endif | ||
1489 | |||
1442 | static struct usb_driver stk_camera_driver = { | 1490 | static struct usb_driver stk_camera_driver = { |
1443 | .name = "stkwebcam", | 1491 | .name = "stkwebcam", |
1444 | .probe = stk_camera_probe, | 1492 | .probe = stk_camera_probe, |
1445 | .disconnect = stk_camera_disconnect, | 1493 | .disconnect = stk_camera_disconnect, |
1446 | .id_table = stkwebcam_table, | 1494 | .id_table = stkwebcam_table, |
1495 | #ifdef CONFIG_PM | ||
1496 | .suspend = stk_camera_suspend, | ||
1497 | .resume = stk_camera_resume, | ||
1498 | #endif | ||
1447 | }; | 1499 | }; |
1448 | 1500 | ||
1449 | 1501 | ||
diff --git a/drivers/media/video/stk-webcam.h b/drivers/media/video/stk-webcam.h index 7e989d1ac1e0..a2164cb1ad26 100644 --- a/drivers/media/video/stk-webcam.h +++ b/drivers/media/video/stk-webcam.h | |||
@@ -79,6 +79,7 @@ enum stk_status { | |||
79 | #define unset_present(dev) ((dev)->status &= \ | 79 | #define unset_present(dev) ((dev)->status &= \ |
80 | ~(S_PRESENT|S_INITIALISED|S_STREAMING)) | 80 | ~(S_PRESENT|S_INITIALISED|S_STREAMING)) |
81 | #define set_initialised(dev) ((dev)->status |= S_INITIALISED) | 81 | #define set_initialised(dev) ((dev)->status |= S_INITIALISED) |
82 | #define unset_initialised(dev) ((dev)->status &= ~S_INITIALISED) | ||
82 | #define set_memallocd(dev) ((dev)->status |= S_MEMALLOCD) | 83 | #define set_memallocd(dev) ((dev)->status |= S_MEMALLOCD) |
83 | #define unset_memallocd(dev) ((dev)->status &= ~S_MEMALLOCD) | 84 | #define unset_memallocd(dev) ((dev)->status &= ~S_MEMALLOCD) |
84 | #define set_streaming(dev) ((dev)->status |= S_STREAMING) | 85 | #define set_streaming(dev) ((dev)->status |= S_STREAMING) |