mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 22:51:42 +00:00
[media] doc-rst: move videobuf documentation to media/kapi
This document describes a kapi framework. Move it to the right place. Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
This commit is contained in:
parent
4c21d4fb1b
commit
9488fed623
@ -1,5 +1,8 @@
|
||||
V4L2 Controls
|
||||
=============
|
||||
|
||||
Introduction
|
||||
============
|
||||
------------
|
||||
|
||||
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
|
||||
@ -26,7 +29,7 @@ for V4L2 drivers and struct v4l2_subdev for sub-device drivers.
|
||||
|
||||
|
||||
Objects in the framework
|
||||
========================
|
||||
------------------------
|
||||
|
||||
There are two main objects:
|
||||
|
||||
@ -39,12 +42,14 @@ controls, possibly to controls owned by other handlers.
|
||||
|
||||
|
||||
Basic usage for V4L2 and sub-device drivers
|
||||
===========================================
|
||||
-------------------------------------------
|
||||
|
||||
1) Prepare the driver:
|
||||
|
||||
1.1) Add the handler to your driver's top-level struct:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
struct foo_dev {
|
||||
...
|
||||
struct v4l2_ctrl_handler ctrl_handler;
|
||||
@ -55,16 +60,20 @@ Basic usage for V4L2 and sub-device drivers
|
||||
|
||||
1.2) Initialize the handler:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);
|
||||
|
||||
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
|
||||
information. It is a hint only.
|
||||
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
|
||||
information. It is a hint only.
|
||||
|
||||
1.3) Hook the control handler into the driver:
|
||||
|
||||
1.3.1) For V4L2 drivers do this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
struct foo_dev {
|
||||
...
|
||||
struct v4l2_device v4l2_dev;
|
||||
@ -75,15 +84,17 @@ Basic usage for V4L2 and sub-device drivers
|
||||
|
||||
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):
|
||||
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.
|
||||
Those are now no longer needed.
|
||||
Finally, remove all control functions from your v4l2_ioctl_ops (if any):
|
||||
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.
|
||||
Those are now no longer needed.
|
||||
|
||||
1.3.2) For sub-device drivers do this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
struct foo_dev {
|
||||
...
|
||||
struct v4l2_subdev sd;
|
||||
@ -94,10 +105,12 @@ Basic usage for V4L2 and sub-device drivers
|
||||
|
||||
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
|
||||
helpers:
|
||||
And set all core control ops in your struct v4l2_subdev_core_ops to these
|
||||
helpers:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
.queryctrl = v4l2_subdev_queryctrl,
|
||||
.querymenu = v4l2_subdev_querymenu,
|
||||
@ -107,12 +120,14 @@ Basic usage for V4L2 and sub-device drivers
|
||||
.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
|
||||
.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
|
||||
|
||||
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
|
||||
no longer be needed.
|
||||
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
|
||||
no longer be needed.
|
||||
|
||||
1.4) Clean up the handler at the end:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
v4l2_ctrl_handler_free(&foo->ctrl_handler);
|
||||
|
||||
|
||||
@ -120,12 +135,16 @@ Basic usage for V4L2 and sub-device drivers
|
||||
|
||||
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,
|
||||
const struct v4l2_ctrl_ops *ops,
|
||||
u32 id, s32 min, s32 max, u32 step, s32 def);
|
||||
|
||||
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,
|
||||
const struct v4l2_ctrl_ops *ops,
|
||||
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:
|
||||
Menu controls with a driver specific menu are added by calling
|
||||
v4l2_ctrl_new_std_menu_items:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(
|
||||
struct v4l2_ctrl_handler *hdl,
|
||||
const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
|
||||
@ -141,12 +162,16 @@ v4l2_ctrl_new_std_menu_items:
|
||||
Integer menu controls with a driver specific menu can be added by calling
|
||||
v4l2_ctrl_new_int_menu:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
|
||||
const struct v4l2_ctrl_ops *ops,
|
||||
u32 id, s32 max, s32 def, const s64 *qmenu_int);
|
||||
|
||||
These functions are typically called right after the v4l2_ctrl_handler_init:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
static const s64 exp_bias_qmenu[] = {
|
||||
-2, -1, 0, 1, 2
|
||||
};
|
||||
@ -223,6 +248,8 @@ a bit faster that way.
|
||||
|
||||
3) Optionally force initial control setup:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
v4l2_ctrl_handler_setup(&foo->ctrl_handler);
|
||||
|
||||
This will call s_ctrl for all controls unconditionally. Effectively this
|
||||
@ -232,12 +259,16 @@ the hardware are in sync.
|
||||
|
||||
4) Finally: implement the v4l2_ctrl_ops
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
static const struct v4l2_ctrl_ops foo_ctrl_ops = {
|
||||
.s_ctrl = foo_s_ctrl,
|
||||
};
|
||||
|
||||
Usually all you need is s_ctrl:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
static int foo_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
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
|
||||
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.
|
||||
In practice the basic usage as described above is sufficient for most drivers.
|
||||
|
||||
===============================================================================
|
||||
The remainder sections deal with more advanced controls topics and scenarios.
|
||||
In practice the basic usage as described above is sufficient for most drivers.
|
||||
|
||||
|
||||
Inheriting Controls
|
||||
===================
|
||||
-------------------
|
||||
|
||||
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
|
||||
@ -286,21 +315,25 @@ of v4l2_device.
|
||||
|
||||
|
||||
Accessing Control Values
|
||||
========================
|
||||
------------------------
|
||||
|
||||
The following union is used inside the control framework to access control
|
||||
values:
|
||||
|
||||
union v4l2_ctrl_ptr {
|
||||
s32 *p_s32;
|
||||
s64 *p_s64;
|
||||
char *p_char;
|
||||
void *p;
|
||||
};
|
||||
.. code-block:: none
|
||||
|
||||
union v4l2_ctrl_ptr {
|
||||
s32 *p_s32;
|
||||
s64 *p_s64;
|
||||
char *p_char;
|
||||
void *p;
|
||||
};
|
||||
|
||||
The v4l2_ctrl struct contains these fields that can be used to access both
|
||||
current and new values:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
s32 val;
|
||||
struct {
|
||||
s32 val;
|
||||
@ -312,6 +345,8 @@ current and new values:
|
||||
|
||||
If the control has a simple s32 type type, then:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
&ctrl->val == ctrl->p_new.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
|
||||
strength read-out that changes continuously. In that case you will need to
|
||||
implement g_volatile_ctrl like this:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
static int foo_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
switch (ctrl->id) {
|
||||
@ -350,6 +387,8 @@ changes.
|
||||
|
||||
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, ...);
|
||||
if (ctrl)
|
||||
ctrl->flags |= V4L2_CTRL_FLAG_VOLATILE;
|
||||
@ -369,6 +408,8 @@ not to introduce deadlocks.
|
||||
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:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
|
||||
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.
|
||||
|
||||
You can also take the handler lock yourself:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
mutex_lock(&state->ctrl_handler.lock);
|
||||
pr_info("String value is '%s'\n", ctrl1->p_cur.p_char);
|
||||
pr_info("Integer value is '%s'\n", ctrl2->cur.val);
|
||||
@ -385,10 +428,12 @@ You can also take the handler lock yourself:
|
||||
|
||||
|
||||
Menu Controls
|
||||
=============
|
||||
-------------
|
||||
|
||||
The v4l2_ctrl struct contains this union:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
union {
|
||||
u32 step;
|
||||
u32 menu_skip_mask;
|
||||
@ -411,10 +456,12 @@ control, or by calling v4l2_ctrl_new_std_menu().
|
||||
|
||||
|
||||
Custom Controls
|
||||
===============
|
||||
---------------
|
||||
|
||||
Driver specific controls can be created using v4l2_ctrl_new_custom():
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
static const struct v4l2_ctrl_config ctrl_filter = {
|
||||
.ops = &ctrl_custom_ops,
|
||||
.id = V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER,
|
||||
@ -437,7 +484,7 @@ control and will fill in the name, type and flags fields accordingly.
|
||||
|
||||
|
||||
Active and Grabbed Controls
|
||||
===========================
|
||||
---------------------------
|
||||
|
||||
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
|
||||
@ -461,16 +508,18 @@ starts or stops streaming.
|
||||
|
||||
|
||||
Control Clusters
|
||||
================
|
||||
----------------
|
||||
|
||||
By default all controls are independent from the others. But in more
|
||||
complex scenarios you can get dependencies from one control to another.
|
||||
In that case you need to 'cluster' them:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
struct foo {
|
||||
struct v4l2_ctrl_handler ctrl_handler;
|
||||
#define AUDIO_CL_VOLUME (0)
|
||||
#define AUDIO_CL_MUTE (1)
|
||||
#define AUDIO_CL_VOLUME (0)
|
||||
#define AUDIO_CL_MUTE (1)
|
||||
struct v4l2_ctrl *audio_cluster[2];
|
||||
...
|
||||
};
|
||||
@ -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
|
||||
all two controls belonging to the audio_cluster:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
static int foo_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
{
|
||||
struct foo *state = container_of(ctrl->handler, struct foo, ctrl_handler);
|
||||
@ -509,12 +560,16 @@ all two controls belonging to the audio_cluster:
|
||||
|
||||
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->cluster[AUDIO_CL_MUTE] == state->audio_cluster[AUDIO_CL_MUTE]
|
||||
|
||||
In practice using cluster arrays like this becomes very tiresome. So instead
|
||||
the following equivalent method is used:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
struct {
|
||||
/* audio cluster */
|
||||
struct v4l2_ctrl *volume;
|
||||
@ -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
|
||||
array with two control pointers. So you can just do:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
state->volume = v4l2_ctrl_new_std(&state->ctrl_handler, ...);
|
||||
state->mute = v4l2_ctrl_new_std(&state->ctrl_handler, ...);
|
||||
v4l2_ctrl_cluster(2, &state->volume);
|
||||
@ -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
|
||||
=======================================================
|
||||
-------------------------------------------------------
|
||||
|
||||
A common type of control cluster is one that handles 'auto-foo/foo'-type
|
||||
controls. Typical examples are autogain/gain, autoexposure/exposure,
|
||||
@ -579,8 +636,10 @@ changing that control affects the control flags of the manual controls.
|
||||
In order to simplify this a special variation of v4l2_ctrl_cluster was
|
||||
introduced:
|
||||
|
||||
void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
|
||||
u8 manual_val, bool set_volatile);
|
||||
.. code-block:: none
|
||||
|
||||
void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
|
||||
u8 manual_val, bool set_volatile);
|
||||
|
||||
The first two arguments are identical to v4l2_ctrl_cluster. The third argument
|
||||
tells the framework which value switches the cluster into manual mode. The
|
||||
@ -597,7 +656,7 @@ flag and volatile handling.
|
||||
|
||||
|
||||
VIDIOC_LOG_STATUS Support
|
||||
=========================
|
||||
-------------------------
|
||||
|
||||
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
|
||||
@ -607,7 +666,7 @@ for you.
|
||||
|
||||
|
||||
Different Handlers for Different Video Nodes
|
||||
============================================
|
||||
--------------------------------------------
|
||||
|
||||
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
|
||||
@ -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
|
||||
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_MUTE, ...);
|
||||
v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...);
|
||||
@ -644,6 +705,8 @@ all controls.
|
||||
|
||||
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, ...);
|
||||
v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_BRIGHTNESS, ...);
|
||||
v4l2_ctrl_new_std(&video_ctrl_handler, &ops, V4L2_CID_CONTRAST, ...);
|
||||
@ -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.
|
||||
For example:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
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, ...);
|
||||
|
||||
@ -660,7 +725,7 @@ can twiddle.
|
||||
|
||||
|
||||
Finding Controls
|
||||
================
|
||||
----------------
|
||||
|
||||
Normally you have created the controls yourself and you can store the 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.
|
||||
|
||||
You can do that by calling v4l2_ctrl_find:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
struct v4l2_ctrl *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:
|
||||
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:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
struct v4l2_ctrl_handler ctrl_handler;
|
||||
|
||||
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:
|
||||
|
||||
...and in video_ops.s_ctrl:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
case V4L2_CID_BRIGHTNESS:
|
||||
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.
|
||||
|
||||
|
||||
Inheriting Controls
|
||||
===================
|
||||
-------------------
|
||||
|
||||
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
|
||||
@ -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
|
||||
setting the 'is_private' flag of the control to 1:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
static const struct v4l2_ctrl_config ctrl_private = {
|
||||
.ops = &ctrl_custom_ops,
|
||||
.id = V4L2_CID_...,
|
||||
@ -720,7 +793,7 @@ These controls will now be skipped when v4l2_ctrl_add_handler is called.
|
||||
|
||||
|
||||
V4L2_CTRL_TYPE_CTRL_CLASS Controls
|
||||
==================================
|
||||
----------------------------------
|
||||
|
||||
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
|
||||
@ -733,14 +806,16 @@ class is added.
|
||||
|
||||
|
||||
Adding Notify Callbacks
|
||||
=======================
|
||||
-----------------------
|
||||
|
||||
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
|
||||
this function:
|
||||
|
||||
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl,
|
||||
void (*notify)(struct v4l2_ctrl *ctrl, void *priv), void *priv);
|
||||
.. code-block:: none
|
||||
|
||||
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl,
|
||||
void (*notify)(struct v4l2_ctrl *ctrl, void *priv), void *priv);
|
||||
|
||||
Whenever the give control changes value the notify callback will be called
|
||||
with a pointer to the control and the priv pointer that was passed with
|
||||
|
Loading…
Reference in New Issue
Block a user