diff options
Diffstat (limited to 'drivers/media/video/ov772x.c')
-rw-r--r-- | drivers/media/video/ov772x.c | 157 |
1 files changed, 86 insertions, 71 deletions
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 0bce255168bd..3ea650d55b17 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c | |||
@@ -399,8 +399,6 @@ struct ov772x_win_size { | |||
399 | 399 | ||
400 | struct ov772x_priv { | 400 | struct ov772x_priv { |
401 | struct ov772x_camera_info *info; | 401 | struct ov772x_camera_info *info; |
402 | struct i2c_client *client; | ||
403 | struct soc_camera_device icd; | ||
404 | const struct ov772x_color_format *fmt; | 402 | const struct ov772x_color_format *fmt; |
405 | const struct ov772x_win_size *win; | 403 | const struct ov772x_win_size *win; |
406 | int model; | 404 | int model; |
@@ -619,53 +617,56 @@ static int ov772x_reset(struct i2c_client *client) | |||
619 | 617 | ||
620 | static int ov772x_init(struct soc_camera_device *icd) | 618 | static int ov772x_init(struct soc_camera_device *icd) |
621 | { | 619 | { |
622 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 620 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
621 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
623 | int ret = 0; | 622 | int ret = 0; |
624 | 623 | ||
625 | if (priv->info->link.power) { | 624 | if (icl->power) { |
626 | ret = priv->info->link.power(&priv->client->dev, 1); | 625 | ret = icl->power(&client->dev, 1); |
627 | if (ret < 0) | 626 | if (ret < 0) |
628 | return ret; | 627 | return ret; |
629 | } | 628 | } |
630 | 629 | ||
631 | if (priv->info->link.reset) | 630 | if (icl->reset) |
632 | ret = priv->info->link.reset(&priv->client->dev); | 631 | ret = icl->reset(&client->dev); |
633 | 632 | ||
634 | return ret; | 633 | return ret; |
635 | } | 634 | } |
636 | 635 | ||
637 | static int ov772x_release(struct soc_camera_device *icd) | 636 | static int ov772x_release(struct soc_camera_device *icd) |
638 | { | 637 | { |
639 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 638 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
639 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
640 | int ret = 0; | 640 | int ret = 0; |
641 | 641 | ||
642 | if (priv->info->link.power) | 642 | if (icl->power) |
643 | ret = priv->info->link.power(&priv->client->dev, 0); | 643 | ret = icl->power(&client->dev, 0); |
644 | 644 | ||
645 | return ret; | 645 | return ret; |
646 | } | 646 | } |
647 | 647 | ||
648 | static int ov772x_start_capture(struct soc_camera_device *icd) | 648 | static int ov772x_start_capture(struct soc_camera_device *icd) |
649 | { | 649 | { |
650 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 650 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
651 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
651 | 652 | ||
652 | if (!priv->win || !priv->fmt) { | 653 | if (!priv->win || !priv->fmt) { |
653 | dev_err(&icd->dev, "norm or win select error\n"); | 654 | dev_err(&icd->dev, "norm or win select error\n"); |
654 | return -EPERM; | 655 | return -EPERM; |
655 | } | 656 | } |
656 | 657 | ||
657 | ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0); | 658 | ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0); |
658 | 659 | ||
659 | dev_dbg(&icd->dev, | 660 | dev_dbg(&icd->dev, |
660 | "format %s, win %s\n", priv->fmt->name, priv->win->name); | 661 | "format %s, win %s\n", priv->fmt->name, priv->win->name); |
661 | 662 | ||
662 | return 0; | 663 | return 0; |
663 | } | 664 | } |
664 | 665 | ||
665 | static int ov772x_stop_capture(struct soc_camera_device *icd) | 666 | static int ov772x_stop_capture(struct soc_camera_device *icd) |
666 | { | 667 | { |
667 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 668 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
668 | ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); | 669 | ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE); |
669 | return 0; | 670 | return 0; |
670 | } | 671 | } |
671 | 672 | ||
@@ -677,8 +678,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd, | |||
677 | 678 | ||
678 | static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) | 679 | static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) |
679 | { | 680 | { |
680 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 681 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
681 | struct soc_camera_link *icl = &priv->info->link; | 682 | struct ov772x_priv *priv = i2c_get_clientdata(client); |
683 | struct soc_camera_link *icl = to_soc_camera_link(icd); | ||
682 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | | 684 | unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | |
683 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | | 685 | SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | |
684 | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; | 686 | SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; |
@@ -689,7 +691,8 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) | |||
689 | static int ov772x_get_control(struct soc_camera_device *icd, | 691 | static int ov772x_get_control(struct soc_camera_device *icd, |
690 | struct v4l2_control *ctrl) | 692 | struct v4l2_control *ctrl) |
691 | { | 693 | { |
692 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 694 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
695 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
693 | 696 | ||
694 | switch (ctrl->id) { | 697 | switch (ctrl->id) { |
695 | case V4L2_CID_VFLIP: | 698 | case V4L2_CID_VFLIP: |
@@ -705,7 +708,8 @@ static int ov772x_get_control(struct soc_camera_device *icd, | |||
705 | static int ov772x_set_control(struct soc_camera_device *icd, | 708 | static int ov772x_set_control(struct soc_camera_device *icd, |
706 | struct v4l2_control *ctrl) | 709 | struct v4l2_control *ctrl) |
707 | { | 710 | { |
708 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 711 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
712 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
709 | int ret = 0; | 713 | int ret = 0; |
710 | u8 val; | 714 | u8 val; |
711 | 715 | ||
@@ -715,14 +719,14 @@ static int ov772x_set_control(struct soc_camera_device *icd, | |||
715 | priv->flag_vflip = ctrl->value; | 719 | priv->flag_vflip = ctrl->value; |
716 | if (priv->info->flags & OV772X_FLAG_VFLIP) | 720 | if (priv->info->flags & OV772X_FLAG_VFLIP) |
717 | val ^= VFLIP_IMG; | 721 | val ^= VFLIP_IMG; |
718 | ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val); | 722 | ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val); |
719 | break; | 723 | break; |
720 | case V4L2_CID_HFLIP: | 724 | case V4L2_CID_HFLIP: |
721 | val = ctrl->value ? HFLIP_IMG : 0x00; | 725 | val = ctrl->value ? HFLIP_IMG : 0x00; |
722 | priv->flag_hflip = ctrl->value; | 726 | priv->flag_hflip = ctrl->value; |
723 | if (priv->info->flags & OV772X_FLAG_HFLIP) | 727 | if (priv->info->flags & OV772X_FLAG_HFLIP) |
724 | val ^= HFLIP_IMG; | 728 | val ^= HFLIP_IMG; |
725 | ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val); | 729 | ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val); |
726 | break; | 730 | break; |
727 | } | 731 | } |
728 | 732 | ||
@@ -730,9 +734,10 @@ static int ov772x_set_control(struct soc_camera_device *icd, | |||
730 | } | 734 | } |
731 | 735 | ||
732 | static int ov772x_get_chip_id(struct soc_camera_device *icd, | 736 | static int ov772x_get_chip_id(struct soc_camera_device *icd, |
733 | struct v4l2_dbg_chip_ident *id) | 737 | struct v4l2_dbg_chip_ident *id) |
734 | { | 738 | { |
735 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 739 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
740 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
736 | 741 | ||
737 | id->ident = priv->model; | 742 | id->ident = priv->model; |
738 | id->revision = 0; | 743 | id->revision = 0; |
@@ -744,14 +749,14 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd, | |||
744 | static int ov772x_get_register(struct soc_camera_device *icd, | 749 | static int ov772x_get_register(struct soc_camera_device *icd, |
745 | struct v4l2_dbg_register *reg) | 750 | struct v4l2_dbg_register *reg) |
746 | { | 751 | { |
747 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 752 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
748 | int ret; | 753 | int ret; |
749 | 754 | ||
750 | reg->size = 1; | 755 | reg->size = 1; |
751 | if (reg->reg > 0xff) | 756 | if (reg->reg > 0xff) |
752 | return -EINVAL; | 757 | return -EINVAL; |
753 | 758 | ||
754 | ret = i2c_smbus_read_byte_data(priv->client, reg->reg); | 759 | ret = i2c_smbus_read_byte_data(client, reg->reg); |
755 | if (ret < 0) | 760 | if (ret < 0) |
756 | return ret; | 761 | return ret; |
757 | 762 | ||
@@ -763,13 +768,13 @@ static int ov772x_get_register(struct soc_camera_device *icd, | |||
763 | static int ov772x_set_register(struct soc_camera_device *icd, | 768 | static int ov772x_set_register(struct soc_camera_device *icd, |
764 | struct v4l2_dbg_register *reg) | 769 | struct v4l2_dbg_register *reg) |
765 | { | 770 | { |
766 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 771 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
767 | 772 | ||
768 | if (reg->reg > 0xff || | 773 | if (reg->reg > 0xff || |
769 | reg->val > 0xff) | 774 | reg->val > 0xff) |
770 | return -EINVAL; | 775 | return -EINVAL; |
771 | 776 | ||
772 | return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); | 777 | return i2c_smbus_write_byte_data(client, reg->reg, reg->val); |
773 | } | 778 | } |
774 | #endif | 779 | #endif |
775 | 780 | ||
@@ -793,9 +798,11 @@ ov772x_select_win(u32 width, u32 height) | |||
793 | return win; | 798 | return win; |
794 | } | 799 | } |
795 | 800 | ||
796 | static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | 801 | static int ov772x_set_params(struct soc_camera_device *icd, |
797 | u32 pixfmt) | 802 | u32 width, u32 height, u32 pixfmt) |
798 | { | 803 | { |
804 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); | ||
805 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
799 | int ret = -EINVAL; | 806 | int ret = -EINVAL; |
800 | u8 val; | 807 | u8 val; |
801 | int i; | 808 | int i; |
@@ -810,6 +817,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
810 | break; | 817 | break; |
811 | } | 818 | } |
812 | } | 819 | } |
820 | dev_dbg(&icd->dev, "Using fmt %x #%d\n", pixfmt, i); | ||
813 | if (!priv->fmt) | 821 | if (!priv->fmt) |
814 | goto ov772x_set_fmt_error; | 822 | goto ov772x_set_fmt_error; |
815 | 823 | ||
@@ -821,7 +829,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
821 | /* | 829 | /* |
822 | * reset hardware | 830 | * reset hardware |
823 | */ | 831 | */ |
824 | ov772x_reset(priv->client); | 832 | ov772x_reset(client); |
825 | 833 | ||
826 | /* | 834 | /* |
827 | * Edge Ctrl | 835 | * Edge Ctrl |
@@ -835,17 +843,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
835 | * Remove it when manual mode. | 843 | * Remove it when manual mode. |
836 | */ | 844 | */ |
837 | 845 | ||
838 | ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00); | 846 | ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00); |
839 | if (ret < 0) | 847 | if (ret < 0) |
840 | goto ov772x_set_fmt_error; | 848 | goto ov772x_set_fmt_error; |
841 | 849 | ||
842 | ret = ov772x_mask_set(priv->client, | 850 | ret = ov772x_mask_set(client, |
843 | EDGE_TRSHLD, EDGE_THRESHOLD_MASK, | 851 | EDGE_TRSHLD, EDGE_THRESHOLD_MASK, |
844 | priv->info->edgectrl.threshold); | 852 | priv->info->edgectrl.threshold); |
845 | if (ret < 0) | 853 | if (ret < 0) |
846 | goto ov772x_set_fmt_error; | 854 | goto ov772x_set_fmt_error; |
847 | 855 | ||
848 | ret = ov772x_mask_set(priv->client, | 856 | ret = ov772x_mask_set(client, |
849 | EDGE_STRNGT, EDGE_STRENGTH_MASK, | 857 | EDGE_STRNGT, EDGE_STRENGTH_MASK, |
850 | priv->info->edgectrl.strength); | 858 | priv->info->edgectrl.strength); |
851 | if (ret < 0) | 859 | if (ret < 0) |
@@ -857,13 +865,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
857 | * | 865 | * |
858 | * set upper and lower limit | 866 | * set upper and lower limit |
859 | */ | 867 | */ |
860 | ret = ov772x_mask_set(priv->client, | 868 | ret = ov772x_mask_set(client, |
861 | EDGE_UPPER, EDGE_UPPER_MASK, | 869 | EDGE_UPPER, EDGE_UPPER_MASK, |
862 | priv->info->edgectrl.upper); | 870 | priv->info->edgectrl.upper); |
863 | if (ret < 0) | 871 | if (ret < 0) |
864 | goto ov772x_set_fmt_error; | 872 | goto ov772x_set_fmt_error; |
865 | 873 | ||
866 | ret = ov772x_mask_set(priv->client, | 874 | ret = ov772x_mask_set(client, |
867 | EDGE_LOWER, EDGE_LOWER_MASK, | 875 | EDGE_LOWER, EDGE_LOWER_MASK, |
868 | priv->info->edgectrl.lower); | 876 | priv->info->edgectrl.lower); |
869 | if (ret < 0) | 877 | if (ret < 0) |
@@ -873,7 +881,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
873 | /* | 881 | /* |
874 | * set size format | 882 | * set size format |
875 | */ | 883 | */ |
876 | ret = ov772x_write_array(priv->client, priv->win->regs); | 884 | ret = ov772x_write_array(client, priv->win->regs); |
877 | if (ret < 0) | 885 | if (ret < 0) |
878 | goto ov772x_set_fmt_error; | 886 | goto ov772x_set_fmt_error; |
879 | 887 | ||
@@ -882,7 +890,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
882 | */ | 890 | */ |
883 | val = priv->fmt->dsp3; | 891 | val = priv->fmt->dsp3; |
884 | if (val) { | 892 | if (val) { |
885 | ret = ov772x_mask_set(priv->client, | 893 | ret = ov772x_mask_set(client, |
886 | DSP_CTRL3, UV_MASK, val); | 894 | DSP_CTRL3, UV_MASK, val); |
887 | if (ret < 0) | 895 | if (ret < 0) |
888 | goto ov772x_set_fmt_error; | 896 | goto ov772x_set_fmt_error; |
@@ -901,7 +909,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
901 | if (priv->flag_hflip) | 909 | if (priv->flag_hflip) |
902 | val ^= HFLIP_IMG; | 910 | val ^= HFLIP_IMG; |
903 | 911 | ||
904 | ret = ov772x_mask_set(priv->client, | 912 | ret = ov772x_mask_set(client, |
905 | COM3, SWAP_MASK | IMG_MASK, val); | 913 | COM3, SWAP_MASK | IMG_MASK, val); |
906 | if (ret < 0) | 914 | if (ret < 0) |
907 | goto ov772x_set_fmt_error; | 915 | goto ov772x_set_fmt_error; |
@@ -910,7 +918,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
910 | * set COM7 | 918 | * set COM7 |
911 | */ | 919 | */ |
912 | val = priv->win->com7_bit | priv->fmt->com7; | 920 | val = priv->win->com7_bit | priv->fmt->com7; |
913 | ret = ov772x_mask_set(priv->client, | 921 | ret = ov772x_mask_set(client, |
914 | COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), | 922 | COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), |
915 | val); | 923 | val); |
916 | if (ret < 0) | 924 | if (ret < 0) |
@@ -920,7 +928,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, | |||
920 | 928 | ||
921 | ov772x_set_fmt_error: | 929 | ov772x_set_fmt_error: |
922 | 930 | ||
923 | ov772x_reset(priv->client); | 931 | ov772x_reset(client); |
924 | priv->win = NULL; | 932 | priv->win = NULL; |
925 | priv->fmt = NULL; | 933 | priv->fmt = NULL; |
926 | 934 | ||
@@ -930,22 +938,22 @@ ov772x_set_fmt_error: | |||
930 | static int ov772x_set_crop(struct soc_camera_device *icd, | 938 | static int ov772x_set_crop(struct soc_camera_device *icd, |
931 | struct v4l2_rect *rect) | 939 | struct v4l2_rect *rect) |
932 | { | 940 | { |
933 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 941 | struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd)); |
942 | struct ov772x_priv *priv = i2c_get_clientdata(client); | ||
934 | 943 | ||
935 | if (!priv->fmt) | 944 | if (!priv->fmt) |
936 | return -EINVAL; | 945 | return -EINVAL; |
937 | 946 | ||
938 | return ov772x_set_params(priv, rect->width, rect->height, | 947 | return ov772x_set_params(icd, rect->width, rect->height, |
939 | priv->fmt->fourcc); | 948 | priv->fmt->fourcc); |
940 | } | 949 | } |
941 | 950 | ||
942 | static int ov772x_set_fmt(struct soc_camera_device *icd, | 951 | static int ov772x_set_fmt(struct soc_camera_device *icd, |
943 | struct v4l2_format *f) | 952 | struct v4l2_format *f) |
944 | { | 953 | { |
945 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | ||
946 | struct v4l2_pix_format *pix = &f->fmt.pix; | 954 | struct v4l2_pix_format *pix = &f->fmt.pix; |
947 | 955 | ||
948 | return ov772x_set_params(priv, pix->width, pix->height, | 956 | return ov772x_set_params(icd, pix->width, pix->height, |
949 | pix->pixelformat); | 957 | pix->pixelformat); |
950 | } | 958 | } |
951 | 959 | ||
@@ -967,11 +975,13 @@ static int ov772x_try_fmt(struct soc_camera_device *icd, | |||
967 | return 0; | 975 | return 0; |
968 | } | 976 | } |
969 | 977 | ||
970 | static int ov772x_video_probe(struct soc_camera_device *icd) | 978 | static int ov772x_video_probe(struct soc_camera_device *icd, |
979 | struct i2c_client *client) | ||
971 | { | 980 | { |
972 | struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); | 981 | struct ov772x_priv *priv = i2c_get_clientdata(client); |
973 | u8 pid, ver; | 982 | u8 pid, ver; |
974 | const char *devname; | 983 | const char *devname; |
984 | int ret; | ||
975 | 985 | ||
976 | /* | 986 | /* |
977 | * We must have a parent by now. And it cannot be a wrong one. | 987 | * We must have a parent by now. And it cannot be a wrong one. |
@@ -993,11 +1003,16 @@ static int ov772x_video_probe(struct soc_camera_device *icd) | |||
993 | icd->formats = ov772x_fmt_lists; | 1003 | icd->formats = ov772x_fmt_lists; |
994 | icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); | 1004 | icd->num_formats = ARRAY_SIZE(ov772x_fmt_lists); |
995 | 1005 | ||
1006 | /* Switch master clock on */ | ||
1007 | ret = soc_camera_video_start(icd, &client->dev); | ||
1008 | if (ret) | ||
1009 | return ret; | ||
1010 | |||
996 | /* | 1011 | /* |
997 | * check and show product ID and manufacturer ID | 1012 | * check and show product ID and manufacturer ID |
998 | */ | 1013 | */ |
999 | pid = i2c_smbus_read_byte_data(priv->client, PID); | 1014 | pid = i2c_smbus_read_byte_data(client, PID); |
1000 | ver = i2c_smbus_read_byte_data(priv->client, VER); | 1015 | ver = i2c_smbus_read_byte_data(client, VER); |
1001 | 1016 | ||
1002 | switch (VERSION(pid, ver)) { | 1017 | switch (VERSION(pid, ver)) { |
1003 | case OV7720: | 1018 | case OV7720: |
@@ -1011,7 +1026,8 @@ static int ov772x_video_probe(struct soc_camera_device *icd) | |||
1011 | default: | 1026 | default: |
1012 | dev_err(&icd->dev, | 1027 | dev_err(&icd->dev, |
1013 | "Product ID error %x:%x\n", pid, ver); | 1028 | "Product ID error %x:%x\n", pid, ver); |
1014 | return -ENODEV; | 1029 | ret = -ENODEV; |
1030 | goto ever; | ||
1015 | } | 1031 | } |
1016 | 1032 | ||
1017 | dev_info(&icd->dev, | 1033 | dev_info(&icd->dev, |
@@ -1019,21 +1035,17 @@ static int ov772x_video_probe(struct soc_camera_device *icd) | |||
1019 | devname, | 1035 | devname, |
1020 | pid, | 1036 | pid, |
1021 | ver, | 1037 | ver, |
1022 | i2c_smbus_read_byte_data(priv->client, MIDH), | 1038 | i2c_smbus_read_byte_data(client, MIDH), |
1023 | i2c_smbus_read_byte_data(priv->client, MIDL)); | 1039 | i2c_smbus_read_byte_data(client, MIDL)); |
1024 | |||
1025 | return soc_camera_video_start(icd); | ||
1026 | } | ||
1027 | 1040 | ||
1028 | static void ov772x_video_remove(struct soc_camera_device *icd) | ||
1029 | { | ||
1030 | soc_camera_video_stop(icd); | 1041 | soc_camera_video_stop(icd); |
1042 | |||
1043 | ever: | ||
1044 | return ret; | ||
1031 | } | 1045 | } |
1032 | 1046 | ||
1033 | static struct soc_camera_ops ov772x_ops = { | 1047 | static struct soc_camera_ops ov772x_ops = { |
1034 | .owner = THIS_MODULE, | 1048 | .owner = THIS_MODULE, |
1035 | .probe = ov772x_video_probe, | ||
1036 | .remove = ov772x_video_remove, | ||
1037 | .init = ov772x_init, | 1049 | .init = ov772x_init, |
1038 | .release = ov772x_release, | 1050 | .release = ov772x_release, |
1039 | .start_capture = ov772x_start_capture, | 1051 | .start_capture = ov772x_start_capture, |
@@ -1059,19 +1071,25 @@ static struct soc_camera_ops ov772x_ops = { | |||
1059 | */ | 1071 | */ |
1060 | 1072 | ||
1061 | static int ov772x_probe(struct i2c_client *client, | 1073 | static int ov772x_probe(struct i2c_client *client, |
1062 | const struct i2c_device_id *did) | 1074 | const struct i2c_device_id *did) |
1063 | { | 1075 | { |
1064 | struct ov772x_priv *priv; | 1076 | struct ov772x_priv *priv; |
1065 | struct ov772x_camera_info *info; | 1077 | struct ov772x_camera_info *info; |
1066 | struct soc_camera_device *icd; | 1078 | struct soc_camera_device *icd = client->dev.platform_data; |
1067 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); | 1079 | struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); |
1080 | struct soc_camera_link *icl; | ||
1068 | int ret; | 1081 | int ret; |
1069 | 1082 | ||
1070 | if (!client->dev.platform_data) | 1083 | if (!icd) { |
1084 | dev_err(&client->dev, "MT9M001: missing soc-camera data!\n"); | ||
1071 | return -EINVAL; | 1085 | return -EINVAL; |
1086 | } | ||
1072 | 1087 | ||
1073 | info = container_of(client->dev.platform_data, | 1088 | icl = to_soc_camera_link(icd); |
1074 | struct ov772x_camera_info, link); | 1089 | if (!icl) |
1090 | return -EINVAL; | ||
1091 | |||
1092 | info = container_of(icl, struct ov772x_camera_info, link); | ||
1075 | 1093 | ||
1076 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { | 1094 | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { |
1077 | dev_err(&adapter->dev, | 1095 | dev_err(&adapter->dev, |
@@ -1085,19 +1103,15 @@ static int ov772x_probe(struct i2c_client *client, | |||
1085 | return -ENOMEM; | 1103 | return -ENOMEM; |
1086 | 1104 | ||
1087 | priv->info = info; | 1105 | priv->info = info; |
1088 | priv->client = client; | ||
1089 | i2c_set_clientdata(client, priv); | 1106 | i2c_set_clientdata(client, priv); |
1090 | 1107 | ||
1091 | icd = &priv->icd; | ||
1092 | icd->ops = &ov772x_ops; | 1108 | icd->ops = &ov772x_ops; |
1093 | icd->control = &client->dev; | ||
1094 | icd->width_max = MAX_WIDTH; | 1109 | icd->width_max = MAX_WIDTH; |
1095 | icd->height_max = MAX_HEIGHT; | 1110 | icd->height_max = MAX_HEIGHT; |
1096 | icd->iface = priv->info->link.bus_id; | ||
1097 | |||
1098 | ret = soc_camera_device_register(icd); | ||
1099 | 1111 | ||
1112 | ret = ov772x_video_probe(icd, client); | ||
1100 | if (ret) { | 1113 | if (ret) { |
1114 | icd->ops = NULL; | ||
1101 | i2c_set_clientdata(client, NULL); | 1115 | i2c_set_clientdata(client, NULL); |
1102 | kfree(priv); | 1116 | kfree(priv); |
1103 | } | 1117 | } |
@@ -1108,8 +1122,9 @@ static int ov772x_probe(struct i2c_client *client, | |||
1108 | static int ov772x_remove(struct i2c_client *client) | 1122 | static int ov772x_remove(struct i2c_client *client) |
1109 | { | 1123 | { |
1110 | struct ov772x_priv *priv = i2c_get_clientdata(client); | 1124 | struct ov772x_priv *priv = i2c_get_clientdata(client); |
1125 | struct soc_camera_device *icd = client->dev.platform_data; | ||
1111 | 1126 | ||
1112 | soc_camera_device_unregister(&priv->icd); | 1127 | icd->ops = NULL; |
1113 | i2c_set_clientdata(client, NULL); | 1128 | i2c_set_clientdata(client, NULL); |
1114 | kfree(priv); | 1129 | kfree(priv); |
1115 | return 0; | 1130 | return 0; |