提交 1fdd61c0 编写于 作者: J Jaime Velasco Juan 提交者: Mauro Carvalho Chehab

V4L/DVB (7089): V4L: stkwebcam: Power management support

Signed-off-by: NJaime Velasco Juan <jsagarribay@gmail.com>
Signed-off-by: NMauro Carvalho Chehab <mchehab@infradead.org>
上级 1112fb68
...@@ -682,6 +682,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp) ...@@ -682,6 +682,7 @@ static int v4l_stk_open(struct inode *inode, struct file *fp)
return -ENXIO; return -ENXIO;
fp->private_data = vdev; fp->private_data = vdev;
kref_get(&dev->kref); kref_get(&dev->kref);
usb_autopm_get_interface(dev->interface);
return 0; return 0;
} }
...@@ -703,6 +704,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) ...@@ -703,6 +704,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp)
} }
if (dev->owner != fp) { if (dev->owner != fp) {
usb_autopm_put_interface(dev->interface);
kref_put(&dev->kref, stk_camera_cleanup); kref_put(&dev->kref, stk_camera_cleanup);
return 0; return 0;
} }
...@@ -713,6 +715,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp) ...@@ -713,6 +715,7 @@ static int v4l_stk_release(struct inode *inode, struct file *fp)
dev->owner = NULL; dev->owner = NULL;
usb_autopm_put_interface(dev->interface);
kref_put(&dev->kref, stk_camera_cleanup); kref_put(&dev->kref, stk_camera_cleanup);
return 0; return 0;
...@@ -1085,6 +1088,42 @@ static int stk_vidioc_try_fmt_cap(struct file *filp, ...@@ -1085,6 +1088,42 @@ static int stk_vidioc_try_fmt_cap(struct file *filp,
return 0; return 0;
} }
static int stk_setup_format(struct stk_camera *dev)
{
int i = 0;
int depth;
if (dev->vsettings.palette == V4L2_PIX_FMT_SBGGR8)
depth = 1;
else
depth = 2;
while (stk_sizes[i].m != dev->vsettings.mode
&& i < ARRAY_SIZE(stk_sizes))
i++;
if (i == ARRAY_SIZE(stk_sizes)) {
STK_ERROR("Something is broken in %s\n", __FUNCTION__);
return -EFAULT;
}
/* This registers controls some timings, not sure of what. */
stk_camera_write_reg(dev, 0x001b, 0x0e);
if (dev->vsettings.mode == MODE_SXGA)
stk_camera_write_reg(dev, 0x001c, 0x0e);
else
stk_camera_write_reg(dev, 0x001c, 0x46);
/*
* Registers 0x0115 0x0114 are the size of each line (bytes),
* regs 0x0117 0x0116 are the heigth of the image.
*/
stk_camera_write_reg(dev, 0x0115,
((stk_sizes[i].w * depth) >> 8) & 0xff);
stk_camera_write_reg(dev, 0x0114,
(stk_sizes[i].w * depth) & 0xff);
stk_camera_write_reg(dev, 0x0117,
(stk_sizes[i].h >> 8) & 0xff);
stk_camera_write_reg(dev, 0x0116,
stk_sizes[i].h & 0xff);
return stk_sensor_configure(dev);
}
static int stk_vidioc_s_fmt_cap(struct file *filp, static int stk_vidioc_s_fmt_cap(struct file *filp,
void *priv, struct v4l2_format *fmtd) void *priv, struct v4l2_format *fmtd)
{ {
...@@ -1099,10 +1138,10 @@ static int stk_vidioc_s_fmt_cap(struct file *filp, ...@@ -1099,10 +1138,10 @@ static int stk_vidioc_s_fmt_cap(struct file *filp,
return -EBUSY; return -EBUSY;
if (dev->owner && dev->owner != filp) if (dev->owner && dev->owner != filp)
return -EBUSY; return -EBUSY;
dev->owner = filp;
ret = stk_vidioc_try_fmt_cap(filp, priv, fmtd); ret = stk_vidioc_try_fmt_cap(filp, priv, fmtd);
if (ret) if (ret)
return ret; return ret;
dev->owner = filp;
dev->vsettings.palette = fmtd->fmt.pix.pixelformat; dev->vsettings.palette = fmtd->fmt.pix.pixelformat;
stk_free_buffers(dev); stk_free_buffers(dev);
...@@ -1110,25 +1149,7 @@ static int stk_vidioc_s_fmt_cap(struct file *filp, ...@@ -1110,25 +1149,7 @@ static int stk_vidioc_s_fmt_cap(struct file *filp,
dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m; dev->vsettings.mode = stk_sizes[fmtd->fmt.pix.priv].m;
stk_initialise(dev); stk_initialise(dev);
/* This registers controls some timings, not sure of what. */ return stk_setup_format(dev);
stk_camera_write_reg(dev, 0x001b, 0x0e);
if (dev->vsettings.mode == MODE_SXGA)
stk_camera_write_reg(dev, 0x001c, 0x0e);
else
stk_camera_write_reg(dev, 0x001c, 0x46);
/*
* Registers 0x0115 0x0114 are the size of each line (bytes),
* regs 0x0117 0x0116 are the heigth of the image.
*/
stk_camera_write_reg(dev, 0x0115,
(fmtd->fmt.pix.bytesperline >> 8) & 0xff);
stk_camera_write_reg(dev, 0x0114,
fmtd->fmt.pix.bytesperline & 0xff);
stk_camera_write_reg(dev, 0x0117,
(fmtd->fmt.pix.height >> 8) & 0xff);
stk_camera_write_reg(dev, 0x0116,
fmtd->fmt.pix.height & 0xff);
return stk_sensor_configure(dev);
} }
static int stk_vidioc_reqbufs(struct file *filp, static int stk_vidioc_reqbufs(struct file *filp,
...@@ -1422,6 +1443,7 @@ static int stk_camera_probe(struct usb_interface *interface, ...@@ -1422,6 +1443,7 @@ static int stk_camera_probe(struct usb_interface *interface,
} }
stk_create_sysfs_files(&dev->vdev); stk_create_sysfs_files(&dev->vdev);
usb_autopm_enable(dev->interface);
return 0; return 0;
} }
...@@ -1439,11 +1461,41 @@ static void stk_camera_disconnect(struct usb_interface *interface) ...@@ -1439,11 +1461,41 @@ static void stk_camera_disconnect(struct usb_interface *interface)
kref_put(&dev->kref, stk_camera_cleanup); kref_put(&dev->kref, stk_camera_cleanup);
} }
#ifdef CONFIG_PM
int stk_camera_suspend(struct usb_interface *intf, pm_message_t message)
{
struct stk_camera *dev = usb_get_intfdata(intf);
if (is_streaming(dev)) {
stk_stop_stream(dev);
/* yes, this is ugly */
set_streaming(dev);
}
return 0;
}
int stk_camera_resume(struct usb_interface *intf)
{
struct stk_camera *dev = usb_get_intfdata(intf);
if (!is_initialised(dev))
return 0;
unset_initialised(dev);
stk_initialise(dev);
stk_setup_format(dev);
if (is_streaming(dev))
stk_start_stream(dev);
return 0;
}
#endif
static struct usb_driver stk_camera_driver = { static struct usb_driver stk_camera_driver = {
.name = "stkwebcam", .name = "stkwebcam",
.probe = stk_camera_probe, .probe = stk_camera_probe,
.disconnect = stk_camera_disconnect, .disconnect = stk_camera_disconnect,
.id_table = stkwebcam_table, .id_table = stkwebcam_table,
#ifdef CONFIG_PM
.suspend = stk_camera_suspend,
.resume = stk_camera_resume,
#endif
}; };
......
...@@ -79,6 +79,7 @@ enum stk_status { ...@@ -79,6 +79,7 @@ enum stk_status {
#define unset_present(dev) ((dev)->status &= \ #define unset_present(dev) ((dev)->status &= \
~(S_PRESENT|S_INITIALISED|S_STREAMING)) ~(S_PRESENT|S_INITIALISED|S_STREAMING))
#define set_initialised(dev) ((dev)->status |= S_INITIALISED) #define set_initialised(dev) ((dev)->status |= S_INITIALISED)
#define unset_initialised(dev) ((dev)->status &= ~S_INITIALISED)
#define set_memallocd(dev) ((dev)->status |= S_MEMALLOCD) #define set_memallocd(dev) ((dev)->status |= S_MEMALLOCD)
#define unset_memallocd(dev) ((dev)->status &= ~S_MEMALLOCD) #define unset_memallocd(dev) ((dev)->status &= ~S_MEMALLOCD)
#define set_streaming(dev) ((dev)->status |= S_STREAMING) #define set_streaming(dev) ((dev)->status |= S_STREAMING)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册