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