aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pwc/pwc-ctrl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pwc/pwc-ctrl.c')
-rw-r--r--drivers/media/video/pwc/pwc-ctrl.c729
1 files changed, 93 insertions, 636 deletions
diff --git a/drivers/media/video/pwc/pwc-ctrl.c b/drivers/media/video/pwc/pwc-ctrl.c
index 9d800c66807..8e0cc537e1e 100644
--- a/drivers/media/video/pwc/pwc-ctrl.c
+++ b/drivers/media/video/pwc/pwc-ctrl.c
@@ -3,6 +3,7 @@
3 video modes. 3 video modes.
4 (C) 1999-2003 Nemosoft Unv. 4 (C) 1999-2003 Nemosoft Unv.
5 (C) 2004-2006 Luc Saillard (luc@saillard.org) 5 (C) 2004-2006 Luc Saillard (luc@saillard.org)
6 (C) 2011 Hans de Goede <hdegoede@redhat.com>
6 7
7 NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx 8 NOTE: this version of pwc is an unofficial (modified) release of pwc & pcwx
8 driver and thus may have bugs that are not present in the original version. 9 driver and thus may have bugs that are not present in the original version.
@@ -49,55 +50,7 @@
49#include "pwc-dec1.h" 50#include "pwc-dec1.h"
50#include "pwc-dec23.h" 51#include "pwc-dec23.h"
51 52
52/* Request types: video */ 53/* Selectors for status controls used only in this file */
53#define SET_LUM_CTL 0x01
54#define GET_LUM_CTL 0x02
55#define SET_CHROM_CTL 0x03
56#define GET_CHROM_CTL 0x04
57#define SET_STATUS_CTL 0x05
58#define GET_STATUS_CTL 0x06
59#define SET_EP_STREAM_CTL 0x07
60#define GET_EP_STREAM_CTL 0x08
61#define GET_XX_CTL 0x09
62#define SET_XX_CTL 0x0A
63#define GET_XY_CTL 0x0B
64#define SET_XY_CTL 0x0C
65#define SET_MPT_CTL 0x0D
66#define GET_MPT_CTL 0x0E
67
68/* Selectors for the Luminance controls [GS]ET_LUM_CTL */
69#define AGC_MODE_FORMATTER 0x2000
70#define PRESET_AGC_FORMATTER 0x2100
71#define SHUTTER_MODE_FORMATTER 0x2200
72#define PRESET_SHUTTER_FORMATTER 0x2300
73#define PRESET_CONTOUR_FORMATTER 0x2400
74#define AUTO_CONTOUR_FORMATTER 0x2500
75#define BACK_LIGHT_COMPENSATION_FORMATTER 0x2600
76#define CONTRAST_FORMATTER 0x2700
77#define DYNAMIC_NOISE_CONTROL_FORMATTER 0x2800
78#define FLICKERLESS_MODE_FORMATTER 0x2900
79#define AE_CONTROL_SPEED 0x2A00
80#define BRIGHTNESS_FORMATTER 0x2B00
81#define GAMMA_FORMATTER 0x2C00
82
83/* Selectors for the Chrominance controls [GS]ET_CHROM_CTL */
84#define WB_MODE_FORMATTER 0x1000
85#define AWB_CONTROL_SPEED_FORMATTER 0x1100
86#define AWB_CONTROL_DELAY_FORMATTER 0x1200
87#define PRESET_MANUAL_RED_GAIN_FORMATTER 0x1300
88#define PRESET_MANUAL_BLUE_GAIN_FORMATTER 0x1400
89#define COLOUR_MODE_FORMATTER 0x1500
90#define SATURATION_MODE_FORMATTER1 0x1600
91#define SATURATION_MODE_FORMATTER2 0x1700
92
93/* Selectors for the Status controls [GS]ET_STATUS_CTL */
94#define SAVE_USER_DEFAULTS_FORMATTER 0x0200
95#define RESTORE_USER_DEFAULTS_FORMATTER 0x0300
96#define RESTORE_FACTORY_DEFAULTS_FORMATTER 0x0400
97#define READ_AGC_FORMATTER 0x0500
98#define READ_SHUTTER_FORMATTER 0x0600
99#define READ_RED_GAIN_FORMATTER 0x0700
100#define READ_BLUE_GAIN_FORMATTER 0x0800
101#define GET_STATUS_B00 0x0B00 54#define GET_STATUS_B00 0x0B00
102#define SENSOR_TYPE_FORMATTER1 0x0C00 55#define SENSOR_TYPE_FORMATTER1 0x0C00
103#define GET_STATUS_3000 0x3000 56#define GET_STATUS_3000 0x3000
@@ -116,11 +69,6 @@
116/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */ 69/* Formatters for the Video Endpoint controls [GS]ET_EP_STREAM_CTL */
117#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100 70#define VIDEO_OUTPUT_CONTROL_FORMATTER 0x0100
118 71
119/* Formatters for the motorized pan & tilt [GS]ET_MPT_CTL */
120#define PT_RELATIVE_CONTROL_FORMATTER 0x01
121#define PT_RESET_CONTROL_FORMATTER 0x02
122#define PT_STATUS_FORMATTER 0x03
123
124static const char *size2name[PSZ_MAX] = 72static const char *size2name[PSZ_MAX] =
125{ 73{
126 "subQCIF", 74 "subQCIF",
@@ -160,7 +108,7 @@ static void pwc_set_image_buffer_size(struct pwc_device *pdev);
160/****************************************************************************/ 108/****************************************************************************/
161 109
162static int _send_control_msg(struct pwc_device *pdev, 110static int _send_control_msg(struct pwc_device *pdev,
163 u8 request, u16 value, int index, void *buf, int buflen, int timeout) 111 u8 request, u16 value, int index, void *buf, int buflen)
164{ 112{
165 int rc; 113 int rc;
166 void *kbuf = NULL; 114 void *kbuf = NULL;
@@ -177,7 +125,7 @@ static int _send_control_msg(struct pwc_device *pdev,
177 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 125 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
178 value, 126 value,
179 index, 127 index,
180 kbuf, buflen, timeout); 128 kbuf, buflen, USB_CTRL_SET_TIMEOUT);
181 129
182 kfree(kbuf); 130 kfree(kbuf);
183 return rc; 131 return rc;
@@ -197,9 +145,13 @@ static int recv_control_msg(struct pwc_device *pdev,
197 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, 145 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
198 value, 146 value,
199 pdev->vcinterface, 147 pdev->vcinterface,
200 kbuf, buflen, 500); 148 kbuf, buflen, USB_CTRL_GET_TIMEOUT);
201 memcpy(buf, kbuf, buflen); 149 memcpy(buf, kbuf, buflen);
202 kfree(kbuf); 150 kfree(kbuf);
151
152 if (rc < 0)
153 PWC_ERROR("recv_control_msg error %d req %02x val %04x\n",
154 rc, request, value);
203 return rc; 155 return rc;
204} 156}
205 157
@@ -210,18 +162,16 @@ static inline int send_video_command(struct pwc_device *pdev,
210 SET_EP_STREAM_CTL, 162 SET_EP_STREAM_CTL,
211 VIDEO_OUTPUT_CONTROL_FORMATTER, 163 VIDEO_OUTPUT_CONTROL_FORMATTER,
212 index, 164 index,
213 buf, buflen, 1000); 165 buf, buflen);
214} 166}
215 167
216static inline int send_control_msg(struct pwc_device *pdev, 168static inline int send_control_msg(struct pwc_device *pdev,
217 u8 request, u16 value, void *buf, int buflen) 169 u8 request, u16 value, void *buf, int buflen)
218{ 170{
219 return _send_control_msg(pdev, 171 return _send_control_msg(pdev,
220 request, value, pdev->vcinterface, buf, buflen, 500); 172 request, value, pdev->vcinterface, buf, buflen);
221} 173}
222 174
223
224
225static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames) 175static int set_video_mode_Nala(struct pwc_device *pdev, int size, int frames)
226{ 176{
227 unsigned char buf[3]; 177 unsigned char buf[3];
@@ -549,246 +499,78 @@ static void pwc_set_image_buffer_size(struct pwc_device *pdev)
549 pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE; 499 pdev->offset.y = ((pdev->view.y - pdev->image.y) / 2) & 0xFFFE;
550} 500}
551 501
552/* BRIGHTNESS */ 502int pwc_get_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
553int pwc_get_brightness(struct pwc_device *pdev)
554{ 503{
555 char buf;
556 int ret; 504 int ret;
505 u8 buf;
557 506
558 ret = recv_control_msg(pdev, 507 ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
559 GET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf));
560 if (ret < 0) 508 if (ret < 0)
561 return ret; 509 return ret;
562 return buf;
563}
564
565int pwc_set_brightness(struct pwc_device *pdev, int value)
566{
567 char buf;
568 510
569 if (value < 0) 511 *data = buf;
570 value = 0; 512 return 0;
571 if (value > 0xffff)
572 value = 0xffff;
573 buf = (value >> 9) & 0x7f;
574 return send_control_msg(pdev,
575 SET_LUM_CTL, BRIGHTNESS_FORMATTER, &buf, sizeof(buf));
576} 513}
577 514
578/* CONTRAST */ 515int pwc_set_u8_ctrl(struct pwc_device *pdev, u8 request, u16 value, u8 data)
579
580int pwc_get_contrast(struct pwc_device *pdev)
581{ 516{
582 char buf;
583 int ret; 517 int ret;
584 518
585 ret = recv_control_msg(pdev, 519 ret = send_control_msg(pdev, request, value, &data, sizeof(data));
586 GET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf));
587 if (ret < 0) 520 if (ret < 0)
588 return ret; 521 return ret;
589 return buf;
590}
591 522
592int pwc_set_contrast(struct pwc_device *pdev, int value) 523 return 0;
593{
594 char buf;
595
596 if (value < 0)
597 value = 0;
598 if (value > 0xffff)
599 value = 0xffff;
600 buf = (value >> 10) & 0x3f;
601 return send_control_msg(pdev,
602 SET_LUM_CTL, CONTRAST_FORMATTER, &buf, sizeof(buf));
603} 524}
604 525
605/* GAMMA */ 526int pwc_get_s8_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
606
607int pwc_get_gamma(struct pwc_device *pdev)
608{ 527{
609 char buf;
610 int ret; 528 int ret;
529 s8 buf;
611 530
612 ret = recv_control_msg(pdev, 531 ret = recv_control_msg(pdev, request, value, &buf, sizeof(buf));
613 GET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf));
614 if (ret < 0) 532 if (ret < 0)
615 return ret; 533 return ret;
616 return buf;
617}
618
619int pwc_set_gamma(struct pwc_device *pdev, int value)
620{
621 char buf;
622
623 if (value < 0)
624 value = 0;
625 if (value > 0xffff)
626 value = 0xffff;
627 buf = (value >> 11) & 0x1f;
628 return send_control_msg(pdev,
629 SET_LUM_CTL, GAMMA_FORMATTER, &buf, sizeof(buf));
630}
631
632
633/* SATURATION */
634
635/* return a value between [-100 , 100] */
636int pwc_get_saturation(struct pwc_device *pdev, int *value)
637{
638 char buf;
639 int ret, saturation_register;
640 534
641 if (pdev->type < 675) 535 *data = buf;
642 return -EINVAL;
643 if (pdev->type < 730)
644 saturation_register = SATURATION_MODE_FORMATTER2;
645 else
646 saturation_register = SATURATION_MODE_FORMATTER1;
647 ret = recv_control_msg(pdev,
648 GET_CHROM_CTL, saturation_register, &buf, sizeof(buf));
649 if (ret < 0)
650 return ret;
651 *value = (signed)buf;
652 return 0; 536 return 0;
653} 537}
654 538
655/* @param value saturation color between [-100 , 100] */ 539int pwc_get_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, int *data)
656int pwc_set_saturation(struct pwc_device *pdev, int value)
657{
658 char buf;
659 int saturation_register;
660
661 if (pdev->type < 675)
662 return -EINVAL;
663 if (value < -100)
664 value = -100;
665 if (value > 100)
666 value = 100;
667 if (pdev->type < 730)
668 saturation_register = SATURATION_MODE_FORMATTER2;
669 else
670 saturation_register = SATURATION_MODE_FORMATTER1;
671 return send_control_msg(pdev,
672 SET_CHROM_CTL, saturation_register, &buf, sizeof(buf));
673}
674
675/* AGC */
676
677int pwc_set_agc(struct pwc_device *pdev, int mode, int value)
678{ 540{
679 char buf;
680 int ret; 541 int ret;
542 u8 buf[2];
681 543
682 if (mode) 544 ret = recv_control_msg(pdev, request, value, buf, sizeof(buf));
683 buf = 0x0; /* auto */
684 else
685 buf = 0xff; /* fixed */
686
687 ret = send_control_msg(pdev,
688 SET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf));
689
690 if (!mode && ret >= 0) {
691 if (value < 0)
692 value = 0;
693 if (value > 0xffff)
694 value = 0xffff;
695 buf = (value >> 10) & 0x3F;
696 ret = send_control_msg(pdev,
697 SET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf));
698 }
699 if (ret < 0) 545 if (ret < 0)
700 return ret; 546 return ret;
547
548 *data = (buf[1] << 8) | buf[0];
701 return 0; 549 return 0;
702} 550}
703 551
704int pwc_get_agc(struct pwc_device *pdev, int *value) 552int pwc_set_u16_ctrl(struct pwc_device *pdev, u8 request, u16 value, u16 data)
705{ 553{
706 unsigned char buf;
707 int ret; 554 int ret;
555 u8 buf[2];
708 556
709 ret = recv_control_msg(pdev, 557 buf[0] = data & 0xff;
710 GET_LUM_CTL, AGC_MODE_FORMATTER, &buf, sizeof(buf)); 558 buf[1] = data >> 8;
559 ret = send_control_msg(pdev, request, value, buf, sizeof(buf));
711 if (ret < 0) 560 if (ret < 0)
712 return ret; 561 return ret;
713 562
714 if (buf != 0) { /* fixed */
715 ret = recv_control_msg(pdev,
716 GET_LUM_CTL, PRESET_AGC_FORMATTER, &buf, sizeof(buf));
717 if (ret < 0)
718 return ret;
719 if (buf > 0x3F)
720 buf = 0x3F;
721 *value = (buf << 10);
722 }
723 else { /* auto */
724 ret = recv_control_msg(pdev,
725 GET_STATUS_CTL, READ_AGC_FORMATTER, &buf, sizeof(buf));
726 if (ret < 0)
727 return ret;
728 /* Gah... this value ranges from 0x00 ... 0x9F */
729 if (buf > 0x9F)
730 buf = 0x9F;
731 *value = -(48 + buf * 409);
732 }
733
734 return 0; 563 return 0;
735} 564}
736 565
737int pwc_set_shutter_speed(struct pwc_device *pdev, int mode, int value) 566int pwc_button_ctrl(struct pwc_device *pdev, u16 value)
738{
739 char buf[2];
740 int speed, ret;
741
742
743 if (mode)
744 buf[0] = 0x0; /* auto */
745 else
746 buf[0] = 0xff; /* fixed */
747
748 ret = send_control_msg(pdev,
749 SET_LUM_CTL, SHUTTER_MODE_FORMATTER, &buf, 1);
750
751 if (!mode && ret >= 0) {
752 if (value < 0)
753 value = 0;
754 if (value > 0xffff)
755 value = 0xffff;
756
757 if (DEVICE_USE_CODEC2(pdev->type)) {
758 /* speed ranges from 0x0 to 0x290 (656) */
759 speed = (value / 100);
760 buf[1] = speed >> 8;
761 buf[0] = speed & 0xff;
762 } else if (DEVICE_USE_CODEC3(pdev->type)) {
763 /* speed seems to range from 0x0 to 0xff */
764 buf[1] = 0;
765 buf[0] = value >> 8;
766 }
767
768 ret = send_control_msg(pdev,
769 SET_LUM_CTL, PRESET_SHUTTER_FORMATTER,
770 &buf, sizeof(buf));
771 }
772 return ret;
773}
774
775/* This function is not exported to v4l1, so output values between 0 -> 256 */
776int pwc_get_shutter_speed(struct pwc_device *pdev, int *value)
777{ 567{
778 unsigned char buf[2];
779 int ret; 568 int ret;
780 569
781 ret = recv_control_msg(pdev, 570 ret = send_control_msg(pdev, SET_STATUS_CTL, value, NULL, 0);
782 GET_STATUS_CTL, READ_SHUTTER_FORMATTER, &buf, sizeof(buf));
783 if (ret < 0) 571 if (ret < 0)
784 return ret; 572 return ret;
785 *value = buf[0] + (buf[1] << 8); 573
786 if (DEVICE_USE_CODEC2(pdev->type)) {
787 /* speed ranges from 0x0 to 0x290 (656) */
788 *value *= 256/656;
789 } else if (DEVICE_USE_CODEC3(pdev->type)) {
790 /* speed seems to range from 0x0 to 0xff */
791 }
792 return 0; 574 return 0;
793} 575}
794 576
@@ -817,162 +599,6 @@ void pwc_camera_power(struct pwc_device *pdev, int power)
817 power ? "on" : "off", r); 599 power ? "on" : "off", r);
818} 600}
819 601
820/* private calls */
821int pwc_restore_user(struct pwc_device *pdev)
822{
823 return send_control_msg(pdev,
824 SET_STATUS_CTL, RESTORE_USER_DEFAULTS_FORMATTER, NULL, 0);
825}
826
827int pwc_save_user(struct pwc_device *pdev)
828{
829 return send_control_msg(pdev,
830 SET_STATUS_CTL, SAVE_USER_DEFAULTS_FORMATTER, NULL, 0);
831}
832
833int pwc_restore_factory(struct pwc_device *pdev)
834{
835 return send_control_msg(pdev,
836 SET_STATUS_CTL, RESTORE_FACTORY_DEFAULTS_FORMATTER, NULL, 0);
837}
838
839 /* ************************************************* */
840 /* Patch by Alvarado: (not in the original version */
841
842 /*
843 * the camera recognizes modes from 0 to 4:
844 *
845 * 00: indoor (incandescant lighting)
846 * 01: outdoor (sunlight)
847 * 02: fluorescent lighting
848 * 03: manual
849 * 04: auto
850 */
851int pwc_set_awb(struct pwc_device *pdev, int mode)
852{
853 char buf;
854 int ret;
855
856 if (mode < 0)
857 mode = 0;
858
859 if (mode > 4)
860 mode = 4;
861
862 buf = mode & 0x07; /* just the lowest three bits */
863
864 ret = send_control_msg(pdev,
865 SET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf));
866
867 if (ret < 0)
868 return ret;
869 return 0;
870}
871
872int pwc_get_awb(struct pwc_device *pdev)
873{
874 unsigned char buf;
875 int ret;
876
877 ret = recv_control_msg(pdev,
878 GET_CHROM_CTL, WB_MODE_FORMATTER, &buf, sizeof(buf));
879
880 if (ret < 0)
881 return ret;
882 return buf;
883}
884
885int pwc_set_red_gain(struct pwc_device *pdev, int value)
886{
887 unsigned char buf;
888
889 if (value < 0)
890 value = 0;
891 if (value > 0xffff)
892 value = 0xffff;
893 /* only the msb is considered */
894 buf = value >> 8;
895 return send_control_msg(pdev,
896 SET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER,
897 &buf, sizeof(buf));
898}
899
900int pwc_get_red_gain(struct pwc_device *pdev, int *value)
901{
902 unsigned char buf;
903 int ret;
904
905 ret = recv_control_msg(pdev,
906 GET_CHROM_CTL, PRESET_MANUAL_RED_GAIN_FORMATTER,
907 &buf, sizeof(buf));
908 if (ret < 0)
909 return ret;
910 *value = buf << 8;
911 return 0;
912}
913
914
915int pwc_set_blue_gain(struct pwc_device *pdev, int value)
916{
917 unsigned char buf;
918
919 if (value < 0)
920 value = 0;
921 if (value > 0xffff)
922 value = 0xffff;
923 /* only the msb is considered */
924 buf = value >> 8;
925 return send_control_msg(pdev,
926 SET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER,
927 &buf, sizeof(buf));
928}
929
930int pwc_get_blue_gain(struct pwc_device *pdev, int *value)
931{
932 unsigned char buf;
933 int ret;
934
935 ret = recv_control_msg(pdev,
936 GET_CHROM_CTL, PRESET_MANUAL_BLUE_GAIN_FORMATTER,
937 &buf, sizeof(buf));
938 if (ret < 0)
939 return ret;
940 *value = buf << 8;
941 return 0;
942}
943
944
945/* The following two functions are different, since they only read the
946 internal red/blue gains, which may be different from the manual
947 gains set or read above.
948 */
949static int pwc_read_red_gain(struct pwc_device *pdev, int *value)
950{
951 unsigned char buf;
952 int ret;
953
954 ret = recv_control_msg(pdev,
955 GET_STATUS_CTL, READ_RED_GAIN_FORMATTER, &buf, sizeof(buf));
956 if (ret < 0)
957 return ret;
958 *value = buf << 8;
959 return 0;
960}
961
962static int pwc_read_blue_gain(struct pwc_device *pdev, int *value)
963{
964 unsigned char buf;
965 int ret;
966
967 ret = recv_control_msg(pdev,
968 GET_STATUS_CTL, READ_BLUE_GAIN_FORMATTER, &buf, sizeof(buf));
969 if (ret < 0)
970 return ret;
971 *value = buf << 8;
972 return 0;
973}
974
975
976static int pwc_set_wb_speed(struct pwc_device *pdev, int speed) 602static int pwc_set_wb_speed(struct pwc_device *pdev, int speed)
977{ 603{
978 unsigned char buf; 604 unsigned char buf;
@@ -1070,164 +696,6 @@ static int pwc_get_leds(struct pwc_device *pdev, int *on_value, int *off_value)
1070 return 0; 696 return 0;
1071} 697}
1072 698
1073int pwc_set_contour(struct pwc_device *pdev, int contour)
1074{
1075 unsigned char buf;
1076 int ret;
1077
1078 if (contour < 0)
1079 buf = 0xff; /* auto contour on */
1080 else
1081 buf = 0x0; /* auto contour off */
1082 ret = send_control_msg(pdev,
1083 SET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf));
1084 if (ret < 0)
1085 return ret;
1086
1087 if (contour < 0)
1088 return 0;
1089 if (contour > 0xffff)
1090 contour = 0xffff;
1091
1092 buf = (contour >> 10); /* contour preset is [0..3f] */
1093 ret = send_control_msg(pdev,
1094 SET_LUM_CTL, PRESET_CONTOUR_FORMATTER, &buf, sizeof(buf));
1095 if (ret < 0)
1096 return ret;
1097 return 0;
1098}
1099
1100int pwc_get_contour(struct pwc_device *pdev, int *contour)
1101{
1102 unsigned char buf;
1103 int ret;
1104
1105 ret = recv_control_msg(pdev,
1106 GET_LUM_CTL, AUTO_CONTOUR_FORMATTER, &buf, sizeof(buf));
1107 if (ret < 0)
1108 return ret;
1109
1110 if (buf == 0) {
1111 /* auto mode off, query current preset value */
1112 ret = recv_control_msg(pdev,
1113 GET_LUM_CTL, PRESET_CONTOUR_FORMATTER,
1114 &buf, sizeof(buf));
1115 if (ret < 0)
1116 return ret;
1117 *contour = buf << 10;
1118 }
1119 else
1120 *contour = -1;
1121 return 0;
1122}
1123
1124
1125int pwc_set_backlight(struct pwc_device *pdev, int backlight)
1126{
1127 unsigned char buf;
1128
1129 if (backlight)
1130 buf = 0xff;
1131 else
1132 buf = 0x0;
1133 return send_control_msg(pdev,
1134 SET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER,
1135 &buf, sizeof(buf));
1136}
1137
1138int pwc_get_backlight(struct pwc_device *pdev, int *backlight)
1139{
1140 int ret;
1141 unsigned char buf;
1142
1143 ret = recv_control_msg(pdev,
1144 GET_LUM_CTL, BACK_LIGHT_COMPENSATION_FORMATTER,
1145 &buf, sizeof(buf));
1146 if (ret < 0)
1147 return ret;
1148 *backlight = !!buf;
1149 return 0;
1150}
1151
1152int pwc_set_colour_mode(struct pwc_device *pdev, int colour)
1153{
1154 unsigned char buf;
1155
1156 if (colour)
1157 buf = 0xff;
1158 else
1159 buf = 0x0;
1160 return send_control_msg(pdev,
1161 SET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf));
1162}
1163
1164int pwc_get_colour_mode(struct pwc_device *pdev, int *colour)
1165{
1166 int ret;
1167 unsigned char buf;
1168
1169 ret = recv_control_msg(pdev,
1170 GET_CHROM_CTL, COLOUR_MODE_FORMATTER, &buf, sizeof(buf));
1171 if (ret < 0)
1172 return ret;
1173 *colour = !!buf;
1174 return 0;
1175}
1176
1177
1178int pwc_set_flicker(struct pwc_device *pdev, int flicker)
1179{
1180 unsigned char buf;
1181
1182 if (flicker)
1183 buf = 0xff;
1184 else
1185 buf = 0x0;
1186 return send_control_msg(pdev,
1187 SET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf));
1188}
1189
1190int pwc_get_flicker(struct pwc_device *pdev, int *flicker)
1191{
1192 int ret;
1193 unsigned char buf;
1194
1195 ret = recv_control_msg(pdev,
1196 GET_LUM_CTL, FLICKERLESS_MODE_FORMATTER, &buf, sizeof(buf));
1197 if (ret < 0)
1198 return ret;
1199 *flicker = !!buf;
1200 return 0;
1201}
1202
1203int pwc_set_dynamic_noise(struct pwc_device *pdev, int noise)
1204{
1205 unsigned char buf;
1206
1207 if (noise < 0)
1208 noise = 0;
1209 if (noise > 3)
1210 noise = 3;
1211 buf = noise;
1212 return send_control_msg(pdev,
1213 SET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER,
1214 &buf, sizeof(buf));
1215}
1216
1217int pwc_get_dynamic_noise(struct pwc_device *pdev, int *noise)
1218{
1219 int ret;
1220 unsigned char buf;
1221
1222 ret = recv_control_msg(pdev,
1223 GET_LUM_CTL, DYNAMIC_NOISE_CONTROL_FORMATTER,
1224 &buf, sizeof(buf));
1225 if (ret < 0)
1226 return ret;
1227 *noise = buf;
1228 return 0;
1229}
1230
1231static int _pwc_mpt_reset(struct pwc_device *pdev, int flags) 699static int _pwc_mpt_reset(struct pwc_device *pdev, int flags)
1232{ 700{
1233 unsigned char buf; 701 unsigned char buf;
@@ -1357,37 +825,41 @@ int pwc_get_cmos_sensor(struct pwc_device *pdev, int *sensor)
1357/* copy local variable to arg */ 825/* copy local variable to arg */
1358#define ARG_OUT(ARG_name) /* nothing */ 826#define ARG_OUT(ARG_name) /* nothing */
1359 827
828/*
829 * Our ctrls use native values, but the old custom pwc ioctl interface expects
830 * values from 0 - 65535, define 2 helper functions to scale things. */
831static int pwc_ioctl_g_ctrl(struct v4l2_ctrl *ctrl)
832{
833 return v4l2_ctrl_g_ctrl(ctrl) * 65535 / ctrl->maximum;
834}
835
836static int pwc_ioctl_s_ctrl(struct v4l2_ctrl *ctrl, int val)
837{
838 return v4l2_ctrl_s_ctrl(ctrl, val * ctrl->maximum / 65535);
839}
840
1360long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg) 841long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1361{ 842{
1362 long ret = 0; 843 long ret = 0;
1363 844
1364 switch(cmd) { 845 switch(cmd) {
1365 case VIDIOCPWCRUSER: 846 case VIDIOCPWCRUSER:
1366 { 847 ret = pwc_button_ctrl(pdev, RESTORE_USER_DEFAULTS_FORMATTER);
1367 if (pwc_restore_user(pdev))
1368 ret = -EINVAL;
1369 break; 848 break;
1370 }
1371 849
1372 case VIDIOCPWCSUSER: 850 case VIDIOCPWCSUSER:
1373 { 851 ret = pwc_button_ctrl(pdev, SAVE_USER_DEFAULTS_FORMATTER);
1374 if (pwc_save_user(pdev))
1375 ret = -EINVAL;
1376 break; 852 break;
1377 }
1378 853
1379 case VIDIOCPWCFACTORY: 854 case VIDIOCPWCFACTORY:
1380 { 855 ret = pwc_button_ctrl(pdev, RESTORE_FACTORY_DEFAULTS_FORMATTER);
1381 if (pwc_restore_factory(pdev))
1382 ret = -EINVAL;
1383 break; 856 break;
1384 }
1385 857
1386 case VIDIOCPWCSCQUAL: 858 case VIDIOCPWCSCQUAL:
1387 { 859 {
1388 ARG_DEF(int, qual) 860 ARG_DEF(int, qual)
1389 861
1390 if (pdev->iso_init) { 862 if (vb2_is_streaming(&pdev->vb_queue)) {
1391 ret = -EBUSY; 863 ret = -EBUSY;
1392 break; 864 break;
1393 } 865 }
@@ -1431,71 +903,59 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1431 case VIDIOCPWCSAGC: 903 case VIDIOCPWCSAGC:
1432 { 904 {
1433 ARG_DEF(int, agc) 905 ARG_DEF(int, agc)
1434
1435 ARG_IN(agc) 906 ARG_IN(agc)
1436 if (pwc_set_agc(pdev, ARGR(agc) < 0 ? 1 : 0, ARGR(agc))) 907 ret = v4l2_ctrl_s_ctrl(pdev->autogain, ARGR(agc) < 0);
1437 ret = -EINVAL; 908 if (ret == 0 && ARGR(agc) >= 0)
909 ret = pwc_ioctl_s_ctrl(pdev->gain, ARGR(agc));
1438 break; 910 break;
1439 } 911 }
1440 912
1441 case VIDIOCPWCGAGC: 913 case VIDIOCPWCGAGC:
1442 { 914 {
1443 ARG_DEF(int, agc) 915 ARG_DEF(int, agc)
1444 916 if (v4l2_ctrl_g_ctrl(pdev->autogain))
1445 if (pwc_get_agc(pdev, ARGA(agc))) 917 ARGR(agc) = -1;
1446 ret = -EINVAL; 918 else
919 ARGR(agc) = pwc_ioctl_g_ctrl(pdev->gain);
1447 ARG_OUT(agc) 920 ARG_OUT(agc)
1448 break; 921 break;
1449 } 922 }
1450 923
1451 case VIDIOCPWCSSHUTTER: 924 case VIDIOCPWCSSHUTTER:
1452 { 925 {
1453 ARG_DEF(int, shutter_speed) 926 ARG_DEF(int, shutter)
1454 927 ARG_IN(shutter)
1455 ARG_IN(shutter_speed) 928 ret = v4l2_ctrl_s_ctrl(pdev->exposure_auto,
1456 ret = pwc_set_shutter_speed(pdev, ARGR(shutter_speed) < 0 ? 1 : 0, ARGR(shutter_speed)); 929 /* Menu idx 0 = auto, idx 1 = manual */
930 ARGR(shutter) >= 0);
931 if (ret == 0 && ARGR(shutter) >= 0)
932 ret = pwc_ioctl_s_ctrl(pdev->exposure, ARGR(shutter));
1457 break; 933 break;
1458 } 934 }
1459 935
1460 case VIDIOCPWCSAWB: 936 case VIDIOCPWCSAWB:
1461 { 937 {
1462 ARG_DEF(struct pwc_whitebalance, wb) 938 ARG_DEF(struct pwc_whitebalance, wb)
1463
1464 ARG_IN(wb) 939 ARG_IN(wb)
1465 ret = pwc_set_awb(pdev, ARGR(wb).mode); 940 ret = v4l2_ctrl_s_ctrl(pdev->auto_white_balance,
1466 if (ret >= 0 && ARGR(wb).mode == PWC_WB_MANUAL) { 941 ARGR(wb).mode);
1467 pwc_set_red_gain(pdev, ARGR(wb).manual_red); 942 if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL)
1468 pwc_set_blue_gain(pdev, ARGR(wb).manual_blue); 943 ret = pwc_ioctl_s_ctrl(pdev->red_balance,
1469 } 944 ARGR(wb).manual_red);
945 if (ret == 0 && ARGR(wb).mode == PWC_WB_MANUAL)
946 ret = pwc_ioctl_s_ctrl(pdev->blue_balance,
947 ARGR(wb).manual_blue);
1470 break; 948 break;
1471 } 949 }
1472 950
1473 case VIDIOCPWCGAWB: 951 case VIDIOCPWCGAWB:
1474 { 952 {
1475 ARG_DEF(struct pwc_whitebalance, wb) 953 ARG_DEF(struct pwc_whitebalance, wb)
1476 954 ARGR(wb).mode = v4l2_ctrl_g_ctrl(pdev->auto_white_balance);
1477 memset(ARGA(wb), 0, sizeof(struct pwc_whitebalance)); 955 ARGR(wb).manual_red = ARGR(wb).read_red =
1478 ARGR(wb).mode = pwc_get_awb(pdev); 956 pwc_ioctl_g_ctrl(pdev->red_balance);
1479 if (ARGR(wb).mode < 0) 957 ARGR(wb).manual_blue = ARGR(wb).read_blue =
1480 ret = -EINVAL; 958 pwc_ioctl_g_ctrl(pdev->blue_balance);
1481 else {
1482 if (ARGR(wb).mode == PWC_WB_MANUAL) {
1483 ret = pwc_get_red_gain(pdev, &ARGR(wb).manual_red);
1484 if (ret < 0)
1485 break;
1486 ret = pwc_get_blue_gain(pdev, &ARGR(wb).manual_blue);
1487 if (ret < 0)
1488 break;
1489 }
1490 if (ARGR(wb).mode == PWC_WB_AUTO) {
1491 ret = pwc_read_red_gain(pdev, &ARGR(wb).read_red);
1492 if (ret < 0)
1493 break;
1494 ret = pwc_read_blue_gain(pdev, &ARGR(wb).read_blue);
1495 if (ret < 0)
1496 break;
1497 }
1498 }
1499 ARG_OUT(wb) 959 ARG_OUT(wb)
1500 break; 960 break;
1501 } 961 }
@@ -1549,17 +1009,20 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1549 case VIDIOCPWCSCONTOUR: 1009 case VIDIOCPWCSCONTOUR:
1550 { 1010 {
1551 ARG_DEF(int, contour) 1011 ARG_DEF(int, contour)
1552
1553 ARG_IN(contour) 1012 ARG_IN(contour)
1554 ret = pwc_set_contour(pdev, ARGR(contour)); 1013 ret = v4l2_ctrl_s_ctrl(pdev->autocontour, ARGR(contour) < 0);
1014 if (ret == 0 && ARGR(contour) >= 0)
1015 ret = pwc_ioctl_s_ctrl(pdev->contour, ARGR(contour));
1555 break; 1016 break;
1556 } 1017 }
1557 1018
1558 case VIDIOCPWCGCONTOUR: 1019 case VIDIOCPWCGCONTOUR:
1559 { 1020 {
1560 ARG_DEF(int, contour) 1021 ARG_DEF(int, contour)
1561 1022 if (v4l2_ctrl_g_ctrl(pdev->autocontour))
1562 ret = pwc_get_contour(pdev, ARGA(contour)); 1023 ARGR(contour) = -1;
1024 else
1025 ARGR(contour) = pwc_ioctl_g_ctrl(pdev->contour);
1563 ARG_OUT(contour) 1026 ARG_OUT(contour)
1564 break; 1027 break;
1565 } 1028 }
@@ -1567,17 +1030,15 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1567 case VIDIOCPWCSBACKLIGHT: 1030 case VIDIOCPWCSBACKLIGHT:
1568 { 1031 {
1569 ARG_DEF(int, backlight) 1032 ARG_DEF(int, backlight)
1570
1571 ARG_IN(backlight) 1033 ARG_IN(backlight)
1572 ret = pwc_set_backlight(pdev, ARGR(backlight)); 1034 ret = v4l2_ctrl_s_ctrl(pdev->backlight, ARGR(backlight));
1573 break; 1035 break;
1574 } 1036 }
1575 1037
1576 case VIDIOCPWCGBACKLIGHT: 1038 case VIDIOCPWCGBACKLIGHT:
1577 { 1039 {
1578 ARG_DEF(int, backlight) 1040 ARG_DEF(int, backlight)
1579 1041 ARGR(backlight) = v4l2_ctrl_g_ctrl(pdev->backlight);
1580 ret = pwc_get_backlight(pdev, ARGA(backlight));
1581 ARG_OUT(backlight) 1042 ARG_OUT(backlight)
1582 break; 1043 break;
1583 } 1044 }
@@ -1585,17 +1046,15 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1585 case VIDIOCPWCSFLICKER: 1046 case VIDIOCPWCSFLICKER:
1586 { 1047 {
1587 ARG_DEF(int, flicker) 1048 ARG_DEF(int, flicker)
1588
1589 ARG_IN(flicker) 1049 ARG_IN(flicker)
1590 ret = pwc_set_flicker(pdev, ARGR(flicker)); 1050 ret = v4l2_ctrl_s_ctrl(pdev->flicker, ARGR(flicker));
1591 break; 1051 break;
1592 } 1052 }
1593 1053
1594 case VIDIOCPWCGFLICKER: 1054 case VIDIOCPWCGFLICKER:
1595 { 1055 {
1596 ARG_DEF(int, flicker) 1056 ARG_DEF(int, flicker)
1597 1057 ARGR(flicker) = v4l2_ctrl_g_ctrl(pdev->flicker);
1598 ret = pwc_get_flicker(pdev, ARGA(flicker));
1599 ARG_OUT(flicker) 1058 ARG_OUT(flicker)
1600 break; 1059 break;
1601 } 1060 }
@@ -1603,17 +1062,15 @@ long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg)
1603 case VIDIOCPWCSDYNNOISE: 1062 case VIDIOCPWCSDYNNOISE:
1604 { 1063 {
1605 ARG_DEF(int, dynnoise) 1064 ARG_DEF(int, dynnoise)
1606
1607 ARG_IN(dynnoise) 1065 ARG_IN(dynnoise)
1608 ret = pwc_set_dynamic_noise(pdev, ARGR(dynnoise)); 1066 ret = v4l2_ctrl_s_ctrl(pdev->noise_reduction, ARGR(dynnoise));
1609 break; 1067 break;
1610 } 1068 }
1611 1069
1612 case VIDIOCPWCGDYNNOISE: 1070 case VIDIOCPWCGDYNNOISE:
1613 { 1071 {
1614 ARG_DEF(int, dynnoise) 1072 ARG_DEF(int, dynnoise)
1615 1073 ARGR(dynnoise) = v4l2_ctrl_g_ctrl(pdev->noise_reduction);
1616 ret = pwc_get_dynamic_noise(pdev, ARGA(dynnoise));
1617 ARG_OUT(dynnoise); 1074 ARG_OUT(dynnoise);
1618 break; 1075 break;
1619 } 1076 }