aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2014-02-08 11:33:46 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-02-24 11:11:17 -0500
commitb2b3593e331cce1718d7388f8a1182b5195be5fb (patch)
tree3f3edebc2f2425c9392b732e40891efd74e1e16e /drivers/media/i2c
parente68084c661953e7b7d78a952156d35e83187c038 (diff)
[media] mt9t001: Add regulator support
The sensor needs two power supplies, VAA and VDD. Require a regulator for each of them. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r--drivers/media/i2c/mt9t001.c206
1 files changed, 156 insertions, 50 deletions
diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c
index d41c70eaf838..9a0bb063aa9b 100644
--- a/drivers/media/i2c/mt9t001.c
+++ b/drivers/media/i2c/mt9t001.c
@@ -13,8 +13,9 @@
13 */ 13 */
14 14
15#include <linux/i2c.h> 15#include <linux/i2c.h>
16#include <linux/module.h>
17#include <linux/log2.h> 16#include <linux/log2.h>
17#include <linux/module.h>
18#include <linux/regulator/consumer.h>
18#include <linux/slab.h> 19#include <linux/slab.h>
19#include <linux/videodev2.h> 20#include <linux/videodev2.h>
20#include <linux/v4l2-mediabus.h> 21#include <linux/v4l2-mediabus.h>
@@ -55,6 +56,7 @@
55#define MT9T001_OUTPUT_CONTROL_SYNC (1 << 0) 56#define MT9T001_OUTPUT_CONTROL_SYNC (1 << 0)
56#define MT9T001_OUTPUT_CONTROL_CHIP_ENABLE (1 << 1) 57#define MT9T001_OUTPUT_CONTROL_CHIP_ENABLE (1 << 1)
57#define MT9T001_OUTPUT_CONTROL_TEST_DATA (1 << 6) 58#define MT9T001_OUTPUT_CONTROL_TEST_DATA (1 << 6)
59#define MT9T001_OUTPUT_CONTROL_DEF 0x0002
58#define MT9T001_SHUTTER_WIDTH_HIGH 0x08 60#define MT9T001_SHUTTER_WIDTH_HIGH 0x08
59#define MT9T001_SHUTTER_WIDTH_LOW 0x09 61#define MT9T001_SHUTTER_WIDTH_LOW 0x09
60#define MT9T001_SHUTTER_WIDTH_MIN 1 62#define MT9T001_SHUTTER_WIDTH_MIN 1
@@ -116,6 +118,11 @@ struct mt9t001 {
116 struct v4l2_subdev subdev; 118 struct v4l2_subdev subdev;
117 struct media_pad pad; 119 struct media_pad pad;
118 120
121 struct regulator_bulk_data regulators[2];
122
123 struct mutex power_lock; /* lock to protect power_count */
124 int power_count;
125
119 struct v4l2_mbus_framefmt format; 126 struct v4l2_mbus_framefmt format;
120 struct v4l2_rect crop; 127 struct v4l2_rect crop;
121 128
@@ -159,6 +166,62 @@ static int mt9t001_set_output_control(struct mt9t001 *mt9t001, u16 clear,
159 return 0; 166 return 0;
160} 167}
161 168
169static int mt9t001_reset(struct mt9t001 *mt9t001)
170{
171 struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
172 int ret;
173
174 /* Reset the chip and stop data read out */
175 ret = mt9t001_write(client, MT9T001_RESET, 1);
176 if (ret < 0)
177 return ret;
178
179 ret = mt9t001_write(client, MT9T001_RESET, 0);
180 if (ret < 0)
181 return ret;
182
183 mt9t001->output_control = MT9T001_OUTPUT_CONTROL_DEF;
184
185 return mt9t001_set_output_control(mt9t001,
186 MT9T001_OUTPUT_CONTROL_CHIP_ENABLE,
187 0);
188}
189
190static int mt9t001_power_on(struct mt9t001 *mt9t001)
191{
192 /* Bring up the supplies */
193 return regulator_bulk_enable(ARRAY_SIZE(mt9t001->regulators),
194 mt9t001->regulators);
195}
196
197static void mt9t001_power_off(struct mt9t001 *mt9t001)
198{
199 regulator_bulk_disable(ARRAY_SIZE(mt9t001->regulators),
200 mt9t001->regulators);
201
202static int __mt9t001_set_power(struct mt9t001 *mt9t001, bool on)
203{
204 struct i2c_client *client = v4l2_get_subdevdata(&mt9t001->subdev);
205 int ret;
206
207 if (!on) {
208 mt9t001_power_off(mt9t001);
209 return 0;
210 }
211
212 ret = mt9t001_power_on(mt9t001);
213 if (ret < 0)
214 return ret;
215
216 ret = mt9t001_reset(mt9t001);
217 if (ret < 0) {
218 dev_err(&client->dev, "Failed to reset the camera\n");
219 return ret;
220 }
221
222 return v4l2_ctrl_handler_setup(&mt9t001->ctrls);
223}
224
162/* ----------------------------------------------------------------------------- 225/* -----------------------------------------------------------------------------
163 * V4L2 subdev video operations 226 * V4L2 subdev video operations
164 */ 227 */
@@ -195,6 +258,7 @@ static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
195{ 258{
196 const u16 mode = MT9T001_OUTPUT_CONTROL_CHIP_ENABLE; 259 const u16 mode = MT9T001_OUTPUT_CONTROL_CHIP_ENABLE;
197 struct i2c_client *client = v4l2_get_subdevdata(subdev); 260 struct i2c_client *client = v4l2_get_subdevdata(subdev);
261 struct mt9t001_platform_data *pdata = client->dev.platform_data;
198 struct mt9t001 *mt9t001 = to_mt9t001(subdev); 262 struct mt9t001 *mt9t001 = to_mt9t001(subdev);
199 struct v4l2_mbus_framefmt *format = &mt9t001->format; 263 struct v4l2_mbus_framefmt *format = &mt9t001->format;
200 struct v4l2_rect *crop = &mt9t001->crop; 264 struct v4l2_rect *crop = &mt9t001->crop;
@@ -205,6 +269,14 @@ static int mt9t001_s_stream(struct v4l2_subdev *subdev, int enable)
205 if (!enable) 269 if (!enable)
206 return mt9t001_set_output_control(mt9t001, mode, 0); 270 return mt9t001_set_output_control(mt9t001, mode, 0);
207 271
272 /* Configure the pixel clock polarity */
273 if (pdata->clk_pol) {
274 ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
275 MT9T001_PIXEL_CLOCK_INVERT);
276 if (ret < 0)
277 return ret;
278 }
279
208 /* Configure the window size and row/column bin */ 280 /* Configure the window size and row/column bin */
209 hratio = DIV_ROUND_CLOSEST(crop->width, format->width); 281 hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
210 vratio = DIV_ROUND_CLOSEST(crop->height, format->height); 282 vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
@@ -630,9 +702,67 @@ static const struct v4l2_ctrl_config mt9t001_gains[] = {
630}; 702};
631 703
632/* ----------------------------------------------------------------------------- 704/* -----------------------------------------------------------------------------
705 * V4L2 subdev core operations
706 */
707
708static int mt9t001_set_power(struct v4l2_subdev *subdev, int on)
709{
710 struct mt9t001 *mt9t001 = to_mt9t001(subdev);
711 int ret = 0;
712
713 mutex_lock(&mt9t001->power_lock);
714
715 /* If the power count is modified from 0 to != 0 or from != 0 to 0,
716 * update the power state.
717 */
718 if (mt9t001->power_count == !on) {
719 ret = __mt9t001_set_power(mt9t001, !!on);
720 if (ret < 0)
721 goto out;
722 }
723
724 /* Update the power count. */
725 mt9t001->power_count += on ? 1 : -1;
726 WARN_ON(mt9t001->power_count < 0);
727
728out:
729 mutex_unlock(&mt9t001->power_lock);
730 return ret;
731}
732
733/* -----------------------------------------------------------------------------
633 * V4L2 subdev internal operations 734 * V4L2 subdev internal operations
634 */ 735 */
635 736
737static int mt9t001_registered(struct v4l2_subdev *subdev)
738{
739 struct i2c_client *client = v4l2_get_subdevdata(subdev);
740 struct mt9t001 *mt9t001 = to_mt9t001(subdev);
741 s32 data;
742 int ret;
743
744 ret = mt9t001_power_on(mt9t001);
745 if (ret < 0) {
746 dev_err(&client->dev, "MT9T001 power up failed\n");
747 return ret;
748 }
749
750 /* Read out the chip version register */
751 data = mt9t001_read(client, MT9T001_CHIP_VERSION);
752 mt9t001_power_off(mt9t001);
753
754 if (data != MT9T001_CHIP_ID) {
755 dev_err(&client->dev,
756 "MT9T001 not detected, wrong version 0x%04x\n", data);
757 return -ENODEV;
758 }
759
760 dev_info(&client->dev, "MT9T001 detected at address 0x%02x\n",
761 client->addr);
762
763 return 0;
764}
765
636static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh) 766static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
637{ 767{
638 struct v4l2_mbus_framefmt *format; 768 struct v4l2_mbus_framefmt *format;
@@ -651,9 +781,18 @@ static int mt9t001_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
651 format->field = V4L2_FIELD_NONE; 781 format->field = V4L2_FIELD_NONE;
652 format->colorspace = V4L2_COLORSPACE_SRGB; 782 format->colorspace = V4L2_COLORSPACE_SRGB;
653 783
654 return 0; 784 return mt9t001_set_power(subdev, 1);
655} 785}
656 786
787static int mt9t001_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
788{
789 return mt9t001_set_power(subdev, 0);
790}
791
792static struct v4l2_subdev_core_ops mt9t001_subdev_core_ops = {
793 .s_power = mt9t001_set_power,
794};
795
657static struct v4l2_subdev_video_ops mt9t001_subdev_video_ops = { 796static struct v4l2_subdev_video_ops mt9t001_subdev_video_ops = {
658 .s_stream = mt9t001_s_stream, 797 .s_stream = mt9t001_s_stream,
659}; 798};
@@ -668,58 +807,17 @@ static struct v4l2_subdev_pad_ops mt9t001_subdev_pad_ops = {
668}; 807};
669 808
670static struct v4l2_subdev_ops mt9t001_subdev_ops = { 809static struct v4l2_subdev_ops mt9t001_subdev_ops = {
810 .core = &mt9t001_subdev_core_ops,
671 .video = &mt9t001_subdev_video_ops, 811 .video = &mt9t001_subdev_video_ops,
672 .pad = &mt9t001_subdev_pad_ops, 812 .pad = &mt9t001_subdev_pad_ops,
673}; 813};
674 814
675static struct v4l2_subdev_internal_ops mt9t001_subdev_internal_ops = { 815static struct v4l2_subdev_internal_ops mt9t001_subdev_internal_ops = {
816 .registered = mt9t001_registered,
676 .open = mt9t001_open, 817 .open = mt9t001_open,
818 .close = mt9t001_close,
677}; 819};
678 820
679static int mt9t001_video_probe(struct i2c_client *client)
680{
681 struct mt9t001_platform_data *pdata = client->dev.platform_data;
682 s32 data;
683 int ret;
684
685 dev_info(&client->dev, "Probing MT9T001 at address 0x%02x\n",
686 client->addr);
687
688 /* Reset the chip and stop data read out */
689 ret = mt9t001_write(client, MT9T001_RESET, 1);
690 if (ret < 0)
691 return ret;
692
693 ret = mt9t001_write(client, MT9T001_RESET, 0);
694 if (ret < 0)
695 return ret;
696
697 ret = mt9t001_write(client, MT9T001_OUTPUT_CONTROL, 0);
698 if (ret < 0)
699 return ret;
700
701 /* Configure the pixel clock polarity */
702 if (pdata->clk_pol) {
703 ret = mt9t001_write(client, MT9T001_PIXEL_CLOCK,
704 MT9T001_PIXEL_CLOCK_INVERT);
705 if (ret < 0)
706 return ret;
707 }
708
709 /* Read and check the sensor version */
710 data = mt9t001_read(client, MT9T001_CHIP_VERSION);
711 if (data != MT9T001_CHIP_ID) {
712 dev_err(&client->dev, "MT9T001 not detected, wrong version "
713 "0x%04x\n", data);
714 return -ENODEV;
715 }
716
717 dev_info(&client->dev, "MT9T001 detected at address 0x%02x\n",
718 client->addr);
719
720 return ret;
721}
722
723static int mt9t001_probe(struct i2c_client *client, 821static int mt9t001_probe(struct i2c_client *client,
724 const struct i2c_device_id *did) 822 const struct i2c_device_id *did)
725{ 823{
@@ -740,14 +838,22 @@ static int mt9t001_probe(struct i2c_client *client,
740 return -EIO; 838 return -EIO;
741 } 839 }
742 840
743 ret = mt9t001_video_probe(client);
744 if (ret < 0)
745 return ret;
746
747 mt9t001 = devm_kzalloc(&client->dev, sizeof(*mt9t001), GFP_KERNEL); 841 mt9t001 = devm_kzalloc(&client->dev, sizeof(*mt9t001), GFP_KERNEL);
748 if (!mt9t001) 842 if (!mt9t001)
749 return -ENOMEM; 843 return -ENOMEM;
750 844
845 mutex_init(&mt9t001->power_lock);
846 mt9t001->output_control = MT9T001_OUTPUT_CONTROL_DEF;
847
848 mt9t001->regulators[0].supply = "vdd";
849 mt9t001->regulators[1].supply = "vaa";
850
851 ret = devm_regulator_bulk_get(&client->dev, 2, mt9t001->regulators);
852 if (ret < 0) {
853 dev_err(&client->dev, "Unable to get regulators\n");
854 return ret;
855 }
856
751 v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) + 857 v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
752 ARRAY_SIZE(mt9t001_gains) + 4); 858 ARRAY_SIZE(mt9t001_gains) + 4);
753 859