Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Video for Linux Two | |
3 | * | |
4 | * A generic video device interface for the LINUX operating system | |
5 | * using a set of device structures/vectors for low level operations. | |
6 | * | |
7 | * This file replaces the videodev.c file that comes with the | |
8 | * regular kernel distribution. | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or | |
11 | * modify it under the terms of the GNU General Public License | |
12 | * as published by the Free Software Foundation; either version | |
13 | * 2 of the License, or (at your option) any later version. | |
14 | * | |
43db48d3 | 15 | * Author: Bill Dirks <bill@thedirks.org> |
1da177e4 LT |
16 | * based on code by Alan Cox, <alan@cymru.net> |
17 | * | |
18 | */ | |
19 | ||
20 | /* | |
21 | * Video capture interface for Linux | |
22 | * | |
23 | * A generic video device interface for the LINUX operating system | |
24 | * using a set of device structures/vectors for low level operations. | |
25 | * | |
26 | * This program is free software; you can redistribute it and/or | |
27 | * modify it under the terms of the GNU General Public License | |
28 | * as published by the Free Software Foundation; either version | |
29 | * 2 of the License, or (at your option) any later version. | |
30 | * | |
d9b01449 | 31 | * Author: Alan Cox, <alan@lxorguk.ukuu.org.uk> |
1da177e4 LT |
32 | * |
33 | * Fixes: | |
34 | */ | |
35 | ||
36 | /* | |
37 | * Video4linux 1/2 integration by Justin Schoeman | |
38 | * <justin@suntiger.ee.up.ac.za> | |
39 | * 2.4 PROCFS support ported from 2.4 kernels by | |
96de0e25 | 40 | * Iñaki García Etxebarria <garetxe@euskalnet.net> |
1da177e4 LT |
41 | * Makefile fix by "W. Michael Petullo" <mike@flyn.org> |
42 | * 2.4 devfs support ported from 2.4 kernels by | |
43 | * Dan Merillat <dan@merillat.org> | |
44 | * Added Gerd Knorrs v4l1 enhancements (Justin Schoeman) | |
45 | */ | |
46 | ||
1da177e4 LT |
47 | #include <linux/module.h> |
48 | #include <linux/types.h> | |
49 | #include <linux/kernel.h> | |
1da177e4 LT |
50 | #include <linux/mm.h> |
51 | #include <linux/string.h> | |
52 | #include <linux/errno.h> | |
f3d092b8 | 53 | #include <linux/i2c.h> |
85e09219 DB |
54 | #if defined(CONFIG_SPI) |
55 | #include <linux/spi/spi.h> | |
56 | #endif | |
1da177e4 LT |
57 | #include <asm/uaccess.h> |
58 | #include <asm/system.h> | |
59 | #include <asm/pgtable.h> | |
60 | #include <asm/io.h> | |
61 | #include <asm/div64.h> | |
401998fa | 62 | #define __OLD_VIDIOC_ /* To allow fixing old calls*/ |
5e453dc7 | 63 | #include <media/v4l2-common.h> |
dd99120c | 64 | #include <media/v4l2-device.h> |
3434eb7e | 65 | #include <media/v4l2-chip-ident.h> |
1da177e4 | 66 | |
33b687cf | 67 | #include <linux/videodev2.h> |
1da177e4 LT |
68 | |
69 | MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr"); | |
70 | MODULE_DESCRIPTION("misc helper functions for v4l2 device drivers"); | |
71 | MODULE_LICENSE("GPL"); | |
72 | ||
73 | /* | |
74 | * | |
75 | * V 4 L 2 D R I V E R H E L P E R A P I | |
76 | * | |
77 | */ | |
78 | ||
79 | /* | |
80 | * Video Standard Operations (contributed by Michael Schimek) | |
81 | */ | |
82 | ||
1da177e4 | 83 | |
1da177e4 LT |
84 | /* ----------------------------------------------------------------- */ |
85 | /* priority handling */ | |
86 | ||
87 | #define V4L2_PRIO_VALID(val) (val == V4L2_PRIORITY_BACKGROUND || \ | |
88 | val == V4L2_PRIORITY_INTERACTIVE || \ | |
89 | val == V4L2_PRIORITY_RECORD) | |
90 | ||
91 | int v4l2_prio_init(struct v4l2_prio_state *global) | |
92 | { | |
93 | memset(global,0,sizeof(*global)); | |
94 | return 0; | |
95 | } | |
057596ee | 96 | EXPORT_SYMBOL(v4l2_prio_init); |
1da177e4 LT |
97 | |
98 | int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local, | |
99 | enum v4l2_priority new) | |
100 | { | |
101 | if (!V4L2_PRIO_VALID(new)) | |
102 | return -EINVAL; | |
103 | if (*local == new) | |
104 | return 0; | |
105 | ||
106 | atomic_inc(&global->prios[new]); | |
107 | if (V4L2_PRIO_VALID(*local)) | |
108 | atomic_dec(&global->prios[*local]); | |
109 | *local = new; | |
110 | return 0; | |
111 | } | |
057596ee | 112 | EXPORT_SYMBOL(v4l2_prio_change); |
1da177e4 LT |
113 | |
114 | int v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local) | |
115 | { | |
116 | return v4l2_prio_change(global,local,V4L2_PRIORITY_DEFAULT); | |
117 | } | |
057596ee | 118 | EXPORT_SYMBOL(v4l2_prio_open); |
1da177e4 LT |
119 | |
120 | int v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority *local) | |
121 | { | |
122 | if (V4L2_PRIO_VALID(*local)) | |
123 | atomic_dec(&global->prios[*local]); | |
124 | return 0; | |
125 | } | |
057596ee | 126 | EXPORT_SYMBOL(v4l2_prio_close); |
1da177e4 LT |
127 | |
128 | enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global) | |
129 | { | |
130 | if (atomic_read(&global->prios[V4L2_PRIORITY_RECORD]) > 0) | |
131 | return V4L2_PRIORITY_RECORD; | |
132 | if (atomic_read(&global->prios[V4L2_PRIORITY_INTERACTIVE]) > 0) | |
133 | return V4L2_PRIORITY_INTERACTIVE; | |
134 | if (atomic_read(&global->prios[V4L2_PRIORITY_BACKGROUND]) > 0) | |
135 | return V4L2_PRIORITY_BACKGROUND; | |
136 | return V4L2_PRIORITY_UNSET; | |
137 | } | |
057596ee | 138 | EXPORT_SYMBOL(v4l2_prio_max); |
1da177e4 LT |
139 | |
140 | int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority *local) | |
141 | { | |
142 | if (*local < v4l2_prio_max(global)) | |
143 | return -EBUSY; | |
144 | return 0; | |
145 | } | |
057596ee | 146 | EXPORT_SYMBOL(v4l2_prio_check); |
1da177e4 LT |
147 | |
148 | /* ----------------------------------------------------------------- */ | |
149 | ||
9cb2318b HV |
150 | /* Helper functions for control handling */ |
151 | ||
152 | /* Check for correctness of the ctrl's value based on the data from | |
153 | struct v4l2_queryctrl and the available menu items. Note that | |
154 | menu_items may be NULL, in that case it is ignored. */ | |
155 | int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl, | |
156 | const char **menu_items) | |
157 | { | |
158 | if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED) | |
159 | return -EINVAL; | |
160 | if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED) | |
161 | return -EBUSY; | |
6b5a9492 HV |
162 | if (qctrl->type == V4L2_CTRL_TYPE_STRING) |
163 | return 0; | |
9cb2318b HV |
164 | if (qctrl->type == V4L2_CTRL_TYPE_BUTTON || |
165 | qctrl->type == V4L2_CTRL_TYPE_INTEGER64 || | |
166 | qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS) | |
167 | return 0; | |
168 | if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum) | |
169 | return -ERANGE; | |
170 | if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) { | |
171 | if (menu_items[ctrl->value] == NULL || | |
172 | menu_items[ctrl->value][0] == '\0') | |
173 | return -EINVAL; | |
174 | } | |
175 | return 0; | |
176 | } | |
057596ee | 177 | EXPORT_SYMBOL(v4l2_ctrl_check); |
9cb2318b HV |
178 | |
179 | /* Returns NULL or a character pointer array containing the menu for | |
180 | the given control ID. The pointer array ends with a NULL pointer. | |
181 | An empty string signifies a menu entry that is invalid. This allows | |
182 | drivers to disable certain options if it is not supported. */ | |
183 | const char **v4l2_ctrl_get_menu(u32 id) | |
184 | { | |
185 | static const char *mpeg_audio_sampling_freq[] = { | |
186 | "44.1 kHz", | |
187 | "48 kHz", | |
188 | "32 kHz", | |
189 | NULL | |
190 | }; | |
191 | static const char *mpeg_audio_encoding[] = { | |
e6b5da88 HV |
192 | "MPEG-1/2 Layer I", |
193 | "MPEG-1/2 Layer II", | |
194 | "MPEG-1/2 Layer III", | |
195 | "MPEG-2/4 AAC", | |
196 | "AC-3", | |
9cb2318b HV |
197 | NULL |
198 | }; | |
199 | static const char *mpeg_audio_l1_bitrate[] = { | |
200 | "32 kbps", | |
201 | "64 kbps", | |
202 | "96 kbps", | |
203 | "128 kbps", | |
204 | "160 kbps", | |
205 | "192 kbps", | |
206 | "224 kbps", | |
207 | "256 kbps", | |
208 | "288 kbps", | |
209 | "320 kbps", | |
210 | "352 kbps", | |
211 | "384 kbps", | |
212 | "416 kbps", | |
213 | "448 kbps", | |
214 | NULL | |
215 | }; | |
216 | static const char *mpeg_audio_l2_bitrate[] = { | |
217 | "32 kbps", | |
218 | "48 kbps", | |
219 | "56 kbps", | |
220 | "64 kbps", | |
221 | "80 kbps", | |
222 | "96 kbps", | |
223 | "112 kbps", | |
224 | "128 kbps", | |
225 | "160 kbps", | |
226 | "192 kbps", | |
227 | "224 kbps", | |
228 | "256 kbps", | |
229 | "320 kbps", | |
230 | "384 kbps", | |
231 | NULL | |
232 | }; | |
233 | static const char *mpeg_audio_l3_bitrate[] = { | |
234 | "32 kbps", | |
235 | "40 kbps", | |
236 | "48 kbps", | |
237 | "56 kbps", | |
238 | "64 kbps", | |
239 | "80 kbps", | |
240 | "96 kbps", | |
241 | "112 kbps", | |
242 | "128 kbps", | |
243 | "160 kbps", | |
244 | "192 kbps", | |
245 | "224 kbps", | |
246 | "256 kbps", | |
247 | "320 kbps", | |
248 | NULL | |
249 | }; | |
e6b5da88 HV |
250 | static const char *mpeg_audio_ac3_bitrate[] = { |
251 | "32 kbps", | |
252 | "40 kbps", | |
253 | "48 kbps", | |
254 | "56 kbps", | |
255 | "64 kbps", | |
256 | "80 kbps", | |
257 | "96 kbps", | |
258 | "112 kbps", | |
259 | "128 kbps", | |
260 | "160 kbps", | |
261 | "192 kbps", | |
262 | "224 kbps", | |
263 | "256 kbps", | |
264 | "320 kbps", | |
265 | "384 kbps", | |
266 | "448 kbps", | |
267 | "512 kbps", | |
268 | "576 kbps", | |
269 | "640 kbps", | |
270 | NULL | |
271 | }; | |
9cb2318b HV |
272 | static const char *mpeg_audio_mode[] = { |
273 | "Stereo", | |
274 | "Joint Stereo", | |
275 | "Dual", | |
276 | "Mono", | |
277 | NULL | |
278 | }; | |
279 | static const char *mpeg_audio_mode_extension[] = { | |
280 | "Bound 4", | |
281 | "Bound 8", | |
282 | "Bound 12", | |
283 | "Bound 16", | |
284 | NULL | |
285 | }; | |
286 | static const char *mpeg_audio_emphasis[] = { | |
287 | "No Emphasis", | |
288 | "50/15 us", | |
289 | "CCITT J17", | |
290 | NULL | |
291 | }; | |
292 | static const char *mpeg_audio_crc[] = { | |
293 | "No CRC", | |
294 | "16-bit CRC", | |
295 | NULL | |
296 | }; | |
297 | static const char *mpeg_video_encoding[] = { | |
298 | "MPEG-1", | |
299 | "MPEG-2", | |
188919ac | 300 | "MPEG-4 AVC", |
9cb2318b HV |
301 | NULL |
302 | }; | |
303 | static const char *mpeg_video_aspect[] = { | |
304 | "1x1", | |
305 | "4x3", | |
306 | "16x9", | |
307 | "2.21x1", | |
308 | NULL | |
309 | }; | |
310 | static const char *mpeg_video_bitrate_mode[] = { | |
311 | "Variable Bitrate", | |
312 | "Constant Bitrate", | |
313 | NULL | |
314 | }; | |
315 | static const char *mpeg_stream_type[] = { | |
316 | "MPEG-2 Program Stream", | |
317 | "MPEG-2 Transport Stream", | |
318 | "MPEG-1 System Stream", | |
319 | "MPEG-2 DVD-compatible Stream", | |
320 | "MPEG-1 VCD-compatible Stream", | |
321 | "MPEG-2 SVCD-compatible Stream", | |
322 | NULL | |
323 | }; | |
8cbde94b HV |
324 | static const char *mpeg_stream_vbi_fmt[] = { |
325 | "No VBI", | |
99523511 | 326 | "Private packet, IVTV format", |
8cbde94b HV |
327 | NULL |
328 | }; | |
74980159 LP |
329 | static const char *camera_power_line_frequency[] = { |
330 | "Disabled", | |
331 | "50 Hz", | |
332 | "60 Hz", | |
333 | NULL | |
334 | }; | |
335 | static const char *camera_exposure_auto[] = { | |
336 | "Auto Mode", | |
337 | "Manual Mode", | |
338 | "Shutter Priority Mode", | |
339 | "Aperture Priority Mode", | |
340 | NULL | |
341 | }; | |
11c469e6 HV |
342 | static const char *colorfx[] = { |
343 | "None", | |
344 | "Black & White", | |
345 | "Sepia", | |
346 | NULL | |
347 | }; | |
fdf82dc2 EV |
348 | static const char *tune_preemphasis[] = { |
349 | "No preemphasis", | |
350 | "50 useconds", | |
351 | "75 useconds", | |
352 | NULL, | |
353 | }; | |
9cb2318b HV |
354 | |
355 | switch (id) { | |
356 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: | |
357 | return mpeg_audio_sampling_freq; | |
358 | case V4L2_CID_MPEG_AUDIO_ENCODING: | |
359 | return mpeg_audio_encoding; | |
360 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: | |
361 | return mpeg_audio_l1_bitrate; | |
362 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | |
363 | return mpeg_audio_l2_bitrate; | |
364 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | |
365 | return mpeg_audio_l3_bitrate; | |
e6b5da88 HV |
366 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: |
367 | return mpeg_audio_ac3_bitrate; | |
9cb2318b HV |
368 | case V4L2_CID_MPEG_AUDIO_MODE: |
369 | return mpeg_audio_mode; | |
370 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | |
371 | return mpeg_audio_mode_extension; | |
372 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: | |
373 | return mpeg_audio_emphasis; | |
374 | case V4L2_CID_MPEG_AUDIO_CRC: | |
375 | return mpeg_audio_crc; | |
376 | case V4L2_CID_MPEG_VIDEO_ENCODING: | |
377 | return mpeg_video_encoding; | |
378 | case V4L2_CID_MPEG_VIDEO_ASPECT: | |
379 | return mpeg_video_aspect; | |
380 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | |
381 | return mpeg_video_bitrate_mode; | |
382 | case V4L2_CID_MPEG_STREAM_TYPE: | |
383 | return mpeg_stream_type; | |
8cbde94b HV |
384 | case V4L2_CID_MPEG_STREAM_VBI_FMT: |
385 | return mpeg_stream_vbi_fmt; | |
74980159 LP |
386 | case V4L2_CID_POWER_LINE_FREQUENCY: |
387 | return camera_power_line_frequency; | |
388 | case V4L2_CID_EXPOSURE_AUTO: | |
389 | return camera_exposure_auto; | |
11c469e6 HV |
390 | case V4L2_CID_COLORFX: |
391 | return colorfx; | |
fdf82dc2 EV |
392 | case V4L2_CID_TUNE_PREEMPHASIS: |
393 | return tune_preemphasis; | |
9cb2318b HV |
394 | default: |
395 | return NULL; | |
396 | } | |
397 | } | |
057596ee | 398 | EXPORT_SYMBOL(v4l2_ctrl_get_menu); |
9cb2318b | 399 | |
69028d70 HV |
400 | /* Return the control name. */ |
401 | const char *v4l2_ctrl_get_name(u32 id) | |
9cb2318b | 402 | { |
69028d70 | 403 | switch (id) { |
9cb2318b | 404 | /* USER controls */ |
74980159 | 405 | case V4L2_CID_USER_CLASS: return "User Controls"; |
81dde91f HV |
406 | case V4L2_CID_BRIGHTNESS: return "Brightness"; |
407 | case V4L2_CID_CONTRAST: return "Contrast"; | |
408 | case V4L2_CID_SATURATION: return "Saturation"; | |
409 | case V4L2_CID_HUE: return "Hue"; | |
74980159 | 410 | case V4L2_CID_AUDIO_VOLUME: return "Volume"; |
74980159 LP |
411 | case V4L2_CID_AUDIO_BALANCE: return "Balance"; |
412 | case V4L2_CID_AUDIO_BASS: return "Bass"; | |
413 | case V4L2_CID_AUDIO_TREBLE: return "Treble"; | |
81dde91f | 414 | case V4L2_CID_AUDIO_MUTE: return "Mute"; |
74980159 | 415 | case V4L2_CID_AUDIO_LOUDNESS: return "Loudness"; |
74980159 LP |
416 | case V4L2_CID_BLACK_LEVEL: return "Black Level"; |
417 | case V4L2_CID_AUTO_WHITE_BALANCE: return "White Balance, Automatic"; | |
418 | case V4L2_CID_DO_WHITE_BALANCE: return "Do White Balance"; | |
419 | case V4L2_CID_RED_BALANCE: return "Red Balance"; | |
420 | case V4L2_CID_BLUE_BALANCE: return "Blue Balance"; | |
421 | case V4L2_CID_GAMMA: return "Gamma"; | |
422 | case V4L2_CID_EXPOSURE: return "Exposure"; | |
423 | case V4L2_CID_AUTOGAIN: return "Gain, Automatic"; | |
424 | case V4L2_CID_GAIN: return "Gain"; | |
425 | case V4L2_CID_HFLIP: return "Horizontal Flip"; | |
426 | case V4L2_CID_VFLIP: return "Vertical Flip"; | |
427 | case V4L2_CID_HCENTER: return "Horizontal Center"; | |
428 | case V4L2_CID_VCENTER: return "Vertical Center"; | |
429 | case V4L2_CID_POWER_LINE_FREQUENCY: return "Power Line Frequency"; | |
430 | case V4L2_CID_HUE_AUTO: return "Hue, Automatic"; | |
431 | case V4L2_CID_WHITE_BALANCE_TEMPERATURE: return "White Balance Temperature"; | |
432 | case V4L2_CID_SHARPNESS: return "Sharpness"; | |
433 | case V4L2_CID_BACKLIGHT_COMPENSATION: return "Backlight Compensation"; | |
434 | case V4L2_CID_CHROMA_AGC: return "Chroma AGC"; | |
f1a4f9ea | 435 | case V4L2_CID_CHROMA_GAIN: return "Chroma Gain"; |
74980159 | 436 | case V4L2_CID_COLOR_KILLER: return "Color Killer"; |
11c469e6 | 437 | case V4L2_CID_COLORFX: return "Color Effects"; |
a3415c15 FS |
438 | case V4L2_CID_AUTOBRIGHTNESS: return "Brightness, Automatic"; |
439 | case V4L2_CID_BAND_STOP_FILTER: return "Band-Stop Filter"; | |
85213630 | 440 | case V4L2_CID_ROTATE: return "Rotate"; |
a3415c15 | 441 | case V4L2_CID_BG_COLOR: return "Background Color"; |
9cb2318b HV |
442 | |
443 | /* MPEG controls */ | |
69028d70 HV |
444 | case V4L2_CID_MPEG_CLASS: return "MPEG Encoder Controls"; |
445 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: return "Audio Sampling Frequency"; | |
446 | case V4L2_CID_MPEG_AUDIO_ENCODING: return "Audio Encoding"; | |
447 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: return "Audio Layer I Bitrate"; | |
448 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: return "Audio Layer II Bitrate"; | |
449 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: return "Audio Layer III Bitrate"; | |
f723af16 | 450 | case V4L2_CID_MPEG_AUDIO_AAC_BITRATE: return "Audio AAC Bitrate"; |
69028d70 HV |
451 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: return "Audio AC-3 Bitrate"; |
452 | case V4L2_CID_MPEG_AUDIO_MODE: return "Audio Stereo Mode"; | |
453 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: return "Audio Stereo Mode Extension"; | |
454 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: return "Audio Emphasis"; | |
455 | case V4L2_CID_MPEG_AUDIO_CRC: return "Audio CRC"; | |
456 | case V4L2_CID_MPEG_AUDIO_MUTE: return "Audio Mute"; | |
457 | case V4L2_CID_MPEG_VIDEO_ENCODING: return "Video Encoding"; | |
458 | case V4L2_CID_MPEG_VIDEO_ASPECT: return "Video Aspect"; | |
459 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: return "Video B Frames"; | |
460 | case V4L2_CID_MPEG_VIDEO_GOP_SIZE: return "Video GOP Size"; | |
461 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: return "Video GOP Closure"; | |
462 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: return "Video Pulldown"; | |
463 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: return "Video Bitrate Mode"; | |
464 | case V4L2_CID_MPEG_VIDEO_BITRATE: return "Video Bitrate"; | |
465 | case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK: return "Video Peak Bitrate"; | |
466 | case V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION: return "Video Temporal Decimation"; | |
467 | case V4L2_CID_MPEG_VIDEO_MUTE: return "Video Mute"; | |
468 | case V4L2_CID_MPEG_VIDEO_MUTE_YUV: return "Video Mute YUV"; | |
469 | case V4L2_CID_MPEG_STREAM_TYPE: return "Stream Type"; | |
470 | case V4L2_CID_MPEG_STREAM_PID_PMT: return "Stream PMT Program ID"; | |
471 | case V4L2_CID_MPEG_STREAM_PID_AUDIO: return "Stream Audio Program ID"; | |
472 | case V4L2_CID_MPEG_STREAM_PID_VIDEO: return "Stream Video Program ID"; | |
473 | case V4L2_CID_MPEG_STREAM_PID_PCR: return "Stream PCR Program ID"; | |
474 | case V4L2_CID_MPEG_STREAM_PES_ID_AUDIO: return "Stream PES Audio ID"; | |
475 | case V4L2_CID_MPEG_STREAM_PES_ID_VIDEO: return "Stream PES Video ID"; | |
476 | case V4L2_CID_MPEG_STREAM_VBI_FMT: return "Stream VBI Format"; | |
9cb2318b | 477 | |
74980159 LP |
478 | /* CAMERA controls */ |
479 | case V4L2_CID_CAMERA_CLASS: return "Camera Controls"; | |
480 | case V4L2_CID_EXPOSURE_AUTO: return "Auto Exposure"; | |
481 | case V4L2_CID_EXPOSURE_ABSOLUTE: return "Exposure Time, Absolute"; | |
482 | case V4L2_CID_EXPOSURE_AUTO_PRIORITY: return "Exposure, Dynamic Framerate"; | |
483 | case V4L2_CID_PAN_RELATIVE: return "Pan, Relative"; | |
484 | case V4L2_CID_TILT_RELATIVE: return "Tilt, Relative"; | |
485 | case V4L2_CID_PAN_RESET: return "Pan, Reset"; | |
486 | case V4L2_CID_TILT_RESET: return "Tilt, Reset"; | |
487 | case V4L2_CID_PAN_ABSOLUTE: return "Pan, Absolute"; | |
488 | case V4L2_CID_TILT_ABSOLUTE: return "Tilt, Absolute"; | |
489 | case V4L2_CID_FOCUS_ABSOLUTE: return "Focus, Absolute"; | |
490 | case V4L2_CID_FOCUS_RELATIVE: return "Focus, Relative"; | |
491 | case V4L2_CID_FOCUS_AUTO: return "Focus, Automatic"; | |
492 | case V4L2_CID_ZOOM_ABSOLUTE: return "Zoom, Absolute"; | |
493 | case V4L2_CID_ZOOM_RELATIVE: return "Zoom, Relative"; | |
494 | case V4L2_CID_ZOOM_CONTINUOUS: return "Zoom, Continuous"; | |
495 | case V4L2_CID_PRIVACY: return "Privacy"; | |
496 | ||
fdf82dc2 EV |
497 | /* FM Radio Modulator control */ |
498 | case V4L2_CID_FM_TX_CLASS: return "FM Radio Modulator Controls"; | |
499 | case V4L2_CID_RDS_TX_DEVIATION: return "RDS Signal Deviation"; | |
500 | case V4L2_CID_RDS_TX_PI: return "RDS Program ID"; | |
501 | case V4L2_CID_RDS_TX_PTY: return "RDS Program Type"; | |
502 | case V4L2_CID_RDS_TX_PS_NAME: return "RDS PS Name"; | |
503 | case V4L2_CID_RDS_TX_RADIO_TEXT: return "RDS Radio Text"; | |
504 | case V4L2_CID_AUDIO_LIMITER_ENABLED: return "Audio Limiter Feature Enabled"; | |
505 | case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: return "Audio Limiter Release Time"; | |
506 | case V4L2_CID_AUDIO_LIMITER_DEVIATION: return "Audio Limiter Deviation"; | |
507 | case V4L2_CID_AUDIO_COMPRESSION_ENABLED: return "Audio Compression Feature Enabled"; | |
508 | case V4L2_CID_AUDIO_COMPRESSION_GAIN: return "Audio Compression Gain"; | |
509 | case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: return "Audio Compression Threshold"; | |
510 | case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: return "Audio Compression Attack Time"; | |
511 | case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: return "Audio Compression Release Time"; | |
512 | case V4L2_CID_PILOT_TONE_ENABLED: return "Pilot Tone Feature Enabled"; | |
513 | case V4L2_CID_PILOT_TONE_DEVIATION: return "Pilot Tone Deviation"; | |
514 | case V4L2_CID_PILOT_TONE_FREQUENCY: return "Pilot Tone Frequency"; | |
515 | case V4L2_CID_TUNE_PREEMPHASIS: return "Pre-emphasis settings"; | |
516 | case V4L2_CID_TUNE_POWER_LEVEL: return "Tune Power Level"; | |
517 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor"; | |
518 | ||
9cb2318b | 519 | default: |
69028d70 | 520 | return NULL; |
9cb2318b | 521 | } |
69028d70 HV |
522 | } |
523 | EXPORT_SYMBOL(v4l2_ctrl_get_name); | |
524 | ||
525 | /* Fill in a struct v4l2_queryctrl */ | |
526 | int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def) | |
527 | { | |
528 | const char *name = v4l2_ctrl_get_name(qctrl->id); | |
529 | ||
530 | qctrl->flags = 0; | |
531 | if (name == NULL) | |
532 | return -EINVAL; | |
533 | ||
9cb2318b HV |
534 | switch (qctrl->id) { |
535 | case V4L2_CID_AUDIO_MUTE: | |
536 | case V4L2_CID_AUDIO_LOUDNESS: | |
74980159 LP |
537 | case V4L2_CID_AUTO_WHITE_BALANCE: |
538 | case V4L2_CID_AUTOGAIN: | |
539 | case V4L2_CID_HFLIP: | |
540 | case V4L2_CID_VFLIP: | |
541 | case V4L2_CID_HUE_AUTO: | |
81dde91f HV |
542 | case V4L2_CID_CHROMA_AGC: |
543 | case V4L2_CID_COLOR_KILLER: | |
5eee72e8 | 544 | case V4L2_CID_MPEG_AUDIO_MUTE: |
01f1e44f | 545 | case V4L2_CID_MPEG_VIDEO_MUTE: |
9cb2318b HV |
546 | case V4L2_CID_MPEG_VIDEO_GOP_CLOSURE: |
547 | case V4L2_CID_MPEG_VIDEO_PULLDOWN: | |
74980159 | 548 | case V4L2_CID_EXPOSURE_AUTO_PRIORITY: |
81dde91f | 549 | case V4L2_CID_FOCUS_AUTO: |
74980159 | 550 | case V4L2_CID_PRIVACY: |
fdf82dc2 EV |
551 | case V4L2_CID_AUDIO_LIMITER_ENABLED: |
552 | case V4L2_CID_AUDIO_COMPRESSION_ENABLED: | |
553 | case V4L2_CID_PILOT_TONE_ENABLED: | |
9cb2318b HV |
554 | qctrl->type = V4L2_CTRL_TYPE_BOOLEAN; |
555 | min = 0; | |
556 | max = step = 1; | |
557 | break; | |
81dde91f HV |
558 | case V4L2_CID_PAN_RESET: |
559 | case V4L2_CID_TILT_RESET: | |
560 | qctrl->type = V4L2_CTRL_TYPE_BUTTON; | |
561 | qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; | |
562 | min = max = step = def = 0; | |
563 | break; | |
74980159 | 564 | case V4L2_CID_POWER_LINE_FREQUENCY: |
9cb2318b HV |
565 | case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ: |
566 | case V4L2_CID_MPEG_AUDIO_ENCODING: | |
567 | case V4L2_CID_MPEG_AUDIO_L1_BITRATE: | |
568 | case V4L2_CID_MPEG_AUDIO_L2_BITRATE: | |
569 | case V4L2_CID_MPEG_AUDIO_L3_BITRATE: | |
e6b5da88 | 570 | case V4L2_CID_MPEG_AUDIO_AC3_BITRATE: |
9cb2318b HV |
571 | case V4L2_CID_MPEG_AUDIO_MODE: |
572 | case V4L2_CID_MPEG_AUDIO_MODE_EXTENSION: | |
573 | case V4L2_CID_MPEG_AUDIO_EMPHASIS: | |
574 | case V4L2_CID_MPEG_AUDIO_CRC: | |
575 | case V4L2_CID_MPEG_VIDEO_ENCODING: | |
576 | case V4L2_CID_MPEG_VIDEO_ASPECT: | |
577 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | |
578 | case V4L2_CID_MPEG_STREAM_TYPE: | |
8cbde94b | 579 | case V4L2_CID_MPEG_STREAM_VBI_FMT: |
74980159 | 580 | case V4L2_CID_EXPOSURE_AUTO: |
11c469e6 | 581 | case V4L2_CID_COLORFX: |
fdf82dc2 | 582 | case V4L2_CID_TUNE_PREEMPHASIS: |
9cb2318b HV |
583 | qctrl->type = V4L2_CTRL_TYPE_MENU; |
584 | step = 1; | |
585 | break; | |
fdf82dc2 EV |
586 | case V4L2_CID_RDS_TX_PS_NAME: |
587 | case V4L2_CID_RDS_TX_RADIO_TEXT: | |
588 | qctrl->type = V4L2_CTRL_TYPE_STRING; | |
589 | break; | |
9cb2318b | 590 | case V4L2_CID_USER_CLASS: |
74980159 | 591 | case V4L2_CID_CAMERA_CLASS: |
9cb2318b | 592 | case V4L2_CID_MPEG_CLASS: |
fdf82dc2 | 593 | case V4L2_CID_FM_TX_CLASS: |
9cb2318b HV |
594 | qctrl->type = V4L2_CTRL_TYPE_CTRL_CLASS; |
595 | qctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; | |
596 | min = max = step = def = 0; | |
597 | break; | |
85213630 VH |
598 | case V4L2_CID_BG_COLOR: |
599 | qctrl->type = V4L2_CTRL_TYPE_INTEGER; | |
600 | step = 1; | |
601 | min = 0; | |
602 | /* Max is calculated as RGB888 that is 2^24 */ | |
603 | max = 0xFFFFFF; | |
604 | break; | |
9cb2318b HV |
605 | default: |
606 | qctrl->type = V4L2_CTRL_TYPE_INTEGER; | |
607 | break; | |
608 | } | |
609 | switch (qctrl->id) { | |
610 | case V4L2_CID_MPEG_AUDIO_ENCODING: | |
611 | case V4L2_CID_MPEG_AUDIO_MODE: | |
612 | case V4L2_CID_MPEG_VIDEO_BITRATE_MODE: | |
613 | case V4L2_CID_MPEG_VIDEO_B_FRAMES: | |
614 | case V4L2_CID_MPEG_STREAM_TYPE: | |
615 | qctrl->flags |= V4L2_CTRL_FLAG_UPDATE; | |
616 | break; | |
617 | case V4L2_CID_AUDIO_VOLUME: | |
618 | case V4L2_CID_AUDIO_BALANCE: | |
619 | case V4L2_CID_AUDIO_BASS: | |
620 | case V4L2_CID_AUDIO_TREBLE: | |
621 | case V4L2_CID_BRIGHTNESS: | |
622 | case V4L2_CID_CONTRAST: | |
623 | case V4L2_CID_SATURATION: | |
624 | case V4L2_CID_HUE: | |
81dde91f HV |
625 | case V4L2_CID_RED_BALANCE: |
626 | case V4L2_CID_BLUE_BALANCE: | |
627 | case V4L2_CID_GAMMA: | |
8c84cfda | 628 | case V4L2_CID_SHARPNESS: |
f1a4f9ea | 629 | case V4L2_CID_CHROMA_GAIN: |
fdf82dc2 EV |
630 | case V4L2_CID_RDS_TX_DEVIATION: |
631 | case V4L2_CID_AUDIO_LIMITER_RELEASE_TIME: | |
632 | case V4L2_CID_AUDIO_LIMITER_DEVIATION: | |
633 | case V4L2_CID_AUDIO_COMPRESSION_GAIN: | |
634 | case V4L2_CID_AUDIO_COMPRESSION_THRESHOLD: | |
635 | case V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME: | |
636 | case V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME: | |
637 | case V4L2_CID_PILOT_TONE_DEVIATION: | |
638 | case V4L2_CID_PILOT_TONE_FREQUENCY: | |
639 | case V4L2_CID_TUNE_POWER_LEVEL: | |
640 | case V4L2_CID_TUNE_ANTENNA_CAPACITOR: | |
9cb2318b HV |
641 | qctrl->flags |= V4L2_CTRL_FLAG_SLIDER; |
642 | break; | |
81dde91f HV |
643 | case V4L2_CID_PAN_RELATIVE: |
644 | case V4L2_CID_TILT_RELATIVE: | |
645 | case V4L2_CID_FOCUS_RELATIVE: | |
646 | case V4L2_CID_ZOOM_RELATIVE: | |
647 | qctrl->flags |= V4L2_CTRL_FLAG_WRITE_ONLY; | |
648 | break; | |
9cb2318b HV |
649 | } |
650 | qctrl->minimum = min; | |
651 | qctrl->maximum = max; | |
652 | qctrl->step = step; | |
653 | qctrl->default_value = def; | |
654 | qctrl->reserved[0] = qctrl->reserved[1] = 0; | |
b634a93f | 655 | strlcpy(qctrl->name, name, sizeof(qctrl->name)); |
9cb2318b HV |
656 | return 0; |
657 | } | |
057596ee | 658 | EXPORT_SYMBOL(v4l2_ctrl_query_fill); |
9cb2318b | 659 | |
9cb2318b | 660 | /* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and |
e281db58 HV |
661 | the menu. The qctrl pointer may be NULL, in which case it is ignored. |
662 | If menu_items is NULL, then the menu items are retrieved using | |
663 | v4l2_ctrl_get_menu. */ | |
9cb2318b HV |
664 | int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl, |
665 | const char **menu_items) | |
666 | { | |
667 | int i; | |
668 | ||
1e551266 | 669 | qmenu->reserved = 0; |
e281db58 HV |
670 | if (menu_items == NULL) |
671 | menu_items = v4l2_ctrl_get_menu(qmenu->id); | |
9cb2318b HV |
672 | if (menu_items == NULL || |
673 | (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum))) | |
674 | return -EINVAL; | |
675 | for (i = 0; i < qmenu->index && menu_items[i]; i++) ; | |
676 | if (menu_items[i] == NULL || menu_items[i][0] == '\0') | |
677 | return -EINVAL; | |
b634a93f | 678 | strlcpy(qmenu->name, menu_items[qmenu->index], sizeof(qmenu->name)); |
9cb2318b HV |
679 | return 0; |
680 | } | |
057596ee | 681 | EXPORT_SYMBOL(v4l2_ctrl_query_menu); |
9cb2318b | 682 | |
1e551266 HV |
683 | /* Fill in a struct v4l2_querymenu based on the specified array of valid |
684 | menu items (terminated by V4L2_CTRL_MENU_IDS_END). | |
685 | Use this if there are 'holes' in the list of valid menu items. */ | |
686 | int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids) | |
687 | { | |
688 | const char **menu_items = v4l2_ctrl_get_menu(qmenu->id); | |
689 | ||
690 | qmenu->reserved = 0; | |
691 | if (menu_items == NULL || ids == NULL) | |
692 | return -EINVAL; | |
693 | while (*ids != V4L2_CTRL_MENU_IDS_END) { | |
694 | if (*ids++ == qmenu->index) { | |
b634a93f HV |
695 | strlcpy(qmenu->name, menu_items[qmenu->index], |
696 | sizeof(qmenu->name)); | |
1e551266 HV |
697 | return 0; |
698 | } | |
699 | } | |
700 | return -EINVAL; | |
701 | } | |
702 | EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items); | |
703 | ||
9cb2318b HV |
704 | /* ctrl_classes points to an array of u32 pointers, the last element is |
705 | a NULL pointer. Each u32 array is a 0-terminated array of control IDs. | |
706 | Each array must be sorted low to high and belong to the same control | |
2ba58894 | 707 | class. The array of u32 pointers must also be sorted, from low class IDs |
9cb2318b HV |
708 | to high class IDs. |
709 | ||
710 | This function returns the first ID that follows after the given ID. | |
711 | When no more controls are available 0 is returned. */ | |
712 | u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id) | |
713 | { | |
a46c5fbc | 714 | u32 ctrl_class = V4L2_CTRL_ID2CLASS(id); |
9cb2318b HV |
715 | const u32 *pctrl; |
716 | ||
9cb2318b HV |
717 | if (ctrl_classes == NULL) |
718 | return 0; | |
a46c5fbc HV |
719 | |
720 | /* if no query is desired, then check if the ID is part of ctrl_classes */ | |
721 | if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) { | |
722 | /* find class */ | |
723 | while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) != ctrl_class) | |
724 | ctrl_classes++; | |
725 | if (*ctrl_classes == NULL) | |
726 | return 0; | |
727 | pctrl = *ctrl_classes; | |
728 | /* find control ID */ | |
729 | while (*pctrl && *pctrl != id) pctrl++; | |
730 | return *pctrl ? id : 0; | |
731 | } | |
9cb2318b | 732 | id &= V4L2_CTRL_ID_MASK; |
9cb2318b HV |
733 | id++; /* select next control */ |
734 | /* find first class that matches (or is greater than) the class of | |
735 | the ID */ | |
736 | while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) < ctrl_class) | |
737 | ctrl_classes++; | |
738 | /* no more classes */ | |
739 | if (*ctrl_classes == NULL) | |
740 | return 0; | |
741 | pctrl = *ctrl_classes; | |
742 | /* find first ctrl within the class that is >= ID */ | |
743 | while (*pctrl && *pctrl < id) pctrl++; | |
744 | if (*pctrl) | |
745 | return *pctrl; | |
746 | /* we are at the end of the controls of the current class. */ | |
747 | /* continue with next class if available */ | |
748 | ctrl_classes++; | |
749 | if (*ctrl_classes == NULL) | |
750 | return 0; | |
751 | return **ctrl_classes; | |
752 | } | |
057596ee | 753 | EXPORT_SYMBOL(v4l2_ctrl_next); |
9cb2318b | 754 | |
aecde8b5 | 755 | int v4l2_chip_match_host(const struct v4l2_dbg_match *match) |
a9254475 | 756 | { |
aecde8b5 | 757 | switch (match->type) { |
a9254475 | 758 | case V4L2_CHIP_MATCH_HOST: |
aecde8b5 | 759 | return match->addr == 0; |
a9254475 MCC |
760 | default: |
761 | return 0; | |
762 | } | |
763 | } | |
764 | EXPORT_SYMBOL(v4l2_chip_match_host); | |
765 | ||
766 | #if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) | |
aecde8b5 | 767 | int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match) |
f3d092b8 | 768 | { |
aecde8b5 HV |
769 | int len; |
770 | ||
771 | if (c == NULL || match == NULL) | |
772 | return 0; | |
773 | ||
774 | switch (match->type) { | |
f3d092b8 | 775 | case V4L2_CHIP_MATCH_I2C_DRIVER: |
aecde8b5 HV |
776 | if (c->driver == NULL || c->driver->driver.name == NULL) |
777 | return 0; | |
778 | len = strlen(c->driver->driver.name); | |
779 | /* legacy drivers have a ' suffix, don't try to match that */ | |
780 | if (len && c->driver->driver.name[len - 1] == '\'') | |
781 | len--; | |
782 | return len && !strncmp(c->driver->driver.name, match->name, len); | |
f3d092b8 | 783 | case V4L2_CHIP_MATCH_I2C_ADDR: |
aecde8b5 | 784 | return c->addr == match->addr; |
f3d092b8 HV |
785 | default: |
786 | return 0; | |
787 | } | |
788 | } | |
a9254475 | 789 | EXPORT_SYMBOL(v4l2_chip_match_i2c_client); |
f3d092b8 | 790 | |
aecde8b5 | 791 | int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip, |
3434eb7e HV |
792 | u32 ident, u32 revision) |
793 | { | |
aecde8b5 | 794 | if (!v4l2_chip_match_i2c_client(c, &chip->match)) |
3434eb7e HV |
795 | return 0; |
796 | if (chip->ident == V4L2_IDENT_NONE) { | |
797 | chip->ident = ident; | |
798 | chip->revision = revision; | |
799 | } | |
800 | else { | |
801 | chip->ident = V4L2_IDENT_AMBIGUOUS; | |
802 | chip->revision = 0; | |
803 | } | |
804 | return 0; | |
805 | } | |
a9254475 | 806 | EXPORT_SYMBOL(v4l2_chip_ident_i2c_client); |
f3d092b8 | 807 | |
9cb2318b HV |
808 | /* ----------------------------------------------------------------- */ |
809 | ||
78a3b4db | 810 | /* I2C Helper functions */ |
8ffbc655 | 811 | |
dd99120c HV |
812 | |
813 | void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client, | |
814 | const struct v4l2_subdev_ops *ops) | |
815 | { | |
816 | v4l2_subdev_init(sd, ops); | |
b5b2b7ed | 817 | sd->flags |= V4L2_SUBDEV_FL_IS_I2C; |
dd99120c HV |
818 | /* the owner is the same as the i2c_client's driver owner */ |
819 | sd->owner = client->driver->driver.owner; | |
820 | /* i2c_client and v4l2_subdev point to one another */ | |
821 | v4l2_set_subdevdata(sd, client); | |
822 | i2c_set_clientdata(client, sd); | |
823 | /* initialize name */ | |
824 | snprintf(sd->name, sizeof(sd->name), "%s %d-%04x", | |
825 | client->driver->driver.name, i2c_adapter_id(client->adapter), | |
826 | client->addr); | |
827 | } | |
828 | EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init); | |
829 | ||
830 | ||
831 | ||
f0222c7d HV |
832 | /* Load an i2c sub-device. */ |
833 | struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev, | |
834 | struct i2c_adapter *adapter, const char *module_name, | |
835 | struct i2c_board_info *info, const unsigned short *probe_addrs) | |
836 | { | |
837 | struct v4l2_subdev *sd = NULL; | |
838 | struct i2c_client *client; | |
839 | ||
840 | BUG_ON(!v4l2_dev); | |
841 | ||
842 | if (module_name) | |
843 | request_module(module_name); | |
844 | ||
845 | /* Create the i2c client */ | |
846 | if (info->addr == 0 && probe_addrs) | |
847 | client = i2c_new_probed_device(adapter, info, probe_addrs); | |
848 | else | |
849 | client = i2c_new_device(adapter, info); | |
850 | ||
851 | /* Note: by loading the module first we are certain that c->driver | |
852 | will be set if the driver was found. If the module was not loaded | |
853 | first, then the i2c core tries to delay-load the module for us, | |
854 | and then c->driver is still NULL until the module is finally | |
855 | loaded. This delay-load mechanism doesn't work if other drivers | |
856 | want to use the i2c device, so explicitly loading the module | |
857 | is the best alternative. */ | |
858 | if (client == NULL || client->driver == NULL) | |
859 | goto error; | |
860 | ||
861 | /* Lock the module so we can safely get the v4l2_subdev pointer */ | |
862 | if (!try_module_get(client->driver->driver.owner)) | |
863 | goto error; | |
864 | sd = i2c_get_clientdata(client); | |
865 | ||
866 | /* Register with the v4l2_device which increases the module's | |
867 | use count as well. */ | |
868 | if (v4l2_device_register_subdev(v4l2_dev, sd)) | |
869 | sd = NULL; | |
870 | /* Decrease the module use count to match the first try_module_get. */ | |
871 | module_put(client->driver->driver.owner); | |
872 | ||
873 | if (sd) { | |
874 | /* We return errors from v4l2_subdev_call only if we have the | |
875 | callback as the .s_config is not mandatory */ | |
876 | int err = v4l2_subdev_call(sd, core, s_config, | |
877 | info->irq, info->platform_data); | |
878 | ||
879 | if (err && err != -ENOIOCTLCMD) { | |
880 | v4l2_device_unregister_subdev(sd); | |
881 | sd = NULL; | |
882 | } | |
883 | } | |
884 | ||
885 | error: | |
886 | /* If we have a client but no subdev, then something went wrong and | |
887 | we must unregister the client. */ | |
888 | if (client && sd == NULL) | |
889 | i2c_unregister_device(client); | |
890 | return sd; | |
891 | } | |
892 | EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board); | |
893 | ||
894 | struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev, | |
895 | struct i2c_adapter *adapter, | |
896 | const char *module_name, const char *client_type, | |
897 | int irq, void *platform_data, | |
898 | u8 addr, const unsigned short *probe_addrs) | |
899 | { | |
900 | struct i2c_board_info info; | |
901 | ||
902 | /* Setup the i2c board info with the device type and | |
903 | the device address. */ | |
904 | memset(&info, 0, sizeof(info)); | |
905 | strlcpy(info.type, client_type, sizeof(info.type)); | |
906 | info.addr = addr; | |
907 | info.irq = irq; | |
908 | info.platform_data = platform_data; | |
909 | ||
910 | return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, module_name, | |
911 | &info, probe_addrs); | |
912 | } | |
913 | EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg); | |
914 | ||
ab373190 HV |
915 | /* Return i2c client address of v4l2_subdev. */ |
916 | unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd) | |
917 | { | |
918 | struct i2c_client *client = v4l2_get_subdevdata(sd); | |
919 | ||
920 | return client ? client->addr : I2C_CLIENT_END; | |
921 | } | |
922 | EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_addr); | |
923 | ||
c7d29e2f HV |
924 | /* Return a list of I2C tuner addresses to probe. Use only if the tuner |
925 | addresses are unknown. */ | |
926 | const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type) | |
927 | { | |
928 | static const unsigned short radio_addrs[] = { | |
929 | #if defined(CONFIG_MEDIA_TUNER_TEA5761) || defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE) | |
930 | 0x10, | |
931 | #endif | |
932 | 0x60, | |
933 | I2C_CLIENT_END | |
934 | }; | |
935 | static const unsigned short demod_addrs[] = { | |
936 | 0x42, 0x43, 0x4a, 0x4b, | |
937 | I2C_CLIENT_END | |
938 | }; | |
939 | static const unsigned short tv_addrs[] = { | |
940 | 0x42, 0x43, 0x4a, 0x4b, /* tda8290 */ | |
416a7aa8 | 941 | 0x60, 0x61, 0x62, 0x63, 0x64, |
c7d29e2f HV |
942 | I2C_CLIENT_END |
943 | }; | |
944 | ||
945 | switch (type) { | |
946 | case ADDRS_RADIO: | |
947 | return radio_addrs; | |
948 | case ADDRS_DEMOD: | |
949 | return demod_addrs; | |
950 | case ADDRS_TV: | |
951 | return tv_addrs; | |
952 | case ADDRS_TV_WITH_DEMOD: | |
953 | return tv_addrs + 4; | |
954 | } | |
955 | return NULL; | |
956 | } | |
957 | EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs); | |
958 | ||
d8b29966 TP |
959 | #endif /* defined(CONFIG_I2C) */ |
960 | ||
85e09219 DB |
961 | #if defined(CONFIG_SPI) |
962 | ||
963 | /* Load a spi sub-device. */ | |
964 | ||
965 | void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi, | |
966 | const struct v4l2_subdev_ops *ops) | |
967 | { | |
968 | v4l2_subdev_init(sd, ops); | |
969 | sd->flags |= V4L2_SUBDEV_FL_IS_SPI; | |
970 | /* the owner is the same as the spi_device's driver owner */ | |
971 | sd->owner = spi->dev.driver->owner; | |
972 | /* spi_device and v4l2_subdev point to one another */ | |
973 | v4l2_set_subdevdata(sd, spi); | |
974 | spi_set_drvdata(spi, sd); | |
975 | /* initialize name */ | |
976 | strlcpy(sd->name, spi->dev.driver->name, sizeof(sd->name)); | |
977 | } | |
978 | EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init); | |
979 | ||
980 | struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev, | |
981 | struct spi_master *master, struct spi_board_info *info) | |
982 | { | |
983 | struct v4l2_subdev *sd = NULL; | |
984 | struct spi_device *spi = NULL; | |
985 | ||
986 | BUG_ON(!v4l2_dev); | |
987 | ||
988 | if (info->modalias) | |
989 | request_module(info->modalias); | |
990 | ||
991 | spi = spi_new_device(master, info); | |
992 | ||
993 | if (spi == NULL || spi->dev.driver == NULL) | |
994 | goto error; | |
995 | ||
996 | if (!try_module_get(spi->dev.driver->owner)) | |
997 | goto error; | |
998 | ||
999 | sd = spi_get_drvdata(spi); | |
1000 | ||
1001 | /* Register with the v4l2_device which increases the module's | |
1002 | use count as well. */ | |
1003 | if (v4l2_device_register_subdev(v4l2_dev, sd)) | |
1004 | sd = NULL; | |
1005 | ||
1006 | /* Decrease the module use count to match the first try_module_get. */ | |
1007 | module_put(spi->dev.driver->owner); | |
1008 | ||
1009 | error: | |
1010 | /* If we have a client but no subdev, then something went wrong and | |
1011 | we must unregister the client. */ | |
1012 | if (spi && sd == NULL) | |
1013 | spi_unregister_device(spi); | |
1014 | ||
1015 | return sd; | |
1016 | } | |
1017 | EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev); | |
1018 | ||
1019 | #endif /* defined(CONFIG_SPI) */ | |
1020 | ||
b0d3159b TP |
1021 | /* Clamp x to be between min and max, aligned to a multiple of 2^align. min |
1022 | * and max don't have to be aligned, but there must be at least one valid | |
1023 | * value. E.g., min=17,max=31,align=4 is not allowed as there are no multiples | |
1024 | * of 16 between 17 and 31. */ | |
1025 | static unsigned int clamp_align(unsigned int x, unsigned int min, | |
1026 | unsigned int max, unsigned int align) | |
1027 | { | |
1028 | /* Bits that must be zero to be aligned */ | |
1029 | unsigned int mask = ~((1 << align) - 1); | |
1030 | ||
1031 | /* Round to nearest aligned value */ | |
1032 | if (align) | |
1033 | x = (x + (1 << (align - 1))) & mask; | |
1034 | ||
1035 | /* Clamp to aligned value of min and max */ | |
1036 | if (x < min) | |
1037 | x = (min + ~mask) & mask; | |
1038 | else if (x > max) | |
1039 | x = max & mask; | |
1040 | ||
1041 | return x; | |
1042 | } | |
1043 | ||
1044 | /* Bound an image to have a width between wmin and wmax, and height between | |
1045 | * hmin and hmax, inclusive. Additionally, the width will be a multiple of | |
1046 | * 2^walign, the height will be a multiple of 2^halign, and the overall size | |
1047 | * (width*height) will be a multiple of 2^salign. The image may be shrunk | |
1048 | * or enlarged to fit the alignment constraints. | |
1049 | * | |
1050 | * The width or height maximum must not be smaller than the corresponding | |
1051 | * minimum. The alignments must not be so high there are no possible image | |
1052 | * sizes within the allowed bounds. wmin and hmin must be at least 1 | |
1053 | * (don't use 0). If you don't care about a certain alignment, specify 0, | |
1054 | * as 2^0 is 1 and one byte alignment is equivalent to no alignment. If | |
1055 | * you only want to adjust downward, specify a maximum that's the same as | |
1056 | * the initial value. | |
1057 | */ | |
1058 | void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax, | |
1059 | unsigned int walign, | |
1060 | u32 *h, unsigned int hmin, unsigned int hmax, | |
1061 | unsigned int halign, unsigned int salign) | |
1062 | { | |
1063 | *w = clamp_align(*w, wmin, wmax, walign); | |
1064 | *h = clamp_align(*h, hmin, hmax, halign); | |
1065 | ||
1066 | /* Usually we don't need to align the size and are done now. */ | |
1067 | if (!salign) | |
1068 | return; | |
1069 | ||
1070 | /* How much alignment do we have? */ | |
1071 | walign = __ffs(*w); | |
1072 | halign = __ffs(*h); | |
1073 | /* Enough to satisfy the image alignment? */ | |
1074 | if (walign + halign < salign) { | |
1075 | /* Max walign where there is still a valid width */ | |
1076 | unsigned int wmaxa = __fls(wmax ^ (wmin - 1)); | |
1077 | /* Max halign where there is still a valid height */ | |
1078 | unsigned int hmaxa = __fls(hmax ^ (hmin - 1)); | |
1079 | ||
1080 | /* up the smaller alignment until we have enough */ | |
1081 | do { | |
1082 | if (halign >= hmaxa || | |
1083 | (walign <= halign && walign < wmaxa)) { | |
1084 | *w = clamp_align(*w, wmin, wmax, walign + 1); | |
1085 | walign = __ffs(*w); | |
1086 | } else { | |
1087 | *h = clamp_align(*h, hmin, hmax, halign + 1); | |
1088 | halign = __ffs(*h); | |
1089 | } | |
1090 | } while (halign + walign < salign); | |
1091 | } | |
1092 | } | |
1093 | EXPORT_SYMBOL_GPL(v4l_bound_align_image); | |
2e535ed5 MK |
1094 | |
1095 | /** | |
1096 | * v4l_fill_dv_preset_info - fill description of a digital video preset | |
1097 | * @preset - preset value | |
1098 | * @info - pointer to struct v4l2_dv_enum_preset | |
1099 | * | |
1100 | * drivers can use this helper function to fill description of dv preset | |
1101 | * in info. | |
1102 | */ | |
1103 | int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info) | |
1104 | { | |
1105 | static const struct v4l2_dv_preset_info { | |
1106 | u16 width; | |
1107 | u16 height; | |
1108 | const char *name; | |
1109 | } dv_presets[] = { | |
1110 | { 0, 0, "Invalid" }, /* V4L2_DV_INVALID */ | |
1111 | { 720, 480, "480p@59.94" }, /* V4L2_DV_480P59_94 */ | |
1112 | { 720, 576, "576p@50" }, /* V4L2_DV_576P50 */ | |
1113 | { 1280, 720, "720p@24" }, /* V4L2_DV_720P24 */ | |
1114 | { 1280, 720, "720p@25" }, /* V4L2_DV_720P25 */ | |
1115 | { 1280, 720, "720p@30" }, /* V4L2_DV_720P30 */ | |
1116 | { 1280, 720, "720p@50" }, /* V4L2_DV_720P50 */ | |
1117 | { 1280, 720, "720p@59.94" }, /* V4L2_DV_720P59_94 */ | |
1118 | { 1280, 720, "720p@60" }, /* V4L2_DV_720P60 */ | |
1119 | { 1920, 1080, "1080i@29.97" }, /* V4L2_DV_1080I29_97 */ | |
1120 | { 1920, 1080, "1080i@30" }, /* V4L2_DV_1080I30 */ | |
1121 | { 1920, 1080, "1080i@25" }, /* V4L2_DV_1080I25 */ | |
1122 | { 1920, 1080, "1080i@50" }, /* V4L2_DV_1080I50 */ | |
1123 | { 1920, 1080, "1080i@60" }, /* V4L2_DV_1080I60 */ | |
1124 | { 1920, 1080, "1080p@24" }, /* V4L2_DV_1080P24 */ | |
1125 | { 1920, 1080, "1080p@25" }, /* V4L2_DV_1080P25 */ | |
1126 | { 1920, 1080, "1080p@30" }, /* V4L2_DV_1080P30 */ | |
1127 | { 1920, 1080, "1080p@50" }, /* V4L2_DV_1080P50 */ | |
1128 | { 1920, 1080, "1080p@60" }, /* V4L2_DV_1080P60 */ | |
1129 | }; | |
1130 | ||
1131 | if (info == NULL || preset >= ARRAY_SIZE(dv_presets)) | |
1132 | return -EINVAL; | |
1133 | ||
1134 | info->preset = preset; | |
1135 | info->width = dv_presets[preset].width; | |
1136 | info->height = dv_presets[preset].height; | |
1137 | strlcpy(info->name, dv_presets[preset].name, sizeof(info->name)); | |
1138 | return 0; | |
1139 | } | |
1140 | EXPORT_SYMBOL_GPL(v4l_fill_dv_preset_info); |