media updates for v5.3-rc1

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAl0kcloACgkQCF8+vY7k
 4RU0Mg//c0BK1VjPfh45k3HxDvvoQnaTlQjo1ApvEBa64TR10/JxXi9U+QuhY1H1
 QEOjJJrLe3OdWrcBwFT5s15cBdRKn6jB8s67FgN7CFA8IzG4xBjOovOP4MXYXztz
 TjNlkLwWkkwiQ4C99HInSsmI36ZbnEI3PloJXMrEBnsXQIazjRzMeJ3DKZggSSkN
 jhedASDgnHgSun0rCFh0mN8k2kiMUZ/XxVIqiCuWT1AzyycoHp+HXm9YilnxD7q0
 43X6v4HtxrfJMQWQ8z3Pxb4McHc1j3L8S7Mgu9oSf7oJb12grsDxokytUCnmhFz8
 gvNgx3D2OTQk2nrQlxcfgrbqMs2KXLkXIiqg/dZ35hpNfXIOxiOx77zqqIsg2WHr
 j4qaDcw+TNQU1eUIm0dIcPFi82EMOjAUqHRrvsg94EbBQ1dUniE4GCkCHFU+2TLz
 YIaWXv/WmavrWTydsoIKqbBBOR9OY9+PDjkxgHsSVPSZ9sAskcPQ5MJdkatoZcu/
 glZJD8HEe/w1vi1Ob3ZsXU7KzNWAhIkWvtEWsxAuFGzr8uNfwmzM2a5giNLIV94b
 W+ZYhQT363uliVSOPFRjqqkVliC/HmV2lcNVzlVymWgeKhRj8fI5JqrDhpLz0XD+
 9Rn90mweCzCSw7/fj/keP9mEnMce4XdkkDB/Pyf+dIMiLMOczoU=
 =ABgl
 -----END PGP SIGNATURE-----

Merge tag 'media/v5.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media

Pull media updates from Mauro Carvalho Chehab:

 - new Atmel microship ISC driver

 - coda has gained support for mpeg2 and mpeg4

 - cxusb gained support for analog TV

 - rockchip staging driver was split into two separate staging drivers

 - added a new staging driver for Allegro DVT video IP core

 - added a new staging driver for Amlogic Meson video decoder

 - lots of improvements and cleanups

* tag 'media/v5.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (398 commits)
  media: allegro: use new v4l2_m2m_ioctl_try_encoder_cmd funcs
  media: doc-rst: Fix typos
  media: radio-raremono: change devm_k*alloc to k*alloc
  media: stv0297: fix frequency range limit
  media: rc: Prefer KEY_NUMERIC_* for number buttons on remotes
  media: dvb_frontend: split dvb_frontend_handle_ioctl function
  media: mceusb: disable "nonsensical irdata" messages
  media: rc: remove redundant dev_err message
  media: cec-notifier: add new notifier functions
  media: cec: add struct cec_connector_info support
  media: cec-notifier: rename variables, check kstrdup and n->conn_name
  media: MAINTAINERS: Add maintainers for Media Controller
  media: staging: media: tegra-vde: Defer dmabuf's unmapping
  media: staging: media: tegra-vde: Add IOMMU support
  media: hdpvr: fix locking and a missing msleep
  media: v4l2: Test type instead of cfg->type in v4l2_ctrl_new_custom()
  media: atmel: atmel-isc: fix i386 build error
  media: v4l2-ctrl: Move compound control initialization
  media: hantro: Use vb2_get_buffer
  media: pci: cx88: Change the type of 'missed' to u64
  ...
This commit is contained in:
Linus Torvalds 2019-07-09 09:47:22 -07:00
commit ed63b9c873
591 changed files with 25519 additions and 9457 deletions

View File

@ -1,6 +1,6 @@
What: /sys/kernel/debug/cec/*/error-inj What: /sys/kernel/debug/cec/*/error-inj
Date: March 2018 Date: March 2018
Contact: Hans Verkuil <hans.verkuil@cisco.com> Contact: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Description: Description:
The CEC Framework allows for CEC error injection commands through The CEC Framework allows for CEC error injection commands through

View File

@ -0,0 +1,43 @@
Device-tree bindings for the Allegro DVT video IP codecs present in the Xilinx
ZynqMP SoC. The IP core may either be a H.264/H.265 encoder or H.264/H.265
decoder ip core.
Each actual codec engines is controlled by a microcontroller (MCU). Host
software uses a provided mailbox interface to communicate with the MCU. The
MCU share an interrupt.
Required properties:
- compatible: value should be one of the following
"allegro,al5e-1.1", "allegro,al5e": encoder IP core
"allegro,al5d-1.1", "allegro,al5d": decoder IP core
- reg: base and length of the memory mapped register region and base and
length of the memory mapped sram
- reg-names: must include "regs" and "sram"
- interrupts: shared interrupt from the MCUs to the processing system
- clocks: must contain an entry for each entry in clock-names
- clock-names: must include "core_clk", "mcu_clk", "m_axi_core_aclk",
"m_axi_mcu_aclk", "s_axi_lite_aclk"
Example:
al5e: video-codec@a0009000 {
compatible = "allegro,al5e-1.1", "allegro,al5e";
reg = <0 0xa0009000 0 0x1000>,
<0 0xa0000000 0 0x8000>;
reg-names = "regs", "sram";
interrupts = <0 96 4>;
clocks = <&xlnx_vcu 0>, <&xlnx_vcu 1>,
<&clkc 71>, <&clkc 71>, <&clkc 71>;
clock-names = "core_clk", "mcu_clk", "m_axi_core_aclk",
"m_axi_mcu_aclk", "s_axi_lite_aclk"
};
al5d: video-codec@a0029000 {
compatible = "allegro,al5d-1.1", "allegro,al5d";
reg = <0 0xa0029000 0 0x1000>,
<0 0xa0020000 0 0x8000>;
reg-names = "regs", "sram";
interrupts = <0 96 4>;
clocks = <&xlnx_vcu 2>, <&xlnx_vcu 3>,
<&clkc 71>, <&clkc 71>, <&clkc 71>;
clock-names = "core_clk", "mcu_clk", "m_axi_core_aclk",
"m_axi_mcu_aclk", "s_axi_lite_aclk"
};

View File

@ -0,0 +1,71 @@
Amlogic Video Decoder
================================
The video decoding IP lies within the DOS memory region,
except for the hardware bitstream parser that makes use of an undocumented
region.
It makes use of the following blocks:
- ESPARSER is a bitstream parser that outputs to a VIFIFO. Further VDEC blocks
then feed from this VIFIFO.
- VDEC_1 can decode MPEG-1, MPEG-2, MPEG-4 part 2, MJPEG, H.263, H.264, VC-1.
- VDEC_HEVC can decode HEVC and VP9.
Both VDEC_1 and VDEC_HEVC share the "vdec" IRQ and as such cannot run
concurrently.
Device Tree Bindings:
---------------------
VDEC: Video Decoder
--------------------------
Required properties:
- compatible: value should be different for each SoC family as :
- GXBB (S905) : "amlogic,gxbb-vdec"
- GXL (S905X, S905D) : "amlogic,gxl-vdec"
- GXM (S912) : "amlogic,gxm-vdec"
- reg: base address and size of he following memory-mapped regions :
- dos
- esparser
- reg-names: should contain the names of the previous memory regions
- interrupts: should contain the following IRQs:
- vdec
- esparser
- interrupt-names: should contain the names of the previous interrupts
- amlogic,ao-sysctrl: should point to the AOBUS sysctrl node
- amlogic,canvas: should point to a canvas provider node
- clocks: should contain the following clocks :
- dos_parser
- dos
- vdec_1
- vdec_hevc
- clock-names: should contain the names of the previous clocks
- resets: should contain the parser reset
- reset-names: should be "esparser"
Example:
vdec: video-decoder@c8820000 {
compatible = "amlogic,gxbb-vdec";
reg = <0x0 0xc8820000 0x0 0x10000>,
<0x0 0xc110a580 0x0 0xe4>;
reg-names = "dos", "esparser";
interrupts = <GIC_SPI 44 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 32 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "vdec", "esparser";
amlogic,ao-sysctrl = <&sysctrl_AO>;
amlogic,canvas = <&canvas>;
clocks = <&clkc CLKID_DOS_PARSER>,
<&clkc CLKID_DOS>,
<&clkc CLKID_VDEC_1>,
<&clkc CLKID_VDEC_HEVC>;
clock-names = "dos_parser", "dos", "vdec_1", "vdec_hevc";
resets = <&reset RESET_PARSER>;
reset-names = "esparser";
};

View File

@ -14,8 +14,7 @@ Required properties:
- interrupts : should contain CSI interrupt; - interrupts : should contain CSI interrupt;
- clocks : list of clock specifiers, see - clocks : list of clock specifiers, see
Documentation/devicetree/bindings/clock/clock-bindings.txt for details; Documentation/devicetree/bindings/clock/clock-bindings.txt for details;
- clock-names : must contain "axi", "mclk" and "dcic" entries, matching - clock-names : must contain "mclk";
entries in the clock property;
The device node shall contain one 'port' child node with one child 'endpoint' The device node shall contain one 'port' child node with one child 'endpoint'
node, according to the bindings defined in: node, according to the bindings defined in:
@ -32,10 +31,8 @@ example:
compatible = "fsl,imx7-csi"; compatible = "fsl,imx7-csi";
reg = <0x30710000 0x10000>; reg = <0x30710000 0x10000>;
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX7D_CLK_DUMMY>, clocks = <&clks IMX7D_CSI_MCLK_ROOT_CLK>;
<&clks IMX7D_CSI_MCLK_ROOT_CLK>, clock-names = "mclk";
<&clks IMX7D_CLK_DUMMY>;
clock-names = "axi", "mclk", "dcic";
port { port {
csi_from_csi_mux: endpoint { csi_from_csi_mux: endpoint {

View File

@ -0,0 +1,50 @@
Marvell MMP2 camera host interface
Required properties:
- compatible: Should be "marvell,mmp2-ccic".
- reg: Register base and size.
- interrupts: The interrupt number.
- #clock-cells: Must be 0.
Optional properties:
- clocks: Reference to the input clock as specified by
Documentation/devicetree/bindings/clock/clock-bindings.txt.
- clock-names: Names of the clocks used; "axi" for the AXI bus interface,
"func" for the peripheral clock and "phy" for the parallel
video bus interface.
- clock-output-names: Optional clock source for sensors. Shall be "mclk".
Required subnodes:
- port: The parallel bus interface port with a single endpoint linked to
the sensor's endpoint as described in
Documentation/devicetree/bindings/media/video-interfaces.txt.
Required endpoint properties:
- bus-type: data bus type, <5> or <6> for Parallel or Bt.656 respectively
- pclk-sample: pixel clock polarity
- hsync-active: horizontal synchronization polarity (only required for
parallel bus)
- vsync-active: vertical synchronization polarity (only required for
parallel bus)
Example:
camera0: camera@d420a000 {
compatible = "marvell,mmp2-ccic";
reg = <0xd420a000 0x800>;
interrupts = <42>;
clocks = <&soc_clocks MMP2_CLK_CCIC0>;
clock-names = "axi";
#clock-cells = <0>;
clock-output-names = "mclk";
port {
camera0_0: endpoint {
remote-endpoint = <&ov7670_0>;
bus-type = <5>; /* Parallel */
hsync-active = <1>; /* Active high */
vsync-active = <1>; /* Active high */
pclk-sample = <0>; /* Falling */
};
};
};

View File

@ -6,6 +6,7 @@ Allwinner V3s SoC features a CSI module(CSI1) with parallel interface.
Required properties: Required properties:
- compatible: value must be one of: - compatible: value must be one of:
* "allwinner,sun6i-a31-csi" * "allwinner,sun6i-a31-csi"
* "allwinner,sun8i-a83t-csi"
* "allwinner,sun8i-h3-csi" * "allwinner,sun8i-h3-csi"
* "allwinner,sun8i-v3s-csi" * "allwinner,sun8i-v3s-csi"
* "allwinner,sun50i-a64-csi" * "allwinner,sun50i-a64-csi"

View File

@ -49,6 +49,8 @@ patternProperties:
description: Aeroflex Gaisler AB description: Aeroflex Gaisler AB
"^al,.*": "^al,.*":
description: Annapurna Labs description: Annapurna Labs
"^allegro,.*":
description: Allegro DVT
"^allo,.*": "^allo,.*":
description: Allo.com description: Allo.com
"^allwinner,.*": "^allwinner,.*":

View File

@ -11,12 +11,12 @@ Digital TV devices are implemented by several different drivers:
- Frontend drivers that are usually implemented as two separate drivers: - Frontend drivers that are usually implemented as two separate drivers:
- A tuner driver that implements the logic with commands the part of the - A tuner driver that implements the logic which commands the part of
hardware with is responsible to tune into a digital TV transponder or the hardware responsible for tuning into a digital TV transponder or
physical channel. The output of a tuner is usually a baseband or physical channel. The output of a tuner is usually a baseband or
Intermediate Frequency (IF) signal; Intermediate Frequency (IF) signal;
- A demodulator driver (a.k.a "demod") that implements the logic with - A demodulator driver (a.k.a "demod") that implements the logic which
commands the digital TV decoding hardware. The output of a demod is commands the digital TV decoding hardware. The output of a demod is
a digital stream, with multiple audio, video and data channels typically a digital stream, with multiple audio, video and data channels typically
multiplexed using MPEG Transport Stream [#f1]_. multiplexed using MPEG Transport Stream [#f1]_.

View File

@ -26,8 +26,9 @@ The control framework was created in order to implement all the rules of the
V4L2 specification with respect to controls in a central place. And to make V4L2 specification with respect to controls in a central place. And to make
life as easy as possible for the driver developer. life as easy as possible for the driver developer.
Note that the control framework relies on the presence of a struct v4l2_device Note that the control framework relies on the presence of a struct
for V4L2 drivers and struct v4l2_subdev for sub-device drivers. :c:type:`v4l2_device` for V4L2 drivers and struct :c:type:`v4l2_subdev` for
sub-device drivers.
Objects in the framework Objects in the framework
@ -35,12 +36,13 @@ Objects in the framework
There are two main objects: There are two main objects:
The v4l2_ctrl object describes the control properties and keeps track of the The :c:type:`v4l2_ctrl` object describes the control properties and keeps
control's value (both the current value and the proposed new value). track of the control's value (both the current value and the proposed new
value).
v4l2_ctrl_handler is the object that keeps track of controls. It maintains a :c:type:`v4l2_ctrl_handler` is the object that keeps track of controls. It
list of v4l2_ctrl objects that it owns and another list of references to maintains a list of v4l2_ctrl objects that it owns and another list of
controls, possibly to controls owned by other handlers. references to controls, possibly to controls owned by other handlers.
Basic usage for V4L2 and sub-device drivers Basic usage for V4L2 and sub-device drivers
@ -48,33 +50,15 @@ Basic usage for V4L2 and sub-device drivers
1) Prepare the driver: 1) Prepare the driver:
.. code-block:: c
#include <media/v4l2-ctrls.h>
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 For V4L2 drivers:
struct foo_dev { .. code-block:: c
...
struct v4l2_ctrl_handler ctrl_handler;
...
};
struct foo_dev *foo;
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.
1.3) Hook the control handler into the driver:
1.3.1) For V4L2 drivers do this:
.. code-block:: none
struct foo_dev { struct foo_dev {
... ...
@ -84,18 +68,9 @@ information. It is a hint only.
... ...
}; };
foo->v4l2_dev.ctrl_handler = &foo->ctrl_handler; For sub-device drivers:
Where foo->v4l2_dev is of type struct v4l2_device. .. code-block:: c
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 foo_dev {
... ...
@ -105,39 +80,60 @@ Those are now no longer needed.
... ...
}; };
foo->sd.ctrl_handler = &foo->ctrl_handler; 1.2) Initialize the handler:
Where foo->sd is of type struct v4l2_subdev. .. code-block:: c
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.
1.3) Hook the control handler into the driver:
For V4L2 drivers:
.. code-block:: c
foo->v4l2_dev.ctrl_handler = &foo->ctrl_handler;
For sub-device drivers:
.. code-block:: c
foo->sd.ctrl_handler = &foo->ctrl_handler;
1.4) Clean up the handler at the end: 1.4) Clean up the handler at the end:
.. code-block:: none .. code-block:: c
v4l2_ctrl_handler_free(&foo->ctrl_handler); v4l2_ctrl_handler_free(&foo->ctrl_handler);
2) Add controls: 2) Add controls:
You add non-menu controls by calling v4l2_ctrl_new_std: You add non-menu controls by calling :c:func:`v4l2_ctrl_new_std`:
.. code-block:: none .. code-block:: c
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
:c:func:`v4l2_ctrl_new_std_menu`:
.. code-block:: none .. code-block:: c
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);
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: :c:func:`v4l2_ctrl_new_std_menu_items`:
.. code-block:: none .. code-block:: c
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,
@ -145,17 +141,18 @@ v4l2_ctrl_new_std_menu_items:
s32 skip_mask, s32 def, const char * const *qmenu); s32 skip_mask, s32 def, const char * const *qmenu);
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: :c:func:`v4l2_ctrl_new_int_menu`:
.. code-block:: none .. code-block:: c
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
:c:func:`v4l2_ctrl_handler_init`:
.. code-block:: none .. code-block:: c
static const s64 exp_bias_qmenu[] = { static const s64 exp_bias_qmenu[] = {
-2, -1, 0, 1, 2 -2, -1, 0, 1, 2
@ -192,33 +189,34 @@ These functions are typically called right after the v4l2_ctrl_handler_init:
return err; return err;
} }
The v4l2_ctrl_new_std function returns the v4l2_ctrl pointer to the new The :c:func:`v4l2_ctrl_new_std` function returns the v4l2_ctrl pointer to
control, but if you do not need to access the pointer outside the control ops, the new control, but if you do not need to access the pointer outside the
then there is no need to store it. control ops, then there is no need to store it.
The v4l2_ctrl_new_std function will fill in most fields based on the control The :c:func:`v4l2_ctrl_new_std` function will fill in most fields based on
ID except for the min, max, step and default values. These are passed in the the control ID except for the min, max, step and default values. These are
last four arguments. These values are driver specific while control attributes passed in the last four arguments. These values are driver specific while
like type, name, flags are all global. The control's current value will be set control attributes like type, name, flags are all global. The control's
to the default value. current value will be set to the default value.
The v4l2_ctrl_new_std_menu function is very similar but it is used for menu The :c:func:`v4l2_ctrl_new_std_menu` function is very similar but it is
controls. There is no min argument since that is always 0 for menu controls, used for menu controls. There is no min argument since that is always 0 for
and instead of a step there is a skip_mask argument: if bit X is 1, then menu menu controls, and instead of a step there is a skip_mask argument: if bit
item X is skipped. X is 1, then menu item X is skipped.
The v4l2_ctrl_new_int_menu function creates a new standard integer menu The :c:func:`v4l2_ctrl_new_int_menu` function creates a new standard
control with driver-specific items in the menu. It differs from integer menu control with driver-specific items in the menu. It differs
v4l2_ctrl_new_std_menu in that it doesn't have the mask argument and takes from v4l2_ctrl_new_std_menu in that it doesn't have the mask argument and
as the last argument an array of signed 64-bit integers that form an exact takes as the last argument an array of signed 64-bit integers that form an
menu item list. exact menu item list.
The v4l2_ctrl_new_std_menu_items function is very similar to The :c:func:`v4l2_ctrl_new_std_menu_items` function is very similar to
v4l2_ctrl_new_std_menu but takes an extra parameter qmenu, which is the driver v4l2_ctrl_new_std_menu but takes an extra parameter qmenu, which is the
specific menu for an otherwise standard menu control. A good example for this driver specific menu for an otherwise standard menu control. A good example
control is the test pattern control for capture/display/sensors devices that for this control is the test pattern control for capture/display/sensors
have the capability to generate test patterns. These test patterns are hardware devices that have the capability to generate test patterns. These test
specific, so the contents of the menu will vary from device to device. patterns are hardware specific, so the contents of the menu will vary from
device to device.
Note that if something fails, the function will return NULL or an error and Note that if something fails, the function will return NULL or an error and
set ctrl_handler->error to the error code. If ctrl_handler->error was already set ctrl_handler->error to the error code. If ctrl_handler->error was already
@ -233,7 +231,7 @@ a bit faster that way.
3) Optionally force initial control setup: 3) Optionally force initial control setup:
.. code-block:: none .. code-block:: c
v4l2_ctrl_handler_setup(&foo->ctrl_handler); v4l2_ctrl_handler_setup(&foo->ctrl_handler);
@ -242,9 +240,9 @@ initializes the hardware to the default control values. It is recommended
that you do this as this ensures that both the internal data structures and that you do this as this ensures that both the internal data structures and
the hardware are in sync. the hardware are in sync.
4) Finally: implement the v4l2_ctrl_ops 4) Finally: implement the :c:type:`v4l2_ctrl_ops`
.. code-block:: none .. code-block:: c
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,
@ -252,7 +250,7 @@ the hardware are in sync.
Usually all you need is s_ctrl: Usually all you need is s_ctrl:
.. code-block:: none .. code-block:: c
static int foo_s_ctrl(struct v4l2_ctrl *ctrl) static int foo_s_ctrl(struct v4l2_ctrl *ctrl)
{ {
@ -305,7 +303,7 @@ 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:
.. code-block:: none .. code-block:: c
union v4l2_ctrl_ptr { union v4l2_ctrl_ptr {
s32 *p_s32; s32 *p_s32;
@ -317,7 +315,7 @@ values:
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 .. code-block:: c
s32 val; s32 val;
struct { struct {
@ -330,7 +328,7 @@ 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 .. code-block:: c
&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
@ -354,7 +352,7 @@ 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 .. code-block:: c
static int foo_g_volatile_ctrl(struct v4l2_ctrl *ctrl) static int foo_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
{ {
@ -372,7 +370,7 @@ 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 .. code-block:: c
ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...); ctrl = v4l2_ctrl_new_std(&sd->ctrl_handler, ...);
if (ctrl) if (ctrl)
@ -393,7 +391,7 @@ 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 .. code-block:: c
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);
@ -404,7 +402,7 @@ 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 .. code-block:: c
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);
@ -417,7 +415,7 @@ Menu Controls
The v4l2_ctrl struct contains this union: The v4l2_ctrl struct contains this union:
.. code-block:: none .. code-block:: c
union { union {
u32 step; u32 step;
@ -445,7 +443,7 @@ 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 .. code-block:: c
static const struct v4l2_ctrl_config ctrl_filter = { static const struct v4l2_ctrl_config ctrl_filter = {
.ops = &ctrl_custom_ops, .ops = &ctrl_custom_ops,
@ -499,7 +497,7 @@ 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 .. code-block:: c
struct foo { struct foo {
struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl_handler ctrl_handler;
@ -523,7 +521,7 @@ 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 .. code-block:: c
static int foo_s_ctrl(struct v4l2_ctrl *ctrl) static int foo_s_ctrl(struct v4l2_ctrl *ctrl)
{ {
@ -545,7 +543,7 @@ 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 .. code-block:: c
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]
@ -553,7 +551,7 @@ In the example above the following are equivalent for the VOLUME case:
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 .. code-block:: c
struct { struct {
/* audio cluster */ /* audio cluster */
@ -565,7 +563,7 @@ 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 .. code-block:: c
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, ...);
@ -621,7 +619,7 @@ 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:
.. code-block:: none .. code-block:: c
void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls, void v4l2_ctrl_auto_cluster(unsigned ncontrols, struct v4l2_ctrl **controls,
u8 manual_val, bool set_volatile); u8 manual_val, bool set_volatile);
@ -676,7 +674,7 @@ 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 .. code-block:: c
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, ...);
@ -690,7 +688,7 @@ all controls.
Or you can add specific controls to a handler: Or you can add specific controls to a handler:
.. code-block:: none .. code-block:: c
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, ...);
@ -699,7 +697,7 @@ 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 .. code-block:: c
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, ...);
@ -720,7 +718,7 @@ 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 .. code-block:: c
struct v4l2_ctrl *volume; struct v4l2_ctrl *volume;
@ -729,7 +727,7 @@ 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 .. code-block:: c
struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl_handler ctrl_handler;
@ -738,7 +736,7 @@ 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 .. code-block:: c
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);
@ -760,7 +758,7 @@ 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 .. code-block:: c
static const struct v4l2_ctrl_config ctrl_private = { static const struct v4l2_ctrl_config ctrl_private = {
.ops = &ctrl_custom_ops, .ops = &ctrl_custom_ops,
@ -797,7 +795,7 @@ 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:
.. code-block:: none .. code-block:: c
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, 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);

View File

@ -39,7 +39,7 @@ Revision and Copyright
********************** **********************
Authors: Authors:
- Verkuil, Hans <hans.verkuil@cisco.com> - Verkuil, Hans <hverkuil-cisco@xs4all.nl>
- Initial version. - Initial version.

View File

@ -294,7 +294,8 @@ EINVAL
The requested mode is invalid. The requested mode is invalid.
EPERM EPERM
Monitor mode is requested without having root permissions Monitor mode is requested, but the process does have the ``CAP_NET_ADMIN``
capability.
EBUSY EBUSY
Someone else is already an exclusive follower or initiator. Someone else is already an exclusive follower or initiator.

View File

@ -223,6 +223,18 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
result of the :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`, and once via result of the :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`, and once via
:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`. :ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>`.
* .. _`CEC-MSG-FL-RAW`:
- ``CEC_MSG_FL_RAW``
- 2
- Normally CEC messages are validated before transmitting them. If this
flag is set when :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` is called,
then no validation takes place and the message is transmitted as-is.
This is useful when debugging CEC issues.
This flag is only allowed if the process has the ``CAP_SYS_RAWIO``
capability. If that is not set, then the ``EPERM`` error code is
returned.
.. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{11.0cm}| .. tabularcolumns:: |p{5.6cm}|p{0.9cm}|p{11.0cm}|
@ -358,7 +370,8 @@ ENOTTY
EPERM EPERM
The CEC adapter is not configured, i.e. :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>` The CEC adapter is not configured, i.e. :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`
has never been called. has never been called, or ``CEC_MSG_FL_RAW`` was used from a process that
did not have the ``CAP_SYS_RAWIO`` capability.
ENONET ENONET
The CEC adapter is not configured, i.e. :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>` The CEC adapter is not configured, i.e. :ref:`ioctl CEC_ADAP_S_LOG_ADDRS <CEC_ADAP_S_LOG_ADDRS>`

View File

@ -84,6 +84,11 @@ returned during the enumeration process.
- Pointer to a links array allocated by the application. Ignored if - Pointer to a links array allocated by the application. Ignored if
NULL. NULL.
* - __u32
- ``reserved[4]``
- Reserved for future extensions. Drivers and applications must set
the array to zero.
.. c:type:: media_pad_desc .. c:type:: media_pad_desc
@ -135,7 +140,7 @@ returned during the enumeration process.
- Link flags, see :ref:`media-link-flag` for more details. - Link flags, see :ref:`media-link-flag` for more details.
* - __u32 * - __u32
- ``reserved[4]`` - ``reserved[2]``
- Reserved for future extensions. Drivers and applications must set - Reserved for future extensions. Drivers and applications must set
the array to zero. the array to zero.

View File

@ -54,7 +54,7 @@ the remote via /dev/input/event devices.
- .. row 3 - .. row 3
- ``KEY_0`` - ``KEY_NUMERIC_0``
- Keyboard digit 0 - Keyboard digit 0
@ -62,7 +62,7 @@ the remote via /dev/input/event devices.
- .. row 4 - .. row 4
- ``KEY_1`` - ``KEY_NUMERIC_1``
- Keyboard digit 1 - Keyboard digit 1
@ -70,7 +70,7 @@ the remote via /dev/input/event devices.
- .. row 5 - .. row 5
- ``KEY_2`` - ``KEY_NUMERIC_2``
- Keyboard digit 2 - Keyboard digit 2
@ -78,7 +78,7 @@ the remote via /dev/input/event devices.
- .. row 6 - .. row 6
- ``KEY_3`` - ``KEY_NUMERIC_3``
- Keyboard digit 3 - Keyboard digit 3
@ -86,7 +86,7 @@ the remote via /dev/input/event devices.
- .. row 7 - .. row 7
- ``KEY_4`` - ``KEY_NUMERIC_4``
- Keyboard digit 4 - Keyboard digit 4
@ -94,7 +94,7 @@ the remote via /dev/input/event devices.
- .. row 8 - .. row 8
- ``KEY_5`` - ``KEY_NUMERIC_5``
- Keyboard digit 5 - Keyboard digit 5
@ -102,7 +102,7 @@ the remote via /dev/input/event devices.
- .. row 9 - .. row 9
- ``KEY_6`` - ``KEY_NUMERIC_6``
- Keyboard digit 6 - Keyboard digit 6
@ -110,7 +110,7 @@ the remote via /dev/input/event devices.
- .. row 10 - .. row 10
- ``KEY_7`` - ``KEY_NUMERIC_7``
- Keyboard digit 7 - Keyboard digit 7
@ -118,7 +118,7 @@ the remote via /dev/input/event devices.
- .. row 11 - .. row 11
- ``KEY_8`` - ``KEY_NUMERIC_8``
- Keyboard digit 8 - Keyboard digit 8
@ -126,7 +126,7 @@ the remote via /dev/input/event devices.
- .. row 12 - .. row 12
- ``KEY_9`` - ``KEY_NUMERIC_9``
- Keyboard digit 9 - Keyboard digit 9
@ -196,7 +196,7 @@ the remote via /dev/input/event devices.
- ``KEY_PAUSE`` - ``KEY_PAUSE``
- Pause sroweam - Pause stream
- PAUSE / FREEZE - PAUSE / FREEZE
@ -220,7 +220,7 @@ the remote via /dev/input/event devices.
- ``KEY_STOP`` - ``KEY_STOP``
- Stop sroweam - Stop stream
- STOP - STOP
@ -228,7 +228,7 @@ the remote via /dev/input/event devices.
- ``KEY_RECORD`` - ``KEY_RECORD``
- Start/stop recording sroweam - Start/stop recording stream
- CAPTURE / REC / RECORD/PAUSE - CAPTURE / REC / RECORD/PAUSE
@ -577,7 +577,7 @@ the remote via /dev/input/event devices.
- ``KEY_CLEAR`` - ``KEY_CLEAR``
- Stop sroweam and return to default input video/audio - Stop stream and return to default input video/audio
- CLEAR / RESET / BOSS KEY - CLEAR / RESET / BOSS KEY
@ -593,7 +593,7 @@ the remote via /dev/input/event devices.
- ``KEY_FAVORITES`` - ``KEY_FAVORITES``
- Open the favorites sroweam window - Open the favorites stream window
- TV WALL / Favorites - TV WALL / Favorites

View File

@ -122,6 +122,15 @@ ITU BT.1119
:author: International Telecommunication Union (http://www.itu.ch) :author: International Telecommunication Union (http://www.itu.ch)
.. _h264:
ITU-T Rec. H.264 Specification (04/2017 Edition)
================================================
:title: ITU-T Recommendation H.264 "Advanced Video Coding for Generic Audiovisual Services"
:author: International Telecommunication Union (http://www.itu.ch)
.. _jfif: .. _jfif:
JFIF JFIF

View File

@ -759,6 +759,32 @@ enum v4l2_mpeg_video_h264_level -
.. _v4l2-mpeg-video-mpeg2-level:
``V4L2_CID_MPEG_VIDEO_MPEG2_LEVEL``
(enum)
enum v4l2_mpeg_video_mpeg2_level -
The level information for the MPEG2 elementary stream. Applicable to
MPEG2 codecs. Possible values are:
.. flat-table::
:header-rows: 0
:stub-columns: 0
* - ``V4L2_MPEG_VIDEO_MPEG2_LEVEL_LOW``
- Low Level (LL)
* - ``V4L2_MPEG_VIDEO_MPEG2_LEVEL_MAIN``
- Main Level (ML)
* - ``V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH_1440``
- High-1440 Level (H-14)
* - ``V4L2_MPEG_VIDEO_MPEG2_LEVEL_HIGH``
- High Level (HL)
.. _v4l2-mpeg-video-mpeg4-level: .. _v4l2-mpeg-video-mpeg4-level:
``V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL`` ``V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL``
@ -845,6 +871,36 @@ enum v4l2_mpeg_video_h264_profile -
.. _v4l2-mpeg-video-mpeg2-profile:
``V4L2_CID_MPEG_VIDEO_MPEG2_PROFILE``
(enum)
enum v4l2_mpeg_video_mpeg2_profile -
The profile information for MPEG2. Applicable to MPEG2 codecs.
Possible values are:
.. flat-table::
:header-rows: 0
:stub-columns: 0
* - ``V4L2_MPEG_VIDEO_MPEG2_PROFILE_SIMPLE``
- Simple profile (SP)
* - ``V4L2_MPEG_VIDEO_MPEG2_PROFILE_MAIN``
- Main profile (MP)
* - ``V4L2_MPEG_VIDEO_MPEG2_PROFILE_SNR_SCALABLE``
- SNR Scalable profile (SNR)
* - ``V4L2_MPEG_VIDEO_MPEG2_PROFILE_SPATIALLY_SCALABLE``
- Spatially Scalable profile (Spt)
* - ``V4L2_MPEG_VIDEO_MPEG2_PROFILE_HIGH``
- High profile (HP)
* - ``V4L2_MPEG_VIDEO_MPEG2_PROFILE_MULTIVIEW``
- Multi-view profile (MVP)
.. _v4l2-mpeg-video-mpeg4-profile: .. _v4l2-mpeg-video-mpeg4-profile:
``V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE`` ``V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE``
@ -1395,6 +1451,575 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
- Layer number - Layer number
.. _v4l2-mpeg-h264:
``V4L2_CID_MPEG_VIDEO_H264_SPS (struct)``
Specifies the sequence parameter set (as extracted from the
bitstream) for the associated H264 slice data. This includes the
necessary parameters for configuring a stateless hardware decoding
pipeline for H264. The bitstream parameters are defined according
to :ref:`h264`, section 7.4.2.1.1 "Sequence Parameter Set Data
Semantics". For further documentation, refer to the above
specification, unless there is an explicit comment stating
otherwise.
.. note::
This compound control is not yet part of the public kernel API and
it is expected to change.
.. c:type:: v4l2_ctrl_h264_sps
.. cssclass:: longtable
.. flat-table:: struct v4l2_ctrl_h264_sps
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __u8
- ``profile_idc``
-
* - __u8
- ``constraint_set_flags``
- See :ref:`Sequence Parameter Set Constraints Set Flags <h264_sps_constraints_set_flags>`
* - __u8
- ``level_idc``
-
* - __u8
- ``seq_parameter_set_id``
-
* - __u8
- ``chroma_format_idc``
-
* - __u8
- ``bit_depth_luma_minus8``
-
* - __u8
- ``bit_depth_chroma_minus8``
-
* - __u8
- ``log2_max_frame_num_minus4``
-
* - __u8
- ``pic_order_cnt_type``
-
* - __u8
- ``log2_max_pic_order_cnt_lsb_minus4``
-
* - __u8
- ``max_num_ref_frames``
-
* - __u8
- ``num_ref_frames_in_pic_order_cnt_cycle``
-
* - __s32
- ``offset_for_ref_frame[255]``
-
* - __s32
- ``offset_for_non_ref_pic``
-
* - __s32
- ``offset_for_top_to_bottom_field``
-
* - __u16
- ``pic_width_in_mbs_minus1``
-
* - __u16
- ``pic_height_in_map_units_minus1``
-
* - __u32
- ``flags``
- See :ref:`Sequence Parameter Set Flags <h264_sps_flags>`
.. _h264_sps_constraints_set_flags:
``Sequence Parameter Set Constraints Set Flags``
.. cssclass:: longtable
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_H264_SPS_CONSTRAINT_SET0_FLAG``
- 0x00000001
-
* - ``V4L2_H264_SPS_CONSTRAINT_SET1_FLAG``
- 0x00000002
-
* - ``V4L2_H264_SPS_CONSTRAINT_SET2_FLAG``
- 0x00000004
-
* - ``V4L2_H264_SPS_CONSTRAINT_SET3_FLAG``
- 0x00000008
-
* - ``V4L2_H264_SPS_CONSTRAINT_SET4_FLAG``
- 0x00000010
-
* - ``V4L2_H264_SPS_CONSTRAINT_SET5_FLAG``
- 0x00000020
-
.. _h264_sps_flags:
``Sequence Parameter Set Flags``
.. cssclass:: longtable
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_H264_SPS_FLAG_SEPARATE_COLOUR_PLANE``
- 0x00000001
-
* - ``V4L2_H264_SPS_FLAG_QPPRIME_Y_ZERO_TRANSFORM_BYPASS``
- 0x00000002
-
* - ``V4L2_H264_SPS_FLAG_DELTA_PIC_ORDER_ALWAYS_ZERO``
- 0x00000004
-
* - ``V4L2_H264_SPS_FLAG_GAPS_IN_FRAME_NUM_VALUE_ALLOWED``
- 0x00000008
-
* - ``V4L2_H264_SPS_FLAG_FRAME_MBS_ONLY``
- 0x00000010
-
* - ``V4L2_H264_SPS_FLAG_MB_ADAPTIVE_FRAME_FIELD``
- 0x00000020
-
* - ``V4L2_H264_SPS_FLAG_DIRECT_8X8_INFERENCE``
- 0x00000040
-
``V4L2_CID_MPEG_VIDEO_H264_PPS (struct)``
Specifies the picture parameter set (as extracted from the
bitstream) for the associated H264 slice data. This includes the
necessary parameters for configuring a stateless hardware decoding
pipeline for H264. The bitstream parameters are defined according
to :ref:`h264`, section 7.4.2.2 "Picture Parameter Set RBSP
Semantics". For further documentation, refer to the above
specification, unless there is an explicit comment stating
otherwise.
.. note::
This compound control is not yet part of the public kernel API and
it is expected to change.
.. c:type:: v4l2_ctrl_h264_pps
.. cssclass:: longtable
.. flat-table:: struct v4l2_ctrl_h264_pps
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __u8
- ``pic_parameter_set_id``
-
* - __u8
- ``seq_parameter_set_id``
-
* - __u8
- ``num_slice_groups_minus1``
-
* - __u8
- ``num_ref_idx_l0_default_active_minus1``
-
* - __u8
- ``num_ref_idx_l1_default_active_minus1``
-
* - __u8
- ``weighted_bipred_idc``
-
* - __s8
- ``pic_init_qp_minus26``
-
* - __s8
- ``pic_init_qs_minus26``
-
* - __s8
- ``chroma_qp_index_offset``
-
* - __s8
- ``second_chroma_qp_index_offset``
-
* - __u16
- ``flags``
- See :ref:`Picture Parameter Set Flags <h264_pps_flags>`
.. _h264_pps_flags:
``Picture Parameter Set Flags``
.. cssclass:: longtable
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_H264_PPS_FLAG_ENTROPY_CODING_MODE``
- 0x00000001
-
* - ``V4L2_H264_PPS_FLAG_BOTTOM_FIELD_PIC_ORDER_IN_FRAME_PRESENT``
- 0x00000002
-
* - ``V4L2_H264_PPS_FLAG_WEIGHTED_PRED``
- 0x00000004
-
* - ``V4L2_H264_PPS_FLAG_DEBLOCKING_FILTER_CONTROL_PRESENT``
- 0x00000008
-
* - ``V4L2_H264_PPS_FLAG_CONSTRAINED_INTRA_PRED``
- 0x00000010
-
* - ``V4L2_H264_PPS_FLAG_REDUNDANT_PIC_CNT_PRESENT``
- 0x00000020
-
* - ``V4L2_H264_PPS_FLAG_TRANSFORM_8X8_MODE``
- 0x00000040
-
* - ``V4L2_H264_PPS_FLAG_PIC_SCALING_MATRIX_PRESENT``
- 0x00000080
-
``V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX (struct)``
Specifies the scaling matrix (as extracted from the bitstream) for
the associated H264 slice data. The bitstream parameters are
defined according to :ref:`h264`, section 7.4.2.1.1.1 "Scaling
List Semantics". For further documentation, refer to the above
specification, unless there is an explicit comment stating
otherwise.
.. note::
This compound control is not yet part of the public kernel API and
it is expected to change.
.. c:type:: v4l2_ctrl_h264_scaling_matrix
.. cssclass:: longtable
.. flat-table:: struct v4l2_ctrl_h264_scaling_matrix
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __u8
- ``scaling_list_4x4[6][16]``
-
* - __u8
- ``scaling_list_8x8[6][64]``
-
``V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS (struct)``
Specifies the slice parameters (as extracted from the bitstream)
for the associated H264 slice data. This includes the necessary
parameters for configuring a stateless hardware decoding pipeline
for H264. The bitstream parameters are defined according to
:ref:`h264`, section 7.4.3 "Slice Header Semantics". For further
documentation, refer to the above specification, unless there is
an explicit comment stating otherwise.
.. note::
This compound control is not yet part of the public kernel API
and it is expected to change.
This structure is expected to be passed as an array, with one
entry for each slice included in the bitstream buffer.
.. c:type:: v4l2_ctrl_h264_slice_params
.. cssclass:: longtable
.. flat-table:: struct v4l2_ctrl_h264_slice_params
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __u32
- ``size``
-
* - __u32
- ``header_bit_size``
-
* - __u16
- ``first_mb_in_slice``
-
* - __u8
- ``slice_type``
-
* - __u8
- ``pic_parameter_set_id``
-
* - __u8
- ``colour_plane_id``
-
* - __u8
- ``redundant_pic_cnt``
-
* - __u16
- ``frame_num``
-
* - __u16
- ``idr_pic_id``
-
* - __u16
- ``pic_order_cnt_lsb``
-
* - __s32
- ``delta_pic_order_cnt_bottom``
-
* - __s32
- ``delta_pic_order_cnt0``
-
* - __s32
- ``delta_pic_order_cnt1``
-
* - struct :c:type:`v4l2_h264_pred_weight_table`
- ``pred_weight_table``
-
* - __u32
- ``dec_ref_pic_marking_bit_size``
-
* - __u32
- ``pic_order_cnt_bit_size``
-
* - __u8
- ``cabac_init_idc``
-
* - __s8
- ``slice_qp_delta``
-
* - __s8
- ``slice_qs_delta``
-
* - __u8
- ``disable_deblocking_filter_idc``
-
* - __s8
- ``slice_alpha_c0_offset_div2``
-
* - __s8
- ``slice_beta_offset_div2``
-
* - __u8
- ``num_ref_idx_l0_active_minus1``
-
* - __u8
- ``num_ref_idx_l1_active_minus1``
-
* - __u32
- ``slice_group_change_cycle``
-
* - __u8
- ``ref_pic_list0[32]``
- Reference picture list after applying the per-slice modifications
* - __u8
- ``ref_pic_list1[32]``
- Reference picture list after applying the per-slice modifications
* - __u32
- ``flags``
- See :ref:`Slice Parameter Flags <h264_slice_flags>`
.. _h264_slice_flags:
``Slice Parameter Set Flags``
.. cssclass:: longtable
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_H264_SLICE_FLAG_FIELD_PIC``
- 0x00000001
-
* - ``V4L2_H264_SLICE_FLAG_BOTTOM_FIELD``
- 0x00000002
-
* - ``V4L2_H264_SLICE_FLAG_DIRECT_SPATIAL_MV_PRED``
- 0x00000004
-
* - ``V4L2_H264_SLICE_FLAG_SP_FOR_SWITCH``
- 0x00000008
-
``Prediction Weight Table``
The bitstream parameters are defined according to :ref:`h264`,
section 7.4.3.2 "Prediction Weight Table Semantics". For further
documentation, refer to the above specification, unless there is
an explicit comment stating otherwise.
.. c:type:: v4l2_h264_pred_weight_table
.. cssclass:: longtable
.. flat-table:: struct v4l2_h264_pred_weight_table
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __u16
- ``luma_log2_weight_denom``
-
* - __u16
- ``chroma_log2_weight_denom``
-
* - struct :c:type:`v4l2_h264_weight_factors`
- ``weight_factors[2]``
- The weight factors at index 0 are the weight factors for the reference
list 0, the one at index 1 for the reference list 1.
.. c:type:: v4l2_h264_weight_factors
.. cssclass:: longtable
.. flat-table:: struct v4l2_h264_weight_factors
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __s16
- ``luma_weight[32]``
-
* - __s16
- ``luma_offset[32]``
-
* - __s16
- ``chroma_weight[32][2]``
-
* - __s16
- ``chroma_offset[32][2]``
-
``V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS (struct)``
Specifies the decode parameters (as extracted from the bitstream)
for the associated H264 slice data. This includes the necessary
parameters for configuring a stateless hardware decoding pipeline
for H264. The bitstream parameters are defined according to
:ref:`h264`. For further documentation, refer to the above
specification, unless there is an explicit comment stating
otherwise.
.. note::
This compound control is not yet part of the public kernel API and
it is expected to change.
.. c:type:: v4l2_ctrl_h264_decode_params
.. cssclass:: longtable
.. flat-table:: struct v4l2_ctrl_h264_decode_params
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - struct :c:type:`v4l2_h264_dpb_entry`
- ``dpb[16]``
-
* - __u16
- ``num_slices``
- Number of slices needed to decode the current frame
* - __u16
- ``nal_ref_idc``
- NAL reference ID value coming from the NAL Unit header
* - __u8
- ``ref_pic_list_p0[32]``
- Backward reference list used by P-frames in the original bitstream order
* - __u8
- ``ref_pic_list_b0[32]``
- Backward reference list used by B-frames in the original bitstream order
* - __u8
- ``ref_pic_list_b1[32]``
- Forward reference list used by B-frames in the original bitstream order
* - __s32
- ``top_field_order_cnt``
- Picture Order Count for the coded top field
* - __s32
- ``bottom_field_order_cnt``
- Picture Order Count for the coded bottom field
* - __u32
- ``flags``
- See :ref:`Decode Parameters Flags <h264_decode_params_flags>`
.. _h264_decode_params_flags:
``Decode Parameters Flags``
.. cssclass:: longtable
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_H264_DECODE_PARAM_FLAG_IDR_PIC``
- 0x00000001
- That picture is an IDR picture
.. c:type:: v4l2_h264_dpb_entry
.. cssclass:: longtable
.. flat-table:: struct v4l2_h264_dpb_entry
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __u64
- ``reference_ts``
- Timestamp of the V4L2 capture buffer to use as reference, used
with B-coded and P-coded frames. The timestamp refers to the
``timestamp`` field in struct :c:type:`v4l2_buffer`. Use the
:c:func:`v4l2_timeval_to_ns()` function to convert the struct
:c:type:`timeval` in struct :c:type:`v4l2_buffer` to a __u64.
* - __u16
- ``frame_num``
-
* - __u16
- ``pic_num``
-
* - __s32
- ``top_field_order_cnt``
-
* - __s32
- ``bottom_field_order_cnt``
-
* - __u32
- ``flags``
- See :ref:`DPB Entry Flags <h264_dpb_flags>`
.. _h264_dpb_flags:
``DPB Entries Flags``
.. cssclass:: longtable
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_H264_DPB_ENTRY_FLAG_VALID``
- 0x00000001
- The DPB entry is valid and should be considered
* - ``V4L2_H264_DPB_ENTRY_FLAG_ACTIVE``
- 0x00000002
- The DPB entry is currently being used as a reference frame
* - ``V4L2_H264_DPB_ENTRY_FLAG_LONG_TERM``
- 0x00000004
- The DPB entry is a long term reference frame
.. _v4l2-mpeg-mpeg2: .. _v4l2-mpeg-mpeg2:

View File

@ -85,20 +85,17 @@ be able to see such compound controls. In other words, these controls
with compound types should only be used programmatically. with compound types should only be used programmatically.
Since such compound controls need to expose more information about Since such compound controls need to expose more information about
themselves than is possible with themselves than is possible with :ref:`VIDIOC_QUERYCTRL <VIDIOC_QUERYCTRL>`
:ref:`VIDIOC_QUERYCTRL` the the :ref:`VIDIOC_QUERY_EXT_CTRL <VIDIOC_QUERYCTRL>` ioctl was added. In
:ref:`VIDIOC_QUERY_EXT_CTRL <VIDIOC_QUERYCTRL>` ioctl was added. In particular, this ioctl gives the dimensions of the N-dimensional array if
particular, this ioctl gives the dimensions of the N-dimensional array this control consists of more than one element.
if this control consists of more than one element.
.. note:: .. note::
#. It is important to realize that due to the flexibility of controls it is #. It is important to realize that due to the flexibility of controls it is
necessary to check whether the control you want to set actually is necessary to check whether the control you want to set actually is
supported in the driver and what the valid range of values is. So use supported in the driver and what the valid range of values is. So use
the :ref:`VIDIOC_QUERYCTRL` (or :ref:`VIDIOC_QUERY_EXT_CTRL :ref:`VIDIOC_QUERYCTRL` to check this.
<VIDIOC_QUERYCTRL>`) and :ref:`VIDIOC_QUERYMENU <VIDIOC_QUERYCTRL>`
ioctls to check this.
#. It is possible that some of the menu indices in a control of #. It is possible that some of the menu indices in a control of
type ``V4L2_CTRL_TYPE_MENU`` may not be supported (``VIDIOC_QUERYMENU`` type ``V4L2_CTRL_TYPE_MENU`` may not be supported (``VIDIOC_QUERYMENU``
@ -144,7 +141,7 @@ control class is found:
while (0 == ioctl(fd, VIDIOC_QUERYCTRL, &qctrl)) { while (0 == ioctl(fd, VIDIOC_QUERYCTRL, &qctrl)) {
if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_MPEG) if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_MPEG)
break; break;
/* ... */ /* ... */
qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
} }

View File

@ -51,6 +51,11 @@ determined by the video standard. Hence the distinction between temporal
and spatial order of fields. The diagrams below should make this and spatial order of fields. The diagrams below should make this
clearer. clearer.
In V4L it is assumed that all video cameras transmit fields on the media
bus in the same order they were captured, so if the top field was
captured first (is the older field), the top field is also transmitted
first on the bus.
All video capture and output devices must report the current field All video capture and output devices must report the current field
order. Some drivers may permit the selection of a different order, to order. Some drivers may permit the selection of a different order, to
this end applications initialize the ``field`` field of struct this end applications initialize the ``field`` field of struct
@ -101,10 +106,10 @@ enum v4l2_field
* - ``V4L2_FIELD_INTERLACED`` * - ``V4L2_FIELD_INTERLACED``
- 4 - 4
- Images contain both fields, interleaved line by line. The temporal - Images contain both fields, interleaved line by line. The temporal
order of the fields (whether the top or bottom field is first order of the fields (whether the top or bottom field is older)
transmitted) depends on the current video standard. M/NTSC depends on the current video standard. In M/NTSC the bottom
transmits the bottom field first, all other standards the top field is the older field. In all other standards the top field
field first. is the older field.
* - ``V4L2_FIELD_SEQ_TB`` * - ``V4L2_FIELD_SEQ_TB``
- 5 - 5
- Images contain both fields, the top field lines are stored first - Images contain both fields, the top field lines are stored first
@ -135,11 +140,11 @@ enum v4l2_field
* - ``V4L2_FIELD_INTERLACED_TB`` * - ``V4L2_FIELD_INTERLACED_TB``
- 8 - 8
- Images contain both fields, interleaved line by line, top field - Images contain both fields, interleaved line by line, top field
first. The top field is transmitted first. first. The top field is the older field.
* - ``V4L2_FIELD_INTERLACED_BT`` * - ``V4L2_FIELD_INTERLACED_BT``
- 9 - 9
- Images contain both fields, interleaved line by line, top field - Images contain both fields, interleaved line by line, top field
first. The bottom field is transmitted first. first. The bottom field is the older field.

View File

@ -52,6 +52,31 @@ Compressed Formats
- ``V4L2_PIX_FMT_H264_MVC`` - ``V4L2_PIX_FMT_H264_MVC``
- 'M264' - 'M264'
- H264 MVC video elementary stream. - H264 MVC video elementary stream.
* .. _V4L2-PIX-FMT-H264-SLICE-RAW:
- ``V4L2_PIX_FMT_H264_SLICE_RAW``
- 'S264'
- H264 parsed slice data, without the start code and as
extracted from the H264 bitstream. This format is adapted for
stateless video decoders that implement an H264 pipeline
(using the :ref:`mem2mem` and :ref:`media-request-api`).
Metadata associated with the frame to decode are required to
be passed through the ``V4L2_CID_MPEG_VIDEO_H264_SPS``,
``V4L2_CID_MPEG_VIDEO_H264_PPS``,
``V4L2_CID_MPEG_VIDEO_H264_SCALING_MATRIX``,
``V4L2_CID_MPEG_VIDEO_H264_SLICE_PARAMS`` and
``V4L2_CID_MPEG_VIDEO_H264_DECODE_PARAMS`` controls. See the
:ref:`associated Codec Control IDs <v4l2-mpeg-h264>`. Exactly
one output and one capture buffer must be provided for use
with this pixel format. The output buffer must contain the
appropriate number of macroblocks to decode a full
corresponding frame to the matching capture buffer.
.. note::
This format is not yet part of the public kernel API and it
is expected to change.
* .. _V4L2-PIX-FMT-H263: * .. _V4L2-PIX-FMT-H263:
- ``V4L2_PIX_FMT_H263`` - ``V4L2_PIX_FMT_H263``

View File

@ -31,7 +31,20 @@ describing all planes of that format.
* - __u32 * - __u32
- ``sizeimage`` - ``sizeimage``
- Maximum size in bytes required for image data in this plane. - Maximum size in bytes required for image data in this plane,
set by the driver. When the image consists of variable length
compressed data this is the number of bytes required by the
codec to support the worst-case compression scenario.
The driver will set the value for uncompressed images.
Clients are allowed to set the sizeimage field for variable length
compressed data flagged with ``V4L2_FMT_FLAG_COMPRESSED`` at
:ref:`VIDIOC_ENUM_FMT`, but the driver may ignore it and set the
value itself, or it may modify the provided value based on
alignment requirements or minimum/maximum size requirements.
If the client wants to leave this to the driver, then it should
set sizeimage to 0.
* - __u32 * - __u32
- ``bytesperline`` - ``bytesperline``
- Distance in bytes between the leftmost pixels in two adjacent - Distance in bytes between the leftmost pixels in two adjacent

View File

@ -89,7 +89,18 @@ Single-planar format structure
- Size in bytes of the buffer to hold a complete image, set by the - Size in bytes of the buffer to hold a complete image, set by the
driver. Usually this is ``bytesperline`` times ``height``. When driver. Usually this is ``bytesperline`` times ``height``. When
the image consists of variable length compressed data this is the the image consists of variable length compressed data this is the
maximum number of bytes required to hold an image. number of bytes required by the codec to support the worst-case
compression scenario.
The driver will set the value for uncompressed images.
Clients are allowed to set the sizeimage field for variable length
compressed data flagged with ``V4L2_FMT_FLAG_COMPRESSED`` at
:ref:`VIDIOC_ENUM_FMT`, but the driver may ignore it and set the
value itself, or it may modify the provided value based on
alignment requirements or minimum/maximum size requirements.
If the client wants to leave this to the driver, then it should
set sizeimage to 0.
* - __u32 * - __u32
- ``colorspace`` - ``colorspace``
- Image colorspace, from enum :c:type:`v4l2_colorspace`. - Image colorspace, from enum :c:type:`v4l2_colorspace`.

View File

@ -139,6 +139,14 @@ may continue as normal, but should be aware that data in the dequeued
buffer might be corrupted. When using the multi-planar API, the planes buffer might be corrupted. When using the multi-planar API, the planes
array must be passed in as well. array must be passed in as well.
If the application sets the ``memory`` field to ``V4L2_MEMORY_DMABUF`` to
dequeue a :ref:`DMABUF <dmabuf>` buffer, the driver fills the ``m.fd`` field
with a file descriptor numerically the same as the one given to ``VIDIOC_QBUF``
when the buffer was enqueued. No new file descriptor is created at dequeue time
and the value is only for the application convenience. When the multi-planar
API is used the ``m.fd`` fields of the passed array of struct
:c:type:`v4l2_plane` are filled instead.
By default ``VIDIOC_DQBUF`` blocks when no buffer is in the outgoing By default ``VIDIOC_DQBUF`` blocks when no buffer is in the outgoing
queue. When the ``O_NONBLOCK`` flag was given to the queue. When the ``O_NONBLOCK`` flag was given to the
:ref:`open() <func-open>` function, ``VIDIOC_DQBUF`` returns :ref:`open() <func-open>` function, ``VIDIOC_DQBUF`` returns

View File

@ -443,6 +443,36 @@ See also the examples in :ref:`control`.
- n/a - n/a
- A struct :c:type:`v4l2_ctrl_mpeg2_quantization`, containing MPEG-2 - A struct :c:type:`v4l2_ctrl_mpeg2_quantization`, containing MPEG-2
quantization matrices for stateless video decoders. quantization matrices for stateless video decoders.
* - ``V4L2_CTRL_TYPE_H264_SPS``
- n/a
- n/a
- n/a
- A struct :c:type:`v4l2_ctrl_h264_sps`, containing H264
sequence parameters for stateless video decoders.
* - ``V4L2_CTRL_TYPE_H264_PPS``
- n/a
- n/a
- n/a
- A struct :c:type:`v4l2_ctrl_h264_pps`, containing H264
picture parameters for stateless video decoders.
* - ``V4L2_CTRL_TYPE_H264_SCALING_MATRIX``
- n/a
- n/a
- n/a
- A struct :c:type:`v4l2_ctrl_h264_scaling_matrix`, containing H264
scaling matrices for stateless video decoders.
* - ``V4L2_CTRL_TYPE_H264_SLICE_PARAMS``
- n/a
- n/a
- n/a
- A struct :c:type:`v4l2_ctrl_h264_slice_params`, containing H264
slice parameters for stateless video decoders.
* - ``V4L2_CTRL_TYPE_H264_DECODE_PARAMS``
- n/a
- n/a
- n/a
- A struct :c:type:`v4l2_ctrl_h264_decode_params`, containing H264
decode parameters for stateless video decoders.
.. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}| .. tabularcolumns:: |p{6.6cm}|p{2.2cm}|p{8.7cm}|

View File

@ -64,5 +64,6 @@ For more details see the file COPYING in the source distribution of Linux.
si476x si476x
soc-camera soc-camera
uvcvideo uvcvideo
vimc
vivid vivid
zr364xx zr364xx

View File

@ -0,0 +1,22 @@
# SPDX-License-Identifier: GPL-2.0
digraph board {
rankdir=TB
n00000001 [label="{{} | Sensor A\n/dev/v4l-subdev0 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
n00000001:port0 -> n00000005:port0 [style=bold]
n00000001:port0 -> n0000000b [style=bold]
n00000003 [label="{{} | Sensor B\n/dev/v4l-subdev1 | {<port0> 0}}", shape=Mrecord, style=filled, fillcolor=green]
n00000003:port0 -> n00000008:port0 [style=bold]
n00000003:port0 -> n0000000f [style=bold]
n00000005 [label="{{<port0> 0} | Debayer A\n/dev/v4l-subdev2 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
n00000005:port1 -> n00000017:port0
n00000008 [label="{{<port0> 0} | Debayer B\n/dev/v4l-subdev3 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
n00000008:port1 -> n00000017:port0 [style=dashed]
n0000000b [label="Raw Capture 0\n/dev/video0", shape=box, style=filled, fillcolor=yellow]
n0000000f [label="Raw Capture 1\n/dev/video1", shape=box, style=filled, fillcolor=yellow]
n00000013 [label="RGB/YUV Input\n/dev/video2", shape=box, style=filled, fillcolor=yellow]
n00000013 -> n00000017:port0 [style=dashed]
n00000017 [label="{{<port0> 0} | Scaler\n/dev/v4l-subdev4 | {<port1> 1}}", shape=Mrecord, style=filled, fillcolor=green]
n00000017:port1 -> n0000001a [style=bold]
n0000001a [label="RGB/YUV Capture\n/dev/video3", shape=box, style=filled, fillcolor=yellow]
}

View File

@ -0,0 +1,98 @@
.. SPDX-License-Identifier: GPL-2.0
The Virtual Media Controller Driver (vimc)
==========================================
The vimc driver emulates complex video hardware using the V4L2 API and the Media
API. It has a capture device and three subdevices: sensor, debayer and scaler.
Topology
--------
The topology is hardcoded, although you could modify it in vimc-core and
recompile the driver to achieve your own topology. This is the default topology:
.. _vimc_topology_graph:
.. kernel-figure:: vimc.dot
:alt: vimc.dot
:align: center
Media pipeline graph on vimc
Configuring the topology
~~~~~~~~~~~~~~~~~~~~~~~~
Each subdevice will come with its default configuration (pixelformat, height,
width, ...). One needs to configure the topology in order to match the
configuration on each linked subdevice to stream frames through the pipeline.
If the configuration doesn't match, the stream will fail. The ``v4l-utils``
package is a bundle of user-space applications, that comes with ``media-ctl`` and
``v4l2-ctl`` that can be used to configure the vimc configuration. This sequence
of commands fits for the default topology:
.. code-block:: bash
media-ctl -d platform:vimc -V '"Sensor A":0[fmt:SBGGR8_1X8/640x480]'
media-ctl -d platform:vimc -V '"Debayer A":0[fmt:SBGGR8_1X8/640x480]'
media-ctl -d platform:vimc -V '"Sensor B":0[fmt:SBGGR8_1X8/640x480]'
media-ctl -d platform:vimc -V '"Debayer B":0[fmt:SBGGR8_1X8/640x480]'
v4l2-ctl -z platform:vimc -d "RGB/YUV Capture" -v width=1920,height=1440
v4l2-ctl -z platform:vimc -d "Raw Capture 0" -v pixelformat=BA81
v4l2-ctl -z platform:vimc -d "Raw Capture 1" -v pixelformat=BA81
Subdevices
----------
Subdevices define the behavior of an entity in the topology. Depending on the
subdevice, the entity can have multiple pads of type source or sink.
vimc-sensor:
Generates images in several formats using video test pattern generator.
Exposes:
* 1 Pad source
vimc-debayer:
Transforms images in bayer format into a non-bayer format.
Exposes:
* 1 Pad sink
* 1 Pad source
vimc-scaler:
Scale up the image by a factor of 3. E.g.: a 640x480 image becomes a
1920x1440 image. (this value can be configured, see at
`Module options`_).
Exposes:
* 1 Pad sink
* 1 Pad source
vimc-capture:
Exposes node /dev/videoX to allow userspace to capture the stream.
Exposes:
* 1 Pad sink
* 1 Pad source
Module options
---------------
Vimc has a few module parameters to configure the driver. You should pass
those arguments to each subdevice, not to the vimc module. For example::
vimc_subdevice.param=value
* ``vimc_scaler.sca_mult=<unsigned int>``
Image size multiplier factor to be used to multiply both width and
height, so the image size will be ``sca_mult^2`` bigger than the
original one. Currently, only supports scaling up (the default value
is 3).
* ``vimc_debayer.deb_mean_win_size=<unsigned int>``
Window size to calculate the mean. Note: the window size needs to be an
odd number, as the main pixel stays in the center of the window,
otherwise the next odd number is considered (the default value is 3).

View File

@ -941,6 +941,11 @@ Digital Video Controls
affects the reported colorspace since DVI_D outputs will always use affects the reported colorspace since DVI_D outputs will always use
sRGB. sRGB.
- Display Present:
sets the presence of a "display" on the HDMI output. This affects
the tx_edid_present, tx_hotplug and tx_rxsense controls.
FM Radio Receiver Controls FM Radio Receiver Controls
~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -136,6 +136,11 @@ replace symbol V4L2_CTRL_TYPE_U32 :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_U8 :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_U8 :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_MPEG2_SLICE_PARAMS :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_MPEG2_QUANTIZATION :c:type:`v4l2_ctrl_type` replace symbol V4L2_CTRL_TYPE_MPEG2_QUANTIZATION :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_H264_SPS :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_H264_PPS :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_H264_SCALING_MATRIX :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_H264_SLICE_PARAMS :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_H264_DECODE_PARAMS :c:type:`v4l2_ctrl_type`
# V4L2 capability defines # V4L2 capability defines
replace define V4L2_CAP_VIDEO_CAPTURE device-capabilities replace define V4L2_CAP_VIDEO_CAPTURE device-capabilities

View File

@ -668,6 +668,13 @@ S: Maintained
F: Documentation/i2c/busses/i2c-ali1563 F: Documentation/i2c/busses/i2c-ali1563
F: drivers/i2c/busses/i2c-ali1563.c F: drivers/i2c/busses/i2c-ali1563.c
ALLEGRO DVT VIDEO IP CORE DRIVER
M: Michael Tretter <m.tretter@pengutronix.de>
R: Pengutronix Kernel Team <kernel@pengutronix.de>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/staging/media/allegro-dvt/
ALLWINNER SECURITY SYSTEM ALLWINNER SECURITY SYSTEM
M: Corentin Labbe <clabbe.montjoie@gmail.com> M: Corentin Labbe <clabbe.montjoie@gmail.com>
L: linux-crypto@vger.kernel.org L: linux-crypto@vger.kernel.org
@ -910,7 +917,7 @@ F: drivers/iio/adc/ad7768-1.c
F: Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.txt F: Documentation/devicetree/bindings/iio/adc/adi,ad7768-1.txt
ANALOG DEVICES INC AD9389B DRIVER ANALOG DEVICES INC AD9389B DRIVER
M: Hans Verkuil <hans.verkuil@cisco.com> M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
F: drivers/media/i2c/ad9389b* F: drivers/media/i2c/ad9389b*
@ -942,19 +949,19 @@ S: Maintained
F: drivers/media/i2c/adv748x/* F: drivers/media/i2c/adv748x/*
ANALOG DEVICES INC ADV7511 DRIVER ANALOG DEVICES INC ADV7511 DRIVER
M: Hans Verkuil <hans.verkuil@cisco.com> M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
F: drivers/media/i2c/adv7511* F: drivers/media/i2c/adv7511*
ANALOG DEVICES INC ADV7604 DRIVER ANALOG DEVICES INC ADV7604 DRIVER
M: Hans Verkuil <hans.verkuil@cisco.com> M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
F: drivers/media/i2c/adv7604* F: drivers/media/i2c/adv7604*
ANALOG DEVICES INC ADV7842 DRIVER ANALOG DEVICES INC ADV7842 DRIVER
M: Hans Verkuil <hans.verkuil@cisco.com> M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
F: drivers/media/i2c/adv7842* F: drivers/media/i2c/adv7842*
@ -2350,7 +2357,7 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained S: Maintained
ARM/TEGRA HDMI CEC SUBSYSTEM SUPPORT ARM/TEGRA HDMI CEC SUBSYSTEM SUPPORT
M: Hans Verkuil <hans.verkuil@cisco.com> M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-tegra@vger.kernel.org L: linux-tegra@vger.kernel.org
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
@ -3685,7 +3692,7 @@ F: drivers/crypto/ccree/
W: https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family W: https://developer.arm.com/products/system-ip/trustzone-cryptocell/cryptocell-700-family
CEC FRAMEWORK CEC FRAMEWORK
M: Hans Verkuil <hans.verkuil@cisco.com> M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
W: http://linuxtv.org W: http://linuxtv.org
@ -3702,7 +3709,7 @@ F: Documentation/devicetree/bindings/media/cec.txt
F: Documentation/ABI/testing/debugfs-cec-error-inj F: Documentation/ABI/testing/debugfs-cec-error-inj
CEC GPIO DRIVER CEC GPIO DRIVER
M: Hans Verkuil <hans.verkuil@cisco.com> M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
W: http://linuxtv.org W: http://linuxtv.org
@ -3986,7 +3993,7 @@ S: Supported
F: drivers/platform/x86/classmate-laptop.c F: drivers/platform/x86/classmate-laptop.c
COBALT MEDIA DRIVER COBALT MEDIA DRIVER
M: Hans Verkuil <hans.verkuil@cisco.com> M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
W: https://linuxtv.org W: https://linuxtv.org
@ -6748,7 +6755,7 @@ F: drivers/gnss/
F: include/linux/gnss.h F: include/linux/gnss.h
GO7007 MPEG CODEC GO7007 MPEG CODEC
M: Hans Verkuil <hans.verkuil@cisco.com> M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
F: drivers/media/usb/go7007/ F: drivers/media/usb/go7007/
@ -9681,6 +9688,17 @@ L: linux-iio@vger.kernel.org
S: Maintained S: Maintained
F: drivers/iio/dac/cio-dac.c F: drivers/iio/dac/cio-dac.c
MEDIA CONTROLLER FRAMEWORK
M: Sakari Ailus <sakari.ailus@linux.intel.com>
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
W: https://www.linuxtv.org
T: git git://linuxtv.org/media_tree.git
S: Supported
F: drivers/media/mc/
F: include/media/media-*.h
F: include/uapi/linux/media.h
MEDIA DRIVERS FOR ASCOT2E MEDIA DRIVERS FOR ASCOT2E
M: Sergey Kozlov <serjk@netup.ru> M: Sergey Kozlov <serjk@netup.ru>
M: Abylay Ospan <aospan@netup.ru> M: Abylay Ospan <aospan@netup.ru>
@ -10257,7 +10275,7 @@ F: drivers/watchdog/menz69_wdt.c
MESON AO CEC DRIVER FOR AMLOGIC SOCS MESON AO CEC DRIVER FOR AMLOGIC SOCS
M: Neil Armstrong <narmstrong@baylibre.com> M: Neil Armstrong <narmstrong@baylibre.com>
L: linux-media@lists.freedesktop.org L: linux-media@vger.kernel.org
L: linux-amlogic@lists.infradead.org L: linux-amlogic@lists.infradead.org
W: http://linux-meson.com/ W: http://linux-meson.com/
S: Supported S: Supported
@ -10273,6 +10291,14 @@ S: Maintained
F: drivers/mtd/nand/raw/meson_* F: drivers/mtd/nand/raw/meson_*
F: Documentation/devicetree/bindings/mtd/amlogic,meson-nand.txt F: Documentation/devicetree/bindings/mtd/amlogic,meson-nand.txt
MESON VIDEO DECODER DRIVER FOR AMLOGIC SOCS
M: Maxime Jourdan <mjourdan@baylibre.com>
L: linux-media@vger.kernel.org
L: linux-amlogic@lists.infradead.org
S: Supported
F: drivers/staging/media/meson/vdec/
T: git git://linuxtv.org/media_tree.git
METHODE UDPU SUPPORT METHODE UDPU SUPPORT
M: Vladimir Vid <vladimir.vid@sartura.hr> M: Vladimir Vid <vladimir.vid@sartura.hr>
S: Maintained S: Maintained
@ -10326,7 +10352,9 @@ MICROCHIP ISC DRIVER
M: Eugen Hristev <eugen.hristev@microchip.com> M: Eugen Hristev <eugen.hristev@microchip.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Supported S: Supported
F: drivers/media/platform/atmel/atmel-isc.c F: drivers/media/platform/atmel/atmel-sama5d2-isc.c
F: drivers/media/platform/atmel/atmel-isc.h
F: drivers/media/platform/atmel/atmel-isc-base.c
F: drivers/media/platform/atmel/atmel-isc-regs.h F: drivers/media/platform/atmel/atmel-isc-regs.h
F: Documentation/devicetree/bindings/media/atmel-isc.txt F: Documentation/devicetree/bindings/media/atmel-isc.txt
@ -13542,11 +13570,11 @@ S: Maintained
F: drivers/media/platform/rockchip/rga/ F: drivers/media/platform/rockchip/rga/
F: Documentation/devicetree/bindings/media/rockchip-rga.txt F: Documentation/devicetree/bindings/media/rockchip-rga.txt
ROCKCHIP VPU CODEC DRIVER HANTRO VPU CODEC DRIVER
M: Ezequiel Garcia <ezequiel@collabora.com> M: Ezequiel Garcia <ezequiel@collabora.com>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
F: drivers/staging/media/platform/rockchip/vpu/ F: drivers/staging/media/platform/hantro/
F: Documentation/devicetree/bindings/media/rockchip-vpu.txt F: Documentation/devicetree/bindings/media/rockchip-vpu.txt
ROCKER DRIVER ROCKER DRIVER
@ -16746,7 +16774,7 @@ S: Maintained
F: drivers/net/ethernet/via/via-velocity.* F: drivers/net/ethernet/via/via-velocity.*
VICODEC VIRTUAL CODEC DRIVER VICODEC VIRTUAL CODEC DRIVER
M: Hans Verkuil <hans.verkuil@cisco.com> M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git T: git git://linuxtv.org/media_tree.git
W: https://linuxtv.org W: https://linuxtv.org
@ -16769,6 +16797,7 @@ VIDEOBUF2 FRAMEWORK
M: Pawel Osciak <pawel@osciak.com> M: Pawel Osciak <pawel@osciak.com>
M: Marek Szyprowski <m.szyprowski@samsung.com> M: Marek Szyprowski <m.szyprowski@samsung.com>
M: Kyungmin Park <kyungmin.park@samsung.com> M: Kyungmin Park <kyungmin.park@samsung.com>
R: Tomasz Figa <tfiga@chromium.org>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
F: drivers/media/common/videobuf2/* F: drivers/media/common/videobuf2/*

View File

@ -929,10 +929,6 @@ static int sur40_vidioc_querycap(struct file *file, void *priv,
strlcpy(cap->driver, DRIVER_SHORT, sizeof(cap->driver)); strlcpy(cap->driver, DRIVER_SHORT, sizeof(cap->driver));
strlcpy(cap->card, DRIVER_LONG, sizeof(cap->card)); strlcpy(cap->card, DRIVER_LONG, sizeof(cap->card));
usb_make_path(sur40->usbdev, cap->bus_info, sizeof(cap->bus_info)); usb_make_path(sur40->usbdev, cap->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TOUCH |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0; return 0;
} }
@ -1162,6 +1158,8 @@ static const struct video_device sur40_video_device = {
.fops = &sur40_video_fops, .fops = &sur40_video_fops,
.ioctl_ops = &sur40_video_ioctl_ops, .ioctl_ops = &sur40_video_ioctl_ops,
.release = video_device_release_empty, .release = video_device_release_empty,
.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TOUCH |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING,
}; };
/* USB-specific object needed to register this driver with the USB subsystem. */ /* USB-specific object needed to register this driver with the USB subsystem. */

View File

@ -89,40 +89,7 @@ config MEDIA_CEC_SUPPORT
source "drivers/media/cec/Kconfig" source "drivers/media/cec/Kconfig"
# source "drivers/media/mc/Kconfig"
# Media controller
# Selectable only for webcam/grabbers, as other drivers don't use it
#
config MEDIA_CONTROLLER
bool "Media Controller API"
depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
help
Enable the media controller API used to query media devices internal
topology and configure it dynamically.
This API is mostly used by camera interfaces in embedded platforms.
config MEDIA_CONTROLLER_DVB
bool "Enable Media controller for DVB (EXPERIMENTAL)"
depends on MEDIA_CONTROLLER && DVB_CORE
help
Enable the media controller API support for DVB.
This is currently experimental.
config MEDIA_CONTROLLER_REQUEST_API
bool "Enable Media controller Request API (EXPERIMENTAL)"
depends on MEDIA_CONTROLLER && STAGING_MEDIA
default n
help
DO NOT ENABLE THIS OPTION UNLESS YOU KNOW WHAT YOU'RE DOING.
This option enables the Request API for the Media controller and V4L2
interfaces. It is currently needed by a few stateless codec drivers.
There is currently no intention to provide API or ABI stability for
this new API as of yet.
# #
# Video4Linux support # Video4Linux support
@ -164,7 +131,6 @@ config DVB_MMAP
depends on DVB_CORE depends on DVB_CORE
depends on VIDEO_V4L2=y || VIDEO_V4L2=DVB_CORE depends on VIDEO_V4L2=y || VIDEO_V4L2=DVB_CORE
select VIDEOBUF2_VMALLOC select VIDEOBUF2_VMALLOC
default n
help help
This option enables DVB experimental memory-mapped API, which This option enables DVB experimental memory-mapped API, which
reduces the number of context switches to read DVB buffers, as reduces the number of context switches to read DVB buffers, as
@ -190,7 +156,6 @@ config DVB_NET
config TTPCI_EEPROM config TTPCI_EEPROM
tristate tristate
depends on I2C depends on I2C
default n
source "drivers/media/dvb-core/Kconfig" source "drivers/media/dvb-core/Kconfig"

View File

@ -3,15 +3,6 @@
# Makefile for the kernel multimedia device drivers. # Makefile for the kernel multimedia device drivers.
# #
media-objs := media-device.o media-devnode.o media-entity.o \
media-request.o
ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
ifeq ($(CONFIG_USB),y)
media-objs += media-dev-allocator.o
endif
endif
# #
# I2C drivers should come before other drivers, otherwise they'll fail # I2C drivers should come before other drivers, otherwise they'll fail
# when compiled as builtin drivers # when compiled as builtin drivers
@ -20,10 +11,10 @@ obj-y += i2c/ tuners/
obj-$(CONFIG_DVB_CORE) += dvb-frontends/ obj-$(CONFIG_DVB_CORE) += dvb-frontends/
# #
# Now, let's link-in the media core # Now, let's link-in the media controller core
# #
ifeq ($(CONFIG_MEDIA_CONTROLLER),y) ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
obj-$(CONFIG_MEDIA_SUPPORT) += media.o obj-$(CONFIG_MEDIA_SUPPORT) += mc/
endif endif
obj-$(CONFIG_VIDEO_DEV) += v4l2-core/ obj-$(CONFIG_VIDEO_DEV) += v4l2-core/

View File

@ -16,7 +16,10 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>
#include <drm/drm_connector.h>
#include <drm/drm_device.h>
#include <drm/drm_edid.h> #include <drm/drm_edid.h>
#include <drm/drm_file.h>
#include "cec-priv.h" #include "cec-priv.h"
@ -75,6 +78,16 @@ u16 cec_get_edid_phys_addr(const u8 *edid, unsigned int size,
} }
EXPORT_SYMBOL_GPL(cec_get_edid_phys_addr); EXPORT_SYMBOL_GPL(cec_get_edid_phys_addr);
void cec_fill_conn_info_from_drm(struct cec_connector_info *conn_info,
const struct drm_connector *connector)
{
memset(conn_info, 0, sizeof(*conn_info));
conn_info->type = CEC_CONNECTOR_TYPE_DRM;
conn_info->drm.card_no = connector->dev->primary->index;
conn_info->drm.connector_id = connector->base.id;
}
EXPORT_SYMBOL_GPL(cec_fill_conn_info_from_drm);
/* /*
* Queue a new event for this filehandle. If ts == 0, then set it * Queue a new event for this filehandle. If ts == 0, then set it
* to the current time. * to the current time.
@ -720,6 +733,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
struct cec_fh *fh, bool block) struct cec_fh *fh, bool block)
{ {
struct cec_data *data; struct cec_data *data;
bool is_raw = msg_is_raw(msg);
msg->rx_ts = 0; msg->rx_ts = 0;
msg->tx_ts = 0; msg->tx_ts = 0;
@ -735,15 +749,10 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
/* Make sure the timeout isn't 0. */ /* Make sure the timeout isn't 0. */
msg->timeout = 1000; msg->timeout = 1000;
} }
if (msg->timeout) msg->flags &= CEC_MSG_FL_REPLY_TO_FOLLOWERS | CEC_MSG_FL_RAW;
msg->flags &= CEC_MSG_FL_REPLY_TO_FOLLOWERS;
else
msg->flags = 0;
if (msg->len > 1 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) { if (!msg->timeout)
msg->msg[2] = adap->phys_addr >> 8; msg->flags &= ~CEC_MSG_FL_REPLY_TO_FOLLOWERS;
msg->msg[3] = adap->phys_addr & 0xff;
}
/* Sanity checks */ /* Sanity checks */
if (msg->len == 0 || msg->len > CEC_MAX_MSG_SIZE) { if (msg->len == 0 || msg->len > CEC_MAX_MSG_SIZE) {
@ -765,44 +774,80 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
dprintk(1, "%s: can't reply to poll msg\n", __func__); dprintk(1, "%s: can't reply to poll msg\n", __func__);
return -EINVAL; return -EINVAL;
} }
if (msg->len == 1) {
if (cec_msg_destination(msg) == 0xf) { if (is_raw) {
dprintk(1, "%s: invalid poll message\n", __func__); if (!capable(CAP_SYS_RAWIO))
return -EPERM;
} else {
/* A CDC-Only device can only send CDC messages */
if ((adap->log_addrs.flags & CEC_LOG_ADDRS_FL_CDC_ONLY) &&
(msg->len == 1 || msg->msg[1] != CEC_MSG_CDC_MESSAGE)) {
dprintk(1, "%s: not a CDC message\n", __func__);
return -EINVAL; return -EINVAL;
} }
if (cec_has_log_addr(adap, cec_msg_destination(msg))) {
/* if (msg->len >= 4 && msg->msg[1] == CEC_MSG_CDC_MESSAGE) {
* If the destination is a logical address our adapter msg->msg[2] = adap->phys_addr >> 8;
* has already claimed, then just NACK this. msg->msg[3] = adap->phys_addr & 0xff;
* It depends on the hardware what it will do with a }
* POLL to itself (some OK this), so it is just as
* easy to handle it here so the behavior will be if (msg->len == 1) {
* consistent. if (cec_msg_destination(msg) == 0xf) {
*/ dprintk(1, "%s: invalid poll message\n",
msg->tx_ts = ktime_get_ns(); __func__);
msg->tx_status = CEC_TX_STATUS_NACK | return -EINVAL;
CEC_TX_STATUS_MAX_RETRIES; }
msg->tx_nack_cnt = 1; if (cec_has_log_addr(adap, cec_msg_destination(msg))) {
msg->sequence = ++adap->sequence; /*
if (!msg->sequence) * If the destination is a logical address our
* adapter has already claimed, then just NACK
* this. It depends on the hardware what it will
* do with a POLL to itself (some OK this), so
* it is just as easy to handle it here so the
* behavior will be consistent.
*/
msg->tx_ts = ktime_get_ns();
msg->tx_status = CEC_TX_STATUS_NACK |
CEC_TX_STATUS_MAX_RETRIES;
msg->tx_nack_cnt = 1;
msg->sequence = ++adap->sequence; msg->sequence = ++adap->sequence;
return 0; if (!msg->sequence)
msg->sequence = ++adap->sequence;
return 0;
}
}
if (msg->len > 1 && !cec_msg_is_broadcast(msg) &&
cec_has_log_addr(adap, cec_msg_destination(msg))) {
dprintk(1, "%s: destination is the adapter itself\n",
__func__);
return -EINVAL;
}
if (msg->len > 1 && adap->is_configured &&
!cec_has_log_addr(adap, cec_msg_initiator(msg))) {
dprintk(1, "%s: initiator has unknown logical address %d\n",
__func__, cec_msg_initiator(msg));
return -EINVAL;
}
/*
* Special case: allow Ping and IMAGE/TEXT_VIEW_ON to be
* transmitted to a TV, even if the adapter is unconfigured.
* This makes it possible to detect or wake up displays that
* pull down the HPD when in standby.
*/
if (!adap->is_configured && !adap->is_configuring &&
(msg->len > 2 ||
cec_msg_destination(msg) != CEC_LOG_ADDR_TV ||
(msg->len == 2 && msg->msg[1] != CEC_MSG_IMAGE_VIEW_ON &&
msg->msg[1] != CEC_MSG_TEXT_VIEW_ON))) {
dprintk(1, "%s: adapter is unconfigured\n", __func__);
return -ENONET;
} }
} }
if (msg->len > 1 && !cec_msg_is_broadcast(msg) &&
cec_has_log_addr(adap, cec_msg_destination(msg))) {
dprintk(1, "%s: destination is the adapter itself\n", __func__);
return -EINVAL;
}
if (msg->len > 1 && adap->is_configured &&
!cec_has_log_addr(adap, cec_msg_initiator(msg))) {
dprintk(1, "%s: initiator has unknown logical address %d\n",
__func__, cec_msg_initiator(msg));
return -EINVAL;
}
if (!adap->is_configured && !adap->is_configuring) { if (!adap->is_configured && !adap->is_configuring) {
if (adap->needs_hpd || msg->msg[0] != 0xf0) { if (adap->needs_hpd) {
dprintk(1, "%s: adapter is unconfigured\n", __func__); dprintk(1, "%s: adapter is unconfigured and needs HPD\n",
__func__);
return -ENONET; return -ENONET;
} }
if (msg->reply) { if (msg->reply) {
@ -1566,6 +1611,22 @@ void cec_s_phys_addr_from_edid(struct cec_adapter *adap,
} }
EXPORT_SYMBOL_GPL(cec_s_phys_addr_from_edid); EXPORT_SYMBOL_GPL(cec_s_phys_addr_from_edid);
void cec_s_conn_info(struct cec_adapter *adap,
const struct cec_connector_info *conn_info)
{
if (!(adap->capabilities & CEC_CAP_CONNECTOR_INFO))
return;
mutex_lock(&adap->lock);
if (conn_info)
adap->conn_info = *conn_info;
else
memset(&adap->conn_info, 0, sizeof(adap->conn_info));
cec_post_state_event(adap);
mutex_unlock(&adap->lock);
}
EXPORT_SYMBOL_GPL(cec_s_conn_info);
/* /*
* Called from either the ioctl or a driver to set the logical addresses. * Called from either the ioctl or a driver to set the logical addresses.
* *

View File

@ -198,19 +198,11 @@ static long cec_transmit(struct cec_adapter *adap, struct cec_fh *fh,
if (copy_from_user(&msg, parg, sizeof(msg))) if (copy_from_user(&msg, parg, sizeof(msg)))
return -EFAULT; return -EFAULT;
/* A CDC-Only device can only send CDC messages */
if ((adap->log_addrs.flags & CEC_LOG_ADDRS_FL_CDC_ONLY) &&
(msg.len == 1 || msg.msg[1] != CEC_MSG_CDC_MESSAGE))
return -EINVAL;
mutex_lock(&adap->lock); mutex_lock(&adap->lock);
if (adap->log_addrs.num_log_addrs == 0) if (adap->log_addrs.num_log_addrs == 0)
err = -EPERM; err = -EPERM;
else if (adap->is_configuring) else if (adap->is_configuring)
err = -ENONET; err = -ENONET;
else if (!adap->is_configured &&
(adap->needs_hpd || msg.msg[0] != 0xf0))
err = -ENONET;
else if (cec_is_busy(adap, fh)) else if (cec_is_busy(adap, fh))
err = -EBUSY; err = -EBUSY;
else else

View File

@ -128,13 +128,14 @@ static int __must_check cec_devnode_register(struct cec_devnode *devnode,
devnode->cdev.owner = owner; devnode->cdev.owner = owner;
kobject_set_name(&devnode->cdev.kobj, "cec%d", devnode->minor); kobject_set_name(&devnode->cdev.kobj, "cec%d", devnode->minor);
devnode->registered = true;
ret = cdev_device_add(&devnode->cdev, &devnode->dev); ret = cdev_device_add(&devnode->cdev, &devnode->dev);
if (ret) { if (ret) {
devnode->registered = false;
pr_err("%s: cdev_device_add failed\n", __func__); pr_err("%s: cdev_device_add failed\n", __func__);
goto clr_bit; goto clr_bit;
} }
devnode->registered = true;
return 0; return 0;
clr_bit: clr_bit:
@ -256,6 +257,11 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
struct cec_adapter *adap; struct cec_adapter *adap;
int res; int res;
/*
* Disable this capability until the connector info public API
* is ready.
*/
caps &= ~CEC_CAP_CONNECTOR_INFO;
#ifndef CONFIG_MEDIA_CEC_RC #ifndef CONFIG_MEDIA_CEC_RC
caps &= ~CEC_CAP_RC; caps &= ~CEC_CAP_RC;
#endif #endif

View File

@ -21,8 +21,9 @@ struct cec_notifier {
struct mutex lock; struct mutex lock;
struct list_head head; struct list_head head;
struct kref kref; struct kref kref;
struct device *dev; struct device *hdmi_dev;
const char *conn; struct cec_connector_info conn_info;
const char *conn_name;
struct cec_adapter *cec_adap; struct cec_adapter *cec_adap;
void (*callback)(struct cec_adapter *adap, u16 pa); void (*callback)(struct cec_adapter *adap, u16 pa);
@ -32,14 +33,16 @@ struct cec_notifier {
static LIST_HEAD(cec_notifiers); static LIST_HEAD(cec_notifiers);
static DEFINE_MUTEX(cec_notifiers_lock); static DEFINE_MUTEX(cec_notifiers_lock);
struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char *conn) struct cec_notifier *
cec_notifier_get_conn(struct device *hdmi_dev, const char *conn_name)
{ {
struct cec_notifier *n; struct cec_notifier *n;
mutex_lock(&cec_notifiers_lock); mutex_lock(&cec_notifiers_lock);
list_for_each_entry(n, &cec_notifiers, head) { list_for_each_entry(n, &cec_notifiers, head) {
if (n->dev == dev && if (n->hdmi_dev == hdmi_dev &&
(!conn || !strcmp(n->conn, conn))) { (!conn_name ||
(n->conn_name && !strcmp(n->conn_name, conn_name)))) {
kref_get(&n->kref); kref_get(&n->kref);
mutex_unlock(&cec_notifiers_lock); mutex_unlock(&cec_notifiers_lock);
return n; return n;
@ -48,10 +51,17 @@ struct cec_notifier *cec_notifier_get_conn(struct device *dev, const char *conn)
n = kzalloc(sizeof(*n), GFP_KERNEL); n = kzalloc(sizeof(*n), GFP_KERNEL);
if (!n) if (!n)
goto unlock; goto unlock;
n->dev = dev; n->hdmi_dev = hdmi_dev;
if (conn) if (conn_name) {
n->conn = kstrdup(conn, GFP_KERNEL); n->conn_name = kstrdup(conn_name, GFP_KERNEL);
if (!n->conn_name) {
kfree(n);
n = NULL;
goto unlock;
}
}
n->phys_addr = CEC_PHYS_ADDR_INVALID; n->phys_addr = CEC_PHYS_ADDR_INVALID;
mutex_init(&n->lock); mutex_init(&n->lock);
kref_init(&n->kref); kref_init(&n->kref);
list_add_tail(&n->head, &cec_notifiers); list_add_tail(&n->head, &cec_notifiers);
@ -67,7 +77,7 @@ static void cec_notifier_release(struct kref *kref)
container_of(kref, struct cec_notifier, kref); container_of(kref, struct cec_notifier, kref);
list_del(&n->head); list_del(&n->head);
kfree(n->conn); kfree(n->conn_name);
kfree(n); kfree(n);
} }
@ -79,6 +89,84 @@ void cec_notifier_put(struct cec_notifier *n)
} }
EXPORT_SYMBOL_GPL(cec_notifier_put); EXPORT_SYMBOL_GPL(cec_notifier_put);
struct cec_notifier *
cec_notifier_conn_register(struct device *hdmi_dev, const char *conn_name,
const struct cec_connector_info *conn_info)
{
struct cec_notifier *n = cec_notifier_get_conn(hdmi_dev, conn_name);
if (!n)
return n;
mutex_lock(&n->lock);
n->phys_addr = CEC_PHYS_ADDR_INVALID;
if (conn_info)
n->conn_info = *conn_info;
else
memset(&n->conn_info, 0, sizeof(n->conn_info));
if (n->cec_adap) {
cec_phys_addr_invalidate(n->cec_adap);
cec_s_conn_info(n->cec_adap, conn_info);
}
mutex_unlock(&n->lock);
return n;
}
EXPORT_SYMBOL_GPL(cec_notifier_conn_register);
void cec_notifier_conn_unregister(struct cec_notifier *n)
{
if (!n)
return;
mutex_lock(&n->lock);
memset(&n->conn_info, 0, sizeof(n->conn_info));
n->phys_addr = CEC_PHYS_ADDR_INVALID;
if (n->cec_adap) {
cec_phys_addr_invalidate(n->cec_adap);
cec_s_conn_info(n->cec_adap, NULL);
}
mutex_unlock(&n->lock);
cec_notifier_put(n);
}
EXPORT_SYMBOL_GPL(cec_notifier_conn_unregister);
struct cec_notifier *
cec_notifier_cec_adap_register(struct device *hdmi_dev, const char *conn_name,
struct cec_adapter *adap)
{
struct cec_notifier *n;
if (WARN_ON(!adap))
return NULL;
n = cec_notifier_get_conn(hdmi_dev, conn_name);
if (!n)
return n;
mutex_lock(&n->lock);
n->cec_adap = adap;
adap->conn_info = n->conn_info;
adap->notifier = n;
cec_s_phys_addr(adap, n->phys_addr, false);
mutex_unlock(&n->lock);
return n;
}
EXPORT_SYMBOL_GPL(cec_notifier_cec_adap_register);
void cec_notifier_cec_adap_unregister(struct cec_notifier *n)
{
if (!n)
return;
mutex_lock(&n->lock);
n->cec_adap->notifier = NULL;
n->cec_adap = NULL;
n->callback = NULL;
mutex_unlock(&n->lock);
cec_notifier_put(n);
}
EXPORT_SYMBOL_GPL(cec_notifier_cec_adap_unregister);
void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa) void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa)
{ {
if (n == NULL) if (n == NULL)
@ -88,6 +176,8 @@ void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa)
n->phys_addr = pa; n->phys_addr = pa;
if (n->callback) if (n->callback)
n->callback(n->cec_adap, n->phys_addr); n->callback(n->cec_adap, n->phys_addr);
else if (n->cec_adap)
cec_s_phys_addr(n->cec_adap, n->phys_addr, false);
mutex_unlock(&n->lock); mutex_unlock(&n->lock);
} }
EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr); EXPORT_SYMBOL_GPL(cec_notifier_set_phys_addr);
@ -122,6 +212,10 @@ EXPORT_SYMBOL_GPL(cec_notifier_register);
void cec_notifier_unregister(struct cec_notifier *n) void cec_notifier_unregister(struct cec_notifier *n)
{ {
/* Do nothing unless cec_notifier_register was called first */
if (!n->callback)
return;
mutex_lock(&n->lock); mutex_lock(&n->lock);
n->callback = NULL; n->callback = NULL;
mutex_unlock(&n->lock); mutex_unlock(&n->lock);

View File

@ -20,6 +20,11 @@
/* devnode to cec_adapter */ /* devnode to cec_adapter */
#define to_cec_adapter(node) container_of(node, struct cec_adapter, devnode) #define to_cec_adapter(node) container_of(node, struct cec_adapter, devnode)
static inline bool msg_is_raw(const struct cec_msg *msg)
{
return msg->flags & CEC_MSG_FL_RAW;
}
/* cec-core.c */ /* cec-core.c */
extern int cec_debug; extern int cec_debug;
int cec_get_device(struct cec_devnode *devnode); int cec_get_device(struct cec_devnode *devnode);

View File

@ -608,6 +608,15 @@ int saa7146_register_device(struct video_device *vfd, struct saa7146_dev *dev,
for (i = 0; i < dev->ext_vv_data->num_stds; i++) for (i = 0; i < dev->ext_vv_data->num_stds; i++)
vfd->tvnorms |= dev->ext_vv_data->stds[i].id; vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
strscpy(vfd->name, name, sizeof(vfd->name)); strscpy(vfd->name, name, sizeof(vfd->name));
vfd->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
vfd->device_caps |= dev->ext_vv_data->capabilities;
if (type == VFL_TYPE_GRABBER)
vfd->device_caps &=
~(V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT);
else
vfd->device_caps &=
~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_AUDIO);
video_set_drvdata(vfd, dev); video_set_drvdata(vfd, dev);
err = video_register_device(vfd, type, -1); err = video_register_device(vfd, type, -1);

View File

@ -448,25 +448,15 @@ static int video_end(struct saa7146_fh *fh, struct file *file)
static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap) static int vidioc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
{ {
struct video_device *vdev = video_devdata(file);
struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev; struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver)); strscpy((char *)cap->driver, "saa7146 v4l2", sizeof(cap->driver));
strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card)); strscpy((char *)cap->card, dev->ext->name, sizeof(cap->card));
sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci)); sprintf((char *)cap->bus_info, "PCI:%s", pci_name(dev->pci));
cap->device_caps = cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY |
V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_DEVICE_CAPS;
V4L2_CAP_READWRITE | cap->capabilities |= dev->ext_vv_data->capabilities;
V4L2_CAP_STREAMING;
cap->device_caps |= dev->ext_vv_data->capabilities;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
if (vdev->vfl_type == VFL_TYPE_GRABBER)
cap->device_caps &=
~(V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_OUTPUT);
else
cap->device_caps &=
~(V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_AUDIO);
return 0; return 0;
} }

View File

@ -205,8 +205,13 @@ static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
* NOTE: mmapped areas should be page aligned * NOTE: mmapped areas should be page aligned
*/ */
for (plane = 0; plane < vb->num_planes; ++plane) { for (plane = 0; plane < vb->num_planes; ++plane) {
/* Memops alloc requires size to be page aligned. */
unsigned long size = PAGE_ALIGN(vb->planes[plane].length); unsigned long size = PAGE_ALIGN(vb->planes[plane].length);
/* Did it wrap around? */
if (size < vb->planes[plane].length)
goto free;
mem_priv = call_ptr_memop(vb, alloc, mem_priv = call_ptr_memop(vb, alloc,
q->alloc_devs[plane] ? : q->dev, q->alloc_devs[plane] ? : q->dev,
q->dma_attrs, size, q->dma_dir, q->gfp_flags); q->dma_attrs, size, q->dma_dir, q->gfp_flags);

View File

@ -475,8 +475,7 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr,
buf->dma_dir = dma_dir; buf->dma_dir = dma_dir;
offset = lower_32_bits(offset_in_page(vaddr)); offset = lower_32_bits(offset_in_page(vaddr));
vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE || vec = vb2_create_framevec(vaddr, size);
dma_dir == DMA_BIDIRECTIONAL);
if (IS_ERR(vec)) { if (IS_ERR(vec)) {
ret = PTR_ERR(vec); ret = PTR_ERR(vec);
goto fail_buf; goto fail_buf;

View File

@ -59,7 +59,7 @@ static int vb2_dma_sg_alloc_compacted(struct vb2_dma_sg_buf *buf,
gfp_t gfp_flags) gfp_t gfp_flags)
{ {
unsigned int last_page = 0; unsigned int last_page = 0;
int size = buf->size; unsigned long size = buf->size;
while (size > 0) { while (size > 0) {
struct page *pages; struct page *pages;
@ -239,8 +239,7 @@ static void *vb2_dma_sg_get_userptr(struct device *dev, unsigned long vaddr,
buf->offset = vaddr & ~PAGE_MASK; buf->offset = vaddr & ~PAGE_MASK;
buf->size = size; buf->size = size;
buf->dma_sgt = &buf->sg_table; buf->dma_sgt = &buf->sg_table;
vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE || vec = vb2_create_framevec(vaddr, size);
dma_dir == DMA_BIDIRECTIONAL);
if (IS_ERR(vec)) if (IS_ERR(vec))
goto userptr_fail_pfnvec; goto userptr_fail_pfnvec;
buf->vec = vec; buf->vec = vec;

View File

@ -26,7 +26,6 @@
* vb2_create_framevec() - map virtual addresses to pfns * vb2_create_framevec() - map virtual addresses to pfns
* @start: Virtual user address where we start mapping * @start: Virtual user address where we start mapping
* @length: Length of a range to map * @length: Length of a range to map
* @write: Should we map for writing into the area
* *
* This function allocates and fills in a vector with pfns corresponding to * This function allocates and fills in a vector with pfns corresponding to
* virtual address range passed in arguments. If pfns have corresponding pages, * virtual address range passed in arguments. If pfns have corresponding pages,
@ -35,17 +34,13 @@
* failure. Returned vector needs to be freed via vb2_destroy_pfnvec(). * failure. Returned vector needs to be freed via vb2_destroy_pfnvec().
*/ */
struct frame_vector *vb2_create_framevec(unsigned long start, struct frame_vector *vb2_create_framevec(unsigned long start,
unsigned long length, unsigned long length)
bool write)
{ {
int ret; int ret;
unsigned long first, last; unsigned long first, last;
unsigned long nr; unsigned long nr;
struct frame_vector *vec; struct frame_vector *vec;
unsigned int flags = FOLL_FORCE; unsigned int flags = FOLL_FORCE | FOLL_WRITE;
if (write)
flags |= FOLL_WRITE;
first = start >> PAGE_SHIFT; first = start >> PAGE_SHIFT;
last = (start + length - 1) >> PAGE_SHIFT; last = (start + length - 1) >> PAGE_SHIFT;

View File

@ -563,11 +563,6 @@ static void __fill_v4l2_buffer(struct vb2_buffer *vb, void *pb)
b->flags |= V4L2_BUF_FLAG_REQUEST_FD; b->flags |= V4L2_BUF_FLAG_REQUEST_FD;
b->request_fd = vbuf->request_fd; b->request_fd = vbuf->request_fd;
} }
if (!q->is_output &&
b->flags & V4L2_BUF_FLAG_DONE &&
b->flags & V4L2_BUF_FLAG_LAST)
q->last_buffer_dequeued = true;
} }
/* /*
@ -786,6 +781,11 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
ret = vb2_core_dqbuf(q, NULL, b, nonblocking); ret = vb2_core_dqbuf(q, NULL, b, nonblocking);
if (!q->is_output &&
b->flags & V4L2_BUF_FLAG_DONE &&
b->flags & V4L2_BUF_FLAG_LAST)
q->last_buffer_dequeued = true;
/* /*
* After calling the VIDIOC_DQBUF V4L2_BUF_FLAG_DONE must be * After calling the VIDIOC_DQBUF V4L2_BUF_FLAG_DONE must be
* cleared. * cleared.

View File

@ -87,8 +87,7 @@ static void *vb2_vmalloc_get_userptr(struct device *dev, unsigned long vaddr,
buf->dma_dir = dma_dir; buf->dma_dir = dma_dir;
offset = vaddr & ~PAGE_MASK; offset = vaddr & ~PAGE_MASK;
buf->size = size; buf->size = size;
vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE || vec = vb2_create_framevec(vaddr, size);
dma_dir == DMA_BIDIRECTIONAL);
if (IS_ERR(vec)) { if (IS_ERR(vec)) {
ret = PTR_ERR(vec); ret = PTR_ERR(vec);
goto fail_pfnvec_create; goto fail_pfnvec_create;

View File

@ -19,7 +19,6 @@ config DVB_MAX_ADAPTERS
config DVB_DYNAMIC_MINORS config DVB_DYNAMIC_MINORS
bool "Dynamic DVB minor allocation" bool "Dynamic DVB minor allocation"
depends on DVB_CORE depends on DVB_CORE
default n
help help
If you say Y here, the DVB subsystem will use dynamic minor If you say Y here, the DVB subsystem will use dynamic minor
allocation for any device that uses the DVB major number. allocation for any device that uses the DVB major number.
@ -32,7 +31,6 @@ config DVB_DYNAMIC_MINORS
config DVB_DEMUX_SECTION_LOSS_LOG config DVB_DEMUX_SECTION_LOSS_LOG
bool "Enable DVB demux section packet loss log" bool "Enable DVB demux section packet loss log"
depends on DVB_CORE depends on DVB_CORE
default n
help help
Enable extra log messages meant to detect packet loss Enable extra log messages meant to detect packet loss
inside the Kernel. inside the Kernel.
@ -45,7 +43,6 @@ config DVB_DEMUX_SECTION_LOSS_LOG
config DVB_ULE_DEBUG config DVB_ULE_DEBUG
bool "Enable DVB net ULE packet debug messages" bool "Enable DVB net ULE packet debug messages"
depends on DVB_CORE depends on DVB_CORE
default n
help help
Enable extra log messages meant to detect problems while Enable extra log messages meant to detect problems while
handling DVB network ULE packet loss inside the Kernel. handling DVB network ULE packet loss inside the Kernel.

View File

@ -2311,6 +2311,78 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
return 0; return 0;
} }
static int dvb_get_property(struct dvb_frontend *fe, struct file *file,
struct dtv_properties *tvps)
{
struct dvb_frontend_private *fepriv = fe->frontend_priv;
struct dtv_property *tvp = NULL;
struct dtv_frontend_properties getp;
int i, err;
memcpy(&getp, &fe->dtv_property_cache, sizeof(getp));
dev_dbg(fe->dvb->device, "%s: properties.num = %d\n",
__func__, tvps->num);
dev_dbg(fe->dvb->device, "%s: properties.props = %p\n",
__func__, tvps->props);
/*
* Put an arbitrary limit on the number of messages that can
* be sent at once
*/
if (!tvps->num || tvps->num > DTV_IOCTL_MAX_MSGS)
return -EINVAL;
tvp = memdup_user((void __user *)tvps->props, tvps->num * sizeof(*tvp));
if (IS_ERR(tvp))
return PTR_ERR(tvp);
/*
* Let's use our own copy of property cache, in order to
* avoid mangling with DTV zigzag logic, as drivers might
* return crap, if they don't check if the data is available
* before updating the properties cache.
*/
if (fepriv->state != FESTATE_IDLE) {
err = dtv_get_frontend(fe, &getp, NULL);
if (err < 0)
goto out;
}
for (i = 0; i < tvps->num; i++) {
err = dtv_property_process_get(fe, &getp,
tvp + i, file);
if (err < 0)
goto out;
}
if (copy_to_user((void __user *)tvps->props, tvp,
tvps->num * sizeof(struct dtv_property))) {
err = -EFAULT;
goto out;
}
err = 0;
out:
kfree(tvp);
return err;
}
static int dvb_get_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p_out)
{
struct dtv_frontend_properties getp;
/*
* Let's use our own copy of property cache, in order to
* avoid mangling with DTV zigzag logic, as drivers might
* return crap, if they don't check if the data is available
* before updating the properties cache.
*/
memcpy(&getp, &fe->dtv_property_cache, sizeof(getp));
return dtv_get_frontend(fe, &getp, p_out);
}
static int dvb_frontend_handle_ioctl(struct file *file, static int dvb_frontend_handle_ioctl(struct file *file,
unsigned int cmd, void *parg) unsigned int cmd, void *parg)
{ {
@ -2356,58 +2428,9 @@ static int dvb_frontend_handle_ioctl(struct file *file,
err = 0; err = 0;
break; break;
} }
case FE_GET_PROPERTY: { case FE_GET_PROPERTY:
struct dtv_properties *tvps = parg; err = dvb_get_property(fe, file, parg);
struct dtv_property *tvp = NULL;
struct dtv_frontend_properties getp = fe->dtv_property_cache;
dev_dbg(fe->dvb->device, "%s: properties.num = %d\n",
__func__, tvps->num);
dev_dbg(fe->dvb->device, "%s: properties.props = %p\n",
__func__, tvps->props);
/*
* Put an arbitrary limit on the number of messages that can
* be sent at once
*/
if (!tvps->num || (tvps->num > DTV_IOCTL_MAX_MSGS))
return -EINVAL;
tvp = memdup_user((void __user *)tvps->props, tvps->num * sizeof(*tvp));
if (IS_ERR(tvp))
return PTR_ERR(tvp);
/*
* Let's use our own copy of property cache, in order to
* avoid mangling with DTV zigzag logic, as drivers might
* return crap, if they don't check if the data is available
* before updating the properties cache.
*/
if (fepriv->state != FESTATE_IDLE) {
err = dtv_get_frontend(fe, &getp, NULL);
if (err < 0) {
kfree(tvp);
return err;
}
}
for (i = 0; i < tvps->num; i++) {
err = dtv_property_process_get(fe, &getp,
tvp + i, file);
if (err < 0) {
kfree(tvp);
return err;
}
}
if (copy_to_user((void __user *)tvps->props, tvp,
tvps->num * sizeof(struct dtv_property))) {
kfree(tvp);
return -EFAULT;
}
kfree(tvp);
err = 0;
break; break;
}
case FE_GET_INFO: { case FE_GET_INFO: {
struct dvb_frontend_info *info = parg; struct dvb_frontend_info *info = parg;
@ -2545,7 +2568,6 @@ static int dvb_frontend_handle_ioctl(struct file *file,
fepriv->tune_mode_flags = (unsigned long)parg; fepriv->tune_mode_flags = (unsigned long)parg;
err = 0; err = 0;
break; break;
/* DEPRECATED dish control ioctls */ /* DEPRECATED dish control ioctls */
case FE_DISHNETWORK_SEND_LEGACY_CMD: case FE_DISHNETWORK_SEND_LEGACY_CMD:
@ -2664,22 +2686,14 @@ static int dvb_frontend_handle_ioctl(struct file *file,
break; break;
err = dtv_set_frontend(fe); err = dtv_set_frontend(fe);
break; break;
case FE_GET_EVENT: case FE_GET_EVENT:
err = dvb_frontend_get_event(fe, parg, file->f_flags); err = dvb_frontend_get_event(fe, parg, file->f_flags);
break; break;
case FE_GET_FRONTEND: { case FE_GET_FRONTEND:
struct dtv_frontend_properties getp = fe->dtv_property_cache; err = dvb_get_frontend(fe, parg);
/*
* Let's use our own copy of property cache, in order to
* avoid mangling with DTV zigzag logic, as drivers might
* return crap, if they don't check if the data is available
* before updating the properties cache.
*/
err = dtv_get_frontend(fe, &getp, parg);
break; break;
}
default: default:
return -ENOTSUPP; return -ENOTSUPP;

View File

@ -1,5 +1,5 @@
menu "Customise DVB Frontends" menu "Customise DVB Frontends"
visible if !MEDIA_SUBDRV_AUTOSELECT || COMPILE_TEST visible if !MEDIA_SUBDRV_AUTOSELECT || COMPILE_TEST || EXPERT
comment "Multistandard (satellite) frontends" comment "Multistandard (satellite) frontends"
depends on DVB_CORE depends on DVB_CORE
@ -945,5 +945,4 @@ comment "Tools to develop new frontends"
config DVB_DUMMY_FE config DVB_DUMMY_FE
tristate "Dummy frontend driver" tristate "Dummy frontend driver"
depends on DVB_CORE depends on DVB_CORE
default n
endmenu endmenu

View File

@ -428,9 +428,6 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver)); strscpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
strscpy(cap->card, dev->vdev.name, sizeof(cap->card)); strscpy(cap->card, dev->vdev.name, sizeof(cap->card));
usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info)); usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0; return 0;
} }
@ -1242,6 +1239,8 @@ static struct video_device rtl2832_sdr_template = {
.release = video_device_release_empty, .release = video_device_release_empty,
.fops = &rtl2832_sdr_fops, .fops = &rtl2832_sdr_fops,
.ioctl_ops = &rtl2832_sdr_ioctl_ops, .ioctl_ops = &rtl2832_sdr_ioctl_ops,
.device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
V4L2_CAP_READWRITE | V4L2_CAP_TUNER,
}; };
static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl) static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)

View File

@ -674,8 +674,11 @@ static const struct dvb_frontend_ops si2168_ops = {
.delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A}, .delsys = {SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A},
.info = { .info = {
.name = "Silicon Labs Si2168", .name = "Silicon Labs Si2168",
.symbol_rate_min = 1000000, .frequency_min_hz = 48 * MHz,
.symbol_rate_max = 7200000, .frequency_max_hz = 870 * MHz,
.frequency_stepsize_hz = 62500,
.symbol_rate_min = 1000000,
.symbol_rate_max = 7200000,
.caps = FE_CAN_FEC_1_2 | .caps = FE_CAN_FEC_1_2 |
FE_CAN_FEC_2_3 | FE_CAN_FEC_2_3 |
FE_CAN_FEC_3_4 | FE_CAN_FEC_3_4 |

View File

@ -682,7 +682,7 @@ static const struct dvb_frontend_ops stv0297_ops = {
.delsys = { SYS_DVBC_ANNEX_A }, .delsys = { SYS_DVBC_ANNEX_A },
.info = { .info = {
.name = "ST STV0297 DVB-C", .name = "ST STV0297 DVB-C",
.frequency_min_hz = 470 * MHz, .frequency_min_hz = 47 * MHz,
.frequency_max_hz = 862 * MHz, .frequency_max_hz = 862 * MHz,
.frequency_stepsize_hz = 62500, .frequency_stepsize_hz = 62500,
.symbol_rate_min = 870000, .symbol_rate_min = 870000,

View File

@ -4889,6 +4889,66 @@ static int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir,
return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg); return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
} }
static int stv090x_setup_compound(struct stv090x_state *state)
{
struct stv090x_dev *temp_int;
temp_int = find_dev(state->i2c,
state->config->address);
if (temp_int && state->demod_mode == STV090x_DUAL) {
state->internal = temp_int->internal;
state->internal->num_used++;
dprintk(FE_INFO, 1, "Found Internal Structure!");
} else {
state->internal = kmalloc(sizeof(*state->internal), GFP_KERNEL);
if (!state->internal)
goto error;
temp_int = append_internal(state->internal);
if (!temp_int) {
kfree(state->internal);
goto error;
}
state->internal->num_used = 1;
state->internal->mclk = 0;
state->internal->dev_ver = 0;
state->internal->i2c_adap = state->i2c;
state->internal->i2c_addr = state->config->address;
dprintk(FE_INFO, 1, "Create New Internal Structure!");
mutex_init(&state->internal->demod_lock);
mutex_init(&state->internal->tuner_lock);
if (stv090x_setup(&state->frontend) < 0) {
dprintk(FE_ERROR, 1, "Error setting up device");
goto err_remove;
}
}
if (state->internal->dev_ver >= 0x30)
state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
/* workaround for stuck DiSEqC output */
if (state->config->diseqc_envelope_mode)
stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
state->config->set_gpio = stv090x_set_gpio;
dprintk(FE_ERROR, 1, "Probing %s demodulator(%d) Cut=0x%02x",
state->device == STV0900 ? "STV0900" : "STV0903",
state->config->demod,
state->internal->dev_ver);
return 0;
error:
return -ENOMEM;
err_remove:
remove_dev(state->internal);
kfree(state->internal);
return -ENODEV;
}
static const struct dvb_frontend_ops stv090x_ops = { static const struct dvb_frontend_ops stv090x_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS }, .delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
.info = { .info = {
@ -4921,16 +4981,74 @@ static const struct dvb_frontend_ops stv090x_ops = {
.read_snr = stv090x_read_cnr, .read_snr = stv090x_read_cnr,
}; };
static struct dvb_frontend *stv090x_get_dvb_frontend(struct i2c_client *client)
{
struct stv090x_state *state = i2c_get_clientdata(client);
dev_dbg(&client->dev, "\n");
return &state->frontend;
}
static int stv090x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int ret = 0;
struct stv090x_config *config = client->dev.platform_data;
struct stv090x_state *state = NULL;
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state) {
ret = -ENOMEM;
goto error;
}
state->verbose = &verbose;
state->config = config;
state->i2c = client->adapter;
state->frontend.ops = stv090x_ops;
state->frontend.demodulator_priv = state;
state->demod = config->demod;
/* Single or Dual mode */
state->demod_mode = config->demod_mode;
state->device = config->device;
/* default */
state->rolloff = STV090x_RO_35;
ret = stv090x_setup_compound(state);
if (ret)
goto error;
i2c_set_clientdata(client, state);
/* setup callbacks */
config->get_dvb_frontend = stv090x_get_dvb_frontend;
return 0;
error:
kfree(state);
return ret;
}
static int stv090x_remove(struct i2c_client *client)
{
struct stv090x_state *state = i2c_get_clientdata(client);
stv090x_release(&state->frontend);
return 0;
}
struct dvb_frontend *stv090x_attach(struct stv090x_config *config, struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
struct i2c_adapter *i2c, struct i2c_adapter *i2c,
enum stv090x_demodulator demod) enum stv090x_demodulator demod)
{ {
int ret = 0;
struct stv090x_state *state = NULL; struct stv090x_state *state = NULL;
struct stv090x_dev *temp_int;
state = kzalloc(sizeof (struct stv090x_state), GFP_KERNEL); state = kzalloc(sizeof(*state), GFP_KERNEL);
if (state == NULL) if (!state)
goto error; goto error;
state->verbose = &verbose; state->verbose = &verbose;
@ -4939,67 +5057,42 @@ struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
state->frontend.ops = stv090x_ops; state->frontend.ops = stv090x_ops;
state->frontend.demodulator_priv = state; state->frontend.demodulator_priv = state;
state->demod = demod; state->demod = demod;
state->demod_mode = config->demod_mode; /* Single or Dual mode */ /* Single or Dual mode */
state->demod_mode = config->demod_mode;
state->device = config->device; state->device = config->device;
state->rolloff = STV090x_RO_35; /* default */ /* default */
state->rolloff = STV090x_RO_35;
temp_int = find_dev(state->i2c, ret = stv090x_setup_compound(state);
state->config->address); if (ret)
goto error;
if ((temp_int != NULL) && (state->demod_mode == STV090x_DUAL)) {
state->internal = temp_int->internal;
state->internal->num_used++;
dprintk(FE_INFO, 1, "Found Internal Structure!");
} else {
state->internal = kmalloc(sizeof(struct stv090x_internal),
GFP_KERNEL);
if (!state->internal)
goto error;
temp_int = append_internal(state->internal);
if (!temp_int) {
kfree(state->internal);
goto error;
}
state->internal->num_used = 1;
state->internal->mclk = 0;
state->internal->dev_ver = 0;
state->internal->i2c_adap = state->i2c;
state->internal->i2c_addr = state->config->address;
dprintk(FE_INFO, 1, "Create New Internal Structure!");
mutex_init(&state->internal->demod_lock);
mutex_init(&state->internal->tuner_lock);
if (stv090x_setup(&state->frontend) < 0) {
dprintk(FE_ERROR, 1, "Error setting up device");
goto err_remove;
}
}
if (state->internal->dev_ver >= 0x30)
state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
/* workaround for stuck DiSEqC output */
if (config->diseqc_envelope_mode)
stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
config->set_gpio = stv090x_set_gpio;
dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
state->device == STV0900 ? "STV0900" : "STV0903",
demod,
state->internal->dev_ver);
return &state->frontend; return &state->frontend;
err_remove:
remove_dev(state->internal);
kfree(state->internal);
error: error:
kfree(state); kfree(state);
return NULL; return NULL;
} }
EXPORT_SYMBOL(stv090x_attach); EXPORT_SYMBOL(stv090x_attach);
static const struct i2c_device_id stv090x_id_table[] = {
{"stv090x", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, stv090x_id_table);
static struct i2c_driver stv090x_driver = {
.driver = {
.name = "stv090x",
.suppress_bind_attrs = true,
},
.probe = stv090x_probe,
.remove = stv090x_remove,
.id_table = stv090x_id_table,
};
module_i2c_driver(stv090x_driver);
MODULE_PARM_DESC(verbose, "Set Verbosity level"); MODULE_PARM_DESC(verbose, "Set Verbosity level");
MODULE_AUTHOR("Manu Abraham"); MODULE_AUTHOR("Manu Abraham");
MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend"); MODULE_DESCRIPTION("STV090x Multi-Std Broadcast frontend");

View File

@ -57,6 +57,7 @@ struct stv090x_config {
enum stv090x_device device; enum stv090x_device device;
enum stv090x_mode demod_mode; enum stv090x_mode demod_mode;
enum stv090x_clkmode clk_mode; enum stv090x_clkmode clk_mode;
enum stv090x_demodulator demod;
u32 xtal; /* default: 8000000 */ u32 xtal; /* default: 8000000 */
u8 address; /* default: 0x68 */ u8 address; /* default: 0x68 */
@ -93,6 +94,8 @@ struct stv090x_config {
/* dir = 0 -> output, dir = 1 -> input/open-drain */ /* dir = 0 -> output, dir = 1 -> input/open-drain */
int (*set_gpio)(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value, int (*set_gpio)(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
u8 xor_value); u8 xor_value);
struct dvb_frontend* (*get_dvb_frontend)(struct i2c_client *i2c);
}; };
#if IS_REACHABLE(CONFIG_DVB_STV090x) #if IS_REACHABLE(CONFIG_DVB_STV090x)

View File

@ -237,7 +237,7 @@ struct stv090x_state {
struct stv090x_internal *internal; struct stv090x_internal *internal;
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
const struct stv090x_config *config; struct stv090x_config *config;
struct dvb_frontend frontend; struct dvb_frontend frontend;
u32 *verbose; /* Cached module verbosity */ u32 *verbose; /* Cached module verbosity */

View File

@ -333,6 +333,41 @@ static void stv6110x_release(struct dvb_frontend *fe)
kfree(stv6110x); kfree(stv6110x);
} }
static void st6110x_init_regs(struct stv6110x_state *stv6110x)
{
u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
memcpy(stv6110x->regs, default_regs, 8);
}
static void stv6110x_setup_divider(struct stv6110x_state *stv6110x)
{
switch (stv6110x->config->clk_div) {
default:
case 1:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2],
CTRL2_CO_DIV,
0);
break;
case 2:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2],
CTRL2_CO_DIV,
1);
break;
case 4:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2],
CTRL2_CO_DIV,
2);
break;
case 8:
case 0:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2],
CTRL2_CO_DIV,
3);
break;
}
}
static const struct dvb_tuner_ops stv6110x_ops = { static const struct dvb_tuner_ops stv6110x_ops = {
.info = { .info = {
.name = "STV6110(A) Silicon Tuner", .name = "STV6110(A) Silicon Tuner",
@ -342,7 +377,7 @@ static const struct dvb_tuner_ops stv6110x_ops = {
.release = stv6110x_release .release = stv6110x_release
}; };
static const struct stv6110x_devctl stv6110x_ctl = { static struct stv6110x_devctl stv6110x_ctl = {
.tuner_init = stv6110x_init, .tuner_init = stv6110x_init,
.tuner_sleep = stv6110x_sleep, .tuner_sleep = stv6110x_sleep,
.tuner_set_mode = stv6110x_set_mode, .tuner_set_mode = stv6110x_set_mode,
@ -356,48 +391,104 @@ static const struct stv6110x_devctl stv6110x_ctl = {
.tuner_get_status = stv6110x_get_status, .tuner_get_status = stv6110x_get_status,
}; };
static void stv6110x_set_frontend_opts(struct stv6110x_state *stv6110x)
{
stv6110x->frontend->tuner_priv = stv6110x;
stv6110x->frontend->ops.tuner_ops = stv6110x_ops;
}
static struct stv6110x_devctl *stv6110x_get_devctl(struct i2c_client *client)
{
struct stv6110x_state *stv6110x = i2c_get_clientdata(client);
dev_dbg(&client->dev, "\n");
return stv6110x->devctl;
}
static int stv6110x_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct stv6110x_config *config = client->dev.platform_data;
struct stv6110x_state *stv6110x;
stv6110x = kzalloc(sizeof(*stv6110x), GFP_KERNEL);
if (!stv6110x)
return -ENOMEM;
stv6110x->frontend = config->frontend;
stv6110x->i2c = client->adapter;
stv6110x->config = config;
stv6110x->devctl = &stv6110x_ctl;
st6110x_init_regs(stv6110x);
stv6110x_setup_divider(stv6110x);
stv6110x_set_frontend_opts(stv6110x);
dev_info(&stv6110x->i2c->dev, "Probed STV6110x\n");
i2c_set_clientdata(client, stv6110x);
/* setup callbacks */
config->get_devctl = stv6110x_get_devctl;
return 0;
}
static int stv6110x_remove(struct i2c_client *client)
{
struct stv6110x_state *stv6110x = i2c_get_clientdata(client);
stv6110x_release(stv6110x->frontend);
return 0;
}
const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe, const struct stv6110x_devctl *stv6110x_attach(struct dvb_frontend *fe,
const struct stv6110x_config *config, const struct stv6110x_config *config,
struct i2c_adapter *i2c) struct i2c_adapter *i2c)
{ {
struct stv6110x_state *stv6110x; struct stv6110x_state *stv6110x;
u8 default_regs[] = {0x07, 0x11, 0xdc, 0x85, 0x17, 0x01, 0xe6, 0x1e};
stv6110x = kzalloc(sizeof (struct stv6110x_state), GFP_KERNEL); stv6110x = kzalloc(sizeof(*stv6110x), GFP_KERNEL);
if (!stv6110x) if (!stv6110x)
return NULL; return NULL;
stv6110x->frontend = fe;
stv6110x->i2c = i2c; stv6110x->i2c = i2c;
stv6110x->config = config; stv6110x->config = config;
stv6110x->devctl = &stv6110x_ctl; stv6110x->devctl = &stv6110x_ctl;
memcpy(stv6110x->regs, default_regs, 8);
/* setup divider */ st6110x_init_regs(stv6110x);
switch (stv6110x->config->clk_div) { stv6110x_setup_divider(stv6110x);
default: stv6110x_set_frontend_opts(stv6110x);
case 1:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 0);
break;
case 2:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 1);
break;
case 4:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 2);
break;
case 8:
case 0:
STV6110x_SETFIELD(stv6110x->regs[STV6110x_CTRL2], CTRL2_CO_DIV, 3);
break;
}
fe->tuner_priv = stv6110x; fe->tuner_priv = stv6110x;
fe->ops.tuner_ops = stv6110x_ops; fe->ops.tuner_ops = stv6110x_ops;
printk(KERN_INFO "%s: Attaching STV6110x\n", __func__); dev_info(&stv6110x->i2c->dev, "Attaching STV6110x\n");
return stv6110x->devctl; return stv6110x->devctl;
} }
EXPORT_SYMBOL(stv6110x_attach); EXPORT_SYMBOL(stv6110x_attach);
static const struct i2c_device_id stv6110x_id_table[] = {
{"stv6110x", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, stv6110x_id_table);
static struct i2c_driver stv6110x_driver = {
.driver = {
.name = "stv6110x",
.suppress_bind_attrs = true,
},
.probe = stv6110x_probe,
.remove = stv6110x_remove,
.id_table = stv6110x_id_table,
};
module_i2c_driver(stv6110x_driver);
MODULE_AUTHOR("Manu Abraham"); MODULE_AUTHOR("Manu Abraham");
MODULE_DESCRIPTION("STV6110x Silicon tuner"); MODULE_DESCRIPTION("STV6110x Silicon tuner");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");

View File

@ -15,6 +15,9 @@ struct stv6110x_config {
u8 addr; u8 addr;
u32 refclk; u32 refclk;
u8 clk_div; /* divisor value for the output clock */ u8 clk_div; /* divisor value for the output clock */
struct dvb_frontend *frontend;
struct stv6110x_devctl* (*get_devctl)(struct i2c_client *i2c);
}; };
enum tuner_mode { enum tuner_mode {

View File

@ -54,11 +54,12 @@
#define REFCLOCK_MHz (stv6110x->config->refclk / 1000000) #define REFCLOCK_MHz (stv6110x->config->refclk / 1000000)
struct stv6110x_state { struct stv6110x_state {
struct dvb_frontend *frontend;
struct i2c_adapter *i2c; struct i2c_adapter *i2c;
const struct stv6110x_config *config; const struct stv6110x_config *config;
u8 regs[8]; u8 regs[8];
const struct stv6110x_devctl *devctl; struct stv6110x_devctl *devctl;
}; };
#endif /* __STV6110x_PRIV_H */ #endif /* __STV6110x_PRIV_H */

View File

@ -6,7 +6,7 @@
if VIDEO_V4L2 if VIDEO_V4L2
config VIDEO_IR_I2C config VIDEO_IR_I2C
tristate "I2C module for IR" if !MEDIA_SUBDRV_AUTOSELECT tristate "I2C module for IR" if !MEDIA_SUBDRV_AUTOSELECT || EXPERT
depends on I2C && RC_CORE depends on I2C && RC_CORE
default y default y
help help
@ -23,7 +23,7 @@ config VIDEO_IR_I2C
# #
menu "I2C Encoders, decoders, sensors and other helper chips" menu "I2C Encoders, decoders, sensors and other helper chips"
visible if !MEDIA_SUBDRV_AUTOSELECT || COMPILE_TEST visible if !MEDIA_SUBDRV_AUTOSELECT || COMPILE_TEST || EXPERT
comment "Audio decoders, processors and mixers" comment "Audio decoders, processors and mixers"
@ -511,6 +511,7 @@ config VIDEO_ADV7393
config VIDEO_ADV7511 config VIDEO_ADV7511
tristate "Analog Devices ADV7511 encoder" tristate "Analog Devices ADV7511 encoder"
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
depends on DRM_I2C_ADV7511=n || COMPILE_TEST
select HDMI select HDMI
help help
Support for the Analog Devices ADV7511 video encoder. Support for the Analog Devices ADV7511 video encoder.

View File

@ -35,7 +35,7 @@ obj-$(CONFIG_VIDEO_ADV748X) += adv748x/
obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o
obj-$(CONFIG_VIDEO_ADV7842) += adv7842.o obj-$(CONFIG_VIDEO_ADV7842) += adv7842.o
obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o
obj-$(CONFIG_VIDEO_ADV7511) += adv7511.o obj-$(CONFIG_VIDEO_ADV7511) += adv7511-v4l2.o
obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
obj-$(CONFIG_VIDEO_VS6624) += vs6624.o obj-$(CONFIG_VIDEO_VS6624) += vs6624.o
obj-$(CONFIG_VIDEO_BT819) += bt819.o obj-$(CONFIG_VIDEO_BT819) += bt819.o

View File

@ -5,6 +5,11 @@
* Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved. * Copyright 2013 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/ */
/*
* This file is named adv7511-v4l2.c so it doesn't conflict with the Analog
* Device ADV7511 (config fragment CONFIG_DRM_I2C_ADV7511).
*/
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/module.h> #include <linux/module.h>

View File

@ -229,7 +229,7 @@ static const struct v4l2_subdev_ops ak881x_subdev_ops = {
static int ak881x_probe(struct i2c_client *client, static int ak881x_probe(struct i2c_client *client,
const struct i2c_device_id *did) const struct i2c_device_id *did)
{ {
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = client->adapter;
struct ak881x *ak881x; struct ak881x *ak881x;
u8 ifmode, data; u8 ifmode, data;

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,6 @@
#ifndef _CX25840_CORE_H_ #ifndef _CX25840_CORE_H_
#define _CX25840_CORE_H_ #define _CX25840_CORE_H_
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
@ -44,10 +43,15 @@ enum cx25840_media_pads {
* @mute: audio mute V4L2 control (non-cx2583x devices only) * @mute: audio mute V4L2 control (non-cx2583x devices only)
* @pvr150_workaround: whether we enable workaround for Hauppauge PVR150 * @pvr150_workaround: whether we enable workaround for Hauppauge PVR150
* hardware bug (audio dropping out) * hardware bug (audio dropping out)
* @generic_mode: whether we disable ivtv-specific hacks
* this mode gets turned on when the bridge driver calls
* cx25840 subdevice init core op
* @radio: set if we are currently in the radio mode, otherwise * @radio: set if we are currently in the radio mode, otherwise
* the current mode is non-radio (that is, video) * the current mode is non-radio (that is, video)
* @std: currently set video standard * @std: currently set video standard
* @vid_input: currently set video input * @vid_input: currently set video input
* @vid_config: currently set video output configuration
* only used in the generic mode
* @aud_input: currently set audio input * @aud_input: currently set audio input
* @audclk_freq: currently set audio sample rate * @audclk_freq: currently set audio sample rate
* @audmode: currently set audio mode (when in non-radio mode) * @audmode: currently set audio mode (when in non-radio mode)
@ -74,9 +78,11 @@ struct cx25840_state {
struct v4l2_ctrl *mute; struct v4l2_ctrl *mute;
}; };
int pvr150_workaround; int pvr150_workaround;
bool generic_mode;
int radio; int radio;
v4l2_std_id std; v4l2_std_id std;
enum cx25840_video_input vid_input; enum cx25840_video_input vid_input;
u32 vid_config;
enum cx25840_audio_input aud_input; enum cx25840_audio_input aud_input;
u32 audclk_freq; u32 audclk_freq;
int audmode; int audmode;
@ -84,7 +90,7 @@ struct cx25840_state {
enum cx25840_model id; enum cx25840_model id;
u32 rev; u32 rev;
int is_initialized; int is_initialized;
unsigned vbi_regs_offset; unsigned int vbi_regs_offset;
wait_queue_head_t fw_wait; wait_queue_head_t fw_wait;
struct work_struct fw_work; struct work_struct fw_work;
struct cx25840_ir_state *ir_state; struct cx25840_ir_state *ir_state;
@ -109,6 +115,14 @@ static inline bool is_cx2583x(struct cx25840_state *state)
state->id == CX25837; state->id == CX25837;
} }
static inline bool is_cx2584x(struct cx25840_state *state)
{
return state->id == CX25840 ||
state->id == CX25841 ||
state->id == CX25842 ||
state->id == CX25843;
}
static inline bool is_cx231xx(struct cx25840_state *state) static inline bool is_cx231xx(struct cx25840_state *state)
{ {
return state->id == CX2310X_AV; return state->id == CX2310X_AV;
@ -142,7 +156,8 @@ int cx25840_write(struct i2c_client *client, u16 addr, u8 value);
int cx25840_write4(struct i2c_client *client, u16 addr, u32 value); int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
u8 cx25840_read(struct i2c_client *client, u16 addr); u8 cx25840_read(struct i2c_client *client, u16 addr);
u32 cx25840_read4(struct i2c_client *client, u16 addr); u32 cx25840_read4(struct i2c_client *client, u16 addr);
int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value); int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned int mask,
u8 value);
int cx25840_and_or4(struct i2c_client *client, u16 addr, u32 and_mask, int cx25840_and_or4(struct i2c_client *client, u16 addr, u32 and_mask,
u32 or_value); u32 or_value);
void cx25840_std_setup(struct i2c_client *client); void cx25840_std_setup(struct i2c_client *client);
@ -161,9 +176,12 @@ extern const struct v4l2_ctrl_ops cx25840_audio_ctrl_ops;
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* cx25850-vbi.c */ /* cx25850-vbi.c */
int cx25840_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt); int cx25840_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt);
int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); int cx25840_s_sliced_fmt(struct v4l2_subdev *sd,
int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *fmt); struct v4l2_sliced_vbi_format *fmt);
int cx25840_decode_vbi_line(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi); int cx25840_g_sliced_fmt(struct v4l2_subdev *sd,
struct v4l2_sliced_vbi_format *fmt);
int cx25840_decode_vbi_line(struct v4l2_subdev *sd,
struct v4l2_decode_vbi_line *vbi);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* cx25850-ir.c */ /* cx25850-ir.c */

View File

@ -86,6 +86,7 @@ int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *
memset(svbi->service_lines, 0, sizeof(svbi->service_lines)); memset(svbi->service_lines, 0, sizeof(svbi->service_lines));
svbi->service_set = 0; svbi->service_set = 0;
/* we're done if raw VBI is active */ /* we're done if raw VBI is active */
/* TODO: this will have to be changed for generic_mode VBI */
if ((cx25840_read(client, 0x404) & 0x10) == 0) if ((cx25840_read(client, 0x404) & 0x10) == 0)
return 0; return 0;
@ -128,6 +129,7 @@ int cx25840_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
cx25840_write(client, 0x54f, vbi_offset); cx25840_write(client, 0x54f, vbi_offset);
else else
cx25840_write(client, 0x47f, vbi_offset); cx25840_write(client, 0x47f, vbi_offset);
/* TODO: this will have to be changed for generic_mode VBI */
cx25840_write(client, 0x404, 0x2e); cx25840_write(client, 0x404, 0x2e);
return 0; return 0;
} }
@ -148,6 +150,7 @@ int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *
cx25840_std_setup(client); cx25840_std_setup(client);
/* Sliced VBI */ /* Sliced VBI */
/* TODO: this will have to be changed for generic_mode VBI */
cx25840_write(client, 0x404, 0x32); /* Ancillary data */ cx25840_write(client, 0x404, 0x32); /* Ancillary data */
cx25840_write(client, 0x406, 0x13); cx25840_write(client, 0x406, 0x13);
if (is_cx23888(state)) if (is_cx23888(state))
@ -202,6 +205,7 @@ int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *
} }
cx25840_write(client, state->vbi_regs_offset + 0x43c, 0x16); cx25840_write(client, state->vbi_regs_offset + 0x43c, 0x16);
/* TODO: this will have to be changed for generic_mode VBI */
if (is_cx23888(state)) if (is_cx23888(state))
cx25840_write(client, 0x428, is_pal ? 0x2a : 0x22); cx25840_write(client, 0x428, is_pal ? 0x2a : 0x22);
else else

View File

@ -1111,6 +1111,6 @@ static struct i2c_driver imx214_i2c_driver = {
module_i2c_driver(imx214_i2c_driver); module_i2c_driver(imx214_i2c_driver);
MODULE_DESCRIPTION("Sony IMX214 Camera drier"); MODULE_DESCRIPTION("Sony IMX214 Camera driver");
MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>"); MODULE_AUTHOR("Ricardo Ribalda <ricardo.ribalda@gmail.com>");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");

View File

@ -730,7 +730,7 @@ static int mt9m001_probe(struct i2c_client *client,
const struct i2c_device_id *did) const struct i2c_device_id *did)
{ {
struct mt9m001 *mt9m001; struct mt9m001 *mt9m001;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = client->adapter;
int ret; int ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {

View File

@ -10,6 +10,7 @@
#include <linux/log2.h> #include <linux/log2.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/regulator/consumer.h>
#include <linux/v4l2-mediabus.h> #include <linux/v4l2-mediabus.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/property.h> #include <linux/property.h>
@ -240,6 +241,7 @@ struct mt9m111 {
int power_count; int power_count;
const struct mt9m111_datafmt *fmt; const struct mt9m111_datafmt *fmt;
int lastpage; /* PageMap cache value */ int lastpage; /* PageMap cache value */
struct regulator *regulator;
bool is_streaming; bool is_streaming;
/* user point of view - 0: falling 1: rising edge */ /* user point of view - 0: falling 1: rising edge */
unsigned int pclk_sample:1; unsigned int pclk_sample:1;
@ -979,11 +981,23 @@ static int mt9m111_power_on(struct mt9m111 *mt9m111)
if (ret < 0) if (ret < 0)
return ret; return ret;
ret = regulator_enable(mt9m111->regulator);
if (ret < 0)
goto out_clk_disable;
ret = mt9m111_resume(mt9m111); ret = mt9m111_resume(mt9m111);
if (ret < 0) { if (ret < 0)
dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret); goto out_regulator_disable;
v4l2_clk_disable(mt9m111->clk);
} return 0;
out_regulator_disable:
regulator_disable(mt9m111->regulator);
out_clk_disable:
v4l2_clk_disable(mt9m111->clk);
dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret);
return ret; return ret;
} }
@ -991,6 +1005,7 @@ static int mt9m111_power_on(struct mt9m111 *mt9m111)
static void mt9m111_power_off(struct mt9m111 *mt9m111) static void mt9m111_power_off(struct mt9m111 *mt9m111)
{ {
mt9m111_suspend(mt9m111); mt9m111_suspend(mt9m111);
regulator_disable(mt9m111->regulator);
v4l2_clk_disable(mt9m111->clk); v4l2_clk_disable(mt9m111->clk);
} }
@ -1232,7 +1247,7 @@ static int mt9m111_probe(struct i2c_client *client,
const struct i2c_device_id *did) const struct i2c_device_id *did)
{ {
struct mt9m111 *mt9m111; struct mt9m111 *mt9m111;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = client->adapter;
int ret; int ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
@ -1245,14 +1260,23 @@ static int mt9m111_probe(struct i2c_client *client,
if (!mt9m111) if (!mt9m111)
return -ENOMEM; return -ENOMEM;
ret = mt9m111_probe_fw(client, mt9m111); if (dev_fwnode(&client->dev)) {
if (ret) ret = mt9m111_probe_fw(client, mt9m111);
return ret; if (ret)
return ret;
}
mt9m111->clk = v4l2_clk_get(&client->dev, "mclk"); mt9m111->clk = v4l2_clk_get(&client->dev, "mclk");
if (IS_ERR(mt9m111->clk)) if (IS_ERR(mt9m111->clk))
return PTR_ERR(mt9m111->clk); return PTR_ERR(mt9m111->clk);
mt9m111->regulator = devm_regulator_get(&client->dev, "vdd");
if (IS_ERR(mt9m111->regulator)) {
dev_err(&client->dev, "regulator not found: %ld\n",
PTR_ERR(mt9m111->regulator));
return PTR_ERR(mt9m111->regulator);
}
/* Default HIGHPOWER context */ /* Default HIGHPOWER context */
mt9m111->ctx = &context_b; mt9m111->ctx = &context_b;

View File

@ -1031,7 +1031,7 @@ static int mt9p031_probe(struct i2c_client *client,
const struct i2c_device_id *did) const struct i2c_device_id *did)
{ {
struct mt9p031_platform_data *pdata = mt9p031_get_pdata(client); struct mt9p031_platform_data *pdata = mt9p031_get_pdata(client);
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = client->adapter;
struct mt9p031 *mt9p031; struct mt9p031 *mt9p031;
unsigned int i; unsigned int i;
int ret; int ret;

View File

@ -1224,7 +1224,7 @@ static int ov13858_set_ctrl(struct v4l2_ctrl *ctrl)
ov13858->exposure->minimum, ov13858->exposure->minimum,
max, ov13858->exposure->step, max); max, ov13858->exposure->step, max);
break; break;
}; }
/* /*
* Applying V4L2 control value only happens * Applying V4L2 control value only happens
@ -1262,7 +1262,7 @@ static int ov13858_set_ctrl(struct v4l2_ctrl *ctrl)
"ctrl(id:0x%x,val:0x%x) is not handled\n", "ctrl(id:0x%x,val:0x%x) is not handled\n",
ctrl->id, ctrl->val); ctrl->id, ctrl->val);
break; break;
}; }
pm_runtime_put(&client->dev); pm_runtime_put(&client->dev);

View File

@ -1194,7 +1194,7 @@ static int ov2640_probe(struct i2c_client *client,
const struct i2c_device_id *did) const struct i2c_device_id *did)
{ {
struct ov2640_priv *priv; struct ov2640_priv *priv;
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent); struct i2c_adapter *adapter = client->adapter;
int ret; int ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {

View File

@ -576,7 +576,7 @@ static int ov2685_set_ctrl(struct v4l2_ctrl *ctrl)
__func__, ctrl->id, ctrl->val); __func__, ctrl->id, ctrl->val);
ret = -EINVAL; ret = -EINVAL;
break; break;
}; }
pm_runtime_put(&client->dev); pm_runtime_put(&client->dev);

View File

@ -1143,7 +1143,7 @@ static int ov5695_set_ctrl(struct v4l2_ctrl *ctrl)
dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n", dev_warn(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
__func__, ctrl->id, ctrl->val); __func__, ctrl->id, ctrl->val);
break; break;
}; }
pm_runtime_put(&client->dev); pm_runtime_put(&client->dev);

View File

@ -1006,7 +1006,6 @@ static int ov6650_probe(struct i2c_client *client,
priv->colorspace = V4L2_COLORSPACE_JPEG; priv->colorspace = V4L2_COLORSPACE_JPEG;
priv->subdev.internal_ops = &ov6650_internal_ops; priv->subdev.internal_ops = &ov6650_internal_ops;
priv->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ret = v4l2_async_register_subdev(&priv->subdev); ret = v4l2_async_register_subdev(&priv->subdev);
if (ret) if (ret)

View File

@ -532,7 +532,7 @@ static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl)
struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev); struct i2c_client *client = v4l2_get_subdevdata(&ov7740->subdev);
struct regmap *regmap = ov7740->regmap; struct regmap *regmap = ov7740->regmap;
int ret; int ret;
u8 val = 0; u8 val;
if (!pm_runtime_get_if_in_use(&client->dev)) if (!pm_runtime_get_if_in_use(&client->dev))
return 0; return 0;
@ -551,6 +551,7 @@ static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl)
ret = ov7740_set_contrast(regmap, ctrl->val); ret = ov7740_set_contrast(regmap, ctrl->val);
break; break;
case V4L2_CID_VFLIP: case V4L2_CID_VFLIP:
val = ctrl->val ? REG0C_IMG_FLIP : 0x00;
ret = regmap_update_bits(regmap, REG_REG0C, ret = regmap_update_bits(regmap, REG_REG0C,
REG0C_IMG_FLIP, val); REG0C_IMG_FLIP, val);
break; break;
@ -561,16 +562,16 @@ static int ov7740_set_ctrl(struct v4l2_ctrl *ctrl)
break; break;
case V4L2_CID_AUTOGAIN: case V4L2_CID_AUTOGAIN:
if (!ctrl->val) if (!ctrl->val)
return ov7740_set_gain(regmap, ov7740->gain->val); ret = ov7740_set_gain(regmap, ov7740->gain->val);
else
ret = ov7740_set_autogain(regmap, ctrl->val); ret = ov7740_set_autogain(regmap, ctrl->val);
break; break;
case V4L2_CID_EXPOSURE_AUTO: case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->val == V4L2_EXPOSURE_MANUAL) if (ctrl->val == V4L2_EXPOSURE_MANUAL)
return ov7740_set_exp(regmap, ov7740->exposure->val); ret = ov7740_set_exp(regmap, ov7740->exposure->val);
else
ret = ov7740_set_autoexp(regmap, ctrl->val); ret = ov7740_set_autoexp(regmap, ctrl->val);
break; break;
default: default:
ret = -EINVAL; ret = -EINVAL;
@ -785,7 +786,11 @@ static int ov7740_try_fmt_internal(struct v4l2_subdev *sd,
fsize++; fsize++;
} }
if (i >= ARRAY_SIZE(ov7740_framesizes)) {
fsize = &ov7740_framesizes[0];
fmt->width = fsize->width;
fmt->height = fsize->height;
}
if (ret_frmsize != NULL) if (ret_frmsize != NULL)
*ret_frmsize = fsize; *ret_frmsize = fsize;
@ -1007,8 +1012,6 @@ static int ov7740_init_controls(struct ov7740 *ov7740)
ov7740->gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops, ov7740->gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
V4L2_CID_GAIN, 0, 1023, 1, 500); V4L2_CID_GAIN, 0, 1023, 1, 500);
if (ov7740->gain)
ov7740->gain->flags |= V4L2_CTRL_FLAG_VOLATILE;
ov7740->auto_gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops, ov7740->auto_gain = v4l2_ctrl_new_std(ctrl_hdlr, &ov7740_ctrl_ops,
V4L2_CID_AUTOGAIN, 0, 1, 1, 1); V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
@ -1026,7 +1029,6 @@ static int ov7740_init_controls(struct ov7740 *ov7740)
v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true); v4l2_ctrl_auto_cluster(2, &ov7740->auto_gain, 0, true);
v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure, v4l2_ctrl_auto_cluster(2, &ov7740->auto_exposure,
V4L2_EXPOSURE_MANUAL, true); V4L2_EXPOSURE_MANUAL, true);
v4l2_ctrl_cluster(2, &ov7740->hflip);
if (ctrl_hdlr->error) { if (ctrl_hdlr->error) {
ret = ctrl_hdlr->error; ret = ctrl_hdlr->error;

View File

@ -195,11 +195,11 @@ static const struct ov8856_reg mode_3280x2464_regs[] = {
{0x3800, 0x00}, {0x3800, 0x00},
{0x3801, 0x00}, {0x3801, 0x00},
{0x3802, 0x00}, {0x3802, 0x00},
{0x3803, 0x07}, {0x3803, 0x06},
{0x3804, 0x0c}, {0x3804, 0x0c},
{0x3805, 0xdf}, {0x3805, 0xdf},
{0x3806, 0x09}, {0x3806, 0x09},
{0x3807, 0xa6}, {0x3807, 0xa7},
{0x3808, 0x0c}, {0x3808, 0x0c},
{0x3809, 0xd0}, {0x3809, 0xd0},
{0x380a, 0x09}, {0x380a, 0x09},
@ -211,7 +211,7 @@ static const struct ov8856_reg mode_3280x2464_regs[] = {
{0x3810, 0x00}, {0x3810, 0x00},
{0x3811, 0x00}, {0x3811, 0x00},
{0x3812, 0x00}, {0x3812, 0x00},
{0x3813, 0x00}, {0x3813, 0x01},
{0x3814, 0x01}, {0x3814, 0x01},
{0x3815, 0x01}, {0x3815, 0x01},
{0x3816, 0x00}, {0x3816, 0x00},
@ -385,11 +385,11 @@ static const struct ov8856_reg mode_1640x1232_regs[] = {
{0x3800, 0x00}, {0x3800, 0x00},
{0x3801, 0x00}, {0x3801, 0x00},
{0x3802, 0x00}, {0x3802, 0x00},
{0x3803, 0x07}, {0x3803, 0x06},
{0x3804, 0x0c}, {0x3804, 0x0c},
{0x3805, 0xdf}, {0x3805, 0xdf},
{0x3806, 0x09}, {0x3806, 0x09},
{0x3807, 0xa6}, {0x3807, 0xa7},
{0x3808, 0x06}, {0x3808, 0x06},
{0x3809, 0x68}, {0x3809, 0x68},
{0x380a, 0x04}, {0x380a, 0x04},
@ -401,7 +401,7 @@ static const struct ov8856_reg mode_1640x1232_regs[] = {
{0x3810, 0x00}, {0x3810, 0x00},
{0x3811, 0x00}, {0x3811, 0x00},
{0x3812, 0x00}, {0x3812, 0x00},
{0x3813, 0x00}, {0x3813, 0x01},
{0x3814, 0x03}, {0x3814, 0x03},
{0x3815, 0x01}, {0x3815, 0x01},
{0x3816, 0x00}, {0x3816, 0x00},

View File

@ -691,14 +691,14 @@ static int ov9640_probe(struct i2c_client *client,
priv->gpio_power = devm_gpiod_get(&client->dev, "Camera power", priv->gpio_power = devm_gpiod_get(&client->dev, "Camera power",
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (IS_ERR_OR_NULL(priv->gpio_power)) { if (IS_ERR(priv->gpio_power)) {
ret = PTR_ERR(priv->gpio_power); ret = PTR_ERR(priv->gpio_power);
return ret; return ret;
} }
priv->gpio_reset = devm_gpiod_get(&client->dev, "Camera reset", priv->gpio_reset = devm_gpiod_get(&client->dev, "Camera reset",
GPIOD_OUT_HIGH); GPIOD_OUT_HIGH);
if (IS_ERR_OR_NULL(priv->gpio_reset)) { if (IS_ERR(priv->gpio_reset)) {
ret = PTR_ERR(priv->gpio_reset); ret = PTR_ERR(priv->gpio_reset);
return ret; return ret;
} }

View File

@ -194,7 +194,7 @@ static int jt8ev1_post_streamoff(struct smiapp_sensor *sensor)
return rval; return rval;
/* Wait for 1 ms + one line => 2 ms is likely enough */ /* Wait for 1 ms + one line => 2 ms is likely enough */
usleep_range(2000, 2000); usleep_range(2000, 2050);
/* Restore it */ /* Restore it */
rval = smiapp_write_8(sensor, 0x3205, 0x00); rval = smiapp_write_8(sensor, 0x3205, 0x00);

View File

@ -61,7 +61,10 @@ static const u32 mipid02_supported_fmt_codes[] = {
MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10,
MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SGBRG12_1X12,
MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SRGGB12_1X12,
MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_BGR888_1X24 MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_BGR888_1X24,
MEDIA_BUS_FMT_RGB565_2X8_LE, MEDIA_BUS_FMT_RGB565_2X8_BE,
MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_UYVY8_2X8,
MEDIA_BUS_FMT_JPEG_1X8
}; };
/* regulator supplies */ /* regulator supplies */
@ -99,6 +102,7 @@ struct mipid02_dev {
u8 data_lane1_reg1; u8 data_lane1_reg1;
u8 mode_reg1; u8 mode_reg1;
u8 mode_reg2; u8 mode_reg2;
u8 data_selection_ctrl;
u8 data_id_rreg; u8 data_id_rreg;
u8 pix_width_ctrl; u8 pix_width_ctrl;
u8 pix_width_ctrl_emb; u8 pix_width_ctrl_emb;
@ -128,6 +132,10 @@ static int bpp_from_code(__u32 code)
case MEDIA_BUS_FMT_SRGGB12_1X12: case MEDIA_BUS_FMT_SRGGB12_1X12:
return 12; return 12;
case MEDIA_BUS_FMT_UYVY8_1X16: case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_YUYV8_2X8:
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_RGB565_2X8_LE:
case MEDIA_BUS_FMT_RGB565_2X8_BE:
return 16; return 16;
case MEDIA_BUS_FMT_BGR888_1X24: case MEDIA_BUS_FMT_BGR888_1X24:
return 24; return 24;
@ -155,9 +163,14 @@ static u8 data_type_from_code(__u32 code)
case MEDIA_BUS_FMT_SRGGB12_1X12: case MEDIA_BUS_FMT_SRGGB12_1X12:
return 0x2c; return 0x2c;
case MEDIA_BUS_FMT_UYVY8_1X16: case MEDIA_BUS_FMT_UYVY8_1X16:
case MEDIA_BUS_FMT_YUYV8_2X8:
case MEDIA_BUS_FMT_UYVY8_2X8:
return 0x1e; return 0x1e;
case MEDIA_BUS_FMT_BGR888_1X24: case MEDIA_BUS_FMT_BGR888_1X24:
return 0x24; return 0x24;
case MEDIA_BUS_FMT_RGB565_2X8_LE:
case MEDIA_BUS_FMT_RGB565_2X8_BE:
return 0x22;
default: default:
return 0; return 0;
} }
@ -331,6 +344,25 @@ static int mipid02_detect(struct mipid02_dev *bridge)
return mipid02_read_reg(bridge, MIPID02_CLK_LANE_WR_REG1, &reg); return mipid02_read_reg(bridge, MIPID02_CLK_LANE_WR_REG1, &reg);
} }
static u32 mipid02_get_link_freq_from_cid_link_freq(struct mipid02_dev *bridge,
struct v4l2_subdev *subdev)
{
struct v4l2_querymenu qm = {.id = V4L2_CID_LINK_FREQ, };
struct v4l2_ctrl *ctrl;
int ret;
ctrl = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_LINK_FREQ);
if (!ctrl)
return 0;
qm.index = v4l2_ctrl_g_ctrl(ctrl);
ret = v4l2_querymenu(subdev->ctrl_handler, &qm);
if (ret)
return 0;
return qm.value;
}
static u32 mipid02_get_link_freq_from_cid_pixel_rate(struct mipid02_dev *bridge, static u32 mipid02_get_link_freq_from_cid_pixel_rate(struct mipid02_dev *bridge,
struct v4l2_subdev *subdev) struct v4l2_subdev *subdev)
{ {
@ -358,10 +390,14 @@ static int mipid02_configure_from_rx_speed(struct mipid02_dev *bridge)
struct v4l2_subdev *subdev = bridge->s_subdev; struct v4l2_subdev *subdev = bridge->s_subdev;
u32 link_freq; u32 link_freq;
link_freq = mipid02_get_link_freq_from_cid_pixel_rate(bridge, subdev); link_freq = mipid02_get_link_freq_from_cid_link_freq(bridge, subdev);
if (!link_freq) { if (!link_freq) {
dev_err(&client->dev, "Failed to detect link frequency"); link_freq = mipid02_get_link_freq_from_cid_pixel_rate(bridge,
return -EINVAL; subdev);
if (!link_freq) {
dev_err(&client->dev, "Failed to get link frequency");
return -EINVAL;
}
} }
dev_dbg(&client->dev, "detect link_freq = %d Hz", link_freq); dev_dbg(&client->dev, "detect link_freq = %d Hz", link_freq);
@ -452,6 +488,7 @@ static int mipid02_configure_from_tx(struct mipid02_dev *bridge)
{ {
struct v4l2_fwnode_endpoint *ep = &bridge->tx; struct v4l2_fwnode_endpoint *ep = &bridge->tx;
bridge->r.data_selection_ctrl = SELECTION_MANUAL_WIDTH;
bridge->r.pix_width_ctrl = ep->bus.parallel.bus_width; bridge->r.pix_width_ctrl = ep->bus.parallel.bus_width;
bridge->r.pix_width_ctrl_emb = ep->bus.parallel.bus_width; bridge->r.pix_width_ctrl_emb = ep->bus.parallel.bus_width;
if (ep->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) if (ep->bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH)
@ -467,10 +504,15 @@ static int mipid02_configure_from_code(struct mipid02_dev *bridge)
u8 data_type; u8 data_type;
bridge->r.data_id_rreg = 0; bridge->r.data_id_rreg = 0;
data_type = data_type_from_code(bridge->fmt.code);
if (!data_type) if (bridge->fmt.code != MEDIA_BUS_FMT_JPEG_1X8) {
return -EINVAL; bridge->r.data_selection_ctrl |= SELECTION_MANUAL_DATA;
bridge->r.data_id_rreg = data_type;
data_type = data_type_from_code(bridge->fmt.code);
if (!data_type)
return -EINVAL;
bridge->r.data_id_rreg = data_type;
}
return 0; return 0;
} }
@ -554,7 +596,7 @@ static int mipid02_stream_enable(struct mipid02_dev *bridge)
if (ret) if (ret)
goto error; goto error;
ret = mipid02_write_reg(bridge, MIPID02_DATA_SELECTION_CTRL, ret = mipid02_write_reg(bridge, MIPID02_DATA_SELECTION_CTRL,
SELECTION_MANUAL_DATA | SELECTION_MANUAL_WIDTH); bridge->r.data_selection_ctrl);
if (ret) if (ret)
goto error; goto error;
ret = mipid02_write_reg(bridge, MIPID02_PIX_WIDTH_CTRL, ret = mipid02_write_reg(bridge, MIPID02_PIX_WIDTH_CTRL,

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0
/* /*
* For the STS-Thompson TDA7432 audio processor chip * For the STS-Thompson TDA7432 audio processor chip
* *
@ -9,7 +10,7 @@
* *
* Copyright (c) 2000 Eric Sandeen <eric_sandeen@bigfoot.com> * Copyright (c) 2000 Eric Sandeen <eric_sandeen@bigfoot.com>
* Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@kernel.org> * Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@kernel.org>
* This code is placed under the terms of the GNU General Public License *
* Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu)
* Which was based on tda8425.c by Greg Alexander (c) 1998 * Which was based on tda8425.c by Greg Alexander (c) 1998
* *

View File

@ -934,8 +934,7 @@ static int tw9910_probe(struct i2c_client *client,
{ {
struct tw9910_priv *priv; struct tw9910_priv *priv;
struct tw9910_video_info *info; struct tw9910_video_info *info;
struct i2c_adapter *adapter = struct i2c_adapter *adapter = client->adapter;
to_i2c_adapter(client->dev.parent);
int ret; int ret;
if (!client->dev.platform_data) { if (!client->dev.platform_data) {

View File

@ -190,12 +190,8 @@ static int mlx90640_setup(struct video_i2c_data *data)
unsigned int n, idx; unsigned int n, idx;
for (n = 0; n < data->chip->num_frame_intervals - 1; n++) { for (n = 0; n < data->chip->num_frame_intervals - 1; n++) {
if (data->frame_interval.numerator if (V4L2_FRACT_COMPARE(data->frame_interval, ==,
!= data->chip->frame_intervals[n].numerator) data->chip->frame_intervals[n]))
continue;
if (data->frame_interval.denominator
== data->chip->frame_intervals[n].denominator)
break; break;
} }

33
drivers/media/mc/Kconfig Normal file
View File

@ -0,0 +1,33 @@
#
# Media controller
# Selectable only for webcam/grabbers, as other drivers don't use it
#
config MEDIA_CONTROLLER
bool "Media Controller API"
depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
help
Enable the media controller API used to query media devices internal
topology and configure it dynamically.
This API is mostly used by camera interfaces in embedded platforms.
config MEDIA_CONTROLLER_DVB
bool "Enable Media controller for DVB (EXPERIMENTAL)"
depends on MEDIA_CONTROLLER && DVB_CORE
help
Enable the media controller API support for DVB.
This is currently experimental.
config MEDIA_CONTROLLER_REQUEST_API
bool "Enable Media controller Request API (EXPERIMENTAL)"
depends on MEDIA_CONTROLLER && STAGING_MEDIA
help
DO NOT ENABLE THIS OPTION UNLESS YOU KNOW WHAT YOU'RE DOING.
This option enables the Request API for the Media controller and V4L2
interfaces. It is currently needed by a few stateless codec drivers.
There is currently no intention to provide API or ABI stability for
this new API as of yet.

10
drivers/media/mc/Makefile Normal file
View File

@ -0,0 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
mc-objs := mc-device.o mc-devnode.o mc-entity.o \
mc-request.o
ifeq ($(CONFIG_USB),y)
mc-objs += mc-dev-allocator.o
endif
obj-$(CONFIG_MEDIA_SUPPORT) += mc.o

View File

@ -494,6 +494,7 @@ static long media_device_enum_links32(struct media_device *mdev,
{ {
struct media_links_enum links; struct media_links_enum links;
compat_uptr_t pads_ptr, links_ptr; compat_uptr_t pads_ptr, links_ptr;
int ret;
memset(&links, 0, sizeof(links)); memset(&links, 0, sizeof(links));
@ -505,7 +506,14 @@ static long media_device_enum_links32(struct media_device *mdev,
links.pads = compat_ptr(pads_ptr); links.pads = compat_ptr(pads_ptr);
links.links = compat_ptr(links_ptr); links.links = compat_ptr(links_ptr);
return media_device_enum_links(mdev, &links); ret = media_device_enum_links(mdev, &links);
if (ret)
return ret;
if (copy_to_user(ulinks->reserved, links.reserved,
sizeof(ulinks->reserved)))
return -EFAULT;
return 0;
} }
#define MEDIA_IOC_ENUM_LINKS32 _IOWR('|', 0x02, struct media_links_enum32) #define MEDIA_IOC_ENUM_LINKS32 _IOWR('|', 0x02, struct media_links_enum32)

View File

@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
/* /*
* Handlers for board audio hooks, split from bttv-cards * Handlers for board audio hooks, split from bttv-cards
* *
* Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@kernel.org> * Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@kernel.org>
* This code is placed under the terms of the GNU General Public License
*/ */
#include "bttv-audio-hook.h" #include "bttv-audio-hook.h"

View File

@ -1,4 +1,6 @@
/* /*
* SPDX-License-Identifier: GPL-2.0
*
* Handlers for board audio hooks, split from bttv-cards * Handlers for board audio hooks, split from bttv-cards
* *
* Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@kernel.org> * Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@kernel.org>

View File

@ -2453,7 +2453,6 @@ static int bttv_s_fmt_vid_overlay(struct file *file, void *priv,
static int bttv_querycap(struct file *file, void *priv, static int bttv_querycap(struct file *file, void *priv,
struct v4l2_capability *cap) struct v4l2_capability *cap)
{ {
struct video_device *vdev = video_devdata(file);
struct bttv_fh *fh = priv; struct bttv_fh *fh = priv;
struct bttv *btv = fh->btv; struct bttv *btv = fh->btv;
@ -2464,17 +2463,17 @@ static int bttv_querycap(struct file *file, void *priv,
strscpy(cap->card, btv->video_dev.name, sizeof(cap->card)); strscpy(cap->card, btv->video_dev.name, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info), snprintf(cap->bus_info, sizeof(cap->bus_info),
"PCI:%s", pci_name(btv->c.pci)); "PCI:%s", pci_name(btv->c.pci));
cap->capabilities = cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_DEVICE_CAPS;
if (no_overlay <= 0) if (no_overlay <= 0)
cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY; cap->capabilities |= V4L2_CAP_VIDEO_OVERLAY;
if (video_is_registered(&btv->vbi_dev)) if (video_is_registered(&btv->vbi_dev))
cap->capabilities |= V4L2_CAP_VBI_CAPTURE; cap->capabilities |= V4L2_CAP_VBI_CAPTURE;
if (video_is_registered(&btv->radio_dev)) if (video_is_registered(&btv->radio_dev)) {
cap->capabilities |= V4L2_CAP_RADIO; cap->capabilities |= V4L2_CAP_RADIO;
if (btv->has_tea575x)
cap->capabilities |= V4L2_CAP_HW_FREQ_SEEK;
}
/* /*
* No need to lock here: those vars are initialized during board * No need to lock here: those vars are initialized during board
@ -2484,27 +2483,6 @@ static int bttv_querycap(struct file *file, void *priv,
cap->capabilities |= V4L2_CAP_RDS_CAPTURE; cap->capabilities |= V4L2_CAP_RDS_CAPTURE;
if (btv->tuner_type != TUNER_ABSENT) if (btv->tuner_type != TUNER_ABSENT)
cap->capabilities |= V4L2_CAP_TUNER; cap->capabilities |= V4L2_CAP_TUNER;
if (vdev->vfl_type == VFL_TYPE_GRABBER)
cap->device_caps = cap->capabilities &
(V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_VIDEO_OVERLAY |
V4L2_CAP_TUNER);
else if (vdev->vfl_type == VFL_TYPE_VBI)
cap->device_caps = cap->capabilities &
(V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
V4L2_CAP_TUNER);
else {
cap->device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
if (btv->has_saa6588)
cap->device_caps |= V4L2_CAP_READWRITE |
V4L2_CAP_RDS_CAPTURE;
if (btv->has_tea575x)
cap->device_caps |= V4L2_CAP_HW_FREQ_SEEK;
}
return 0; return 0;
} }
@ -3939,6 +3917,12 @@ static int bttv_register_video(struct bttv *btv)
/* video */ /* video */
vdev_init(btv, &btv->video_dev, &bttv_video_template, "video"); vdev_init(btv, &btv->video_dev, &bttv_video_template, "video");
btv->video_dev.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
if (btv->tuner_type != TUNER_ABSENT)
btv->video_dev.device_caps |= V4L2_CAP_TUNER;
if (no_overlay <= 0)
btv->video_dev.device_caps |= V4L2_CAP_VIDEO_OVERLAY;
if (video_register_device(&btv->video_dev, VFL_TYPE_GRABBER, if (video_register_device(&btv->video_dev, VFL_TYPE_GRABBER,
video_nr[btv->c.nr]) < 0) video_nr[btv->c.nr]) < 0)
@ -3953,6 +3937,10 @@ static int bttv_register_video(struct bttv *btv)
/* vbi */ /* vbi */
vdev_init(btv, &btv->vbi_dev, &bttv_video_template, "vbi"); vdev_init(btv, &btv->vbi_dev, &bttv_video_template, "vbi");
btv->vbi_dev.device_caps = V4L2_CAP_VBI_CAPTURE | V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING | V4L2_CAP_TUNER;
if (btv->tuner_type != TUNER_ABSENT)
btv->vbi_dev.device_caps |= V4L2_CAP_TUNER;
if (video_register_device(&btv->vbi_dev, VFL_TYPE_VBI, if (video_register_device(&btv->vbi_dev, VFL_TYPE_VBI,
vbi_nr[btv->c.nr]) < 0) vbi_nr[btv->c.nr]) < 0)
@ -3964,6 +3952,12 @@ static int bttv_register_video(struct bttv *btv)
return 0; return 0;
/* radio */ /* radio */
vdev_init(btv, &btv->radio_dev, &radio_template, "radio"); vdev_init(btv, &btv->radio_dev, &radio_template, "radio");
btv->radio_dev.device_caps = V4L2_CAP_RADIO | V4L2_CAP_TUNER;
if (btv->has_saa6588)
btv->radio_dev.device_caps |= V4L2_CAP_READWRITE |
V4L2_CAP_RDS_CAPTURE;
if (btv->has_tea575x)
btv->radio_dev.device_caps |= V4L2_CAP_HW_FREQ_SEEK;
btv->radio_dev.ctrl_handler = &btv->radio_ctrl_handler; btv->radio_dev.ctrl_handler = &btv->radio_ctrl_handler;
if (video_register_device(&btv->radio_dev, VFL_TYPE_RADIO, if (video_register_device(&btv->radio_dev, VFL_TYPE_RADIO,
radio_nr[btv->c.nr]) < 0) radio_nr[btv->c.nr]) < 0)

View File

@ -3,7 +3,7 @@ config VIDEO_COBALT
tristate "Cisco Cobalt support" tristate "Cisco Cobalt support"
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
depends on PCI_MSI && MTD_COMPLEX_MAPPINGS depends on PCI_MSI && MTD_COMPLEX_MAPPINGS
depends on GPIOLIB || COMPILE_TEST depends on (GPIOLIB && DRM_I2C_ADV7511=n) || COMPILE_TEST
depends on SND depends on SND
depends on MTD depends on MTD
select I2C_ALGOBIT select I2C_ALGOBIT

View File

@ -483,13 +483,8 @@ static int cobalt_querycap(struct file *file, void *priv_fh,
strscpy(vcap->card, "cobalt", sizeof(vcap->card)); strscpy(vcap->card, "cobalt", sizeof(vcap->card));
snprintf(vcap->bus_info, sizeof(vcap->bus_info), snprintf(vcap->bus_info, sizeof(vcap->bus_info),
"PCIe:%s", pci_name(cobalt->pci_dev)); "PCIe:%s", pci_name(cobalt->pci_dev));
vcap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE; vcap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE |
if (s->is_output) V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_DEVICE_CAPS;
vcap->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
else
vcap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS |
V4L2_CAP_VIDEO_CAPTURE;
if (cobalt->have_hsma_tx) if (cobalt->have_hsma_tx)
vcap->capabilities |= V4L2_CAP_VIDEO_OUTPUT; vcap->capabilities |= V4L2_CAP_VIDEO_OUTPUT;
return 0; return 0;
@ -1274,6 +1269,11 @@ static int cobalt_node_register(struct cobalt *cobalt, int node)
q->lock = &s->lock; q->lock = &s->lock;
q->dev = &cobalt->pci_dev->dev; q->dev = &cobalt->pci_dev->dev;
vdev->queue = q; vdev->queue = q;
vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
if (s->is_output)
vdev->device_caps |= V4L2_CAP_VIDEO_OUTPUT;
else
vdev->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
video_set_drvdata(vdev, s); video_set_drvdata(vdev, s);
ret = vb2_queue_init(q); ret = vb2_queue_init(q);

View File

@ -385,16 +385,13 @@ static int cx18_querycap(struct file *file, void *fh,
struct v4l2_capability *vcap) struct v4l2_capability *vcap)
{ {
struct cx18_open_id *id = fh2id(fh); struct cx18_open_id *id = fh2id(fh);
struct cx18_stream *s = video_drvdata(file);
struct cx18 *cx = id->cx; struct cx18 *cx = id->cx;
strscpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver)); strscpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
strscpy(vcap->card, cx->card_name, sizeof(vcap->card)); strscpy(vcap->card, cx->card_name, sizeof(vcap->card));
snprintf(vcap->bus_info, sizeof(vcap->bus_info), snprintf(vcap->bus_info, sizeof(vcap->bus_info),
"PCI:%s", pci_name(cx->pci_dev)); "PCI:%s", pci_name(cx->pci_dev));
vcap->capabilities = cx->v4l2_cap; /* capabilities */ vcap->capabilities = cx->v4l2_cap | V4L2_CAP_DEVICE_CAPS;
vcap->device_caps = s->v4l2_dev_caps; /* device capabilities */
vcap->capabilities |= V4L2_CAP_DEVICE_CAPS;
return 0; return 0;
} }

View File

@ -411,6 +411,7 @@ static int cx18_reg_dev(struct cx18 *cx, int type)
return 0; return 0;
num = s->video_dev.num; num = s->video_dev.num;
s->video_dev.device_caps = s->v4l2_dev_caps; /* device capabilities */
/* card number + user defined offset + device offset */ /* card number + user defined offset + device offset */
if (type != CX18_ENC_STREAM_TYPE_MPG) { if (type != CX18_ENC_STREAM_TYPE_MPG) {
struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG]; struct cx18_stream *s_mpg = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];

View File

@ -1324,12 +1324,11 @@ static int vidioc_querycap(struct file *file, void *priv,
strscpy(cap->card, cx23885_boards[tsport->dev->board].name, strscpy(cap->card, cx23885_boards[tsport->dev->board].name,
sizeof(cap->card)); sizeof(cap->card));
sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE | cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING; V4L2_CAP_STREAMING | V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_AUDIO | V4L2_CAP_DEVICE_CAPS;
if (dev->tuner_type != TUNER_ABSENT) if (dev->tuner_type != TUNER_ABSENT)
cap->device_caps |= V4L2_CAP_TUNER; cap->capabilities |= V4L2_CAP_TUNER;
cap->capabilities = cap->device_caps | V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_AUDIO | V4L2_CAP_DEVICE_CAPS;
return 0; return 0;
} }
@ -1542,6 +1541,10 @@ int cx23885_417_register(struct cx23885_dev *dev)
video_set_drvdata(dev->v4l_device, dev); video_set_drvdata(dev->v4l_device, dev);
dev->v4l_device->lock = &dev->lock; dev->v4l_device->lock = &dev->lock;
dev->v4l_device->queue = q; dev->v4l_device->queue = q;
dev->v4l_device->device_caps = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
if (dev->tuner_type != TUNER_ABSENT)
dev->v4l_device->device_caps |= V4L2_CAP_TUNER;
err = video_register_device(dev->v4l_device, err = video_register_device(dev->v4l_device,
VFL_TYPE_GRABBER, -1); VFL_TYPE_GRABBER, -1);
if (err < 0) { if (err < 0) {

View File

@ -2647,8 +2647,6 @@ int cx23885_dvb_register(struct cx23885_tsport *port)
dev->pci_bus, dev->pci_bus,
dev->pci_slot); dev->pci_slot);
err = -ENODEV;
/* dvb stuff */ /* dvb stuff */
/* We have to init the queue for each frontend on a port. */ /* We have to init the queue for each frontend on a port. */
pr_info("%s: cx23885 based dvb card\n", dev->name); pr_info("%s: cx23885 based dvb card\n", dev->name);

View File

@ -627,21 +627,17 @@ static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap) struct v4l2_capability *cap)
{ {
struct cx23885_dev *dev = video_drvdata(file); struct cx23885_dev *dev = video_drvdata(file);
struct video_device *vdev = video_devdata(file);
strscpy(cap->driver, "cx23885", sizeof(cap->driver)); strscpy(cap->driver, "cx23885", sizeof(cap->driver));
strscpy(cap->card, cx23885_boards[dev->board].name, strscpy(cap->card, cx23885_boards[dev->board].name,
sizeof(cap->card)); sizeof(cap->card));
sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
cap->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING | V4L2_CAP_AUDIO; cap->capabilities = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
V4L2_CAP_AUDIO | V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_DEVICE_CAPS;
if (dev->tuner_type != TUNER_ABSENT) if (dev->tuner_type != TUNER_ABSENT)
cap->device_caps |= V4L2_CAP_TUNER; cap->capabilities |= V4L2_CAP_TUNER;
if (vdev->vfl_type == VFL_TYPE_VBI)
cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
else
cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
cap->capabilities = cap->device_caps | V4L2_CAP_VBI_CAPTURE |
V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_DEVICE_CAPS;
return 0; return 0;
} }
@ -1306,6 +1302,10 @@ int cx23885_video_register(struct cx23885_dev *dev)
dev->video_dev = cx23885_vdev_init(dev, dev->pci, dev->video_dev = cx23885_vdev_init(dev, dev->pci,
&cx23885_video_template, "video"); &cx23885_video_template, "video");
dev->video_dev->queue = &dev->vb2_vidq; dev->video_dev->queue = &dev->vb2_vidq;
dev->video_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
V4L2_CAP_AUDIO | V4L2_CAP_VIDEO_CAPTURE;
if (dev->tuner_type != TUNER_ABSENT)
dev->video_dev->device_caps |= V4L2_CAP_TUNER;
err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, err = video_register_device(dev->video_dev, VFL_TYPE_GRABBER,
video_nr[dev->nr]); video_nr[dev->nr]);
if (err < 0) { if (err < 0) {
@ -1320,6 +1320,10 @@ int cx23885_video_register(struct cx23885_dev *dev)
dev->vbi_dev = cx23885_vdev_init(dev, dev->pci, dev->vbi_dev = cx23885_vdev_init(dev, dev->pci,
&cx23885_vbi_template, "vbi"); &cx23885_vbi_template, "vbi");
dev->vbi_dev->queue = &dev->vb2_vbiq; dev->vbi_dev->queue = &dev->vb2_vbiq;
dev->vbi_dev->device_caps = V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
V4L2_CAP_AUDIO | V4L2_CAP_VBI_CAPTURE;
if (dev->tuner_type != TUNER_ABSENT)
dev->vbi_dev->device_caps |= V4L2_CAP_TUNER;
err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI, err = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
vbi_nr[dev->nr]); vbi_nr[dev->nr]);
if (err < 0) { if (err < 0) {

View File

@ -426,18 +426,13 @@ static int cx25821_vidioc_querycap(struct file *file, void *priv,
{ {
struct cx25821_channel *chan = video_drvdata(file); struct cx25821_channel *chan = video_drvdata(file);
struct cx25821_dev *dev = chan->dev; struct cx25821_dev *dev = chan->dev;
const u32 cap_input = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
const u32 cap_output = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE;
strscpy(cap->driver, "cx25821", sizeof(cap->driver)); strscpy(cap->driver, "cx25821", sizeof(cap->driver));
strscpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card)); strscpy(cap->card, cx25821_boards[dev->board].name, sizeof(cap->card));
sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci)); sprintf(cap->bus_info, "PCIe:%s", pci_name(dev->pci));
if (chan->id >= VID_CHANNEL_NUM) cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
cap->device_caps = cap_output; V4L2_CAP_READWRITE | V4L2_CAP_STREAMING |
else V4L2_CAP_DEVICE_CAPS;
cap->device_caps = cap_input;
cap->capabilities = cap_input | cap_output | V4L2_CAP_DEVICE_CAPS;
return 0; return 0;
} }
@ -624,6 +619,8 @@ static const struct video_device cx25821_video_device = {
.minor = -1, .minor = -1,
.ioctl_ops = &video_ioctl_ops, .ioctl_ops = &video_ioctl_ops,
.tvnorms = CX25821_NORMS, .tvnorms = CX25821_NORMS,
.device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING,
}; };
static const struct v4l2_file_operations video_out_fops = { static const struct v4l2_file_operations video_out_fops = {
@ -657,6 +654,7 @@ static const struct video_device cx25821_video_out_device = {
.minor = -1, .minor = -1,
.ioctl_ops = &video_out_ioctl_ops, .ioctl_ops = &video_out_ioctl_ops,
.tvnorms = CX25821_NORMS, .tvnorms = CX25821_NORMS,
.device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE,
}; };
void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num) void cx25821_video_unregister(struct cx25821_dev *dev, int chan_num)

View File

@ -95,7 +95,7 @@ MODULE_PARM_DESC(index, "Index value for cx88x capture interface(s).");
MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards"); MODULE_DESCRIPTION("ALSA driver module for cx2388x based TV cards");
MODULE_AUTHOR("Ricardo Cerqueira"); MODULE_AUTHOR("Ricardo Cerqueira");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@kernel.org>"); MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@kernel.org>");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL v2");
MODULE_VERSION(CX88_VERSION); MODULE_VERSION(CX88_VERSION);
MODULE_SUPPORTED_DEVICE("{{Conexant,23881},{{Conexant,23882},{{Conexant,23883}"); MODULE_SUPPORTED_DEVICE("{{Conexant,23881},{{Conexant,23882},{{Conexant,23883}");

Some files were not shown because too many files have changed in this diff Show More