aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/ov772x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/ov772x.c')
-rw-r--r--drivers/media/video/ov772x.c381
1 files changed, 226 insertions, 155 deletions
diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c
index 0bce255168bd..eccb40ab7fec 100644
--- a/drivers/media/video/ov772x.c
+++ b/drivers/media/video/ov772x.c
@@ -22,7 +22,7 @@
22#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/videodev2.h> 23#include <linux/videodev2.h>
24#include <media/v4l2-chip-ident.h> 24#include <media/v4l2-chip-ident.h>
25#include <media/v4l2-common.h> 25#include <media/v4l2-subdev.h>
26#include <media/soc_camera.h> 26#include <media/soc_camera.h>
27#include <media/ov772x.h> 27#include <media/ov772x.h>
28 28
@@ -382,11 +382,10 @@ struct regval_list {
382}; 382};
383 383
384struct ov772x_color_format { 384struct ov772x_color_format {
385 char *name; 385 const struct soc_camera_data_format *format;
386 __u32 fourcc; 386 u8 dsp3;
387 u8 dsp3; 387 u8 com3;
388 u8 com3; 388 u8 com7;
389 u8 com7;
390}; 389};
391 390
392struct ov772x_win_size { 391struct ov772x_win_size {
@@ -398,14 +397,15 @@ struct ov772x_win_size {
398}; 397};
399 398
400struct ov772x_priv { 399struct ov772x_priv {
400 struct v4l2_subdev subdev;
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;
407 unsigned int flag_vflip:1; 405 unsigned short flag_vflip:1;
408 unsigned int flag_hflip:1; 406 unsigned short flag_hflip:1;
407 /* band_filter = COM8[5] ? 256 - BDBASE : 0 */
408 unsigned short band_filter;
409}; 409};
410 410
411#define ENDMARKER { 0xff, 0xff } 411#define ENDMARKER { 0xff, 0xff }
@@ -481,43 +481,43 @@ static const struct soc_camera_data_format ov772x_fmt_lists[] = {
481 */ 481 */
482static const struct ov772x_color_format ov772x_cfmts[] = { 482static const struct ov772x_color_format ov772x_cfmts[] = {
483 { 483 {
484 SETFOURCC(YUYV), 484 .format = &ov772x_fmt_lists[0],
485 .dsp3 = 0x0, 485 .dsp3 = 0x0,
486 .com3 = SWAP_YUV, 486 .com3 = SWAP_YUV,
487 .com7 = OFMT_YUV, 487 .com7 = OFMT_YUV,
488 }, 488 },
489 { 489 {
490 SETFOURCC(YVYU), 490 .format = &ov772x_fmt_lists[1],
491 .dsp3 = UV_ON, 491 .dsp3 = UV_ON,
492 .com3 = SWAP_YUV, 492 .com3 = SWAP_YUV,
493 .com7 = OFMT_YUV, 493 .com7 = OFMT_YUV,
494 }, 494 },
495 { 495 {
496 SETFOURCC(UYVY), 496 .format = &ov772x_fmt_lists[2],
497 .dsp3 = 0x0, 497 .dsp3 = 0x0,
498 .com3 = 0x0, 498 .com3 = 0x0,
499 .com7 = OFMT_YUV, 499 .com7 = OFMT_YUV,
500 }, 500 },
501 { 501 {
502 SETFOURCC(RGB555), 502 .format = &ov772x_fmt_lists[3],
503 .dsp3 = 0x0, 503 .dsp3 = 0x0,
504 .com3 = SWAP_RGB, 504 .com3 = SWAP_RGB,
505 .com7 = FMT_RGB555 | OFMT_RGB, 505 .com7 = FMT_RGB555 | OFMT_RGB,
506 }, 506 },
507 { 507 {
508 SETFOURCC(RGB555X), 508 .format = &ov772x_fmt_lists[4],
509 .dsp3 = 0x0, 509 .dsp3 = 0x0,
510 .com3 = 0x0, 510 .com3 = 0x0,
511 .com7 = FMT_RGB555 | OFMT_RGB, 511 .com7 = FMT_RGB555 | OFMT_RGB,
512 }, 512 },
513 { 513 {
514 SETFOURCC(RGB565), 514 .format = &ov772x_fmt_lists[5],
515 .dsp3 = 0x0, 515 .dsp3 = 0x0,
516 .com3 = SWAP_RGB, 516 .com3 = SWAP_RGB,
517 .com7 = FMT_RGB565 | OFMT_RGB, 517 .com7 = FMT_RGB565 | OFMT_RGB,
518 }, 518 },
519 { 519 {
520 SETFOURCC(RGB565X), 520 .format = &ov772x_fmt_lists[6],
521 .dsp3 = 0x0, 521 .dsp3 = 0x0,
522 .com3 = 0x0, 522 .com3 = 0x0,
523 .com7 = FMT_RGB565 | OFMT_RGB, 523 .com7 = FMT_RGB565 | OFMT_RGB,
@@ -570,6 +570,15 @@ static const struct v4l2_queryctrl ov772x_controls[] = {
570 .step = 1, 570 .step = 1,
571 .default_value = 0, 571 .default_value = 0,
572 }, 572 },
573 {
574 .id = V4L2_CID_BAND_STOP_FILTER,
575 .type = V4L2_CTRL_TYPE_INTEGER,
576 .name = "Band-stop filter",
577 .minimum = 0,
578 .maximum = 256,
579 .step = 1,
580 .default_value = 0,
581 },
573}; 582};
574 583
575 584
@@ -577,6 +586,12 @@ static const struct v4l2_queryctrl ov772x_controls[] = {
577 * general function 586 * general function
578 */ 587 */
579 588
589static struct ov772x_priv *to_ov772x(const struct i2c_client *client)
590{
591 return container_of(i2c_get_clientdata(client), struct ov772x_priv,
592 subdev);
593}
594
580static int ov772x_write_array(struct i2c_client *client, 595static int ov772x_write_array(struct i2c_client *client,
581 const struct regval_list *vals) 596 const struct regval_list *vals)
582{ 597{
@@ -617,58 +632,29 @@ static int ov772x_reset(struct i2c_client *client)
617 * soc_camera_ops function 632 * soc_camera_ops function
618 */ 633 */
619 634
620static int ov772x_init(struct soc_camera_device *icd) 635static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
621{ 636{
622 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); 637 struct i2c_client *client = sd->priv;
623 int ret = 0; 638 struct ov772x_priv *priv = to_ov772x(client);
624 639
625 if (priv->info->link.power) { 640 if (!enable) {
626 ret = priv->info->link.power(&priv->client->dev, 1); 641 ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
627 if (ret < 0) 642 return 0;
628 return ret;
629 } 643 }
630 644
631 if (priv->info->link.reset)
632 ret = priv->info->link.reset(&priv->client->dev);
633
634 return ret;
635}
636
637static int ov772x_release(struct soc_camera_device *icd)
638{
639 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
640 int ret = 0;
641
642 if (priv->info->link.power)
643 ret = priv->info->link.power(&priv->client->dev, 0);
644
645 return ret;
646}
647
648static int ov772x_start_capture(struct soc_camera_device *icd)
649{
650 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
651
652 if (!priv->win || !priv->fmt) { 645 if (!priv->win || !priv->fmt) {
653 dev_err(&icd->dev, "norm or win select error\n"); 646 dev_err(&client->dev, "norm or win select error\n");
654 return -EPERM; 647 return -EPERM;
655 } 648 }
656 649
657 ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, 0); 650 ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0);
658 651
659 dev_dbg(&icd->dev, 652 dev_dbg(&client->dev, "format %s, win %s\n",
660 "format %s, win %s\n", priv->fmt->name, priv->win->name); 653 priv->fmt->format->name, priv->win->name);
661 654
662 return 0; 655 return 0;
663} 656}
664 657
665static int ov772x_stop_capture(struct soc_camera_device *icd)
666{
667 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd);
668 ov772x_mask_set(priv->client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
669 return 0;
670}
671
672static int ov772x_set_bus_param(struct soc_camera_device *icd, 658static int ov772x_set_bus_param(struct soc_camera_device *icd,
673 unsigned long flags) 659 unsigned long flags)
674{ 660{
@@ -677,8 +663,9 @@ static int ov772x_set_bus_param(struct soc_camera_device *icd,
677 663
678static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd) 664static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
679{ 665{
680 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); 666 struct i2c_client *client = to_i2c_client(to_soc_camera_control(icd));
681 struct soc_camera_link *icl = &priv->info->link; 667 struct ov772x_priv *priv = i2c_get_clientdata(client);
668 struct soc_camera_link *icl = to_soc_camera_link(icd);
682 unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER | 669 unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
683 SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH | 670 SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
684 SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth; 671 SOCAM_DATA_ACTIVE_HIGH | priv->info->buswidth;
@@ -686,10 +673,10 @@ static unsigned long ov772x_query_bus_param(struct soc_camera_device *icd)
686 return soc_camera_apply_sensor_flags(icl, flags); 673 return soc_camera_apply_sensor_flags(icl, flags);
687} 674}
688 675
689static int ov772x_get_control(struct soc_camera_device *icd, 676static int ov772x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
690 struct v4l2_control *ctrl)
691{ 677{
692 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); 678 struct i2c_client *client = sd->priv;
679 struct ov772x_priv *priv = to_ov772x(client);
693 680
694 switch (ctrl->id) { 681 switch (ctrl->id) {
695 case V4L2_CID_VFLIP: 682 case V4L2_CID_VFLIP:
@@ -698,14 +685,17 @@ static int ov772x_get_control(struct soc_camera_device *icd,
698 case V4L2_CID_HFLIP: 685 case V4L2_CID_HFLIP:
699 ctrl->value = priv->flag_hflip; 686 ctrl->value = priv->flag_hflip;
700 break; 687 break;
688 case V4L2_CID_BAND_STOP_FILTER:
689 ctrl->value = priv->band_filter;
690 break;
701 } 691 }
702 return 0; 692 return 0;
703} 693}
704 694
705static int ov772x_set_control(struct soc_camera_device *icd, 695static int ov772x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
706 struct v4l2_control *ctrl)
707{ 696{
708 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); 697 struct i2c_client *client = sd->priv;
698 struct ov772x_priv *priv = to_ov772x(client);
709 int ret = 0; 699 int ret = 0;
710 u8 val; 700 u8 val;
711 701
@@ -715,24 +705,48 @@ static int ov772x_set_control(struct soc_camera_device *icd,
715 priv->flag_vflip = ctrl->value; 705 priv->flag_vflip = ctrl->value;
716 if (priv->info->flags & OV772X_FLAG_VFLIP) 706 if (priv->info->flags & OV772X_FLAG_VFLIP)
717 val ^= VFLIP_IMG; 707 val ^= VFLIP_IMG;
718 ret = ov772x_mask_set(priv->client, COM3, VFLIP_IMG, val); 708 ret = ov772x_mask_set(client, COM3, VFLIP_IMG, val);
719 break; 709 break;
720 case V4L2_CID_HFLIP: 710 case V4L2_CID_HFLIP:
721 val = ctrl->value ? HFLIP_IMG : 0x00; 711 val = ctrl->value ? HFLIP_IMG : 0x00;
722 priv->flag_hflip = ctrl->value; 712 priv->flag_hflip = ctrl->value;
723 if (priv->info->flags & OV772X_FLAG_HFLIP) 713 if (priv->info->flags & OV772X_FLAG_HFLIP)
724 val ^= HFLIP_IMG; 714 val ^= HFLIP_IMG;
725 ret = ov772x_mask_set(priv->client, COM3, HFLIP_IMG, val); 715 ret = ov772x_mask_set(client, COM3, HFLIP_IMG, val);
716 break;
717 case V4L2_CID_BAND_STOP_FILTER:
718 if ((unsigned)ctrl->value > 256)
719 ctrl->value = 256;
720 if (ctrl->value == priv->band_filter)
721 break;
722 if (!ctrl->value) {
723 /* Switch the filter off, it is on now */
724 ret = ov772x_mask_set(client, BDBASE, 0xff, 0xff);
725 if (!ret)
726 ret = ov772x_mask_set(client, COM8,
727 BNDF_ON_OFF, 0);
728 } else {
729 /* Switch the filter on, set AEC low limit */
730 val = 256 - ctrl->value;
731 ret = ov772x_mask_set(client, COM8,
732 BNDF_ON_OFF, BNDF_ON_OFF);
733 if (!ret)
734 ret = ov772x_mask_set(client, BDBASE,
735 0xff, val);
736 }
737 if (!ret)
738 priv->band_filter = ctrl->value;
726 break; 739 break;
727 } 740 }
728 741
729 return ret; 742 return ret;
730} 743}
731 744
732static int ov772x_get_chip_id(struct soc_camera_device *icd, 745static int ov772x_g_chip_ident(struct v4l2_subdev *sd,
733 struct v4l2_dbg_chip_ident *id) 746 struct v4l2_dbg_chip_ident *id)
734{ 747{
735 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); 748 struct i2c_client *client = sd->priv;
749 struct ov772x_priv *priv = to_ov772x(client);
736 750
737 id->ident = priv->model; 751 id->ident = priv->model;
738 id->revision = 0; 752 id->revision = 0;
@@ -741,17 +755,17 @@ static int ov772x_get_chip_id(struct soc_camera_device *icd,
741} 755}
742 756
743#ifdef CONFIG_VIDEO_ADV_DEBUG 757#ifdef CONFIG_VIDEO_ADV_DEBUG
744static int ov772x_get_register(struct soc_camera_device *icd, 758static int ov772x_g_register(struct v4l2_subdev *sd,
745 struct v4l2_dbg_register *reg) 759 struct v4l2_dbg_register *reg)
746{ 760{
747 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); 761 struct i2c_client *client = sd->priv;
748 int ret; 762 int ret;
749 763
750 reg->size = 1; 764 reg->size = 1;
751 if (reg->reg > 0xff) 765 if (reg->reg > 0xff)
752 return -EINVAL; 766 return -EINVAL;
753 767
754 ret = i2c_smbus_read_byte_data(priv->client, reg->reg); 768 ret = i2c_smbus_read_byte_data(client, reg->reg);
755 if (ret < 0) 769 if (ret < 0)
756 return ret; 770 return ret;
757 771
@@ -760,21 +774,20 @@ static int ov772x_get_register(struct soc_camera_device *icd,
760 return 0; 774 return 0;
761} 775}
762 776
763static int ov772x_set_register(struct soc_camera_device *icd, 777static int ov772x_s_register(struct v4l2_subdev *sd,
764 struct v4l2_dbg_register *reg) 778 struct v4l2_dbg_register *reg)
765{ 779{
766 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); 780 struct i2c_client *client = sd->priv;
767 781
768 if (reg->reg > 0xff || 782 if (reg->reg > 0xff ||
769 reg->val > 0xff) 783 reg->val > 0xff)
770 return -EINVAL; 784 return -EINVAL;
771 785
772 return i2c_smbus_write_byte_data(priv->client, reg->reg, reg->val); 786 return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
773} 787}
774#endif 788#endif
775 789
776static const struct ov772x_win_size* 790static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height)
777ov772x_select_win(u32 width, u32 height)
778{ 791{
779 __u32 diff; 792 __u32 diff;
780 const struct ov772x_win_size *win; 793 const struct ov772x_win_size *win;
@@ -793,9 +806,10 @@ ov772x_select_win(u32 width, u32 height)
793 return win; 806 return win;
794} 807}
795 808
796static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height, 809static int ov772x_set_params(struct i2c_client *client,
797 u32 pixfmt) 810 u32 *width, u32 *height, u32 pixfmt)
798{ 811{
812 struct ov772x_priv *priv = to_ov772x(client);
799 int ret = -EINVAL; 813 int ret = -EINVAL;
800 u8 val; 814 u8 val;
801 int i; 815 int i;
@@ -805,7 +819,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
805 */ 819 */
806 priv->fmt = NULL; 820 priv->fmt = NULL;
807 for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) { 821 for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) {
808 if (pixfmt == ov772x_cfmts[i].fourcc) { 822 if (pixfmt == ov772x_cfmts[i].format->fourcc) {
809 priv->fmt = ov772x_cfmts + i; 823 priv->fmt = ov772x_cfmts + i;
810 break; 824 break;
811 } 825 }
@@ -816,12 +830,12 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
816 /* 830 /*
817 * select win 831 * select win
818 */ 832 */
819 priv->win = ov772x_select_win(width, height); 833 priv->win = ov772x_select_win(*width, *height);
820 834
821 /* 835 /*
822 * reset hardware 836 * reset hardware
823 */ 837 */
824 ov772x_reset(priv->client); 838 ov772x_reset(client);
825 839
826 /* 840 /*
827 * Edge Ctrl 841 * Edge Ctrl
@@ -835,17 +849,17 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
835 * Remove it when manual mode. 849 * Remove it when manual mode.
836 */ 850 */
837 851
838 ret = ov772x_mask_set(priv->client, DSPAUTO, EDGE_ACTRL, 0x00); 852 ret = ov772x_mask_set(client, DSPAUTO, EDGE_ACTRL, 0x00);
839 if (ret < 0) 853 if (ret < 0)
840 goto ov772x_set_fmt_error; 854 goto ov772x_set_fmt_error;
841 855
842 ret = ov772x_mask_set(priv->client, 856 ret = ov772x_mask_set(client,
843 EDGE_TRSHLD, EDGE_THRESHOLD_MASK, 857 EDGE_TRSHLD, EDGE_THRESHOLD_MASK,
844 priv->info->edgectrl.threshold); 858 priv->info->edgectrl.threshold);
845 if (ret < 0) 859 if (ret < 0)
846 goto ov772x_set_fmt_error; 860 goto ov772x_set_fmt_error;
847 861
848 ret = ov772x_mask_set(priv->client, 862 ret = ov772x_mask_set(client,
849 EDGE_STRNGT, EDGE_STRENGTH_MASK, 863 EDGE_STRNGT, EDGE_STRENGTH_MASK,
850 priv->info->edgectrl.strength); 864 priv->info->edgectrl.strength);
851 if (ret < 0) 865 if (ret < 0)
@@ -857,13 +871,13 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
857 * 871 *
858 * set upper and lower limit 872 * set upper and lower limit
859 */ 873 */
860 ret = ov772x_mask_set(priv->client, 874 ret = ov772x_mask_set(client,
861 EDGE_UPPER, EDGE_UPPER_MASK, 875 EDGE_UPPER, EDGE_UPPER_MASK,
862 priv->info->edgectrl.upper); 876 priv->info->edgectrl.upper);
863 if (ret < 0) 877 if (ret < 0)
864 goto ov772x_set_fmt_error; 878 goto ov772x_set_fmt_error;
865 879
866 ret = ov772x_mask_set(priv->client, 880 ret = ov772x_mask_set(client,
867 EDGE_LOWER, EDGE_LOWER_MASK, 881 EDGE_LOWER, EDGE_LOWER_MASK,
868 priv->info->edgectrl.lower); 882 priv->info->edgectrl.lower);
869 if (ret < 0) 883 if (ret < 0)
@@ -873,7 +887,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
873 /* 887 /*
874 * set size format 888 * set size format
875 */ 889 */
876 ret = ov772x_write_array(priv->client, priv->win->regs); 890 ret = ov772x_write_array(client, priv->win->regs);
877 if (ret < 0) 891 if (ret < 0)
878 goto ov772x_set_fmt_error; 892 goto ov772x_set_fmt_error;
879 893
@@ -882,7 +896,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
882 */ 896 */
883 val = priv->fmt->dsp3; 897 val = priv->fmt->dsp3;
884 if (val) { 898 if (val) {
885 ret = ov772x_mask_set(priv->client, 899 ret = ov772x_mask_set(client,
886 DSP_CTRL3, UV_MASK, val); 900 DSP_CTRL3, UV_MASK, val);
887 if (ret < 0) 901 if (ret < 0)
888 goto ov772x_set_fmt_error; 902 goto ov772x_set_fmt_error;
@@ -901,7 +915,7 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
901 if (priv->flag_hflip) 915 if (priv->flag_hflip)
902 val ^= HFLIP_IMG; 916 val ^= HFLIP_IMG;
903 917
904 ret = ov772x_mask_set(priv->client, 918 ret = ov772x_mask_set(client,
905 COM3, SWAP_MASK | IMG_MASK, val); 919 COM3, SWAP_MASK | IMG_MASK, val);
906 if (ret < 0) 920 if (ret < 0)
907 goto ov772x_set_fmt_error; 921 goto ov772x_set_fmt_error;
@@ -910,47 +924,99 @@ static int ov772x_set_params(struct ov772x_priv *priv, u32 width, u32 height,
910 * set COM7 924 * set COM7
911 */ 925 */
912 val = priv->win->com7_bit | priv->fmt->com7; 926 val = priv->win->com7_bit | priv->fmt->com7;
913 ret = ov772x_mask_set(priv->client, 927 ret = ov772x_mask_set(client,
914 COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK), 928 COM7, (SLCT_MASK | FMT_MASK | OFMT_MASK),
915 val); 929 val);
916 if (ret < 0) 930 if (ret < 0)
917 goto ov772x_set_fmt_error; 931 goto ov772x_set_fmt_error;
918 932
933 /*
934 * set COM8
935 */
936 if (priv->band_filter) {
937 ret = ov772x_mask_set(client, COM8, BNDF_ON_OFF, 1);
938 if (!ret)
939 ret = ov772x_mask_set(client, BDBASE,
940 0xff, 256 - priv->band_filter);
941 if (ret < 0)
942 goto ov772x_set_fmt_error;
943 }
944
945 *width = priv->win->width;
946 *height = priv->win->height;
947
919 return ret; 948 return ret;
920 949
921ov772x_set_fmt_error: 950ov772x_set_fmt_error:
922 951
923 ov772x_reset(priv->client); 952 ov772x_reset(client);
924 priv->win = NULL; 953 priv->win = NULL;
925 priv->fmt = NULL; 954 priv->fmt = NULL;
926 955
927 return ret; 956 return ret;
928} 957}
929 958
930static int ov772x_set_crop(struct soc_camera_device *icd, 959static int ov772x_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
931 struct v4l2_rect *rect)
932{ 960{
933 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); 961 a->c.left = 0;
962 a->c.top = 0;
963 a->c.width = VGA_WIDTH;
964 a->c.height = VGA_HEIGHT;
965 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
934 966
935 if (!priv->fmt) 967 return 0;
936 return -EINVAL; 968}
937 969
938 return ov772x_set_params(priv, rect->width, rect->height, 970static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
939 priv->fmt->fourcc); 971{
972 a->bounds.left = 0;
973 a->bounds.top = 0;
974 a->bounds.width = VGA_WIDTH;
975 a->bounds.height = VGA_HEIGHT;
976 a->defrect = a->bounds;
977 a->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
978 a->pixelaspect.numerator = 1;
979 a->pixelaspect.denominator = 1;
980
981 return 0;
940} 982}
941 983
942static int ov772x_set_fmt(struct soc_camera_device *icd, 984static int ov772x_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
943 struct v4l2_format *f) 985{
986 struct i2c_client *client = sd->priv;
987 struct ov772x_priv *priv = to_ov772x(client);
988 struct v4l2_pix_format *pix = &f->fmt.pix;
989
990 if (!priv->win || !priv->fmt) {
991 u32 width = VGA_WIDTH, height = VGA_HEIGHT;
992 int ret = ov772x_set_params(client, &width, &height,
993 V4L2_PIX_FMT_YUYV);
994 if (ret < 0)
995 return ret;
996 }
997
998 f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
999
1000 pix->width = priv->win->width;
1001 pix->height = priv->win->height;
1002 pix->pixelformat = priv->fmt->format->fourcc;
1003 pix->colorspace = priv->fmt->format->colorspace;
1004 pix->field = V4L2_FIELD_NONE;
1005
1006 return 0;
1007}
1008
1009static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *f)
944{ 1010{
945 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); 1011 struct i2c_client *client = sd->priv;
946 struct v4l2_pix_format *pix = &f->fmt.pix; 1012 struct v4l2_pix_format *pix = &f->fmt.pix;
947 1013
948 return ov772x_set_params(priv, pix->width, pix->height, 1014 return ov772x_set_params(client, &pix->width, &pix->height,
949 pix->pixelformat); 1015 pix->pixelformat);
950} 1016}
951 1017
952static int ov772x_try_fmt(struct soc_camera_device *icd, 1018static int ov772x_try_fmt(struct v4l2_subdev *sd,
953 struct v4l2_format *f) 1019 struct v4l2_format *f)
954{ 1020{
955 struct v4l2_pix_format *pix = &f->fmt.pix; 1021 struct v4l2_pix_format *pix = &f->fmt.pix;
956 const struct ov772x_win_size *win; 1022 const struct ov772x_win_size *win;
@@ -967,9 +1033,10 @@ static int ov772x_try_fmt(struct soc_camera_device *icd,
967 return 0; 1033 return 0;
968} 1034}
969 1035
970static int ov772x_video_probe(struct soc_camera_device *icd) 1036static int ov772x_video_probe(struct soc_camera_device *icd,
1037 struct i2c_client *client)
971{ 1038{
972 struct ov772x_priv *priv = container_of(icd, struct ov772x_priv, icd); 1039 struct ov772x_priv *priv = to_ov772x(client);
973 u8 pid, ver; 1040 u8 pid, ver;
974 const char *devname; 1041 const char *devname;
975 1042
@@ -986,7 +1053,7 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
986 */ 1053 */
987 if (SOCAM_DATAWIDTH_10 != priv->info->buswidth && 1054 if (SOCAM_DATAWIDTH_10 != priv->info->buswidth &&
988 SOCAM_DATAWIDTH_8 != priv->info->buswidth) { 1055 SOCAM_DATAWIDTH_8 != priv->info->buswidth) {
989 dev_err(&icd->dev, "bus width error\n"); 1056 dev_err(&client->dev, "bus width error\n");
990 return -ENODEV; 1057 return -ENODEV;
991 } 1058 }
992 1059
@@ -996,8 +1063,8 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
996 /* 1063 /*
997 * check and show product ID and manufacturer ID 1064 * check and show product ID and manufacturer ID
998 */ 1065 */
999 pid = i2c_smbus_read_byte_data(priv->client, PID); 1066 pid = i2c_smbus_read_byte_data(client, PID);
1000 ver = i2c_smbus_read_byte_data(priv->client, VER); 1067 ver = i2c_smbus_read_byte_data(client, VER);
1001 1068
1002 switch (VERSION(pid, ver)) { 1069 switch (VERSION(pid, ver)) {
1003 case OV7720: 1070 case OV7720:
@@ -1009,69 +1076,77 @@ static int ov772x_video_probe(struct soc_camera_device *icd)
1009 priv->model = V4L2_IDENT_OV7725; 1076 priv->model = V4L2_IDENT_OV7725;
1010 break; 1077 break;
1011 default: 1078 default:
1012 dev_err(&icd->dev, 1079 dev_err(&client->dev,
1013 "Product ID error %x:%x\n", pid, ver); 1080 "Product ID error %x:%x\n", pid, ver);
1014 return -ENODEV; 1081 return -ENODEV;
1015 } 1082 }
1016 1083
1017 dev_info(&icd->dev, 1084 dev_info(&client->dev,
1018 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n", 1085 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
1019 devname, 1086 devname,
1020 pid, 1087 pid,
1021 ver, 1088 ver,
1022 i2c_smbus_read_byte_data(priv->client, MIDH), 1089 i2c_smbus_read_byte_data(client, MIDH),
1023 i2c_smbus_read_byte_data(priv->client, MIDL)); 1090 i2c_smbus_read_byte_data(client, MIDL));
1024
1025 return soc_camera_video_start(icd);
1026}
1027 1091
1028static void ov772x_video_remove(struct soc_camera_device *icd) 1092 return 0;
1029{
1030 soc_camera_video_stop(icd);
1031} 1093}
1032 1094
1033static struct soc_camera_ops ov772x_ops = { 1095static struct soc_camera_ops ov772x_ops = {
1034 .owner = THIS_MODULE,
1035 .probe = ov772x_video_probe,
1036 .remove = ov772x_video_remove,
1037 .init = ov772x_init,
1038 .release = ov772x_release,
1039 .start_capture = ov772x_start_capture,
1040 .stop_capture = ov772x_stop_capture,
1041 .set_crop = ov772x_set_crop,
1042 .set_fmt = ov772x_set_fmt,
1043 .try_fmt = ov772x_try_fmt,
1044 .set_bus_param = ov772x_set_bus_param, 1096 .set_bus_param = ov772x_set_bus_param,
1045 .query_bus_param = ov772x_query_bus_param, 1097 .query_bus_param = ov772x_query_bus_param,
1046 .controls = ov772x_controls, 1098 .controls = ov772x_controls,
1047 .num_controls = ARRAY_SIZE(ov772x_controls), 1099 .num_controls = ARRAY_SIZE(ov772x_controls),
1048 .get_control = ov772x_get_control, 1100};
1049 .set_control = ov772x_set_control, 1101
1050 .get_chip_id = ov772x_get_chip_id, 1102static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = {
1103 .g_ctrl = ov772x_g_ctrl,
1104 .s_ctrl = ov772x_s_ctrl,
1105 .g_chip_ident = ov772x_g_chip_ident,
1051#ifdef CONFIG_VIDEO_ADV_DEBUG 1106#ifdef CONFIG_VIDEO_ADV_DEBUG
1052 .get_register = ov772x_get_register, 1107 .g_register = ov772x_g_register,
1053 .set_register = ov772x_set_register, 1108 .s_register = ov772x_s_register,
1054#endif 1109#endif
1055}; 1110};
1056 1111
1112static struct v4l2_subdev_video_ops ov772x_subdev_video_ops = {
1113 .s_stream = ov772x_s_stream,
1114 .g_fmt = ov772x_g_fmt,
1115 .s_fmt = ov772x_s_fmt,
1116 .try_fmt = ov772x_try_fmt,
1117 .cropcap = ov772x_cropcap,
1118 .g_crop = ov772x_g_crop,
1119};
1120
1121static struct v4l2_subdev_ops ov772x_subdev_ops = {
1122 .core = &ov772x_subdev_core_ops,
1123 .video = &ov772x_subdev_video_ops,
1124};
1125
1057/* 1126/*
1058 * i2c_driver function 1127 * i2c_driver function
1059 */ 1128 */
1060 1129
1061static int ov772x_probe(struct i2c_client *client, 1130static int ov772x_probe(struct i2c_client *client,
1062 const struct i2c_device_id *did) 1131 const struct i2c_device_id *did)
1063{ 1132{
1064 struct ov772x_priv *priv; 1133 struct ov772x_priv *priv;
1065 struct ov772x_camera_info *info; 1134 struct ov772x_camera_info *info;
1066 struct soc_camera_device *icd; 1135 struct soc_camera_device *icd = client->dev.platform_data;
1067 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); 1136 struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
1137 struct soc_camera_link *icl;
1068 int ret; 1138 int ret;
1069 1139
1070 if (!client->dev.platform_data) 1140 if (!icd) {
1141 dev_err(&client->dev, "OV772X: missing soc-camera data!\n");
1071 return -EINVAL; 1142 return -EINVAL;
1143 }
1072 1144
1073 info = container_of(client->dev.platform_data, 1145 icl = to_soc_camera_link(icd);
1074 struct ov772x_camera_info, link); 1146 if (!icl)
1147 return -EINVAL;
1148
1149 info = container_of(icl, struct ov772x_camera_info, link);
1075 1150
1076 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { 1151 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
1077 dev_err(&adapter->dev, 1152 dev_err(&adapter->dev,
@@ -1084,20 +1159,15 @@ static int ov772x_probe(struct i2c_client *client,
1084 if (!priv) 1159 if (!priv)
1085 return -ENOMEM; 1160 return -ENOMEM;
1086 1161
1087 priv->info = info; 1162 priv->info = info;
1088 priv->client = client;
1089 i2c_set_clientdata(client, priv);
1090 1163
1091 icd = &priv->icd; 1164 v4l2_i2c_subdev_init(&priv->subdev, client, &ov772x_subdev_ops);
1092 icd->ops = &ov772x_ops;
1093 icd->control = &client->dev;
1094 icd->width_max = MAX_WIDTH;
1095 icd->height_max = MAX_HEIGHT;
1096 icd->iface = priv->info->link.bus_id;
1097 1165
1098 ret = soc_camera_device_register(icd); 1166 icd->ops = &ov772x_ops;
1099 1167
1168 ret = ov772x_video_probe(icd, client);
1100 if (ret) { 1169 if (ret) {
1170 icd->ops = NULL;
1101 i2c_set_clientdata(client, NULL); 1171 i2c_set_clientdata(client, NULL);
1102 kfree(priv); 1172 kfree(priv);
1103 } 1173 }
@@ -1107,9 +1177,10 @@ static int ov772x_probe(struct i2c_client *client,
1107 1177
1108static int ov772x_remove(struct i2c_client *client) 1178static int ov772x_remove(struct i2c_client *client)
1109{ 1179{
1110 struct ov772x_priv *priv = i2c_get_clientdata(client); 1180 struct ov772x_priv *priv = to_ov772x(client);
1181 struct soc_camera_device *icd = client->dev.platform_data;
1111 1182
1112 soc_camera_device_unregister(&priv->icd); 1183 icd->ops = NULL;
1113 i2c_set_clientdata(client, NULL); 1184 i2c_set_clientdata(client, NULL);
1114 kfree(priv); 1185 kfree(priv);
1115 return 0; 1186 return 0;