aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9m001.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mt9m001.c')
-rw-r--r--drivers/media/video/mt9m001.c157
1 files changed, 68 insertions, 89 deletions
diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c
index 1e4f269fc08b..2a73dac11d37 100644
--- a/drivers/media/video/mt9m001.c
+++ b/drivers/media/video/mt9m001.c
@@ -13,13 +13,13 @@
13#include <linux/i2c.h> 13#include <linux/i2c.h>
14#include <linux/log2.h> 14#include <linux/log2.h>
15 15
16#include <media/v4l2-common.h> 16#include <media/v4l2-subdev.h>
17#include <media/v4l2-chip-ident.h> 17#include <media/v4l2-chip-ident.h>
18#include <media/soc_camera.h> 18#include <media/soc_camera.h>
19 19
20/* mt9m001 i2c address 0x5d 20/* mt9m001 i2c address 0x5d
21 * The platform has to define i2c_board_info 21 * The platform has to define ctruct i2c_board_info objects and link to them
22 * and call i2c_register_board_info() */ 22 * from struct soc_camera_link */
23 23
24/* mt9m001 selected register addresses */ 24/* mt9m001 selected register addresses */
25#define MT9M001_CHIP_VERSION 0x00 25#define MT9M001_CHIP_VERSION 0x00
@@ -69,10 +69,16 @@ static const struct soc_camera_data_format mt9m001_monochrome_formats[] = {
69}; 69};
70 70
71struct mt9m001 { 71struct mt9m001 {
72 struct v4l2_subdev subdev;
72 int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ 73 int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */
73 unsigned char autoexposure; 74 unsigned char autoexposure;
74}; 75};
75 76
77static struct mt9m001 *to_mt9m001(const struct i2c_client *client)
78{
79 return container_of(i2c_get_clientdata(client), struct mt9m001, subdev);
80}
81
76static int reg_read(struct i2c_client *client, const u8 reg) 82static int reg_read(struct i2c_client *client, const u8 reg)
77{ 83{
78 s32 data = i2c_smbus_read_word_data(client, reg); 84 s32 data = i2c_smbus_read_word_data(client, reg);
@@ -110,32 +116,18 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
110static int mt9m001_init(struct soc_camera_device *icd) 116static int mt9m001_init(struct soc_camera_device *icd)
111{ 117{
112 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 118 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
113 struct soc_camera_link *icl = to_soc_camera_link(icd);
114 int ret; 119 int ret;
115 120
116 dev_dbg(&icd->dev, "%s\n", __func__); 121 dev_dbg(&icd->dev, "%s\n", __func__);
117 122
118 if (icl->power) { 123 /*
119 ret = icl->power(&client->dev, 1); 124 * We don't know, whether platform provides reset,
120 if (ret < 0) { 125 * issue a soft reset too
121 dev_err(icd->vdev->parent, 126 */
122 "Platform failed to power-on the camera.\n"); 127 ret = reg_write(client, MT9M001_RESET, 1);
123 return ret; 128 if (!ret)
124 } 129 ret = reg_write(client, MT9M001_RESET, 0);
125 }
126
127 /* The camera could have been already on, we reset it additionally */
128 if (icl->reset)
129 ret = icl->reset(&client->dev);
130 else
131 ret = -ENODEV;
132 130
133 if (ret < 0) {
134 /* Either no platform reset, or platform reset failed */
135 ret = reg_write(client, MT9M001_RESET, 1);
136 if (!ret)
137 ret = reg_write(client, MT9M001_RESET, 0);
138 }
139 /* Disable chip, synchronous option update */ 131 /* Disable chip, synchronous option update */
140 if (!ret) 132 if (!ret)
141 ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0); 133 ret = reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
@@ -146,33 +138,19 @@ static int mt9m001_init(struct soc_camera_device *icd)
146static int mt9m001_release(struct soc_camera_device *icd) 138static int mt9m001_release(struct soc_camera_device *icd)
147{ 139{
148 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 140 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
149 struct soc_camera_link *icl = to_soc_camera_link(icd);
150 141
151 /* Disable the chip */ 142 /* Disable the chip */
152 reg_write(client, MT9M001_OUTPUT_CONTROL, 0); 143 reg_write(client, MT9M001_OUTPUT_CONTROL, 0);
153 144
154 if (icl->power)
155 icl->power(&client->dev, 0);
156
157 return 0; 145 return 0;
158} 146}
159 147
160static int mt9m001_start_capture(struct soc_camera_device *icd) 148static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable)
161{ 149{
162 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 150 struct i2c_client *client = sd->priv;
163 151
164 /* Switch to master "normal" mode */ 152 /* Switch to master "normal" mode or stop sensor readout */
165 if (reg_write(client, MT9M001_OUTPUT_CONTROL, 2) < 0) 153 if (reg_write(client, MT9M001_OUTPUT_CONTROL, enable ? 2 : 0) < 0)
166 return -EIO;
167 return 0;
168}
169
170static int mt9m001_stop_capture(struct soc_camera_device *icd)
171{
172 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
173
174 /* Stop sensor readout */
175 if (reg_write(client, MT9M001_OUTPUT_CONTROL, 0) < 0)
176 return -EIO; 154 return -EIO;
177 return 0; 155 return 0;
178} 156}
@@ -220,7 +198,7 @@ static int mt9m001_set_crop(struct soc_camera_device *icd,
220 struct v4l2_rect *rect) 198 struct v4l2_rect *rect)
221{ 199{
222 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 200 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
223 struct mt9m001 *mt9m001 = i2c_get_clientdata(client); 201 struct mt9m001 *mt9m001 = to_mt9m001(client);
224 int ret; 202 int ret;
225 const u16 hblank = 9, vblank = 25; 203 const u16 hblank = 9, vblank = 25;
226 204
@@ -257,9 +235,10 @@ static int mt9m001_set_crop(struct soc_camera_device *icd,
257 return ret; 235 return ret;
258} 236}
259 237
260static int mt9m001_set_fmt(struct soc_camera_device *icd, 238static int mt9m001_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
261 struct v4l2_format *f)
262{ 239{
240 struct i2c_client *client = sd->priv;
241 struct soc_camera_device *icd = client->dev.platform_data;
263 struct v4l2_rect rect = { 242 struct v4l2_rect rect = {
264 .left = icd->x_current, 243 .left = icd->x_current,
265 .top = icd->y_current, 244 .top = icd->y_current,
@@ -271,9 +250,10 @@ static int mt9m001_set_fmt(struct soc_camera_device *icd,
271 return mt9m001_set_crop(icd, &rect); 250 return mt9m001_set_crop(icd, &rect);
272} 251}
273 252
274static int mt9m001_try_fmt(struct soc_camera_device *icd, 253static int mt9m001_try_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
275 struct v4l2_format *f)
276{ 254{
255 struct i2c_client *client = sd->priv;
256 struct soc_camera_device *icd = client->dev.platform_data;
277 struct v4l2_pix_format *pix = &f->fmt.pix; 257 struct v4l2_pix_format *pix = &f->fmt.pix;
278 258
279 v4l_bound_align_image(&pix->width, 48, 1280, 1, 259 v4l_bound_align_image(&pix->width, 48, 1280, 1,
@@ -283,11 +263,11 @@ static int mt9m001_try_fmt(struct soc_camera_device *icd,
283 return 0; 263 return 0;
284} 264}
285 265
286static int mt9m001_get_chip_id(struct soc_camera_device *icd, 266static int mt9m001_g_chip_ident(struct v4l2_subdev *sd,
287 struct v4l2_dbg_chip_ident *id) 267 struct v4l2_dbg_chip_ident *id)
288{ 268{
289 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 269 struct i2c_client *client = sd->priv;
290 struct mt9m001 *mt9m001 = i2c_get_clientdata(client); 270 struct mt9m001 *mt9m001 = to_mt9m001(client);
291 271
292 if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) 272 if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
293 return -EINVAL; 273 return -EINVAL;
@@ -302,10 +282,10 @@ static int mt9m001_get_chip_id(struct soc_camera_device *icd,
302} 282}
303 283
304#ifdef CONFIG_VIDEO_ADV_DEBUG 284#ifdef CONFIG_VIDEO_ADV_DEBUG
305static int mt9m001_get_register(struct soc_camera_device *icd, 285static int mt9m001_g_register(struct v4l2_subdev *sd,
306 struct v4l2_dbg_register *reg) 286 struct v4l2_dbg_register *reg)
307{ 287{
308 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 288 struct i2c_client *client = sd->priv;
309 289
310 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) 290 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
311 return -EINVAL; 291 return -EINVAL;
@@ -322,10 +302,10 @@ static int mt9m001_get_register(struct soc_camera_device *icd,
322 return 0; 302 return 0;
323} 303}
324 304
325static int mt9m001_set_register(struct soc_camera_device *icd, 305static int mt9m001_s_register(struct v4l2_subdev *sd,
326 struct v4l2_dbg_register *reg) 306 struct v4l2_dbg_register *reg)
327{ 307{
328 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 308 struct i2c_client *client = sd->priv;
329 309
330 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) 310 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
331 return -EINVAL; 311 return -EINVAL;
@@ -378,35 +358,20 @@ static const struct v4l2_queryctrl mt9m001_controls[] = {
378 } 358 }
379}; 359};
380 360
381static int mt9m001_get_control(struct soc_camera_device *, struct v4l2_control *);
382static int mt9m001_set_control(struct soc_camera_device *, struct v4l2_control *);
383
384static struct soc_camera_ops mt9m001_ops = { 361static struct soc_camera_ops mt9m001_ops = {
385 .owner = THIS_MODULE,
386 .init = mt9m001_init, 362 .init = mt9m001_init,
387 .release = mt9m001_release, 363 .release = mt9m001_release,
388 .start_capture = mt9m001_start_capture,
389 .stop_capture = mt9m001_stop_capture,
390 .set_crop = mt9m001_set_crop, 364 .set_crop = mt9m001_set_crop,
391 .set_fmt = mt9m001_set_fmt,
392 .try_fmt = mt9m001_try_fmt,
393 .set_bus_param = mt9m001_set_bus_param, 365 .set_bus_param = mt9m001_set_bus_param,
394 .query_bus_param = mt9m001_query_bus_param, 366 .query_bus_param = mt9m001_query_bus_param,
395 .controls = mt9m001_controls, 367 .controls = mt9m001_controls,
396 .num_controls = ARRAY_SIZE(mt9m001_controls), 368 .num_controls = ARRAY_SIZE(mt9m001_controls),
397 .get_control = mt9m001_get_control,
398 .set_control = mt9m001_set_control,
399 .get_chip_id = mt9m001_get_chip_id,
400#ifdef CONFIG_VIDEO_ADV_DEBUG
401 .get_register = mt9m001_get_register,
402 .set_register = mt9m001_set_register,
403#endif
404}; 369};
405 370
406static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) 371static int mt9m001_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
407{ 372{
408 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 373 struct i2c_client *client = sd->priv;
409 struct mt9m001 *mt9m001 = i2c_get_clientdata(client); 374 struct mt9m001 *mt9m001 = to_mt9m001(client);
410 int data; 375 int data;
411 376
412 switch (ctrl->id) { 377 switch (ctrl->id) {
@@ -423,10 +388,11 @@ static int mt9m001_get_control(struct soc_camera_device *icd, struct v4l2_contro
423 return 0; 388 return 0;
424} 389}
425 390
426static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_control *ctrl) 391static int mt9m001_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
427{ 392{
428 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); 393 struct i2c_client *client = sd->priv;
429 struct mt9m001 *mt9m001 = i2c_get_clientdata(client); 394 struct mt9m001 *mt9m001 = to_mt9m001(client);
395 struct soc_camera_device *icd = client->dev.platform_data;
430 const struct v4l2_queryctrl *qctrl; 396 const struct v4l2_queryctrl *qctrl;
431 int data; 397 int data;
432 398
@@ -521,10 +487,9 @@ static int mt9m001_set_control(struct soc_camera_device *icd, struct v4l2_contro
521static int mt9m001_video_probe(struct soc_camera_device *icd, 487static int mt9m001_video_probe(struct soc_camera_device *icd,
522 struct i2c_client *client) 488 struct i2c_client *client)
523{ 489{
524 struct mt9m001 *mt9m001 = i2c_get_clientdata(client); 490 struct mt9m001 *mt9m001 = to_mt9m001(client);
525 struct soc_camera_link *icl = to_soc_camera_link(icd); 491 struct soc_camera_link *icl = to_soc_camera_link(icd);
526 s32 data; 492 s32 data;
527 int ret;
528 unsigned long flags; 493 unsigned long flags;
529 494
530 /* We must have a parent by now. And it cannot be a wrong one. 495 /* We must have a parent by now. And it cannot be a wrong one.
@@ -533,11 +498,6 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
533 to_soc_camera_host(icd->dev.parent)->nr != icd->iface) 498 to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
534 return -ENODEV; 499 return -ENODEV;
535 500
536 /* Switch master clock on */
537 ret = soc_camera_video_start(icd, &client->dev);
538 if (ret)
539 return ret;
540
541 /* Enable the chip */ 501 /* Enable the chip */
542 data = reg_write(client, MT9M001_CHIP_ENABLE, 1); 502 data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
543 dev_dbg(&icd->dev, "write: %d\n", data); 503 dev_dbg(&icd->dev, "write: %d\n", data);
@@ -545,8 +505,6 @@ static int mt9m001_video_probe(struct soc_camera_device *icd,
545 /* Read out the chip version register */ 505 /* Read out the chip version register */
546 data = reg_read(client, MT9M001_CHIP_VERSION); 506 data = reg_read(client, MT9M001_CHIP_VERSION);
547 507
548 soc_camera_video_stop(icd);
549
550 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */ 508 /* must be 0x8411 or 0x8421 for colour sensor and 8431 for bw */
551 switch (data) { 509 switch (data) {
552 case 0x8411: 510 case 0x8411:
@@ -601,6 +559,27 @@ static void mt9m001_video_remove(struct soc_camera_device *icd)
601 icl->free_bus(icl); 559 icl->free_bus(icl);
602} 560}
603 561
562static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
563 .g_ctrl = mt9m001_g_ctrl,
564 .s_ctrl = mt9m001_s_ctrl,
565 .g_chip_ident = mt9m001_g_chip_ident,
566#ifdef CONFIG_VIDEO_ADV_DEBUG
567 .g_register = mt9m001_g_register,
568 .s_register = mt9m001_s_register,
569#endif
570};
571
572static struct v4l2_subdev_video_ops mt9m001_subdev_video_ops = {
573 .s_stream = mt9m001_s_stream,
574 .s_fmt = mt9m001_s_fmt,
575 .try_fmt = mt9m001_try_fmt,
576};
577
578static struct v4l2_subdev_ops mt9m001_subdev_ops = {
579 .core = &mt9m001_subdev_core_ops,
580 .video = &mt9m001_subdev_video_ops,
581};
582
604static int mt9m001_probe(struct i2c_client *client, 583static int mt9m001_probe(struct i2c_client *client,
605 const struct i2c_device_id *did) 584 const struct i2c_device_id *did)
606{ 585{
@@ -631,7 +610,7 @@ static int mt9m001_probe(struct i2c_client *client,
631 if (!mt9m001) 610 if (!mt9m001)
632 return -ENOMEM; 611 return -ENOMEM;
633 612
634 i2c_set_clientdata(client, mt9m001); 613 v4l2_i2c_subdev_init(&mt9m001->subdev, client, &mt9m001_subdev_ops);
635 614
636 /* Second stage probe - when a capture adapter is there */ 615 /* Second stage probe - when a capture adapter is there */
637 icd->ops = &mt9m001_ops; 616 icd->ops = &mt9m001_ops;
@@ -660,7 +639,7 @@ static int mt9m001_probe(struct i2c_client *client,
660 639
661static int mt9m001_remove(struct i2c_client *client) 640static int mt9m001_remove(struct i2c_client *client)
662{ 641{
663 struct mt9m001 *mt9m001 = i2c_get_clientdata(client); 642 struct mt9m001 *mt9m001 = to_mt9m001(client);
664 struct soc_camera_device *icd = client->dev.platform_data; 643 struct soc_camera_device *icd = client->dev.platform_data;
665 644
666 icd->ops = NULL; 645 icd->ops = NULL;