diff options
Diffstat (limited to 'drivers/media/video/gspca/sunplus.c')
-rw-r--r-- | drivers/media/video/gspca/sunplus.c | 237 |
1 files changed, 54 insertions, 183 deletions
diff --git a/drivers/media/video/gspca/sunplus.c b/drivers/media/video/gspca/sunplus.c index c80f0c0c75b6..9ccfcb1c6479 100644 --- a/drivers/media/video/gspca/sunplus.c +++ b/drivers/media/video/gspca/sunplus.c | |||
@@ -30,18 +30,13 @@ MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>"); | |||
30 | MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver"); | 30 | MODULE_DESCRIPTION("GSPCA/SPCA5xx USB Camera Driver"); |
31 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
32 | 32 | ||
33 | #define QUALITY 85 | ||
34 | |||
33 | /* specific webcam descriptor */ | 35 | /* specific webcam descriptor */ |
34 | struct sd { | 36 | struct sd { |
35 | struct gspca_dev gspca_dev; /* !! must be the first item */ | 37 | struct gspca_dev gspca_dev; /* !! must be the first item */ |
36 | 38 | ||
37 | s8 brightness; | 39 | bool autogain; |
38 | u8 contrast; | ||
39 | u8 colors; | ||
40 | u8 autogain; | ||
41 | u8 quality; | ||
42 | #define QUALITY_MIN 70 | ||
43 | #define QUALITY_MAX 95 | ||
44 | #define QUALITY_DEF 85 | ||
45 | 40 | ||
46 | u8 bridge; | 41 | u8 bridge; |
47 | #define BRIDGE_SPCA504 0 | 42 | #define BRIDGE_SPCA504 0 |
@@ -59,75 +54,6 @@ struct sd { | |||
59 | u8 jpeg_hdr[JPEG_HDR_SZ]; | 54 | u8 jpeg_hdr[JPEG_HDR_SZ]; |
60 | }; | 55 | }; |
61 | 56 | ||
62 | /* V4L2 controls supported by the driver */ | ||
63 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val); | ||
64 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val); | ||
65 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val); | ||
66 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val); | ||
67 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val); | ||
68 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val); | ||
69 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val); | ||
70 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val); | ||
71 | |||
72 | static const struct ctrl sd_ctrls[] = { | ||
73 | { | ||
74 | { | ||
75 | .id = V4L2_CID_BRIGHTNESS, | ||
76 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
77 | .name = "Brightness", | ||
78 | .minimum = -128, | ||
79 | .maximum = 127, | ||
80 | .step = 1, | ||
81 | #define BRIGHTNESS_DEF 0 | ||
82 | .default_value = BRIGHTNESS_DEF, | ||
83 | }, | ||
84 | .set = sd_setbrightness, | ||
85 | .get = sd_getbrightness, | ||
86 | }, | ||
87 | { | ||
88 | { | ||
89 | .id = V4L2_CID_CONTRAST, | ||
90 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
91 | .name = "Contrast", | ||
92 | .minimum = 0, | ||
93 | .maximum = 0xff, | ||
94 | .step = 1, | ||
95 | #define CONTRAST_DEF 0x20 | ||
96 | .default_value = CONTRAST_DEF, | ||
97 | }, | ||
98 | .set = sd_setcontrast, | ||
99 | .get = sd_getcontrast, | ||
100 | }, | ||
101 | { | ||
102 | { | ||
103 | .id = V4L2_CID_SATURATION, | ||
104 | .type = V4L2_CTRL_TYPE_INTEGER, | ||
105 | .name = "Color", | ||
106 | .minimum = 0, | ||
107 | .maximum = 0xff, | ||
108 | .step = 1, | ||
109 | #define COLOR_DEF 0x1a | ||
110 | .default_value = COLOR_DEF, | ||
111 | }, | ||
112 | .set = sd_setcolors, | ||
113 | .get = sd_getcolors, | ||
114 | }, | ||
115 | { | ||
116 | { | ||
117 | .id = V4L2_CID_AUTOGAIN, | ||
118 | .type = V4L2_CTRL_TYPE_BOOLEAN, | ||
119 | .name = "Auto Gain", | ||
120 | .minimum = 0, | ||
121 | .maximum = 1, | ||
122 | .step = 1, | ||
123 | #define AUTOGAIN_DEF 1 | ||
124 | .default_value = AUTOGAIN_DEF, | ||
125 | }, | ||
126 | .set = sd_setautogain, | ||
127 | .get = sd_getautogain, | ||
128 | }, | ||
129 | }; | ||
130 | |||
131 | static const struct v4l2_pix_format vga_mode[] = { | 57 | static const struct v4l2_pix_format vga_mode[] = { |
132 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, | 58 | {320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE, |
133 | .bytesperline = 320, | 59 | .bytesperline = 320, |
@@ -597,31 +523,31 @@ static void spca504B_setQtable(struct gspca_dev *gspca_dev) | |||
597 | spca504B_PollingDataReady(gspca_dev); | 523 | spca504B_PollingDataReady(gspca_dev); |
598 | } | 524 | } |
599 | 525 | ||
600 | static void setbrightness(struct gspca_dev *gspca_dev) | 526 | static void setbrightness(struct gspca_dev *gspca_dev, s32 val) |
601 | { | 527 | { |
602 | struct sd *sd = (struct sd *) gspca_dev; | 528 | struct sd *sd = (struct sd *) gspca_dev; |
603 | u16 reg; | 529 | u16 reg; |
604 | 530 | ||
605 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7; | 531 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f0 : 0x21a7; |
606 | reg_w_riv(gspca_dev, 0x00, reg, sd->brightness); | 532 | reg_w_riv(gspca_dev, 0x00, reg, val); |
607 | } | 533 | } |
608 | 534 | ||
609 | static void setcontrast(struct gspca_dev *gspca_dev) | 535 | static void setcontrast(struct gspca_dev *gspca_dev, s32 val) |
610 | { | 536 | { |
611 | struct sd *sd = (struct sd *) gspca_dev; | 537 | struct sd *sd = (struct sd *) gspca_dev; |
612 | u16 reg; | 538 | u16 reg; |
613 | 539 | ||
614 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8; | 540 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f1 : 0x21a8; |
615 | reg_w_riv(gspca_dev, 0x00, reg, sd->contrast); | 541 | reg_w_riv(gspca_dev, 0x00, reg, val); |
616 | } | 542 | } |
617 | 543 | ||
618 | static void setcolors(struct gspca_dev *gspca_dev) | 544 | static void setcolors(struct gspca_dev *gspca_dev, s32 val) |
619 | { | 545 | { |
620 | struct sd *sd = (struct sd *) gspca_dev; | 546 | struct sd *sd = (struct sd *) gspca_dev; |
621 | u16 reg; | 547 | u16 reg; |
622 | 548 | ||
623 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae; | 549 | reg = sd->bridge == BRIDGE_SPCA536 ? 0x20f6 : 0x21ae; |
624 | reg_w_riv(gspca_dev, 0x00, reg, sd->colors); | 550 | reg_w_riv(gspca_dev, 0x00, reg, val); |
625 | } | 551 | } |
626 | 552 | ||
627 | static void init_ctl_reg(struct gspca_dev *gspca_dev) | 553 | static void init_ctl_reg(struct gspca_dev *gspca_dev) |
@@ -629,10 +555,6 @@ static void init_ctl_reg(struct gspca_dev *gspca_dev) | |||
629 | struct sd *sd = (struct sd *) gspca_dev; | 555 | struct sd *sd = (struct sd *) gspca_dev; |
630 | int pollreg = 1; | 556 | int pollreg = 1; |
631 | 557 | ||
632 | setbrightness(gspca_dev); | ||
633 | setcontrast(gspca_dev); | ||
634 | setcolors(gspca_dev); | ||
635 | |||
636 | switch (sd->bridge) { | 558 | switch (sd->bridge) { |
637 | case BRIDGE_SPCA504: | 559 | case BRIDGE_SPCA504: |
638 | case BRIDGE_SPCA504C: | 560 | case BRIDGE_SPCA504C: |
@@ -704,11 +626,6 @@ static int sd_config(struct gspca_dev *gspca_dev, | |||
704 | cam->nmodes = ARRAY_SIZE(vga_mode2); | 626 | cam->nmodes = ARRAY_SIZE(vga_mode2); |
705 | break; | 627 | break; |
706 | } | 628 | } |
707 | sd->brightness = BRIGHTNESS_DEF; | ||
708 | sd->contrast = CONTRAST_DEF; | ||
709 | sd->colors = COLOR_DEF; | ||
710 | sd->autogain = AUTOGAIN_DEF; | ||
711 | sd->quality = QUALITY_DEF; | ||
712 | return 0; | 629 | return 0; |
713 | } | 630 | } |
714 | 631 | ||
@@ -807,7 +724,7 @@ static int sd_start(struct gspca_dev *gspca_dev) | |||
807 | /* create the JPEG header */ | 724 | /* create the JPEG header */ |
808 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, | 725 | jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width, |
809 | 0x22); /* JPEG 411 */ | 726 | 0x22); /* JPEG 411 */ |
810 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | 727 | jpeg_set_qual(sd->jpeg_hdr, QUALITY); |
811 | 728 | ||
812 | if (sd->bridge == BRIDGE_SPCA504B) | 729 | if (sd->bridge == BRIDGE_SPCA504B) |
813 | spca504B_setQtable(gspca_dev); | 730 | spca504B_setQtable(gspca_dev); |
@@ -1012,116 +929,69 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, | |||
1012 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); | 929 | gspca_frame_add(gspca_dev, INTER_PACKET, data, len); |
1013 | } | 930 | } |
1014 | 931 | ||
1015 | static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val) | 932 | static int sd_s_ctrl(struct v4l2_ctrl *ctrl) |
1016 | { | ||
1017 | struct sd *sd = (struct sd *) gspca_dev; | ||
1018 | |||
1019 | sd->brightness = val; | ||
1020 | if (gspca_dev->streaming) | ||
1021 | setbrightness(gspca_dev); | ||
1022 | return gspca_dev->usb_err; | ||
1023 | } | ||
1024 | |||
1025 | static int sd_getbrightness(struct gspca_dev *gspca_dev, __s32 *val) | ||
1026 | { | ||
1027 | struct sd *sd = (struct sd *) gspca_dev; | ||
1028 | |||
1029 | *val = sd->brightness; | ||
1030 | return 0; | ||
1031 | } | ||
1032 | |||
1033 | static int sd_setcontrast(struct gspca_dev *gspca_dev, __s32 val) | ||
1034 | { | 933 | { |
1035 | struct sd *sd = (struct sd *) gspca_dev; | 934 | struct gspca_dev *gspca_dev = |
935 | container_of(ctrl->handler, struct gspca_dev, ctrl_handler); | ||
936 | struct sd *sd = (struct sd *)gspca_dev; | ||
1036 | 937 | ||
1037 | sd->contrast = val; | 938 | gspca_dev->usb_err = 0; |
1038 | if (gspca_dev->streaming) | ||
1039 | setcontrast(gspca_dev); | ||
1040 | return gspca_dev->usb_err; | ||
1041 | } | ||
1042 | 939 | ||
1043 | static int sd_getcontrast(struct gspca_dev *gspca_dev, __s32 *val) | 940 | if (!gspca_dev->streaming) |
1044 | { | 941 | return 0; |
1045 | struct sd *sd = (struct sd *) gspca_dev; | ||
1046 | 942 | ||
1047 | *val = sd->contrast; | 943 | switch (ctrl->id) { |
1048 | return 0; | 944 | case V4L2_CID_BRIGHTNESS: |
1049 | } | 945 | setbrightness(gspca_dev, ctrl->val); |
1050 | 946 | break; | |
1051 | static int sd_setcolors(struct gspca_dev *gspca_dev, __s32 val) | 947 | case V4L2_CID_CONTRAST: |
1052 | { | 948 | setcontrast(gspca_dev, ctrl->val); |
1053 | struct sd *sd = (struct sd *) gspca_dev; | 949 | break; |
1054 | 950 | case V4L2_CID_SATURATION: | |
1055 | sd->colors = val; | 951 | setcolors(gspca_dev, ctrl->val); |
1056 | if (gspca_dev->streaming) | 952 | break; |
1057 | setcolors(gspca_dev); | 953 | case V4L2_CID_AUTOGAIN: |
954 | sd->autogain = ctrl->val; | ||
955 | break; | ||
956 | } | ||
1058 | return gspca_dev->usb_err; | 957 | return gspca_dev->usb_err; |
1059 | } | 958 | } |
1060 | 959 | ||
1061 | static int sd_getcolors(struct gspca_dev *gspca_dev, __s32 *val) | 960 | static const struct v4l2_ctrl_ops sd_ctrl_ops = { |
1062 | { | 961 | .s_ctrl = sd_s_ctrl, |
1063 | struct sd *sd = (struct sd *) gspca_dev; | 962 | }; |
1064 | |||
1065 | *val = sd->colors; | ||
1066 | return 0; | ||
1067 | } | ||
1068 | |||
1069 | static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val) | ||
1070 | { | ||
1071 | struct sd *sd = (struct sd *) gspca_dev; | ||
1072 | |||
1073 | sd->autogain = val; | ||
1074 | return 0; | ||
1075 | } | ||
1076 | |||
1077 | static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val) | ||
1078 | { | ||
1079 | struct sd *sd = (struct sd *) gspca_dev; | ||
1080 | |||
1081 | *val = sd->autogain; | ||
1082 | return 0; | ||
1083 | } | ||
1084 | |||
1085 | static int sd_set_jcomp(struct gspca_dev *gspca_dev, | ||
1086 | struct v4l2_jpegcompression *jcomp) | ||
1087 | { | ||
1088 | struct sd *sd = (struct sd *) gspca_dev; | ||
1089 | |||
1090 | if (jcomp->quality < QUALITY_MIN) | ||
1091 | sd->quality = QUALITY_MIN; | ||
1092 | else if (jcomp->quality > QUALITY_MAX) | ||
1093 | sd->quality = QUALITY_MAX; | ||
1094 | else | ||
1095 | sd->quality = jcomp->quality; | ||
1096 | if (gspca_dev->streaming) | ||
1097 | jpeg_set_qual(sd->jpeg_hdr, sd->quality); | ||
1098 | return gspca_dev->usb_err; | ||
1099 | } | ||
1100 | 963 | ||
1101 | static int sd_get_jcomp(struct gspca_dev *gspca_dev, | 964 | static int sd_init_controls(struct gspca_dev *gspca_dev) |
1102 | struct v4l2_jpegcompression *jcomp) | ||
1103 | { | 965 | { |
1104 | struct sd *sd = (struct sd *) gspca_dev; | 966 | struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler; |
1105 | 967 | ||
1106 | memset(jcomp, 0, sizeof *jcomp); | 968 | gspca_dev->vdev.ctrl_handler = hdl; |
1107 | jcomp->quality = sd->quality; | 969 | v4l2_ctrl_handler_init(hdl, 4); |
1108 | jcomp->jpeg_markers = V4L2_JPEG_MARKER_DHT | 970 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, |
1109 | | V4L2_JPEG_MARKER_DQT; | 971 | V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); |
972 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
973 | V4L2_CID_CONTRAST, 0, 255, 1, 0x20); | ||
974 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
975 | V4L2_CID_SATURATION, 0, 255, 1, 0x1a); | ||
976 | v4l2_ctrl_new_std(hdl, &sd_ctrl_ops, | ||
977 | V4L2_CID_AUTOGAIN, 0, 1, 1, 1); | ||
978 | |||
979 | if (hdl->error) { | ||
980 | pr_err("Could not initialize controls\n"); | ||
981 | return hdl->error; | ||
982 | } | ||
1110 | return 0; | 983 | return 0; |
1111 | } | 984 | } |
1112 | 985 | ||
1113 | /* sub-driver description */ | 986 | /* sub-driver description */ |
1114 | static const struct sd_desc sd_desc = { | 987 | static const struct sd_desc sd_desc = { |
1115 | .name = MODULE_NAME, | 988 | .name = MODULE_NAME, |
1116 | .ctrls = sd_ctrls, | ||
1117 | .nctrls = ARRAY_SIZE(sd_ctrls), | ||
1118 | .config = sd_config, | 989 | .config = sd_config, |
1119 | .init = sd_init, | 990 | .init = sd_init, |
991 | .init_controls = sd_init_controls, | ||
1120 | .start = sd_start, | 992 | .start = sd_start, |
1121 | .stopN = sd_stopN, | 993 | .stopN = sd_stopN, |
1122 | .pkt_scan = sd_pkt_scan, | 994 | .pkt_scan = sd_pkt_scan, |
1123 | .get_jcomp = sd_get_jcomp, | ||
1124 | .set_jcomp = sd_set_jcomp, | ||
1125 | }; | 995 | }; |
1126 | 996 | ||
1127 | /* -- module initialisation -- */ | 997 | /* -- module initialisation -- */ |
@@ -1208,6 +1078,7 @@ static struct usb_driver sd_driver = { | |||
1208 | #ifdef CONFIG_PM | 1078 | #ifdef CONFIG_PM |
1209 | .suspend = gspca_suspend, | 1079 | .suspend = gspca_suspend, |
1210 | .resume = gspca_resume, | 1080 | .resume = gspca_resume, |
1081 | .reset_resume = gspca_resume, | ||
1211 | #endif | 1082 | #endif |
1212 | }; | 1083 | }; |
1213 | 1084 | ||