aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video')
-rw-r--r--drivers/media/video/pwc/pwc-v4l.c127
1 files changed, 53 insertions, 74 deletions
diff --git a/drivers/media/video/pwc/pwc-v4l.c b/drivers/media/video/pwc/pwc-v4l.c
index 6873bf50869f..0a41ebbb7bcb 100644
--- a/drivers/media/video/pwc/pwc-v4l.c
+++ b/drivers/media/video/pwc/pwc-v4l.c
@@ -83,6 +83,7 @@ static const struct v4l2_ctrl_config pwc_contour_cfg = {
83 .id = PWC_CID_CUSTOM(contour), 83 .id = PWC_CID_CUSTOM(contour),
84 .type = V4L2_CTRL_TYPE_INTEGER, 84 .type = V4L2_CTRL_TYPE_INTEGER,
85 .name = "Contour", 85 .name = "Contour",
86 .flags = V4L2_CTRL_FLAG_SLIDER,
86 .min = 0, 87 .min = 0,
87 .max = 63, 88 .max = 63,
88 .step = 1, 89 .step = 1,
@@ -206,8 +207,7 @@ int pwc_init_controls(struct pwc_device *pdev)
206 pdev->blue_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops, 207 pdev->blue_balance = v4l2_ctrl_new_std(hdl, &pwc_ctrl_ops,
207 V4L2_CID_BLUE_BALANCE, 0, 255, 1, def); 208 V4L2_CID_BLUE_BALANCE, 0, 255, 1, def);
208 209
209 v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual, 210 v4l2_ctrl_auto_cluster(3, &pdev->auto_white_balance, awb_manual, true);
210 pdev->auto_white_balance->cur.val == awb_auto);
211 211
212 /* autogain, gain */ 212 /* autogain, gain */
213 r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AGC_MODE_FORMATTER, &def); 213 r = pwc_get_u8_ctrl(pdev, GET_LUM_CTL, AGC_MODE_FORMATTER, &def);
@@ -331,12 +331,12 @@ int pwc_init_controls(struct pwc_device *pdev)
331 pdev->restore_user = v4l2_ctrl_new_custom(hdl, &pwc_restore_user_cfg, 331 pdev->restore_user = v4l2_ctrl_new_custom(hdl, &pwc_restore_user_cfg,
332 NULL); 332 NULL);
333 if (pdev->restore_user) 333 if (pdev->restore_user)
334 pdev->restore_user->flags = V4L2_CTRL_FLAG_UPDATE; 334 pdev->restore_user->flags |= V4L2_CTRL_FLAG_UPDATE;
335 pdev->restore_factory = v4l2_ctrl_new_custom(hdl, 335 pdev->restore_factory = v4l2_ctrl_new_custom(hdl,
336 &pwc_restore_factory_cfg, 336 &pwc_restore_factory_cfg,
337 NULL); 337 NULL);
338 if (pdev->restore_factory) 338 if (pdev->restore_factory)
339 pdev->restore_factory->flags = V4L2_CTRL_FLAG_UPDATE; 339 pdev->restore_factory->flags |= V4L2_CTRL_FLAG_UPDATE;
340 340
341 if (!(pdev->features & FEATURE_MOTOR_PANTILT)) 341 if (!(pdev->features & FEATURE_MOTOR_PANTILT))
342 return hdl->error; 342 return hdl->error;
@@ -563,8 +563,10 @@ static int pwc_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
563 563
564 switch (ctrl->id) { 564 switch (ctrl->id) {
565 case V4L2_CID_AUTO_WHITE_BALANCE: 565 case V4L2_CID_AUTO_WHITE_BALANCE:
566 if (pdev->color_bal_valid && time_before(jiffies, 566 if (pdev->color_bal_valid &&
567 pdev->last_color_bal_update + HZ / 4)) { 567 (pdev->auto_white_balance->val != awb_auto ||
568 time_before(jiffies,
569 pdev->last_color_bal_update + HZ / 4))) {
568 pdev->red_balance->val = pdev->last_red_balance; 570 pdev->red_balance->val = pdev->last_red_balance;
569 pdev->blue_balance->val = pdev->last_blue_balance; 571 pdev->blue_balance->val = pdev->last_blue_balance;
570 break; 572 break;
@@ -630,7 +632,7 @@ leave:
630 632
631static int pwc_set_awb(struct pwc_device *pdev) 633static int pwc_set_awb(struct pwc_device *pdev)
632{ 634{
633 int ret = 0; 635 int ret;
634 636
635 if (pdev->auto_white_balance->is_new) { 637 if (pdev->auto_white_balance->is_new) {
636 ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL, 638 ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
@@ -639,52 +641,34 @@ static int pwc_set_awb(struct pwc_device *pdev)
639 if (ret) 641 if (ret)
640 return ret; 642 return ret;
641 643
642 /* Update val when coming from auto or going to a preset */ 644 if (pdev->auto_white_balance->val != awb_manual)
643 if ((pdev->red_balance->flags & V4L2_CTRL_FLAG_VOLATILE) ||
644 pdev->auto_white_balance->val == awb_indoor ||
645 pdev->auto_white_balance->val == awb_outdoor ||
646 pdev->auto_white_balance->val == awb_fl) {
647 if (!pdev->red_balance->is_new)
648 pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
649 READ_RED_GAIN_FORMATTER,
650 &pdev->red_balance->val);
651 if (!pdev->blue_balance->is_new)
652 pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
653 READ_BLUE_GAIN_FORMATTER,
654 &pdev->blue_balance->val);
655 }
656 if (pdev->auto_white_balance->val == awb_auto) {
657 pdev->red_balance->flags |= V4L2_CTRL_FLAG_VOLATILE;
658 pdev->blue_balance->flags |= V4L2_CTRL_FLAG_VOLATILE;
659 pdev->color_bal_valid = false; /* Force cache update */ 645 pdev->color_bal_valid = false; /* Force cache update */
660 } else {
661 pdev->red_balance->flags &= ~V4L2_CTRL_FLAG_VOLATILE;
662 pdev->blue_balance->flags &= ~V4L2_CTRL_FLAG_VOLATILE;
663 }
664 } 646 }
647 if (pdev->auto_white_balance->val != awb_manual)
648 return 0;
665 649
666 if (ret == 0 && pdev->red_balance->is_new) { 650 if (pdev->red_balance->is_new) {
667 if (pdev->auto_white_balance->val != awb_manual)
668 return -EBUSY;
669 ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL, 651 ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
670 PRESET_MANUAL_RED_GAIN_FORMATTER, 652 PRESET_MANUAL_RED_GAIN_FORMATTER,
671 pdev->red_balance->val); 653 pdev->red_balance->val);
654 if (ret)
655 return ret;
672 } 656 }
673 657
674 if (ret == 0 && pdev->blue_balance->is_new) { 658 if (pdev->blue_balance->is_new) {
675 if (pdev->auto_white_balance->val != awb_manual)
676 return -EBUSY;
677 ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL, 659 ret = pwc_set_u8_ctrl(pdev, SET_CHROM_CTL,
678 PRESET_MANUAL_BLUE_GAIN_FORMATTER, 660 PRESET_MANUAL_BLUE_GAIN_FORMATTER,
679 pdev->blue_balance->val); 661 pdev->blue_balance->val);
662 if (ret)
663 return ret;
680 } 664 }
681 return ret; 665 return 0;
682} 666}
683 667
684/* For CODEC2 models which have separate autogain and auto exposure */ 668/* For CODEC2 models which have separate autogain and auto exposure */
685static int pwc_set_autogain(struct pwc_device *pdev) 669static int pwc_set_autogain(struct pwc_device *pdev)
686{ 670{
687 int ret = 0; 671 int ret;
688 672
689 if (pdev->autogain->is_new) { 673 if (pdev->autogain->is_new) {
690 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, 674 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
@@ -692,27 +676,28 @@ static int pwc_set_autogain(struct pwc_device *pdev)
692 pdev->autogain->val ? 0 : 0xff); 676 pdev->autogain->val ? 0 : 0xff);
693 if (ret) 677 if (ret)
694 return ret; 678 return ret;
679
695 if (pdev->autogain->val) 680 if (pdev->autogain->val)
696 pdev->gain_valid = false; /* Force cache update */ 681 pdev->gain_valid = false; /* Force cache update */
697 else if (!pdev->gain->is_new)
698 pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
699 READ_AGC_FORMATTER,
700 &pdev->gain->val);
701 } 682 }
702 if (ret == 0 && pdev->gain->is_new) { 683
703 if (pdev->autogain->val) 684 if (pdev->autogain->val)
704 return -EBUSY; 685 return 0;
686
687 if (pdev->gain->is_new) {
705 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, 688 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
706 PRESET_AGC_FORMATTER, 689 PRESET_AGC_FORMATTER,
707 pdev->gain->val); 690 pdev->gain->val);
691 if (ret)
692 return ret;
708 } 693 }
709 return ret; 694 return 0;
710} 695}
711 696
712/* For CODEC2 models which have separate autogain and auto exposure */ 697/* For CODEC2 models which have separate autogain and auto exposure */
713static int pwc_set_exposure_auto(struct pwc_device *pdev) 698static int pwc_set_exposure_auto(struct pwc_device *pdev)
714{ 699{
715 int ret = 0; 700 int ret;
716 int is_auto = pdev->exposure_auto->val == V4L2_EXPOSURE_AUTO; 701 int is_auto = pdev->exposure_auto->val == V4L2_EXPOSURE_AUTO;
717 702
718 if (pdev->exposure_auto->is_new) { 703 if (pdev->exposure_auto->is_new) {
@@ -721,27 +706,28 @@ static int pwc_set_exposure_auto(struct pwc_device *pdev)
721 is_auto ? 0 : 0xff); 706 is_auto ? 0 : 0xff);
722 if (ret) 707 if (ret)
723 return ret; 708 return ret;
709
724 if (is_auto) 710 if (is_auto)
725 pdev->exposure_valid = false; /* Force cache update */ 711 pdev->exposure_valid = false; /* Force cache update */
726 else if (!pdev->exposure->is_new)
727 pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
728 READ_SHUTTER_FORMATTER,
729 &pdev->exposure->val);
730 } 712 }
731 if (ret == 0 && pdev->exposure->is_new) { 713
732 if (is_auto) 714 if (is_auto)
733 return -EBUSY; 715 return 0;
716
717 if (pdev->exposure->is_new) {
734 ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL, 718 ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
735 PRESET_SHUTTER_FORMATTER, 719 PRESET_SHUTTER_FORMATTER,
736 pdev->exposure->val); 720 pdev->exposure->val);
721 if (ret)
722 return ret;
737 } 723 }
738 return ret; 724 return 0;
739} 725}
740 726
741/* For CODEC3 models which have autogain controlling both gain and exposure */ 727/* For CODEC3 models which have autogain controlling both gain and exposure */
742static int pwc_set_autogain_expo(struct pwc_device *pdev) 728static int pwc_set_autogain_expo(struct pwc_device *pdev)
743{ 729{
744 int ret = 0; 730 int ret;
745 731
746 if (pdev->autogain->is_new) { 732 if (pdev->autogain->is_new) {
747 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, 733 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
@@ -749,35 +735,32 @@ static int pwc_set_autogain_expo(struct pwc_device *pdev)
749 pdev->autogain->val ? 0 : 0xff); 735 pdev->autogain->val ? 0 : 0xff);
750 if (ret) 736 if (ret)
751 return ret; 737 return ret;
738
752 if (pdev->autogain->val) { 739 if (pdev->autogain->val) {
753 pdev->gain_valid = false; /* Force cache update */ 740 pdev->gain_valid = false; /* Force cache update */
754 pdev->exposure_valid = false; /* Force cache update */ 741 pdev->exposure_valid = false; /* Force cache update */
755 } else {
756 if (!pdev->gain->is_new)
757 pwc_get_u8_ctrl(pdev, GET_STATUS_CTL,
758 READ_AGC_FORMATTER,
759 &pdev->gain->val);
760 if (!pdev->exposure->is_new)
761 pwc_get_u16_ctrl(pdev, GET_STATUS_CTL,
762 READ_SHUTTER_FORMATTER,
763 &pdev->exposure->val);
764 } 742 }
765 } 743 }
766 if (ret == 0 && pdev->gain->is_new) { 744
767 if (pdev->autogain->val) 745 if (pdev->autogain->val)
768 return -EBUSY; 746 return 0;
747
748 if (pdev->gain->is_new) {
769 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, 749 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
770 PRESET_AGC_FORMATTER, 750 PRESET_AGC_FORMATTER,
771 pdev->gain->val); 751 pdev->gain->val);
752 if (ret)
753 return ret;
772 } 754 }
773 if (ret == 0 && pdev->exposure->is_new) { 755
774 if (pdev->autogain->val) 756 if (pdev->exposure->is_new) {
775 return -EBUSY;
776 ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL, 757 ret = pwc_set_u16_ctrl(pdev, SET_LUM_CTL,
777 PRESET_SHUTTER_FORMATTER, 758 PRESET_SHUTTER_FORMATTER,
778 pdev->exposure->val); 759 pdev->exposure->val);
760 if (ret)
761 return ret;
779 } 762 }
780 return ret; 763 return 0;
781} 764}
782 765
783static int pwc_set_motor(struct pwc_device *pdev) 766static int pwc_set_motor(struct pwc_device *pdev)
@@ -878,10 +861,6 @@ static int pwc_s_ctrl(struct v4l2_ctrl *ctrl)
878 pdev->autocontour->val ? 0 : 0xff); 861 pdev->autocontour->val ? 0 : 0xff);
879 } 862 }
880 if (ret == 0 && pdev->contour->is_new) { 863 if (ret == 0 && pdev->contour->is_new) {
881 if (pdev->autocontour->val) {
882 ret = -EBUSY;
883 break;
884 }
885 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL, 864 ret = pwc_set_u8_ctrl(pdev, SET_LUM_CTL,
886 PRESET_CONTOUR_FORMATTER, 865 PRESET_CONTOUR_FORMATTER,
887 pdev->contour->val); 866 pdev->contour->val);