1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#include "gspca.h"
17
18
19
20
21
22
23int gspca_expo_autogain(
24 struct gspca_dev *gspca_dev,
25 int avg_lum,
26 int desired_avg_lum,
27 int deadzone,
28 int gain_knee,
29 int exposure_knee)
30{
31 s32 gain, orig_gain, exposure, orig_exposure;
32 int i, steps, retval = 0;
33
34 if (v4l2_ctrl_g_ctrl(gspca_dev->autogain) == 0)
35 return 0;
36
37 orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
38 orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
39
40
41
42 steps = abs(desired_avg_lum - avg_lum) / deadzone;
43
44 gspca_dbg(gspca_dev, D_FRAM, "autogain: lum: %d, desired: %d, steps: %d\n",
45 avg_lum, desired_avg_lum, steps);
46
47 for (i = 0; i < steps; i++) {
48 if (avg_lum > desired_avg_lum) {
49 if (gain > gain_knee)
50 gain--;
51 else if (exposure > exposure_knee)
52 exposure--;
53 else if (gain > gspca_dev->gain->default_value)
54 gain--;
55 else if (exposure > gspca_dev->exposure->minimum)
56 exposure--;
57 else if (gain > gspca_dev->gain->minimum)
58 gain--;
59 else
60 break;
61 } else {
62 if (gain < gspca_dev->gain->default_value)
63 gain++;
64 else if (exposure < exposure_knee)
65 exposure++;
66 else if (gain < gain_knee)
67 gain++;
68 else if (exposure < gspca_dev->exposure->maximum)
69 exposure++;
70 else if (gain < gspca_dev->gain->maximum)
71 gain++;
72 else
73 break;
74 }
75 }
76
77 if (gain != orig_gain) {
78 v4l2_ctrl_s_ctrl(gspca_dev->gain, gain);
79 retval = 1;
80 }
81 if (exposure != orig_exposure) {
82 v4l2_ctrl_s_ctrl(gspca_dev->exposure, exposure);
83 retval = 1;
84 }
85
86 if (retval)
87 gspca_dbg(gspca_dev, D_FRAM, "autogain: changed gain: %d, expo: %d\n",
88 gain, exposure);
89 return retval;
90}
91EXPORT_SYMBOL(gspca_expo_autogain);
92
93
94
95
96
97
98
99
100
101
102
103
104
105int gspca_coarse_grained_expo_autogain(
106 struct gspca_dev *gspca_dev,
107 int avg_lum,
108 int desired_avg_lum,
109 int deadzone)
110{
111 s32 gain_low, gain_high, gain, orig_gain, exposure, orig_exposure;
112 int steps, retval = 0;
113
114 if (v4l2_ctrl_g_ctrl(gspca_dev->autogain) == 0)
115 return 0;
116
117 orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
118 orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
119
120 gain_low = (s32)(gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
121 5 * 2 + gspca_dev->gain->minimum;
122 gain_high = (s32)(gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
123 5 * 4 + gspca_dev->gain->minimum;
124
125
126
127 steps = (desired_avg_lum - avg_lum) / deadzone;
128
129 gspca_dbg(gspca_dev, D_FRAM, "autogain: lum: %d, desired: %d, steps: %d\n",
130 avg_lum, desired_avg_lum, steps);
131
132 if ((gain + steps) > gain_high &&
133 exposure < gspca_dev->exposure->maximum) {
134 gain = gain_high;
135 gspca_dev->exp_too_low_cnt++;
136 gspca_dev->exp_too_high_cnt = 0;
137 } else if ((gain + steps) < gain_low &&
138 exposure > gspca_dev->exposure->minimum) {
139 gain = gain_low;
140 gspca_dev->exp_too_high_cnt++;
141 gspca_dev->exp_too_low_cnt = 0;
142 } else {
143 gain += steps;
144 if (gain > gspca_dev->gain->maximum)
145 gain = gspca_dev->gain->maximum;
146 else if (gain < gspca_dev->gain->minimum)
147 gain = gspca_dev->gain->minimum;
148 gspca_dev->exp_too_high_cnt = 0;
149 gspca_dev->exp_too_low_cnt = 0;
150 }
151
152 if (gspca_dev->exp_too_high_cnt > 3) {
153 exposure--;
154 gspca_dev->exp_too_high_cnt = 0;
155 } else if (gspca_dev->exp_too_low_cnt > 3) {
156 exposure++;
157 gspca_dev->exp_too_low_cnt = 0;
158 }
159
160 if (gain != orig_gain) {
161 v4l2_ctrl_s_ctrl(gspca_dev->gain, gain);
162 retval = 1;
163 }
164 if (exposure != orig_exposure) {
165 v4l2_ctrl_s_ctrl(gspca_dev->exposure, exposure);
166 retval = 1;
167 }
168
169 if (retval)
170 gspca_dbg(gspca_dev, D_FRAM, "autogain: changed gain: %d, expo: %d\n",
171 gain, exposure);
172 return retval;
173}
174EXPORT_SYMBOL(gspca_coarse_grained_expo_autogain);
175