diff options
Diffstat (limited to 'drivers/media/video')
-rw-r--r-- | drivers/media/video/pwc/pwc-v4l.c | 127 |
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 | ||
631 | static int pwc_set_awb(struct pwc_device *pdev) | 633 | static 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 */ |
685 | static int pwc_set_autogain(struct pwc_device *pdev) | 669 | static 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 */ |
713 | static int pwc_set_exposure_auto(struct pwc_device *pdev) | 698 | static 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 */ |
742 | static int pwc_set_autogain_expo(struct pwc_device *pdev) | 728 | static 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 | ||
783 | static int pwc_set_motor(struct pwc_device *pdev) | 766 | static 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); |