aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9t031.c
diff options
context:
space:
mode:
authorValentin Longchamp <valentin.longchamp@epfl.ch>2010-02-09 05:59:12 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-05-17 23:46:21 -0400
commit535653b1c22c29d4e8f554928efc87fe138f917d (patch)
tree68a93e7f63c3cc62b54e2039b0fcb350a10b6b5c /drivers/media/video/mt9t031.c
parent4f9fb5ed020324d6c151db34460df572b0fdc491 (diff)
V4L/DVB: mt9t031: use runtime pm support to restore ADDRESS_MODE registers
If the platform hooks are provided, soc_camera powers off the device on close and powers it on on open. This resets the ADDRESS_MODE registers which then can be different to the value the driver has computed for them. This patch setups runtime pm usage for mt9t031 and uses the resume function to write the ADDRESS_MODE registers in order to fix the above described problem. Signed-off-by: Valentin Longchamp <valentin.longchamp@epfl.ch> Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/mt9t031.c')
-rw-r--r--drivers/media/video/mt9t031.c66
1 files changed, 62 insertions, 4 deletions
diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c
index a9061bff79b2..78b4e091d2d5 100644
--- a/drivers/media/video/mt9t031.c
+++ b/drivers/media/video/mt9t031.c
@@ -8,14 +8,16 @@
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 */ 9 */
10 10
11#include <linux/videodev2.h> 11#include <linux/device.h>
12#include <linux/slab.h>
13#include <linux/i2c.h> 12#include <linux/i2c.h>
14#include <linux/log2.h> 13#include <linux/log2.h>
14#include <linux/pm.h>
15#include <linux/slab.h>
16#include <linux/videodev2.h>
15 17
16#include <media/v4l2-subdev.h>
17#include <media/v4l2-chip-ident.h>
18#include <media/soc_camera.h> 18#include <media/soc_camera.h>
19#include <media/v4l2-chip-ident.h>
20#include <media/v4l2-subdev.h>
19 21
20/* 22/*
21 * mt9t031 i2c address 0x5d 23 * mt9t031 i2c address 0x5d
@@ -681,12 +683,66 @@ static int mt9t031_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
681} 683}
682 684
683/* 685/*
686 * Power Management:
687 * This function does nothing for now but must be present for pm to work
688 */
689static int mt9t031_runtime_suspend(struct device *dev)
690{
691 return 0;
692}
693
694/*
695 * Power Management:
696 * COLUMN_ADDRESS_MODE and ROW_ADDRESS_MODE are not rewritten if unchanged
697 * they are however changed at reset if the platform hook is present
698 * thus we rewrite them with the values stored by the driver
699 */
700static int mt9t031_runtime_resume(struct device *dev)
701{
702 struct video_device *vdev = to_video_device(dev);
703 struct soc_camera_device *icd = container_of(vdev->parent,
704 struct soc_camera_device, dev);
705 struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
706 struct i2c_client *client = sd->priv;
707 struct mt9t031 *mt9t031 = to_mt9t031(client);
708
709 int ret;
710 u16 xbin, ybin;
711
712 xbin = min(mt9t031->xskip, (u16)3);
713 ybin = min(mt9t031->yskip, (u16)3);
714
715 ret = reg_write(client, MT9T031_COLUMN_ADDRESS_MODE,
716 ((xbin - 1) << 4) | (mt9t031->xskip - 1));
717 if (ret < 0)
718 return ret;
719
720 ret = reg_write(client, MT9T031_ROW_ADDRESS_MODE,
721 ((ybin - 1) << 4) | (mt9t031->yskip - 1));
722 if (ret < 0)
723 return ret;
724
725 return 0;
726}
727
728static struct dev_pm_ops mt9t031_dev_pm_ops = {
729 .runtime_suspend = mt9t031_runtime_suspend,
730 .runtime_resume = mt9t031_runtime_resume,
731};
732
733static struct device_type mt9t031_dev_type = {
734 .name = "MT9T031",
735 .pm = &mt9t031_dev_pm_ops,
736};
737
738/*
684 * Interface active, can use i2c. If it fails, it can indeed mean, that 739 * Interface active, can use i2c. If it fails, it can indeed mean, that
685 * this wasn't our capture interface, so, we wait for the right one 740 * this wasn't our capture interface, so, we wait for the right one
686 */ 741 */
687static int mt9t031_video_probe(struct i2c_client *client) 742static int mt9t031_video_probe(struct i2c_client *client)
688{ 743{
689 struct mt9t031 *mt9t031 = to_mt9t031(client); 744 struct mt9t031 *mt9t031 = to_mt9t031(client);
745 struct video_device *vdev = soc_camera_i2c_to_vdev(client);
690 s32 data; 746 s32 data;
691 int ret; 747 int ret;
692 748
@@ -712,6 +768,8 @@ static int mt9t031_video_probe(struct i2c_client *client)
712 ret = mt9t031_idle(client); 768 ret = mt9t031_idle(client);
713 if (ret < 0) 769 if (ret < 0)
714 dev_err(&client->dev, "Failed to initialise the camera\n"); 770 dev_err(&client->dev, "Failed to initialise the camera\n");
771 else
772 vdev->dev.type = &mt9t031_dev_type;
715 773
716 /* mt9t031_idle() has reset the chip to default. */ 774 /* mt9t031_idle() has reset the chip to default. */
717 mt9t031->exposure = 255; 775 mt9t031->exposure = 255;