1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47#include <linux/module.h>
48#include <linux/types.h>
49#include <linux/kernel.h>
50#include <linux/mm.h>
51#include <linux/string.h>
52#include <linux/errno.h>
53#include <linux/i2c.h>
54#if defined(CONFIG_SPI)
55#include <linux/spi/spi.h>
56#endif
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>
62#include <media/v4l2-common.h>
63#include <media/v4l2-device.h>
64#include <media/v4l2-ctrls.h>
65#include <media/v4l2-chip-ident.h>
66
67#include <linux/videodev2.h>
68
69MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr");
70MODULE_DESCRIPTION("misc helper functions for v4l2 device drivers");
71MODULE_LICENSE("GPL");
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
89 const char * const *menu_items)
90{
91 if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED)
92 return -EINVAL;
93 if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
94 return -EBUSY;
95 if (qctrl->type == V4L2_CTRL_TYPE_STRING)
96 return 0;
97 if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
98 qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
99 qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
100 return 0;
101 if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum)
102 return -ERANGE;
103 if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) {
104 if (menu_items[ctrl->value] == NULL ||
105 menu_items[ctrl->value][0] == '\0')
106 return -EINVAL;
107 }
108 return 0;
109}
110EXPORT_SYMBOL(v4l2_ctrl_check);
111
112
113int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
114{
115 const char *name;
116
117 v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type,
118 &min, &max, &step, &def, &qctrl->flags);
119
120 if (name == NULL)
121 return -EINVAL;
122
123 qctrl->minimum = min;
124 qctrl->maximum = max;
125 qctrl->step = step;
126 qctrl->default_value = def;
127 qctrl->reserved[0] = qctrl->reserved[1] = 0;
128 strlcpy(qctrl->name, name, sizeof(qctrl->name));
129 return 0;
130}
131EXPORT_SYMBOL(v4l2_ctrl_query_fill);
132
133
134
135
136
137int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl,
138 const char * const *menu_items)
139{
140 int i;
141
142 qmenu->reserved = 0;
143 if (menu_items == NULL)
144 menu_items = v4l2_ctrl_get_menu(qmenu->id);
145 if (menu_items == NULL ||
146 (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum)))
147 return -EINVAL;
148 for (i = 0; i < qmenu->index && menu_items[i]; i++) ;
149 if (menu_items[i] == NULL || menu_items[i][0] == '\0')
150 return -EINVAL;
151 strlcpy(qmenu->name, menu_items[qmenu->index], sizeof(qmenu->name));
152 return 0;
153}
154EXPORT_SYMBOL(v4l2_ctrl_query_menu);
155
156
157
158
159int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids)
160{
161 const char * const *menu_items = v4l2_ctrl_get_menu(qmenu->id);
162
163 qmenu->reserved = 0;
164 if (menu_items == NULL || ids == NULL)
165 return -EINVAL;
166 while (*ids != V4L2_CTRL_MENU_IDS_END) {
167 if (*ids++ == qmenu->index) {
168 strlcpy(qmenu->name, menu_items[qmenu->index],
169 sizeof(qmenu->name));
170 return 0;
171 }
172 }
173 return -EINVAL;
174}
175EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items);
176
177
178
179
180
181
182
183
184
185u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
186{
187 u32 ctrl_class = V4L2_CTRL_ID2CLASS(id);
188 const u32 *pctrl;
189
190 if (ctrl_classes == NULL)
191 return 0;
192
193
194 if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) {
195
196 while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) != ctrl_class)
197 ctrl_classes++;
198 if (*ctrl_classes == NULL)
199 return 0;
200 pctrl = *ctrl_classes;
201
202 while (*pctrl && *pctrl != id) pctrl++;
203 return *pctrl ? id : 0;
204 }
205 id &= V4L2_CTRL_ID_MASK;
206 id++;
207
208
209 while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) < ctrl_class)
210 ctrl_classes++;
211
212 if (*ctrl_classes == NULL)
213 return 0;
214 pctrl = *ctrl_classes;
215
216 while (*pctrl && *pctrl < id) pctrl++;
217 if (*pctrl)
218 return *pctrl;
219
220
221 ctrl_classes++;
222 if (*ctrl_classes == NULL)
223 return 0;
224 return **ctrl_classes;
225}
226EXPORT_SYMBOL(v4l2_ctrl_next);
227
228int v4l2_chip_match_host(const struct v4l2_dbg_match *match)
229{
230 switch (match->type) {
231 case V4L2_CHIP_MATCH_HOST:
232 return match->addr == 0;
233 default:
234 return 0;
235 }
236}
237EXPORT_SYMBOL(v4l2_chip_match_host);
238
239#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
240int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match)
241{
242 int len;
243
244 if (c == NULL || match == NULL)
245 return 0;
246
247 switch (match->type) {
248 case V4L2_CHIP_MATCH_I2C_DRIVER:
249 if (c->driver == NULL || c->driver->driver.name == NULL)
250 return 0;
251 len = strlen(c->driver->driver.name);
252
253 if (len && c->driver->driver.name[len - 1] == '\'')
254 len--;
255 return len && !strncmp(c->driver->driver.name, match->name, len);
256 case V4L2_CHIP_MATCH_I2C_ADDR:
257 return c->addr == match->addr;
258 default:
259 return 0;
260 }
261}
262EXPORT_SYMBOL(v4l2_chip_match_i2c_client);
263
264int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip,
265 u32 ident, u32 revision)
266{
267 if (!v4l2_chip_match_i2c_client(c, &chip->match))
268 return 0;
269 if (chip->ident == V4L2_IDENT_NONE) {
270 chip->ident = ident;
271 chip->revision = revision;
272 }
273 else {
274 chip->ident = V4L2_IDENT_AMBIGUOUS;
275 chip->revision = 0;
276 }
277 return 0;
278}
279EXPORT_SYMBOL(v4l2_chip_ident_i2c_client);
280
281
282
283
284
285
286void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
287 const struct v4l2_subdev_ops *ops)
288{
289 v4l2_subdev_init(sd, ops);
290 sd->flags |= V4L2_SUBDEV_FL_IS_I2C;
291
292 sd->owner = client->driver->driver.owner;
293
294 v4l2_set_subdevdata(sd, client);
295 i2c_set_clientdata(client, sd);
296
297 snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
298 client->driver->driver.name, i2c_adapter_id(client->adapter),
299 client->addr);
300}
301EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init);
302
303
304
305
306struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
307 struct i2c_adapter *adapter, struct i2c_board_info *info,
308 const unsigned short *probe_addrs)
309{
310 struct v4l2_subdev *sd = NULL;
311 struct i2c_client *client;
312
313 BUG_ON(!v4l2_dev);
314
315 request_module(I2C_MODULE_PREFIX "%s", info->type);
316
317
318 if (info->addr == 0 && probe_addrs)
319 client = i2c_new_probed_device(adapter, info, probe_addrs,
320 NULL);
321 else
322 client = i2c_new_device(adapter, info);
323
324
325
326
327
328
329
330
331 if (client == NULL || client->driver == NULL)
332 goto error;
333
334
335 if (!try_module_get(client->driver->driver.owner))
336 goto error;
337 sd = i2c_get_clientdata(client);
338
339
340
341 if (v4l2_device_register_subdev(v4l2_dev, sd))
342 sd = NULL;
343
344 module_put(client->driver->driver.owner);
345
346error:
347
348
349 if (client && sd == NULL)
350 i2c_unregister_device(client);
351 return sd;
352}
353EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board);
354
355struct v4l2_subdev *v4l2_i2c_new_subdev(struct v4l2_device *v4l2_dev,
356 struct i2c_adapter *adapter, const char *client_type,
357 u8 addr, const unsigned short *probe_addrs)
358{
359 struct i2c_board_info info;
360
361
362
363 memset(&info, 0, sizeof(info));
364 strlcpy(info.type, client_type, sizeof(info.type));
365 info.addr = addr;
366
367 return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, &info, probe_addrs);
368}
369EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev);
370
371
372unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd)
373{
374 struct i2c_client *client = v4l2_get_subdevdata(sd);
375
376 return client ? client->addr : I2C_CLIENT_END;
377}
378EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_addr);
379
380
381
382const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type)
383{
384 static const unsigned short radio_addrs[] = {
385#if defined(CONFIG_MEDIA_TUNER_TEA5761) || defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE)
386 0x10,
387#endif
388 0x60,
389 I2C_CLIENT_END
390 };
391 static const unsigned short demod_addrs[] = {
392 0x42, 0x43, 0x4a, 0x4b,
393 I2C_CLIENT_END
394 };
395 static const unsigned short tv_addrs[] = {
396 0x42, 0x43, 0x4a, 0x4b,
397 0x60, 0x61, 0x62, 0x63, 0x64,
398 I2C_CLIENT_END
399 };
400
401 switch (type) {
402 case ADDRS_RADIO:
403 return radio_addrs;
404 case ADDRS_DEMOD:
405 return demod_addrs;
406 case ADDRS_TV:
407 return tv_addrs;
408 case ADDRS_TV_WITH_DEMOD:
409 return tv_addrs + 4;
410 }
411 return NULL;
412}
413EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs);
414
415#endif
416
417#if defined(CONFIG_SPI)
418
419
420
421void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
422 const struct v4l2_subdev_ops *ops)
423{
424 v4l2_subdev_init(sd, ops);
425 sd->flags |= V4L2_SUBDEV_FL_IS_SPI;
426
427 sd->owner = spi->dev.driver->owner;
428
429 v4l2_set_subdevdata(sd, spi);
430 spi_set_drvdata(spi, sd);
431
432 strlcpy(sd->name, spi->dev.driver->name, sizeof(sd->name));
433}
434EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
435
436struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
437 struct spi_master *master, struct spi_board_info *info)
438{
439 struct v4l2_subdev *sd = NULL;
440 struct spi_device *spi = NULL;
441
442 BUG_ON(!v4l2_dev);
443
444 if (info->modalias)
445 request_module(info->modalias);
446
447 spi = spi_new_device(master, info);
448
449 if (spi == NULL || spi->dev.driver == NULL)
450 goto error;
451
452 if (!try_module_get(spi->dev.driver->owner))
453 goto error;
454
455 sd = spi_get_drvdata(spi);
456
457
458
459 if (v4l2_device_register_subdev(v4l2_dev, sd))
460 sd = NULL;
461
462
463 module_put(spi->dev.driver->owner);
464
465error:
466
467
468 if (spi && sd == NULL)
469 spi_unregister_device(spi);
470
471 return sd;
472}
473EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);
474
475#endif
476
477
478
479
480
481static unsigned int clamp_align(unsigned int x, unsigned int min,
482 unsigned int max, unsigned int align)
483{
484
485 unsigned int mask = ~((1 << align) - 1);
486
487
488 if (align)
489 x = (x + (1 << (align - 1))) & mask;
490
491
492 if (x < min)
493 x = (min + ~mask) & mask;
494 else if (x > max)
495 x = max & mask;
496
497 return x;
498}
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
515 unsigned int walign,
516 u32 *h, unsigned int hmin, unsigned int hmax,
517 unsigned int halign, unsigned int salign)
518{
519 *w = clamp_align(*w, wmin, wmax, walign);
520 *h = clamp_align(*h, hmin, hmax, halign);
521
522
523 if (!salign)
524 return;
525
526
527 walign = __ffs(*w);
528 halign = __ffs(*h);
529
530 if (walign + halign < salign) {
531
532 unsigned int wmaxa = __fls(wmax ^ (wmin - 1));
533
534 unsigned int hmaxa = __fls(hmax ^ (hmin - 1));
535
536
537 do {
538 if (halign >= hmaxa ||
539 (walign <= halign && walign < wmaxa)) {
540 *w = clamp_align(*w, wmin, wmax, walign + 1);
541 walign = __ffs(*w);
542 } else {
543 *h = clamp_align(*h, hmin, hmax, halign + 1);
544 halign = __ffs(*h);
545 }
546 } while (halign + walign < salign);
547 }
548}
549EXPORT_SYMBOL_GPL(v4l_bound_align_image);
550
551
552
553
554
555
556
557
558
559int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info)
560{
561 static const struct v4l2_dv_preset_info {
562 u16 width;
563 u16 height;
564 const char *name;
565 } dv_presets[] = {
566 { 0, 0, "Invalid" },
567 { 720, 480, "480p@59.94" },
568 { 720, 576, "576p@50" },
569 { 1280, 720, "720p@24" },
570 { 1280, 720, "720p@25" },
571 { 1280, 720, "720p@30" },
572 { 1280, 720, "720p@50" },
573 { 1280, 720, "720p@59.94" },
574 { 1280, 720, "720p@60" },
575 { 1920, 1080, "1080i@29.97" },
576 { 1920, 1080, "1080i@30" },
577 { 1920, 1080, "1080i@25" },
578 { 1920, 1080, "1080i@50" },
579 { 1920, 1080, "1080i@60" },
580 { 1920, 1080, "1080p@24" },
581 { 1920, 1080, "1080p@25" },
582 { 1920, 1080, "1080p@30" },
583 { 1920, 1080, "1080p@50" },
584 { 1920, 1080, "1080p@60" },
585 };
586
587 if (info == NULL || preset >= ARRAY_SIZE(dv_presets))
588 return -EINVAL;
589
590 info->preset = preset;
591 info->width = dv_presets[preset].width;
592 info->height = dv_presets[preset].height;
593 strlcpy(info->name, dv_presets[preset].name, sizeof(info->name));
594 return 0;
595}
596EXPORT_SYMBOL_GPL(v4l_fill_dv_preset_info);
597
598const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
599 const struct v4l2_discrete_probe *probe,
600 s32 width, s32 height)
601{
602 int i;
603 u32 error, min_error = UINT_MAX;
604 const struct v4l2_frmsize_discrete *size, *best = NULL;
605
606 if (!probe)
607 return best;
608
609 for (i = 0, size = probe->sizes; i < probe->num_sizes; i++, size++) {
610 error = abs(size->width - width) + abs(size->height - height);
611 if (error < min_error) {
612 min_error = error;
613 best = size;
614 }
615 if (!error)
616 break;
617 }
618
619 return best;
620}
621EXPORT_SYMBOL_GPL(v4l2_find_nearest_format);
622