• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/media/video/
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 *
15 * Author:	Bill Dirks <bill@thedirks.org>
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 *
31 * Author:	Alan Cox, <alan@lxorguk.ukuu.org.uk>
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
40 *  I��aki Garc��a Etxebarria <garetxe@euskalnet.net>
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
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#define __OLD_VIDIOC_ /* To allow fixing old calls*/
63#include <media/v4l2-common.h>
64#include <media/v4l2-device.h>
65#include <media/v4l2-ctrls.h>
66#include <media/v4l2-chip-ident.h>
67
68#include <linux/videodev2.h>
69
70MODULE_AUTHOR("Bill Dirks, Justin Schoeman, Gerd Knorr");
71MODULE_DESCRIPTION("misc helper functions for v4l2 device drivers");
72MODULE_LICENSE("GPL");
73
74/*
75 *
76 *	V 4 L 2   D R I V E R   H E L P E R   A P I
77 *
78 */
79
80/*
81 *  Video Standard Operations (contributed by Michael Schimek)
82 */
83
84
85/* ----------------------------------------------------------------- */
86/* priority handling                                                 */
87
88#define V4L2_PRIO_VALID(val) (val == V4L2_PRIORITY_BACKGROUND   || \
89			      val == V4L2_PRIORITY_INTERACTIVE  || \
90			      val == V4L2_PRIORITY_RECORD)
91
92void v4l2_prio_init(struct v4l2_prio_state *global)
93{
94	memset(global, 0, sizeof(*global));
95}
96EXPORT_SYMBOL(v4l2_prio_init);
97
98int 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}
112EXPORT_SYMBOL(v4l2_prio_change);
113
114void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local)
115{
116	v4l2_prio_change(global, local, V4L2_PRIORITY_DEFAULT);
117}
118EXPORT_SYMBOL(v4l2_prio_open);
119
120void 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}
125EXPORT_SYMBOL(v4l2_prio_close);
126
127enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global)
128{
129	if (atomic_read(&global->prios[V4L2_PRIORITY_RECORD]) > 0)
130		return V4L2_PRIORITY_RECORD;
131	if (atomic_read(&global->prios[V4L2_PRIORITY_INTERACTIVE]) > 0)
132		return V4L2_PRIORITY_INTERACTIVE;
133	if (atomic_read(&global->prios[V4L2_PRIORITY_BACKGROUND]) > 0)
134		return V4L2_PRIORITY_BACKGROUND;
135	return V4L2_PRIORITY_UNSET;
136}
137EXPORT_SYMBOL(v4l2_prio_max);
138
139int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local)
140{
141	return (local < v4l2_prio_max(global)) ? -EBUSY : 0;
142}
143EXPORT_SYMBOL(v4l2_prio_check);
144
145/* ----------------------------------------------------------------- */
146
147/* Helper functions for control handling			     */
148
149/* Check for correctness of the ctrl's value based on the data from
150   struct v4l2_queryctrl and the available menu items. Note that
151   menu_items may be NULL, in that case it is ignored. */
152int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
153		const char **menu_items)
154{
155	if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED)
156		return -EINVAL;
157	if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
158		return -EBUSY;
159	if (qctrl->type == V4L2_CTRL_TYPE_STRING)
160		return 0;
161	if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
162	    qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
163	    qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
164		return 0;
165	if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum)
166		return -ERANGE;
167	if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) {
168		if (menu_items[ctrl->value] == NULL ||
169		    menu_items[ctrl->value][0] == '\0')
170			return -EINVAL;
171	}
172	return 0;
173}
174EXPORT_SYMBOL(v4l2_ctrl_check);
175
176/* Fill in a struct v4l2_queryctrl */
177int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
178{
179	const char *name;
180
181	v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type,
182		       &min, &max, &step, &def, &qctrl->flags);
183
184	if (name == NULL)
185		return -EINVAL;
186
187	qctrl->minimum = min;
188	qctrl->maximum = max;
189	qctrl->step = step;
190	qctrl->default_value = def;
191	qctrl->reserved[0] = qctrl->reserved[1] = 0;
192	strlcpy(qctrl->name, name, sizeof(qctrl->name));
193	return 0;
194}
195EXPORT_SYMBOL(v4l2_ctrl_query_fill);
196
197/* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and
198   the menu. The qctrl pointer may be NULL, in which case it is ignored.
199   If menu_items is NULL, then the menu items are retrieved using
200   v4l2_ctrl_get_menu. */
201int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl,
202	       const char **menu_items)
203{
204	int i;
205
206	qmenu->reserved = 0;
207	if (menu_items == NULL)
208		menu_items = v4l2_ctrl_get_menu(qmenu->id);
209	if (menu_items == NULL ||
210	    (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum)))
211		return -EINVAL;
212	for (i = 0; i < qmenu->index && menu_items[i]; i++) ;
213	if (menu_items[i] == NULL || menu_items[i][0] == '\0')
214		return -EINVAL;
215	strlcpy(qmenu->name, menu_items[qmenu->index], sizeof(qmenu->name));
216	return 0;
217}
218EXPORT_SYMBOL(v4l2_ctrl_query_menu);
219
220/* Fill in a struct v4l2_querymenu based on the specified array of valid
221   menu items (terminated by V4L2_CTRL_MENU_IDS_END).
222   Use this if there are 'holes' in the list of valid menu items. */
223int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids)
224{
225	const char **menu_items = v4l2_ctrl_get_menu(qmenu->id);
226
227	qmenu->reserved = 0;
228	if (menu_items == NULL || ids == NULL)
229		return -EINVAL;
230	while (*ids != V4L2_CTRL_MENU_IDS_END) {
231		if (*ids++ == qmenu->index) {
232			strlcpy(qmenu->name, menu_items[qmenu->index],
233					sizeof(qmenu->name));
234			return 0;
235		}
236	}
237	return -EINVAL;
238}
239EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items);
240
241/* ctrl_classes points to an array of u32 pointers, the last element is
242   a NULL pointer. Each u32 array is a 0-terminated array of control IDs.
243   Each array must be sorted low to high and belong to the same control
244   class. The array of u32 pointers must also be sorted, from low class IDs
245   to high class IDs.
246
247   This function returns the first ID that follows after the given ID.
248   When no more controls are available 0 is returned. */
249u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
250{
251	u32 ctrl_class = V4L2_CTRL_ID2CLASS(id);
252	const u32 *pctrl;
253
254	if (ctrl_classes == NULL)
255		return 0;
256
257	/* if no query is desired, then check if the ID is part of ctrl_classes */
258	if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) {
259		/* find class */
260		while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) != ctrl_class)
261			ctrl_classes++;
262		if (*ctrl_classes == NULL)
263			return 0;
264		pctrl = *ctrl_classes;
265		/* find control ID */
266		while (*pctrl && *pctrl != id) pctrl++;
267		return *pctrl ? id : 0;
268	}
269	id &= V4L2_CTRL_ID_MASK;
270	id++;	/* select next control */
271	/* find first class that matches (or is greater than) the class of
272	   the ID */
273	while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) < ctrl_class)
274		ctrl_classes++;
275	/* no more classes */
276	if (*ctrl_classes == NULL)
277		return 0;
278	pctrl = *ctrl_classes;
279	/* find first ctrl within the class that is >= ID */
280	while (*pctrl && *pctrl < id) pctrl++;
281	if (*pctrl)
282		return *pctrl;
283	/* we are at the end of the controls of the current class. */
284	/* continue with next class if available */
285	ctrl_classes++;
286	if (*ctrl_classes == NULL)
287		return 0;
288	return **ctrl_classes;
289}
290EXPORT_SYMBOL(v4l2_ctrl_next);
291
292int v4l2_chip_match_host(const struct v4l2_dbg_match *match)
293{
294	switch (match->type) {
295	case V4L2_CHIP_MATCH_HOST:
296		return match->addr == 0;
297	default:
298		return 0;
299	}
300}
301EXPORT_SYMBOL(v4l2_chip_match_host);
302
303#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
304int v4l2_chip_match_i2c_client(struct i2c_client *c, const struct v4l2_dbg_match *match)
305{
306	int len;
307
308	if (c == NULL || match == NULL)
309		return 0;
310
311	switch (match->type) {
312	case V4L2_CHIP_MATCH_I2C_DRIVER:
313		if (c->driver == NULL || c->driver->driver.name == NULL)
314			return 0;
315		len = strlen(c->driver->driver.name);
316		/* legacy drivers have a ' suffix, don't try to match that */
317		if (len && c->driver->driver.name[len - 1] == '\'')
318			len--;
319		return len && !strncmp(c->driver->driver.name, match->name, len);
320	case V4L2_CHIP_MATCH_I2C_ADDR:
321		return c->addr == match->addr;
322	default:
323		return 0;
324	}
325}
326EXPORT_SYMBOL(v4l2_chip_match_i2c_client);
327
328int v4l2_chip_ident_i2c_client(struct i2c_client *c, struct v4l2_dbg_chip_ident *chip,
329		u32 ident, u32 revision)
330{
331	if (!v4l2_chip_match_i2c_client(c, &chip->match))
332		return 0;
333	if (chip->ident == V4L2_IDENT_NONE) {
334		chip->ident = ident;
335		chip->revision = revision;
336	}
337	else {
338		chip->ident = V4L2_IDENT_AMBIGUOUS;
339		chip->revision = 0;
340	}
341	return 0;
342}
343EXPORT_SYMBOL(v4l2_chip_ident_i2c_client);
344
345/* ----------------------------------------------------------------- */
346
347/* I2C Helper functions */
348
349
350void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
351		const struct v4l2_subdev_ops *ops)
352{
353	v4l2_subdev_init(sd, ops);
354	sd->flags |= V4L2_SUBDEV_FL_IS_I2C;
355	/* the owner is the same as the i2c_client's driver owner */
356	sd->owner = client->driver->driver.owner;
357	/* i2c_client and v4l2_subdev point to one another */
358	v4l2_set_subdevdata(sd, client);
359	i2c_set_clientdata(client, sd);
360	/* initialize name */
361	snprintf(sd->name, sizeof(sd->name), "%s %d-%04x",
362		client->driver->driver.name, i2c_adapter_id(client->adapter),
363		client->addr);
364}
365EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_init);
366
367
368
369/* Load an i2c sub-device. */
370struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
371		struct i2c_adapter *adapter, const char *module_name,
372		struct i2c_board_info *info, const unsigned short *probe_addrs)
373{
374	struct v4l2_subdev *sd = NULL;
375	struct i2c_client *client;
376
377	BUG_ON(!v4l2_dev);
378
379	if (module_name)
380		request_module(module_name);
381
382	/* Create the i2c client */
383	if (info->addr == 0 && probe_addrs)
384		client = i2c_new_probed_device(adapter, info, probe_addrs,
385					       NULL);
386	else
387		client = i2c_new_device(adapter, info);
388
389	/* Note: by loading the module first we are certain that c->driver
390	   will be set if the driver was found. If the module was not loaded
391	   first, then the i2c core tries to delay-load the module for us,
392	   and then c->driver is still NULL until the module is finally
393	   loaded. This delay-load mechanism doesn't work if other drivers
394	   want to use the i2c device, so explicitly loading the module
395	   is the best alternative. */
396	if (client == NULL || client->driver == NULL)
397		goto error;
398
399	/* Lock the module so we can safely get the v4l2_subdev pointer */
400	if (!try_module_get(client->driver->driver.owner))
401		goto error;
402	sd = i2c_get_clientdata(client);
403
404	/* Register with the v4l2_device which increases the module's
405	   use count as well. */
406	if (v4l2_device_register_subdev(v4l2_dev, sd))
407		sd = NULL;
408	/* Decrease the module use count to match the first try_module_get. */
409	module_put(client->driver->driver.owner);
410
411	if (sd) {
412		/* We return errors from v4l2_subdev_call only if we have the
413		   callback as the .s_config is not mandatory */
414		int err = v4l2_subdev_call(sd, core, s_config,
415				info->irq, info->platform_data);
416
417		if (err && err != -ENOIOCTLCMD) {
418			v4l2_device_unregister_subdev(sd);
419			sd = NULL;
420		}
421	}
422
423error:
424	/* If we have a client but no subdev, then something went wrong and
425	   we must unregister the client. */
426	if (client && sd == NULL)
427		i2c_unregister_device(client);
428	return sd;
429}
430EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_board);
431
432struct v4l2_subdev *v4l2_i2c_new_subdev_cfg(struct v4l2_device *v4l2_dev,
433		struct i2c_adapter *adapter,
434		const char *module_name, const char *client_type,
435		int irq, void *platform_data,
436		u8 addr, const unsigned short *probe_addrs)
437{
438	struct i2c_board_info info;
439
440	/* Setup the i2c board info with the device type and
441	   the device address. */
442	memset(&info, 0, sizeof(info));
443	strlcpy(info.type, client_type, sizeof(info.type));
444	info.addr = addr;
445	info.irq = irq;
446	info.platform_data = platform_data;
447
448	return v4l2_i2c_new_subdev_board(v4l2_dev, adapter, module_name,
449			&info, probe_addrs);
450}
451EXPORT_SYMBOL_GPL(v4l2_i2c_new_subdev_cfg);
452
453/* Return i2c client address of v4l2_subdev. */
454unsigned short v4l2_i2c_subdev_addr(struct v4l2_subdev *sd)
455{
456	struct i2c_client *client = v4l2_get_subdevdata(sd);
457
458	return client ? client->addr : I2C_CLIENT_END;
459}
460EXPORT_SYMBOL_GPL(v4l2_i2c_subdev_addr);
461
462/* Return a list of I2C tuner addresses to probe. Use only if the tuner
463   addresses are unknown. */
464const unsigned short *v4l2_i2c_tuner_addrs(enum v4l2_i2c_tuner_type type)
465{
466	static const unsigned short radio_addrs[] = {
467#if defined(CONFIG_MEDIA_TUNER_TEA5761) || defined(CONFIG_MEDIA_TUNER_TEA5761_MODULE)
468		0x10,
469#endif
470		0x60,
471		I2C_CLIENT_END
472	};
473	static const unsigned short demod_addrs[] = {
474		0x42, 0x43, 0x4a, 0x4b,
475		I2C_CLIENT_END
476	};
477	static const unsigned short tv_addrs[] = {
478		0x42, 0x43, 0x4a, 0x4b,		/* tda8290 */
479		0x60, 0x61, 0x62, 0x63, 0x64,
480		I2C_CLIENT_END
481	};
482
483	switch (type) {
484	case ADDRS_RADIO:
485		return radio_addrs;
486	case ADDRS_DEMOD:
487		return demod_addrs;
488	case ADDRS_TV:
489		return tv_addrs;
490	case ADDRS_TV_WITH_DEMOD:
491		return tv_addrs + 4;
492	}
493	return NULL;
494}
495EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs);
496
497#endif /* defined(CONFIG_I2C) */
498
499#if defined(CONFIG_SPI)
500
501/* Load a spi sub-device. */
502
503void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
504		const struct v4l2_subdev_ops *ops)
505{
506	v4l2_subdev_init(sd, ops);
507	sd->flags |= V4L2_SUBDEV_FL_IS_SPI;
508	/* the owner is the same as the spi_device's driver owner */
509	sd->owner = spi->dev.driver->owner;
510	/* spi_device and v4l2_subdev point to one another */
511	v4l2_set_subdevdata(sd, spi);
512	spi_set_drvdata(spi, sd);
513	/* initialize name */
514	strlcpy(sd->name, spi->dev.driver->name, sizeof(sd->name));
515}
516EXPORT_SYMBOL_GPL(v4l2_spi_subdev_init);
517
518struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
519		struct spi_master *master, struct spi_board_info *info)
520{
521	struct v4l2_subdev *sd = NULL;
522	struct spi_device *spi = NULL;
523
524	BUG_ON(!v4l2_dev);
525
526	if (info->modalias)
527		request_module(info->modalias);
528
529	spi = spi_new_device(master, info);
530
531	if (spi == NULL || spi->dev.driver == NULL)
532		goto error;
533
534	if (!try_module_get(spi->dev.driver->owner))
535		goto error;
536
537	sd = spi_get_drvdata(spi);
538
539	/* Register with the v4l2_device which increases the module's
540	   use count as well. */
541	if (v4l2_device_register_subdev(v4l2_dev, sd))
542		sd = NULL;
543
544	/* Decrease the module use count to match the first try_module_get. */
545	module_put(spi->dev.driver->owner);
546
547error:
548	/* If we have a client but no subdev, then something went wrong and
549	   we must unregister the client. */
550	if (spi && sd == NULL)
551		spi_unregister_device(spi);
552
553	return sd;
554}
555EXPORT_SYMBOL_GPL(v4l2_spi_new_subdev);
556
557#endif /* defined(CONFIG_SPI) */
558
559/* Clamp x to be between min and max, aligned to a multiple of 2^align.  min
560 * and max don't have to be aligned, but there must be at least one valid
561 * value.  E.g., min=17,max=31,align=4 is not allowed as there are no multiples
562 * of 16 between 17 and 31.  */
563static unsigned int clamp_align(unsigned int x, unsigned int min,
564				unsigned int max, unsigned int align)
565{
566	/* Bits that must be zero to be aligned */
567	unsigned int mask = ~((1 << align) - 1);
568
569	/* Round to nearest aligned value */
570	if (align)
571		x = (x + (1 << (align - 1))) & mask;
572
573	/* Clamp to aligned value of min and max */
574	if (x < min)
575		x = (min + ~mask) & mask;
576	else if (x > max)
577		x = max & mask;
578
579	return x;
580}
581
582/* Bound an image to have a width between wmin and wmax, and height between
583 * hmin and hmax, inclusive.  Additionally, the width will be a multiple of
584 * 2^walign, the height will be a multiple of 2^halign, and the overall size
585 * (width*height) will be a multiple of 2^salign.  The image may be shrunk
586 * or enlarged to fit the alignment constraints.
587 *
588 * The width or height maximum must not be smaller than the corresponding
589 * minimum.  The alignments must not be so high there are no possible image
590 * sizes within the allowed bounds.  wmin and hmin must be at least 1
591 * (don't use 0).  If you don't care about a certain alignment, specify 0,
592 * as 2^0 is 1 and one byte alignment is equivalent to no alignment.  If
593 * you only want to adjust downward, specify a maximum that's the same as
594 * the initial value.
595 */
596void v4l_bound_align_image(u32 *w, unsigned int wmin, unsigned int wmax,
597			   unsigned int walign,
598			   u32 *h, unsigned int hmin, unsigned int hmax,
599			   unsigned int halign, unsigned int salign)
600{
601	*w = clamp_align(*w, wmin, wmax, walign);
602	*h = clamp_align(*h, hmin, hmax, halign);
603
604	/* Usually we don't need to align the size and are done now. */
605	if (!salign)
606		return;
607
608	/* How much alignment do we have? */
609	walign = __ffs(*w);
610	halign = __ffs(*h);
611	/* Enough to satisfy the image alignment? */
612	if (walign + halign < salign) {
613		/* Max walign where there is still a valid width */
614		unsigned int wmaxa = __fls(wmax ^ (wmin - 1));
615		/* Max halign where there is still a valid height */
616		unsigned int hmaxa = __fls(hmax ^ (hmin - 1));
617
618		/* up the smaller alignment until we have enough */
619		do {
620			if (halign >= hmaxa ||
621			    (walign <= halign && walign < wmaxa)) {
622				*w = clamp_align(*w, wmin, wmax, walign + 1);
623				walign = __ffs(*w);
624			} else {
625				*h = clamp_align(*h, hmin, hmax, halign + 1);
626				halign = __ffs(*h);
627			}
628		} while (halign + walign < salign);
629	}
630}
631EXPORT_SYMBOL_GPL(v4l_bound_align_image);
632
633/**
634 * v4l_fill_dv_preset_info - fill description of a digital video preset
635 * @preset - preset value
636 * @info - pointer to struct v4l2_dv_enum_preset
637 *
638 * drivers can use this helper function to fill description of dv preset
639 * in info.
640 */
641int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info)
642{
643	static const struct v4l2_dv_preset_info {
644		u16 width;
645		u16 height;
646		const char *name;
647	} dv_presets[] = {
648		{ 0, 0, "Invalid" },		/* V4L2_DV_INVALID */
649		{ 720,  480, "480p@59.94" },	/* V4L2_DV_480P59_94 */
650		{ 720,  576, "576p@50" },	/* V4L2_DV_576P50 */
651		{ 1280, 720, "720p@24" },	/* V4L2_DV_720P24 */
652		{ 1280, 720, "720p@25" },	/* V4L2_DV_720P25 */
653		{ 1280, 720, "720p@30" },	/* V4L2_DV_720P30 */
654		{ 1280, 720, "720p@50" },	/* V4L2_DV_720P50 */
655		{ 1280, 720, "720p@59.94" },	/* V4L2_DV_720P59_94 */
656		{ 1280, 720, "720p@60" },	/* V4L2_DV_720P60 */
657		{ 1920, 1080, "1080i@29.97" },	/* V4L2_DV_1080I29_97 */
658		{ 1920, 1080, "1080i@30" },	/* V4L2_DV_1080I30 */
659		{ 1920, 1080, "1080i@25" },	/* V4L2_DV_1080I25 */
660		{ 1920, 1080, "1080i@50" },	/* V4L2_DV_1080I50 */
661		{ 1920, 1080, "1080i@60" },	/* V4L2_DV_1080I60 */
662		{ 1920, 1080, "1080p@24" },	/* V4L2_DV_1080P24 */
663		{ 1920, 1080, "1080p@25" },	/* V4L2_DV_1080P25 */
664		{ 1920, 1080, "1080p@30" },	/* V4L2_DV_1080P30 */
665		{ 1920, 1080, "1080p@50" },	/* V4L2_DV_1080P50 */
666		{ 1920, 1080, "1080p@60" },	/* V4L2_DV_1080P60 */
667	};
668
669	if (info == NULL || preset >= ARRAY_SIZE(dv_presets))
670		return -EINVAL;
671
672	info->preset = preset;
673	info->width = dv_presets[preset].width;
674	info->height = dv_presets[preset].height;
675	strlcpy(info->name, dv_presets[preset].name, sizeof(info->name));
676	return 0;
677}
678EXPORT_SYMBOL_GPL(v4l_fill_dv_preset_info);
679