aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/mt9v022.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/mt9v022.c')
-rw-r--r--drivers/media/video/mt9v022.c119
1 files changed, 60 insertions, 59 deletions
diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c
index dbdcc86ae50d..959cc299f1ae 100644
--- a/drivers/media/video/mt9v022.c
+++ b/drivers/media/video/mt9v022.c
@@ -85,8 +85,6 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = {
85}; 85};
86 86
87struct mt9v022 { 87struct mt9v022 {
88 struct i2c_client *client;
89 struct soc_camera_device icd;
90 int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ 88 int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
91 u16 chip_control; 89 u16 chip_control;
92}; 90};
@@ -127,9 +125,9 @@ static int reg_clear(struct i2c_client *client, const u8 reg,
127 125
128static int mt9v022_init(struct soc_camera_device *icd) 126static int mt9v022_init(struct soc_camera_device *icd)
129{ 127{
130 struct i2c_client *client = to_i2c_client(icd->control); 128 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
131 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 129 struct soc_camera_link *icl = to_soc_camera_link(icd);
132 struct soc_camera_link *icl = client->dev.platform_data; 130 struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
133 int ret; 131 int ret;
134 132
135 if (icl->power) { 133 if (icl->power) {
@@ -173,19 +171,19 @@ static int mt9v022_init(struct soc_camera_device *icd)
173 171
174static int mt9v022_release(struct soc_camera_device *icd) 172static int mt9v022_release(struct soc_camera_device *icd)
175{ 173{
176 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 174 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
177 struct soc_camera_link *icl = mt9v022->client->dev.platform_data; 175 struct soc_camera_link *icl = to_soc_camera_link(icd);
178 176
179 if (icl->power) 177 if (icl->power)
180 icl->power(&mt9v022->client->dev, 0); 178 icl->power(&client->dev, 0);
181 179
182 return 0; 180 return 0;
183} 181}
184 182
185static int mt9v022_start_capture(struct soc_camera_device *icd) 183static int mt9v022_start_capture(struct soc_camera_device *icd)
186{ 184{
187 struct i2c_client *client = to_i2c_client(icd->control); 185 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
188 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 186 struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
189 /* Switch to master "normal" mode */ 187 /* Switch to master "normal" mode */
190 mt9v022->chip_control &= ~0x10; 188 mt9v022->chip_control &= ~0x10;
191 if (reg_write(client, MT9V022_CHIP_CONTROL, 189 if (reg_write(client, MT9V022_CHIP_CONTROL,
@@ -196,8 +194,8 @@ static int mt9v022_start_capture(struct soc_camera_device *icd)
196 194
197static int mt9v022_stop_capture(struct soc_camera_device *icd) 195static int mt9v022_stop_capture(struct soc_camera_device *icd)
198{ 196{
199 struct i2c_client *client = to_i2c_client(icd->control); 197 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
200 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 198 struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
201 /* Switch to snapshot mode */ 199 /* Switch to snapshot mode */
202 mt9v022->chip_control |= 0x10; 200 mt9v022->chip_control |= 0x10;
203 if (reg_write(client, MT9V022_CHIP_CONTROL, 201 if (reg_write(client, MT9V022_CHIP_CONTROL,
@@ -209,9 +207,9 @@ static int mt9v022_stop_capture(struct soc_camera_device *icd)
209static int mt9v022_set_bus_param(struct soc_camera_device *icd, 207static int mt9v022_set_bus_param(struct soc_camera_device *icd,
210 unsigned long flags) 208 unsigned long flags)
211{ 209{
212 struct i2c_client *client = to_i2c_client(icd->control); 210 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
213 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 211 struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
214 struct soc_camera_link *icl = client->dev.platform_data; 212 struct soc_camera_link *icl = to_soc_camera_link(icd);
215 unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK; 213 unsigned int width_flag = flags & SOCAM_DATAWIDTH_MASK;
216 int ret; 214 int ret;
217 u16 pixclk = 0; 215 u16 pixclk = 0;
@@ -263,8 +261,7 @@ static int mt9v022_set_bus_param(struct soc_camera_device *icd,
263 261
264static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd) 262static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
265{ 263{
266 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 264 struct soc_camera_link *icl = to_soc_camera_link(icd);
267 struct soc_camera_link *icl = mt9v022->client->dev.platform_data;
268 unsigned int width_flag; 265 unsigned int width_flag;
269 266
270 if (icl->query_bus_param) 267 if (icl->query_bus_param)
@@ -283,7 +280,7 @@ static unsigned long mt9v022_query_bus_param(struct soc_camera_device *icd)
283static int mt9v022_set_crop(struct soc_camera_device *icd, 280static int mt9v022_set_crop(struct soc_camera_device *icd,
284 struct v4l2_rect *rect) 281 struct v4l2_rect *rect)
285{ 282{
286 struct i2c_client *client = to_i2c_client(icd->control); 283 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
287 int ret; 284 int ret;
288 285
289 /* Like in example app. Contradicts the datasheet though */ 286 /* Like in example app. Contradicts the datasheet though */
@@ -326,7 +323,8 @@ static int mt9v022_set_crop(struct soc_camera_device *icd,
326static int mt9v022_set_fmt(struct soc_camera_device *icd, 323static int mt9v022_set_fmt(struct soc_camera_device *icd,
327 struct v4l2_format *f) 324 struct v4l2_format *f)
328{ 325{
329 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 326 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
327 struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
330 struct v4l2_pix_format *pix = &f->fmt.pix; 328 struct v4l2_pix_format *pix = &f->fmt.pix;
331 struct v4l2_rect rect = { 329 struct v4l2_rect rect = {
332 .left = icd->x_current, 330 .left = icd->x_current,
@@ -374,12 +372,13 @@ static int mt9v022_try_fmt(struct soc_camera_device *icd,
374static int mt9v022_get_chip_id(struct soc_camera_device *icd, 372static int mt9v022_get_chip_id(struct soc_camera_device *icd,
375 struct v4l2_dbg_chip_ident *id) 373 struct v4l2_dbg_chip_ident *id)
376{ 374{
377 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 375 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
376 struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
378 377
379 if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR) 378 if (id->match.type != V4L2_CHIP_MATCH_I2C_ADDR)
380 return -EINVAL; 379 return -EINVAL;
381 380
382 if (id->match.addr != mt9v022->client->addr) 381 if (id->match.addr != client->addr)
383 return -ENODEV; 382 return -ENODEV;
384 383
385 id->ident = mt9v022->model; 384 id->ident = mt9v022->model;
@@ -392,7 +391,7 @@ static int mt9v022_get_chip_id(struct soc_camera_device *icd,
392static int mt9v022_get_register(struct soc_camera_device *icd, 391static int mt9v022_get_register(struct soc_camera_device *icd,
393 struct v4l2_dbg_register *reg) 392 struct v4l2_dbg_register *reg)
394{ 393{
395 struct i2c_client *client = to_i2c_client(icd->control); 394 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
396 395
397 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) 396 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
398 return -EINVAL; 397 return -EINVAL;
@@ -412,7 +411,7 @@ static int mt9v022_get_register(struct soc_camera_device *icd,
412static int mt9v022_set_register(struct soc_camera_device *icd, 411static int mt9v022_set_register(struct soc_camera_device *icd,
413 struct v4l2_dbg_register *reg) 412 struct v4l2_dbg_register *reg)
414{ 413{
415 struct i2c_client *client = to_i2c_client(icd->control); 414 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
416 415
417 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff) 416 if (reg->match.type != V4L2_CHIP_MATCH_I2C_ADDR || reg->reg > 0xff)
418 return -EINVAL; 417 return -EINVAL;
@@ -481,15 +480,11 @@ static const struct v4l2_queryctrl mt9v022_controls[] = {
481 } 480 }
482}; 481};
483 482
484static int mt9v022_video_probe(struct soc_camera_device *);
485static void mt9v022_video_remove(struct soc_camera_device *);
486static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *); 483static int mt9v022_get_control(struct soc_camera_device *, struct v4l2_control *);
487static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *); 484static int mt9v022_set_control(struct soc_camera_device *, struct v4l2_control *);
488 485
489static struct soc_camera_ops mt9v022_ops = { 486static struct soc_camera_ops mt9v022_ops = {
490 .owner = THIS_MODULE, 487 .owner = THIS_MODULE,
491 .probe = mt9v022_video_probe,
492 .remove = mt9v022_video_remove,
493 .init = mt9v022_init, 488 .init = mt9v022_init,
494 .release = mt9v022_release, 489 .release = mt9v022_release,
495 .start_capture = mt9v022_start_capture, 490 .start_capture = mt9v022_start_capture,
@@ -513,7 +508,7 @@ static struct soc_camera_ops mt9v022_ops = {
513static int mt9v022_get_control(struct soc_camera_device *icd, 508static int mt9v022_get_control(struct soc_camera_device *icd,
514 struct v4l2_control *ctrl) 509 struct v4l2_control *ctrl)
515{ 510{
516 struct i2c_client *client = to_i2c_client(icd->control); 511 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
517 int data; 512 int data;
518 513
519 switch (ctrl->id) { 514 switch (ctrl->id) {
@@ -549,7 +544,7 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
549 struct v4l2_control *ctrl) 544 struct v4l2_control *ctrl)
550{ 545{
551 int data; 546 int data;
552 struct i2c_client *client = to_i2c_client(icd->control); 547 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
553 const struct v4l2_queryctrl *qctrl; 548 const struct v4l2_queryctrl *qctrl;
554 549
555 qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id); 550 qctrl = soc_camera_find_qctrl(&mt9v022_ops, ctrl->id);
@@ -646,11 +641,11 @@ static int mt9v022_set_control(struct soc_camera_device *icd,
646 641
647/* Interface active, can use i2c. If it fails, it can indeed mean, that 642/* Interface active, can use i2c. If it fails, it can indeed mean, that
648 * this wasn't our capture interface, so, we wait for the right one */ 643 * this wasn't our capture interface, so, we wait for the right one */
649static int mt9v022_video_probe(struct soc_camera_device *icd) 644static int mt9v022_video_probe(struct soc_camera_device *icd,
645 struct i2c_client *client)
650{ 646{
651 struct i2c_client *client = to_i2c_client(icd->control); 647 struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
652 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 648 struct soc_camera_link *icl = to_soc_camera_link(icd);
653 struct soc_camera_link *icl = client->dev.platform_data;
654 s32 data; 649 s32 data;
655 int ret; 650 int ret;
656 unsigned long flags; 651 unsigned long flags;
@@ -659,6 +654,11 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
659 to_soc_camera_host(icd->dev.parent)->nr != icd->iface) 654 to_soc_camera_host(icd->dev.parent)->nr != icd->iface)
660 return -ENODEV; 655 return -ENODEV;
661 656
657 /* Switch master clock on */
658 ret = soc_camera_video_start(icd, &client->dev);
659 if (ret)
660 return ret;
661
662 /* Read out the chip version register */ 662 /* Read out the chip version register */
663 data = reg_read(client, MT9V022_CHIP_VERSION); 663 data = reg_read(client, MT9V022_CHIP_VERSION);
664 664
@@ -678,6 +678,8 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
678 udelay(200); 678 udelay(200);
679 if (reg_read(client, MT9V022_RESET)) { 679 if (reg_read(client, MT9V022_RESET)) {
680 dev_err(&icd->dev, "Resetting MT9V022 failed!\n"); 680 dev_err(&icd->dev, "Resetting MT9V022 failed!\n");
681 if (ret > 0)
682 ret = -EIO;
681 goto ei2c; 683 goto ei2c;
682 } 684 }
683 685
@@ -694,7 +696,7 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
694 } 696 }
695 697
696 if (ret < 0) 698 if (ret < 0)
697 goto eisis; 699 goto ei2c;
698 700
699 icd->num_formats = 0; 701 icd->num_formats = 0;
700 702
@@ -716,29 +718,23 @@ static int mt9v022_video_probe(struct soc_camera_device *icd)
716 if (flags & SOCAM_DATAWIDTH_8) 718 if (flags & SOCAM_DATAWIDTH_8)
717 icd->num_formats++; 719 icd->num_formats++;
718 720
719 ret = soc_camera_video_start(icd);
720 if (ret < 0)
721 goto eisis;
722
723 dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n", 721 dev_info(&icd->dev, "Detected a MT9V022 chip ID %x, %s sensor\n",
724 data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ? 722 data, mt9v022->model == V4L2_IDENT_MT9V022IX7ATM ?
725 "monochrome" : "colour"); 723 "monochrome" : "colour");
726 724
727 return 0;
728
729eisis:
730ei2c: 725ei2c:
726 soc_camera_video_stop(icd);
727
731 return ret; 728 return ret;
732} 729}
733 730
734static void mt9v022_video_remove(struct soc_camera_device *icd) 731static void mt9v022_video_remove(struct soc_camera_device *icd)
735{ 732{
736 struct mt9v022 *mt9v022 = container_of(icd, struct mt9v022, icd); 733 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
737 struct soc_camera_link *icl = mt9v022->client->dev.platform_data; 734 struct soc_camera_link *icl = to_soc_camera_link(icd);
738 735
739 dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", mt9v022->client->addr, 736 dev_dbg(&icd->dev, "Video %x removed: %p, %p\n", client->addr,
740 icd->dev.parent, icd->vdev); 737 icd->dev.parent, icd->vdev);
741 soc_camera_video_stop(icd);
742 if (icl->free_bus) 738 if (icl->free_bus)
743 icl->free_bus(icl); 739 icl->free_bus(icl);
744} 740}
@@ -747,11 +743,17 @@ static int mt9v022_probe(struct i2c_client *client,
747 const struct i2c_device_id *did) 743 const struct i2c_device_id *did)
748{ 744{
749 struct mt9v022 *mt9v022; 745 struct mt9v022 *mt9v022;
750 struct soc_camera_device *icd; 746 struct soc_camera_device *icd = client->dev.platform_data;
751 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 747 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
752 struct soc_camera_link *icl = client->dev.platform_data; 748 struct soc_camera_link *icl;
753 int ret; 749 int ret;
754 750
751 if (!icd) {
752 dev_err(&client->dev, "MT9V022: missing soc-camera data!\n");
753 return -EINVAL;
754 }
755
756 icl = to_soc_camera_link(icd);
755 if (!icl) { 757 if (!icl) {
756 dev_err(&client->dev, "MT9V022 driver needs platform data\n"); 758 dev_err(&client->dev, "MT9V022 driver needs platform data\n");
757 return -EINVAL; 759 return -EINVAL;
@@ -768,12 +770,9 @@ static int mt9v022_probe(struct i2c_client *client,
768 return -ENOMEM; 770 return -ENOMEM;
769 771
770 mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT; 772 mt9v022->chip_control = MT9V022_CHIP_CONTROL_DEFAULT;
771 mt9v022->client = client;
772 i2c_set_clientdata(client, mt9v022); 773 i2c_set_clientdata(client, mt9v022);
773 774
774 icd = &mt9v022->icd;
775 icd->ops = &mt9v022_ops; 775 icd->ops = &mt9v022_ops;
776 icd->control = &client->dev;
777 icd->x_min = 1; 776 icd->x_min = 1;
778 icd->y_min = 4; 777 icd->y_min = 4;
779 icd->x_current = 1; 778 icd->x_current = 1;
@@ -783,24 +782,26 @@ static int mt9v022_probe(struct i2c_client *client,
783 icd->height_min = 32; 782 icd->height_min = 32;
784 icd->height_max = 480; 783 icd->height_max = 480;
785 icd->y_skip_top = 1; 784 icd->y_skip_top = 1;
786 icd->iface = icl->bus_id;
787
788 ret = soc_camera_device_register(icd);
789 if (ret)
790 goto eisdr;
791 785
792 return 0; 786 ret = mt9v022_video_probe(icd, client);
787 if (ret) {
788 icd->ops = NULL;
789 i2c_set_clientdata(client, NULL);
790 kfree(mt9v022);
791 }
793 792
794eisdr:
795 kfree(mt9v022);
796 return ret; 793 return ret;
797} 794}
798 795
799static int mt9v022_remove(struct i2c_client *client) 796static int mt9v022_remove(struct i2c_client *client)
800{ 797{
801 struct mt9v022 *mt9v022 = i2c_get_clientdata(client); 798 struct mt9v022 *mt9v022 = i2c_get_clientdata(client);
799 struct soc_camera_device *icd = client->dev.platform_data;
802 800
803 soc_camera_device_unregister(&mt9v022->icd); 801 icd->ops = NULL;
802 mt9v022_video_remove(icd);
803 i2c_set_clientdata(client, NULL);
804 client->driver = NULL;
804 kfree(mt9v022); 805 kfree(mt9v022);
805 806
806 return 0; 807 return 0;