Commit 9488fed6 authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

[media] doc-rst: move videobuf documentation to media/kapi

This document describes a kapi framework. Move it to the right
place.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 4c21d4fb
V4L2 Controls
=============
Introduction Introduction
============ ------------
The V4L2 control API seems simple enough, but quickly becomes very hard to The V4L2 control API seems simple enough, but quickly becomes very hard to
implement correctly in drivers. But much of the code needed to handle controls implement correctly in drivers. But much of the code needed to handle controls
...@@ -26,7 +29,7 @@ for V4L2 drivers and struct v4l2_subdev for sub-device drivers. ...@@ -26,7 +29,7 @@ for V4L2 drivers and struct v4l2_subdev for sub-device drivers.
Objects in the framework Objects in the framework
======================== ------------------------
There are two main objects: There are two main objects:
...@@ -39,12 +42,14 @@ controls, possibly to controls owned by other handlers. ...@@ -39,12 +42,14 @@ controls, possibly to controls owned by other handlers.
Basic usage for V4L2 and sub-device drivers Basic usage for V4L2 and sub-device drivers
=========================================== -------------------------------------------
1) Prepare the driver: 1) Prepare the driver:
1.1) Add the handler to your driver's top-level struct: 1.1) Add the handler to your driver's top-level struct:
.. code-block:: none
struct foo_dev { struct foo_dev {
... ...
struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl_handler ctrl_handler;
...@@ -55,16 +60,20 @@ Basic usage for V4L2 and sub-device drivers ...@@ -55,16 +60,20 @@ Basic usage for V4L2 and sub-device drivers
1.2) Initialize the handler: 1.2) Initialize the handler:
.. code-block:: none
v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls); v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);
The second argument is a hint telling the function how many controls this The second argument is a hint telling the function how many controls this
handler is expected to handle. It will allocate a hashtable based on this handler is expected to handle. It will allocate a hashtable based on this
information. It is a hint only. information. It is a hint only.
1.3) Hook the control handler into the driver: 1.3) Hook the control handler into the driver:
1.3.1) For V4L2 drivers do this: 1.3.1) For V4L2 drivers do this:
.. code-block:: none
struct foo_dev { struct foo_dev {
... ...
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;
...@@ -75,15 +84,17 @@ Basic usage for V4L2 and sub-device drivers ...@@ -75,15 +84,17 @@ Basic usage for V4L2 and sub-device drivers
foo->v4l2_dev.ctrl_handler = &foo->ctrl_handler; foo->v4l2_dev.ctrl_handler = &foo->ctrl_handler;
Where foo->v4l2_dev is of type struct v4l2_device. Where foo->v4l2_dev is of type struct v4l2_device.
Finally, remove all control functions from your v4l2_ioctl_ops (if any): Finally, remove all control functions from your v4l2_ioctl_ops (if any):
vidioc_queryctrl, vidioc_query_ext_ctrl, vidioc_querymenu, vidioc_g_ctrl, vidioc_queryctrl, vidioc_query_ext_ctrl, vidioc_querymenu, vidioc_g_ctrl,
vidioc_s_ctrl, vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls. vidioc_s_ctrl, vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls.
Those are now no longer needed. Those are now no longer needed.
1.3.2) For sub-device drivers do this: 1.3.2) For sub-device drivers do this:
.. code-block:: none
struct foo_dev { struct foo_dev {
... ...
struct v4l2_subdev sd; struct v4l2_subdev sd;
...@@ -94,10 +105,12 @@ Basic usage for V4L2 and sub-device drivers ...@@ -94,10 +105,12 @@ Basic usage for V4L2 and sub-device drivers
foo->sd.ctrl_handler = &foo->ctrl_handler; foo->sd.ctrl_handler = &foo->ctrl_handler;
Where foo->sd is of type struct v4l2_subdev. Where foo->sd is of type struct v4l2_subdev.
And set all core control ops in your struct v4l2_subdev_core_ops to these And set all core control ops in your struct v4l2_subdev_core_ops to these
helpers: helpers:
.. code-block:: none
.queryctrl = v4l2_subdev_queryctrl, .queryctrl = v4l2_subdev_queryctrl,
.querymenu = v4l2_subdev_querymenu, .querymenu = v4l2_subdev_querymenu,
...@@ -107,12 +120,14 @@ Basic usage for V4L2 and sub-device drivers ...@@ -107,12 +120,14 @@ Basic usage for V4L2 and sub-device drivers
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls, .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
.s_ext_ctrls = v4l2_subdev_s_ext_ctrls, .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
Note: this is a temporary solution only. Once all V4L2 drivers that depend Note: this is a temporary solution only. Once all V4L2 drivers that depend
on subdev drivers are converted to the control framework these helpers will on subdev drivers are converted to the control framework these helpers will
no longer be needed. no longer be needed.
1.4) Clean up the handler at the end: 1.4) Clean up the handler at the end:
.. code-block:: none
v4l2_ctrl_handler_free(&foo->ctrl_handler); v4l2_ctrl_handler_free(&foo->ctrl_handler);
...@@ -120,12 +135,16 @@ Basic usage for V4L2 and sub-device drivers ...@@ -120,12 +135,16 @@ Basic usage for V4L2 and sub-device drivers
You add non-menu controls by calling v4l2_ctrl_new_std: You add non-menu controls by calling v4l2_ctrl_new_std:
.. code-block:: none
struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops, const struct v4l2_ctrl_ops *ops,
u32 id, s32 min, s32 max, u32 step, s32 def); u32 id, s32 min, s32 max, u32 step, s32 def);
Menu and integer menu controls are added by calling v4l2_ctrl_new_std_menu: Menu and integer menu controls are added by calling v4l2_ctrl_new_std_menu:
.. code-block:: none
struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops, const struct v4l2_ctrl_ops *ops,
u32 id, s32 max, s32 skip_mask, s32 def); u32 id, s32 max, s32 skip_mask, s32 def);
...@@ -133,6 +152,8 @@ Menu and integer menu controls are added by calling v4l2_ctrl_new_std_menu: ...@@ -133,6 +152,8 @@ Menu and integer menu controls are added by calling v4l2_ctrl_new_std_menu:
Menu controls with a driver specific menu are added by calling Menu controls with a driver specific menu are added by calling
v4l2_ctrl_new_std_menu_items: v4l2_ctrl_new_std_menu_items:
.. code-block:: none
struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items( struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(
struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops, u32 id, s32 max, const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
...@@ -141,12 +162,16 @@ v4l2_ctrl_new_std_menu_items: ...@@ -141,12 +162,16 @@ v4l2_ctrl_new_std_menu_items:
Integer menu controls with a driver specific menu can be added by calling Integer menu controls with a driver specific menu can be added by calling
v4l2_ctrl_new_int_menu: v4l2_ctrl_new_int_menu:
.. code-block:: none
struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl, struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops, const struct v4l2_ctrl_ops *ops,
u32 id, s32 max, s32 def, const s64 *qmenu_int); u32 id, s32 max, s32 def, const s64 *qmenu_int);
These functions are typically called right after the v4l2_ctrl_handler_init: These functions are typically called right after the v4l2_ctrl_handler_init:
.. code-block:: none
static const s64 exp_bias_qmenu[] = { static const s64 exp_bias_qmenu[] = {
-2, -1, 0, 1, 2 -2, -1, 0, 1, 2
}; };
...@@ -223,6 +248,8 @@ a bit faster that way. ...@@ -223,6 +248,8 @@ a bit faster that way.
3) Optionally force initial control setup: 3) Optionally force initial control setup:
.. code-block:: none
v4l2_ctrl_handler_setup(&foo->ctrl_handler); v4l2_ctrl_handler_setup(&foo->ctrl_handler);
This will call s_ctrl for all controls unconditionally. Effectively this This will call s_ctrl for all controls unconditionally. Effectively this
...@@ -232,12 +259,16 @@ the hardware are in sync. ...@@ -232,12 +259,16 @@ the hardware are in sync.
4) Finally: implement the v4l2_ctrl_ops 4) Finally: implement the v4l2_ctrl_ops
.. code-block:: none
static const struct v4l2_ctrl_ops foo_ctrl_ops = { static const struct v4l2_ctrl_ops foo_ctrl_ops = {
.s_ctrl = foo_s_ctrl, .s_ctrl = foo_s_ctrl,
}; };
Usually all you need is s_ctrl: Usually all you need is s_ctrl:
.. code-block:: none
static int foo_s_ctrl(struct v4l2_ctrl *ctrl) static int foo_s_ctrl(struct v4l2_ctrl *ctrl)
{ {
struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler); struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler);
...@@ -262,16 +293,14 @@ to do any validation of control values, or implement QUERYCTRL, QUERY_EXT_CTRL ...@@ -262,16 +293,14 @@ to do any validation of control values, or implement QUERYCTRL, QUERY_EXT_CTRL
and QUERYMENU. And G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported. and QUERYMENU. And G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported.
============================================================================== .. note::
The remainder of this document deals with more advanced topics and scenarios. The remainder sections deal with more advanced controls topics and scenarios.
In practice the basic usage as described above is sufficient for most drivers. In practice the basic usage as described above is sufficient for most drivers.
===============================================================================
Inheriting Controls Inheriting Controls
=================== -------------------
When a sub-device is registered with a V4L2 driver by calling When a sub-device is registered with a V4L2 driver by calling
v4l2_device_register_subdev() and the ctrl_handler fields of both v4l2_subdev v4l2_device_register_subdev() and the ctrl_handler fields of both v4l2_subdev
...@@ -286,21 +315,25 @@ of v4l2_device. ...@@ -286,21 +315,25 @@ of v4l2_device.
Accessing Control Values Accessing Control Values
======================== ------------------------
The following union is used inside the control framework to access control The following union is used inside the control framework to access control
values: values:
union v4l2_ctrl_ptr { .. code-block:: none
union v4l2_ctrl_ptr {
s32 *p_s32; s32 *p_s32;
s64 *p_s64; s64 *p_s64;
char *p_char; char *p_char;
void *p; void *p;
}; };
The v4l2_ctrl struct contains these fields that can be used to access both The v4l2_ctrl struct contains these fields that can be used to access both
current and new values: current and new values:
.. code-block:: none
s32 val; s32 val;
struct { struct {
s32 val; s32 val;
...@@ -312,6 +345,8 @@ current and new values: ...@@ -312,6 +345,8 @@ current and new values:
If the control has a simple s32 type type, then: If the control has a simple s32 type type, then:
.. code-block:: none
&ctrl->val == ctrl->p_new.p_s32 &ctrl->val == ctrl->p_new.p_s32
&ctrl->cur.val == ctrl->p_cur.p_s32 &ctrl->cur.val == ctrl->p_cur.p_s32
...@@ -334,6 +369,8 @@ exception is for controls that return a volatile register such as a signal ...@@ -334,6 +369,8 @@ exception is for controls that return a volatile register such as a signal
strength read-out that changes continuously. In that case you will need to strength read-out that changes continuously. In that case you will need to
implement g_volatile_ctrl like this: implement g_volatile_ctrl like this:
.. code-block:: none
static int foo_g_volatile_ctrl(struct v4l2_ctrl *ctrl) static int foo_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{ {
switch (ctrl->id) { switch (ctrl->id) {
...@@ -350,6 +387,8 @@ changes. ...@@ -350,6 +387,8 @@ changes.
To mark a control as volatile you have to set V4L2_CTRL_FLAG_VOLATILE: To mark a control as volatile you have to set V4L2_CTRL_FLAG_VOLATILE:
.. code-block:: none
ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...); ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...);
if (ctrl) if (ctrl)
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE; ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
...@@ -369,6 +408,8 @@ not to introduce deadlocks. ...@@ -369,6 +408,8 @@ not to introduce deadlocks.
Outside of the control ops you have to go through to helper functions to get Outside of the control ops you have to go through to helper functions to get
or set a single control value safely in your driver: or set a single control value safely in your driver:
.. code-block:: none
s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl); s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val); int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
...@@ -378,6 +419,8 @@ will result in a deadlock since these helpers lock the handler as well. ...@@ -378,6 +419,8 @@ will result in a deadlock since these helpers lock the handler as well.
You can also take the handler lock yourself: You can also take the handler lock yourself:
.. code-block:: none
mutex_lock(&state->ctrl_handler.lock); mutex_lock(&state->ctrl_handler.lock);
pr_info("String value is '%s'\n", ctrl1->p_cur.p_char); pr_info("String value is '%s'\n", ctrl1->p_cur.p_char);
pr_info("Integer value is '%s'\n", ctrl2->cur.val); pr_info("Integer value is '%s'\n", ctrl2->cur.val);
...@@ -385,10 +428,12 @@ You can also take the handler lock yourself: ...@@ -385,10 +428,12 @@ You can also take the handler lock yourself:
Menu Controls Menu Controls
============= -------------
The v4l2_ctrl struct contains this union: The v4l2_ctrl struct contains this union:
.. code-block:: none
union { union {
u32 step; u32 step;
u32 menu_skip_mask; u32 menu_skip_mask;
...@@ -411,10 +456,12 @@ control, or by calling v4l2_ctrl_new_std_menu(). ...@@ -411,10 +456,12 @@ control, or by calling v4l2_ctrl_new_std_menu().
Custom Controls Custom Controls
=============== ---------------
Driver specific controls can be created using v4l2_ctrl_new_custom(): Driver specific controls can be created using v4l2_ctrl_new_custom():
.. code-block:: none
static const struct v4l2_ctrl_config ctrl_filter = { static const struct v4l2_ctrl_config ctrl_filter = {
.ops = &ctrl_custom_ops, .ops = &ctrl_custom_ops,
.id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER, .id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
...@@ -437,7 +484,7 @@ control and will fill in the name, type and flags fields accordingly. ...@@ -437,7 +484,7 @@ control and will fill in the name, type and flags fields accordingly.
Active and Grabbed Controls Active and Grabbed Controls
=========================== ---------------------------
If you get more complex relationships between controls, then you may have to If you get more complex relationships between controls, then you may have to
activate and deactivate controls. For example, if the Chroma AGC control is activate and deactivate controls. For example, if the Chroma AGC control is
...@@ -461,16 +508,18 @@ starts or stops streaming. ...@@ -461,16 +508,18 @@ starts or stops streaming.
Control Clusters Control Clusters
================ ----------------
By default all controls are independent from the others. But in more By default all controls are independent from the others. But in more
complex scenarios you can get dependencies from one control to another. complex scenarios you can get dependencies from one control to another.
In that case you need to 'cluster' them: In that case you need to 'cluster' them:
.. code-block:: none
struct foo { struct foo {
struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl_handler ctrl_handler;
#define AUDIO_CL_VOLUME (0) #define AUDIO_CL_VOLUME (0)
#define AUDIO_CL_MUTE (1) #define AUDIO_CL_MUTE (1)
struct v4l2_ctrl *audio_cluster[2]; struct v4l2_ctrl *audio_cluster[2];
... ...
}; };
...@@ -489,6 +538,8 @@ composite control. Similar to how a 'struct' works in C. ...@@ -489,6 +538,8 @@ composite control. Similar to how a 'struct' works in C.
So when s_ctrl is called with V4L2_CID_AUDIO_VOLUME as argument, you should set So when s_ctrl is called with V4L2_CID_AUDIO_VOLUME as argument, you should set
all two controls belonging to the audio_cluster: all two controls belonging to the audio_cluster:
.. code-block:: none
static int foo_s_ctrl(struct v4l2_ctrl *ctrl) static int foo_s_ctrl(struct v4l2_ctrl *ctrl)
{ {
struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler); struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler);
...@@ -509,12 +560,16 @@ all two controls belonging to the audio_cluster: ...@@ -509,12 +560,16 @@ all two controls belonging to the audio_cluster:
In the example above the following are equivalent for the VOLUME case: In the example above the following are equivalent for the VOLUME case:
.. code-block:: none
ctrl == ctrl->cluster[AUDIO_CL_VOLUME] == state->audio_cluster[AUDIO_CL_VOLUME] ctrl == ctrl->cluster[AUDIO_CL_VOLUME] == state->audio_cluster[AUDIO_CL_VOLUME]
ctrl->cluster[AUDIO_CL_MUTE] == state->audio_cluster[AUDIO_CL_MUTE] ctrl->cluster[AUDIO_CL_MUTE] == state->audio_cluster[AUDIO_CL_MUTE]
In practice using cluster arrays like this becomes very tiresome. So instead In practice using cluster arrays like this becomes very tiresome. So instead
the following equivalent method is used: the following equivalent method is used:
.. code-block:: none
struct { struct {
/* audio cluster */ /* audio cluster */
struct v4l2_ctrl *volume; struct v4l2_ctrl *volume;
...@@ -525,6 +580,8 @@ The anonymous struct is used to clearly 'cluster' these two control pointers, ...@@ -525,6 +580,8 @@ The anonymous struct is used to clearly 'cluster' these two control pointers,
but it serves no other purpose. The effect is the same as creating an but it serves no other purpose. The effect is the same as creating an
array with two control pointers. So you can just do: array with two control pointers. So you can just do:
.. code-block:: none
state->volume = v4l2_ctrl_new_std(&state->ctrl_handler, ...); state->volume = v4l2_ctrl_new_std(&state->ctrl_handler, ...);
state->mute = v4l2_ctrl_new_std(&state->ctrl_handler, ...); state->mute = v4l2_ctrl_new_std(&state->ctrl_handler, ...);
v4l2_ctrl_cluster(2, &state->volume); v4l2_ctrl_cluster(2, &state->volume);
...@@ -554,7 +611,7 @@ The 'is_new' flag is always 1 when called from v4l2_ctrl_handler_setup(). ...@@ -554,7 +611,7 @@ The 'is_new' flag is always 1 when called from v4l2_ctrl_handler_setup().
Handling autogain/gain-type Controls with Auto Clusters Handling autogain/gain-type Controls with Auto Clusters
======================================================= -------------------------------------------------------
A common type of control cluster is one that handles 'auto-foo/foo'-type A common type of control cluster is one that handles 'auto-foo/foo'-type
controls. Typical examples are autogain/gain, autoexposure/exposure, controls. Typical examples are autogain/gain, autoexposure/exposure,
...@@ -579,7 +636,9 @@ changing that control affects the control flags of the manual controls. ...@@ -579,7 +636,9 @@ changing that control affects the control flags of the manual controls.
In order to simplify this a special variation of v4l2_ctrl_cluster was In order to simplify this a special variation of v4l2_ctrl_cluster was
introduced: introduced:
void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls, .. code-block:: none
void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
u8 manual_val, bool set_volatile); u8 manual_val, bool set_volatile);
The first two arguments are identical to v4l2_ctrl_cluster. The third argument The first two arguments are identical to v4l2_ctrl_cluster. The third argument
...@@ -597,7 +656,7 @@ flag and volatile handling. ...@@ -597,7 +656,7 @@ flag and volatile handling.
VIDIOC_LOG_STATUS Support VIDIOC_LOG_STATUS Support
========================= -------------------------
This ioctl allow you to dump the current status of a driver to the kernel log. This ioctl allow you to dump the current status of a driver to the kernel log.
The v4l2_ctrl_handler_log_status(ctrl_handler, prefix) can be used to dump the The v4l2_ctrl_handler_log_status(ctrl_handler, prefix) can be used to dump the
...@@ -607,7 +666,7 @@ for you. ...@@ -607,7 +666,7 @@ for you.
Different Handlers for Different Video Nodes Different Handlers for Different Video Nodes
============================================ --------------------------------------------
Usually the V4L2 driver has just one control handler that is global for Usually the V4L2 driver has just one control handler that is global for
all video nodes. But you can also specify different control handlers for all video nodes. But you can also specify different control handlers for
...@@ -632,6 +691,8 @@ of another handler (e.g. for a video device node), then you should first add ...@@ -632,6 +691,8 @@ of another handler (e.g. for a video device node), then you should first add
the controls to the first handler, add the other controls to the second the controls to the first handler, add the other controls to the second
handler and finally add the first handler to the second. For example: handler and finally add the first handler to the second. For example:
.. code-block:: none
v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_VOLUME, ...); v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_VOLUME, ...);
v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...); v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...); v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...);
...@@ -644,6 +705,8 @@ all controls. ...@@ -644,6 +705,8 @@ all controls.
Or you can add specific controls to a handler: Or you can add specific controls to a handler:
.. code-block:: none
volume = v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_AUDIO_VOLUME, ...); volume = v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_AUDIO_VOLUME, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...); v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...); v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...);
...@@ -651,6 +714,8 @@ Or you can add specific controls to a handler: ...@@ -651,6 +714,8 @@ Or you can add specific controls to a handler:
What you should not do is make two identical controls for two handlers. What you should not do is make two identical controls for two handlers.
For example: For example:
.. code-block:: none
v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...); v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...);
v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_AUDIO_MUTE, ...); v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_AUDIO_MUTE, ...);
...@@ -660,7 +725,7 @@ can twiddle. ...@@ -660,7 +725,7 @@ can twiddle.
Finding Controls Finding Controls
================ ----------------
Normally you have created the controls yourself and you can store the struct Normally you have created the controls yourself and you can store the struct
v4l2_ctrl pointer into your own struct. v4l2_ctrl pointer into your own struct.
...@@ -670,6 +735,8 @@ not own. For example, if you have to find a volume control from a subdev. ...@@ -670,6 +735,8 @@ not own. For example, if you have to find a volume control from a subdev.
You can do that by calling v4l2_ctrl_find: You can do that by calling v4l2_ctrl_find:
.. code-block:: none
struct v4l2_ctrl *volume; struct v4l2_ctrl *volume;
volume = v4l2_ctrl_find(sd->ctrl_handler, V4L2_CID_AUDIO_VOLUME); volume = v4l2_ctrl_find(sd->ctrl_handler, V4L2_CID_AUDIO_VOLUME);
...@@ -677,6 +744,8 @@ You can do that by calling v4l2_ctrl_find: ...@@ -677,6 +744,8 @@ You can do that by calling v4l2_ctrl_find:
Since v4l2_ctrl_find will lock the handler you have to be careful where you Since v4l2_ctrl_find will lock the handler you have to be careful where you
use it. For example, this is not a good idea: use it. For example, this is not a good idea:
.. code-block:: none
struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl_handler ctrl_handler;
v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...); v4l2_ctrl_new_std(&ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...);
...@@ -684,6 +753,8 @@ use it. For example, this is not a good idea: ...@@ -684,6 +753,8 @@ use it. For example, this is not a good idea:
...and in video_ops.s_ctrl: ...and in video_ops.s_ctrl:
.. code-block:: none
case V4L2_CID_BRIGHTNESS: case V4L2_CID_BRIGHTNESS:
contrast = v4l2_find_ctrl(&ctrl_handler, V4L2_CID_CONTRAST); contrast = v4l2_find_ctrl(&ctrl_handler, V4L2_CID_CONTRAST);
... ...
...@@ -695,7 +766,7 @@ It is recommended not to use this function from inside the control ops. ...@@ -695,7 +766,7 @@ It is recommended not to use this function from inside the control ops.
Inheriting Controls Inheriting Controls
=================== -------------------
When one control handler is added to another using v4l2_ctrl_add_handler, then When one control handler is added to another using v4l2_ctrl_add_handler, then
by default all controls from one are merged to the other. But a subdev might by default all controls from one are merged to the other. But a subdev might
...@@ -704,6 +775,8 @@ not when it is used in consumer-level hardware. In that case you want to keep ...@@ -704,6 +775,8 @@ not when it is used in consumer-level hardware. In that case you want to keep
those low-level controls local to the subdev. You can do this by simply those low-level controls local to the subdev. You can do this by simply
setting the 'is_private' flag of the control to 1: setting the 'is_private' flag of the control to 1:
.. code-block:: none
static const struct v4l2_ctrl_config ctrl_private = { static const struct v4l2_ctrl_config ctrl_private = {
.ops = &ctrl_custom_ops, .ops = &ctrl_custom_ops,
.id = V4L2_CID_..., .id = V4L2_CID_...,
...@@ -720,7 +793,7 @@ These controls will now be skipped when v4l2_ctrl_add_handler is called. ...@@ -720,7 +793,7 @@ These controls will now be skipped when v4l2_ctrl_add_handler is called.
V4L2_CTRL_TYPE_CTRL_CLASS Controls V4L2_CTRL_TYPE_CTRL_CLASS Controls
================================== ----------------------------------
Controls of this type can be used by GUIs to get the name of the control class. Controls of this type can be used by GUIs to get the name of the control class.
A fully featured GUI can make a dialog with multiple tabs with each tab A fully featured GUI can make a dialog with multiple tabs with each tab
...@@ -733,13 +806,15 @@ class is added. ...@@ -733,13 +806,15 @@ class is added.
Adding Notify Callbacks Adding Notify Callbacks
======================= -----------------------
Sometimes the platform or bridge driver needs to be notified when a control Sometimes the platform or bridge driver needs to be notified when a control
from a sub-device driver changes. You can set a notify callback by calling from a sub-device driver changes. You can set a notify callback by calling
this function: this function:
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, .. code-block:: none
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl,
void (*notify)(struct v4l2_ctrl *ctrl, void *priv), void *priv); void (*notify)(struct v4l2_ctrl *ctrl, void *priv), void *priv);
Whenever the give control changes value the notify callback will be called Whenever the give control changes value the notify callback will be called
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment