media updates for v5.17-rc1

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAmHPqrMACgkQCF8+vY7k
 4RUM2g//VzdGU6kq19k7++N7ewGV1VhTnwAXCzdjjMuigdYpTnH/i2fIN/3BS2Mw
 RQVTc3Ys26SGdaKCPsMONKjNwQk62hiaQGW4gwnCZ9Me+hgR3e6z67rJa6XWpKuw
 aH81Z+XFfyn3Oo8qu7jqCABRCWXfKuxs8Vmc8XdcjvrqlREpiQ0c10oXiboeOoWE
 RmVPrnJ94pK8J859dO01cRkDCCo2G9AL9vnBHVA5050VEskSb20+8EmJQDfmkgsO
 Itd6JpCK97QTH5gtF44iO3CDWi5f3x9ODWJkQXJEZRAiKORZkcQUpCOXafQjb2vN
 YgxO86F/sD7XlhZ3V5AjvztZuQPTmnLNcgnrIVUa7iCAWDft1xBIsjQ+BxV9uROe
 g3/Yl6J+Y2Qi+wfAVhCJ94pfA2ZCIoN/+loVi9TQ22X4+tbr6+K4qWu3y1eu9bTW
 TYVD//nUMZz/ljFBAgj4OM6RhtMCqI6c2IB3weOEey5wcR641M0mVHPmzgNo5VMQ
 mFYkRXwrHrbsWWXxRB9yEJKK6P0MsDWAvoD8QBFvaOmqEBr7gG4ET44G76lcFoyD
 Tks4+MZQFQvzas/Xd/GndFlD/T4Cyn+CoPLP1SaP3R01mldoSA39o/cVZlHbZgjI
 8zFnPCAsE2C/w+Oko/vGLQZyyetJ8PzohPmlMy8XPaejYulHQqA=
 =cCwW
 -----END PGP SIGNATURE-----

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

Pull media updates from Mauro Carvalho Chehab:

 - New sensor driver: ov5693

 - A new driver for STM32 Chrom-ART Accelerator

 - Added V4L2 core helper functions for VP9 codec

 - Hantro driver has gained support for VP9 codecs

 - Added support for Maxim MAX96712 Quad GMSL2 Deserializer

 - The staging atomisp driver has gained lots of improvements, fixes and
   cleanups. It now works with userptr

 - Lots of random driver improvements as usual

* tag 'media/v5.17-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (397 commits)
  media: ipu3-cio2: Add support for instantiating i2c-clients for VCMs
  media: ipu3-cio2: Call cio2_bridge_init() before anything else
  media: ipu3-cio2: Defer probing until the PMIC is fully setup
  media: hantro: Add support for Allwinner H6
  media: dt-bindings: allwinner: document H6 Hantro G2 binding
  media: hantro: Convert imx8m_vpu_g2_irq to helper
  media: hantro: move postproc enablement for old cores
  media: hantro: vp9: add support for legacy register set
  media: hantro: vp9: use double buffering if needed
  media: hantro: add support for reset lines
  media: hantro: Fix probe func error path
  media: i2c: hi846: use pm_runtime_force_suspend/resume for system suspend
  media: i2c: hi846: check return value of regulator_bulk_disable()
  media: hi556: Support device probe in non-zero ACPI D state
  media: ov5675: Support device probe in non-zero ACPI D state
  media: imx208: Support device probe in non-zero ACPI D state
  media: ov2740: support device probe in non-zero ACPI D state
  media: ov5670: Support device probe in non-zero ACPI D state
  media: ov8856: support device probe in non-zero ACPI D state
  media: ov8865: Disable only enabled regulators on error path
  ...
This commit is contained in:
Linus Torvalds 2022-01-10 18:55:43 -08:00
commit 9bcbf894b6
373 changed files with 15502 additions and 11308 deletions

View File

@ -44,6 +44,7 @@ Andrew Vasquez <andrew.vasquez@qlogic.com>
Andrey Konovalov <andreyknvl@gmail.com> <andreyknvl@google.com>
Andrey Ryabinin <ryabinin.a.a@gmail.com> <a.ryabinin@samsung.com>
Andrey Ryabinin <ryabinin.a.a@gmail.com> <aryabinin@virtuozzo.com>
Andrzej Hajda <andrzej.hajda@intel.com> <a.hajda@samsung.com>
Andy Adamson <andros@citi.umich.edu>
Antoine Tenart <atenart@kernel.org> <antoine.tenart@bootlin.com>
Antoine Tenart <atenart@kernel.org> <antoine.tenart@free-electrons.com>

View File

@ -60,6 +60,7 @@ s5p-mfc Samsung S5P MFC Video Codec
sh_veu SuperH VEU mem2mem video processing
sh_vou SuperH VOU video output
stm32-dcmi STM32 Digital Camera Memory Interface (DCMI)
stm32-dma2d STM32 Chrom-Art Accelerator Unit
sun4i-csi Allwinner A10 CMOS Sensor Interface Support
sun6i-csi Allwinner V3s Camera Sensor Interface
sun8i-di Allwinner Deinterlace

View File

@ -20,6 +20,7 @@ properties:
- allwinner,sun8i-h3-video-engine
- allwinner,sun8i-v3s-video-engine
- allwinner,sun8i-r40-video-engine
- allwinner,sun20i-d1-video-engine
- allwinner,sun50i-a64-video-engine
- allwinner,sun50i-h5-video-engine
- allwinner,sun50i-h6-video-engine

View File

@ -0,0 +1,64 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: "http://devicetree.org/schemas/media/allwinner,sun50i-h6-vpu-g2.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: Hantro G2 VPU codec implemented on Allwinner H6 SoC
maintainers:
- Jernej Skrabec <jernej.skrabec@gmail.com>
description:
Hantro G2 video decode accelerator present on Allwinner H6 SoC.
properties:
compatible:
const: allwinner,sun50i-h6-vpu-g2
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: Bus Clock
- description: Module Clock
clock-names:
items:
- const: bus
- const: mod
resets:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/sun50i-h6-ccu.h>
#include <dt-bindings/reset/sun50i-h6-ccu.h>
video-codec-g2@1c00000 {
compatible = "allwinner,sun50i-h6-vpu-g2";
reg = <0x01c00000 0x1000>;
interrupts = <GIC_SPI 90 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_VP9>, <&ccu CLK_VP9>;
clock-names = "bus", "mod";
resets = <&ccu RST_BUS_VP9>;
};
...

View File

@ -1,116 +0,0 @@
* Analog Devices ADV748X video decoder with HDMI receiver
The ADV7481 and ADV7482 are multi format video decoders with an integrated
HDMI receiver. They can output CSI-2 on two independent outputs TXA and TXB
from three input sources HDMI, analog and TTL.
Required Properties:
- compatible: Must contain one of the following
- "adi,adv7481" for the ADV7481
- "adi,adv7482" for the ADV7482
- reg: I2C slave addresses
The ADV748x has up to twelve 256-byte maps that can be accessed via the
main I2C ports. Each map has it own I2C address and acts as a standard
slave device on the I2C bus. The main address is mandatory, others are
optional and remain at default values if not specified.
Optional Properties:
- interrupt-names: Should specify the interrupts as "intrq1", "intrq2" and/or
"intrq3". All interrupts are optional. The "intrq3" interrupt
is only available on the adv7481
- interrupts: Specify the interrupt lines for the ADV748x
- reg-names : Names of maps with programmable addresses.
It shall contain all maps needing a non-default address.
Possible map names are:
"main", "dpll", "cp", "hdmi", "edid", "repeater",
"infoframe", "cbus", "cec", "sdp", "txa", "txb"
The device node must contain one 'port' child node per device input and output
port, in accordance with the video interface bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The port nodes
are numbered as follows.
Name Type Port
---------------------------------------
AIN0 sink 0
AIN1 sink 1
AIN2 sink 2
AIN3 sink 3
AIN4 sink 4
AIN5 sink 5
AIN6 sink 6
AIN7 sink 7
HDMI sink 8
TTL sink 9
TXA source 10
TXB source 11
The digital output port nodes, when present, shall contain at least one
endpoint. Each of those endpoints shall contain the data-lanes property as
described in video-interfaces.txt.
Required source endpoint properties:
- data-lanes: an array of physical data lane indexes
The accepted value(s) for this property depends on which of the two
sources are described. For TXA 1, 2 or 4 data lanes can be described
while for TXB only 1 data lane is valid. See video-interfaces.txt
for detailed description.
Ports are optional if they are not connected to anything at the hardware level.
Example:
video-receiver@70 {
compatible = "adi,adv7482";
reg = <0x70 0x71 0x72 0x73 0x74 0x75
0x60 0x61 0x62 0x63 0x64 0x65>;
reg-names = "main", "dpll", "cp", "hdmi", "edid", "repeater",
"infoframe", "cbus", "cec", "sdp", "txa", "txb";
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&gpio6>;
interrupt-names = "intrq1", "intrq2";
interrupts = <30 IRQ_TYPE_LEVEL_LOW>,
<31 IRQ_TYPE_LEVEL_LOW>;
port@7 {
reg = <7>;
adv7482_ain7: endpoint {
remote-endpoint = <&cvbs_in>;
};
};
port@8 {
reg = <8>;
adv7482_hdmi: endpoint {
remote-endpoint = <&hdmi_in>;
};
};
port@a {
reg = <10>;
adv7482_txa: endpoint {
clock-lanes = <0>;
data-lanes = <1 2 3 4>;
remote-endpoint = <&csi40_in>;
};
};
port@b {
reg = <11>;
adv7482_txb: endpoint {
clock-lanes = <0>;
data-lanes = <1>;
remote-endpoint = <&csi20_in>;
};
};
};

View File

@ -0,0 +1,212 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/adv748x.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Analog Devices ADV748X video decoder with HDMI receiver
maintainers:
- Kieran Bingham <kieran.bingham@ideasonboard.com>
- Niklas Söderlund <niklas.soderlund@ragnatech.se>
description:
The ADV7481 and ADV7482 are multi format video decoders with an integrated
HDMI receiver. They can output CSI-2 on two independent outputs TXA and TXB
from three input sources HDMI, analog and TTL.
properties:
compatible:
items:
- enum:
- adi,adv7481
- adi,adv7482
reg:
minItems: 1
maxItems: 12
description:
The ADV748x has up to twelve 256-byte maps that can be accessed via the
main I2C ports. Each map has it own I2C address and acts as a standard
slave device on the I2C bus. The main address is mandatory, others are
optional and remain at default values if not specified.
reg-names:
minItems: 1
items:
- const: main
- enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ]
- enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ]
- enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ]
- enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ]
- enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ]
- enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ]
- enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ]
- enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ]
- enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ]
- enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ]
- enum: [ dpll, cp, hdmi, edid, repeater, infoframe, cbus, cec, sdp, txa, txb ]
interrupts: true
interrupt-names: true
ports:
$ref: /schemas/graph.yaml#/properties/ports
patternProperties:
"^port@[0-7]$":
$ref: /schemas/graph.yaml#/properties/port
description: Input port nodes for analog inputs AIN[0-7].
properties:
port@8:
$ref: /schemas/graph.yaml#/properties/port
description: Input port node for HDMI.
port@9:
$ref: /schemas/graph.yaml#/properties/port
description: Input port node for TTL.
port@a:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Output port node, single endpoint describing the CSI-2 transmitter TXA.
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
clock-lanes:
maxItems: 1
data-lanes:
minItems: 1
maxItems: 4
required:
- clock-lanes
- data-lanes
port@b:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Output port node, single endpoint describing the CSI-2 transmitter TXB.
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
clock-lanes:
maxItems: 1
data-lanes:
maxItems: 1
required:
- clock-lanes
- data-lanes
allOf:
- if:
properties:
compatible:
contains:
const: adi,adv7481
then:
properties:
interrupts:
minItems: 1
maxItems: 3
interrupt-names:
minItems: 1
maxItems: 3
items:
enum: [ intrq1, intrq2, intrq3 ]
else:
properties:
interrupts:
minItems: 1
maxItems: 2
interrupt-names:
minItems: 1
maxItems: 2
items:
enum: [ intrq1, intrq2 ]
additionalProperties: false
required:
- compatible
- reg
- ports
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
video-receiver@70 {
compatible = "adi,adv7482";
reg = <0x70 0x71 0x72 0x73 0x74 0x75
0x60 0x61 0x62 0x63 0x64 0x65>;
reg-names = "main", "dpll", "cp", "hdmi", "edid", "repeater",
"infoframe", "cbus", "cec", "sdp", "txa", "txb";
interrupt-parent = <&gpio6>;
interrupts = <30 IRQ_TYPE_LEVEL_LOW>, <31 IRQ_TYPE_LEVEL_LOW>;
interrupt-names = "intrq1", "intrq2";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@7 {
reg = <7>;
adv7482_ain7: endpoint {
remote-endpoint = <&cvbs_in>;
};
};
port@8 {
reg = <8>;
adv7482_hdmi: endpoint {
remote-endpoint = <&hdmi_in>;
};
};
port@a {
reg = <10>;
adv7482_txa: endpoint {
clock-lanes = <0>;
data-lanes = <1 2 3 4>;
remote-endpoint = <&csi40_in>;
};
};
port@b {
reg = <11>;
adv7482_txb: endpoint {
clock-lanes = <0>;
data-lanes = <1>;
remote-endpoint = <&csi20_in>;
};
};
};
};
};

View File

@ -1,25 +0,0 @@
* Renesas JPEG Processing Unit
The JPEG processing unit (JPU) incorporates the JPEG codec with an encoding
and decoding function conforming to the JPEG baseline process, so that the JPU
can encode image data and decode JPEG data quickly.
Required properties:
- compatible: "renesas,jpu-<soctype>", "renesas,rcar-gen2-jpu" as fallback.
Examples with soctypes are:
- "renesas,jpu-r8a7790" for R-Car H2
- "renesas,jpu-r8a7791" for R-Car M2-W
- "renesas,jpu-r8a7792" for R-Car V2H
- "renesas,jpu-r8a7793" for R-Car M2-N
- reg: Base address and length of the registers block for the JPU.
- interrupts: JPU interrupt specifier.
- clocks: A phandle + clock-specifier pair for the JPU functional clock.
Example: R8A7790 (R-Car H2) JPU node
jpeg-codec@fe980000 {
compatible = "renesas,jpu-r8a7790", "renesas,rcar-gen2-jpu";
reg = <0 0xfe980000 0 0x10300>;
interrupts = <0 272 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp1_clks R8A7790_CLK_JPU>;
};

View File

@ -0,0 +1,65 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/renesas,jpu.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Renesas JPEG Processing Unit
maintainers:
- Mikhail Ulyanov <mikhail.ulyanov@cogentembedded.com>
description:
The JPEG processing unit (JPU) incorporates the JPEG codec with an encoding
and decoding function conforming to the JPEG baseline process, so that the
JPU can encode image data and decode JPEG data quickly.
properties:
compatible:
items:
- enum:
- renesas,jpu-r8a7790 # R-Car H2
- renesas,jpu-r8a7791 # R-Car M2-W
- renesas,jpu-r8a7792 # R-Car V2H
- renesas,jpu-r8a7793 # R-Car M2-N
- const: renesas,rcar-gen2-jpu # R-Car Gen2
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
power-domains:
maxItems: 1
resets:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
- power-domains
- resets
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/r8a7790-cpg-mssr.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/r8a7790-sysc.h>
jpeg-codec@fe980000 {
compatible = "renesas,jpu-r8a7790", "renesas,rcar-gen2-jpu";
reg = <0xfe980000 0x10300>;
interrupts = <GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cpg CPG_MOD 106>;
power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
resets = <&cpg 106>;
};

View File

@ -0,0 +1,71 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/st,stm32-dma2d.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: STMicroelectronics STM32 Chrom-Art Accelerator DMA2D binding
description:
Chrom-ART Accelerator(DMA2D), graphical hardware accelerator
enabling enhanced graphical user interface with minimum CPU load
It can perform the following operations.
- Filling a part or the whole of a destination image with a specific color.
- Copying a part or the whole of a source image into a part or the whole of
a destination image.
- Copying a part or the whole of a source image into a part or the whole of
a destination image with a pixel format conversion.
- Blending a part and/or two complete source images with different pixel
format and copy the result into a part or the whole of a destination image
with a different color format. (TODO)
maintainers:
- Dillon Min <dillon.minfei@gmail.com>
properties:
compatible:
const: st,stm32-dma2d
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 1
clock-names:
items:
- const: dma2d
resets:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/stm32fx-clock.h>
#include <dt-bindings/mfd/stm32f4-rcc.h>
dma2d: dma2d@4002b000 {
compatible = "st,stm32-dma2d";
reg = <0x4002b000 0xc00>;
interrupts = <90>;
resets = <&rcc STM32F4_AHB1_RESET(DMA2D)>;
clocks = <&rcc 0 STM32F4_AHB1_CLOCK(DMA2D)>;
clock-names = "dma2d";
};
...

View File

@ -21,6 +21,7 @@ Video4Linux (V4L) drivers
pvrusb2
pxa_camera
radiotrack
rkisp1
saa7134-devel
sh_mobile_ceu_camera
tuners

View File

@ -48,9 +48,12 @@ it will return -1 and set errno to the ``ETIMEDOUT`` error code.
A received message can be:
1. a message received from another CEC device (the ``sequence`` field will
be 0).
2. the result of an earlier non-blocking transmit (the ``sequence`` field will
be non-zero).
be 0, ``tx_status`` will be 0 and ``rx_status`` will be non-zero).
2. the transmit result of an earlier non-blocking transmit (the ``sequence``
field will be non-zero, ``tx_status`` will be non-zero and ``rx_status``
will be 0).
3. the reply to an earlier non-blocking transmit (the ``sequence`` field will
be non-zero, ``tx_status`` will be 0 and ``rx_status`` will be non-zero).
To send a CEC message the application has to fill in the struct
:c:type:`cec_msg` and pass it to :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>`.
@ -64,12 +67,11 @@ idea to fully fill up the transmit queue.
If the file descriptor is in non-blocking mode then the transmit will
return 0 and the result of the transmit will be available via
:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>` once the transmit has finished
(including waiting for a reply, if requested).
The ``sequence`` field is filled in for every transmit and this can be
checked against the received messages to find the corresponding transmit
result.
:ref:`ioctl CEC_RECEIVE <CEC_RECEIVE>` once the transmit has finished.
If a non-blocking transmit also specified waiting for a reply, then
the reply will arrive in a later message. The ``sequence`` field can
be used to associate both transmit results and replies with the original
transmit.
Normally calling :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` when the physical
address is invalid (due to e.g. a disconnect) will return ``ENONET``.
@ -123,17 +125,16 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
- ``sequence``
- A non-zero sequence number is automatically assigned by the CEC framework
for all transmitted messages. It is used by the CEC framework when it queues
the transmit result (when transmit was called in non-blocking mode). This
allows the application to associate the received message with the original
transmit.
the transmit result for a non-blocking transmit. This allows the application
to associate the received message with the original transmit.
In addition, if a non-blocking transmit will wait for a reply (ii.e. ``timeout``
was not 0), then the ``sequence`` field of the reply will be set to the sequence
value of the original transmit. This allows the application to associate the
received message with the original transmit.
* - __u32
- ``flags``
- Flags. See :ref:`cec-msg-flags` for a list of available flags.
* - __u8
- ``tx_status``
- The status bits of the transmitted message. See
:ref:`cec-tx-status` for the possible status values. It is 0 if
this message was received, not transmitted.
* - __u8
- ``msg[16]``
- The message payload. For :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` this is filled in by the
@ -162,15 +163,17 @@ View On' messages from initiator 0xf ('Unregistered') to destination 0 ('TV').
* - __u8
- ``rx_status``
- The status bits of the received message. See
:ref:`cec-rx-status` for the possible status values. It is 0 if
this message was transmitted, not received, unless this is the
reply to a transmitted message. In that case both ``rx_status``
and ``tx_status`` are set.
:ref:`cec-rx-status` for the possible status values.
* - __u8
- ``tx_status``
- The status bits of the transmitted message. See
:ref:`cec-tx-status` for the possible status values. It is 0 if
this message was received, not transmitted.
:ref:`cec-tx-status` for the possible status values.
When calling :ref:`ioctl CEC_TRANSMIT <CEC_TRANSMIT>` in non-blocking mode,
this field will be 0 if the transmit started, or non-0 if the transmit
result is known immediately. The latter would be the case when attempting
to transmit a Poll message to yourself. That results in a
:ref:`CEC_TX_STATUS_NACK <CEC-TX-STATUS-NACK>` without ever actually
transmitting the Poll message.
* - __u8
- ``tx_arb_lost_cnt``
- A counter of the number of transmit attempts that resulted in the

View File

@ -33,6 +33,7 @@ ignore define LIRC_CAN_SET_REC_DUTY_CYCLE
# Obsolete ioctls
ignore ioctl LIRC_GET_LENGTH
ignore ioctl LIRC_SET_REC_TIMEOUT_REPORTS
# rc protocols
@ -73,6 +74,7 @@ ignore define PULSE_MASK
ignore define LIRC_MODE2_SPACE
ignore define LIRC_MODE2_PULSE
ignore define LIRC_MODE2_TIMEOUT
ignore define LIRC_VALUE_MASK
ignore define LIRC_MODE2_MASK

View File

@ -117,11 +117,9 @@ on the following table.
``LIRC_MODE2_TIMEOUT``
If timeout reports are enabled with
:ref:`lirc_set_rec_timeout_reports`, when the timeout set with
:ref:`lirc_set_rec_timeout` expires due to no IR being detected,
this packet will be sent, with the number of microseconds with
no IR.
When the timeout set with :ref:`lirc_set_rec_timeout` expires due
to no IR being detected, this packet will be sent, with the number
of microseconds with no IR.
.. _lirc-mode-pulse:

View File

@ -22,6 +22,5 @@ LIRC Function Reference
lirc-set-rec-carrier-range
lirc-set-send-carrier
lirc-set-transmitter-mask
lirc-set-rec-timeout-reports
lirc-set-measure-carrier-mode
lirc-set-wideband-receiver

View File

@ -1,49 +0,0 @@
.. SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later
.. c:namespace:: RC
.. _lirc_set_rec_timeout_reports:
**********************************
ioctl LIRC_SET_REC_TIMEOUT_REPORTS
**********************************
Name
====
LIRC_SET_REC_TIMEOUT_REPORTS - enable or disable timeout reports for IR receive
Synopsis
========
.. c:macro:: LIRC_SET_REC_TIMEOUT_REPORTS
``int ioctl(int fd, LIRC_SET_REC_TIMEOUT_REPORTS, __u32 *enable)``
Arguments
=========
``fd``
File descriptor returned by open().
``enable``
enable = 1 means enable timeout report, enable = 0 means disable timeout
reports.
Description
===========
.. _lirc-mode2-timeout:
Enable or disable timeout reports for IR receive. By default, timeout reports
should be turned off.
.. note::
This ioctl is only valid for :ref:`LIRC_MODE_MODE2 <lirc-mode-mode2>`.
Return Value
============
On success 0 is returned, on error -1 and the ``errno`` variable is set
appropriately. The generic error codes are described at the
:ref:`Generic Error Codes <gen-errors>` chapter.

View File

@ -417,3 +417,13 @@ VP8
:title: RFC 6386: "VP8 Data Format and Decoding Guide"
:author: J. Bankoski et al.
.. _vp9:
VP9
===
:title: VP9 Bitstream & Decoding Process Specification
:author: Adrian Grange (Google), Peter de Rivaz (Argon Design), Jonathan Hunt (Argon Design)

View File

@ -56,7 +56,7 @@ file: media/v4l/capture.c
static void errno_exit(const char *s)
{
fprintf(stderr, "%s error %d, %s\\n", s, errno, strerror(errno));
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
exit(EXIT_FAILURE);
}
@ -201,7 +201,7 @@ file: media/v4l/capture.c
}
if (0 == r) {
fprintf(stderr, "select timeout\\n");
fprintf(stderr, "select timeout\n");
exit(EXIT_FAILURE);
}
@ -307,7 +307,7 @@ file: media/v4l/capture.c
buffers = calloc(1, sizeof(*buffers));
if (!buffers) {
fprintf(stderr, "Out of memory\\n");
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
@ -315,7 +315,7 @@ file: media/v4l/capture.c
buffers[0].start = malloc(buffer_size);
if (!buffers[0].start) {
fprintf(stderr, "Out of memory\\n");
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
}
@ -341,7 +341,7 @@ file: media/v4l/capture.c
}
if (req.count < 2) {
fprintf(stderr, "Insufficient buffer memory on %s\\n",
fprintf(stderr, "Insufficient buffer memory on %s\n",
dev_name);
exit(EXIT_FAILURE);
}
@ -349,7 +349,7 @@ file: media/v4l/capture.c
buffers = calloc(req.count, sizeof(*buffers));
if (!buffers) {
fprintf(stderr, "Out of memory\\n");
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
@ -401,7 +401,7 @@ file: media/v4l/capture.c
buffers = calloc(4, sizeof(*buffers));
if (!buffers) {
fprintf(stderr, "Out of memory\\n");
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
@ -410,7 +410,7 @@ file: media/v4l/capture.c
buffers[n_buffers].start = malloc(buffer_size);
if (!buffers[n_buffers].start) {
fprintf(stderr, "Out of memory\\n");
fprintf(stderr, "Out of memory\n");
exit(EXIT_FAILURE);
}
}
@ -426,7 +426,7 @@ file: media/v4l/capture.c
if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) {
if (EINVAL == errno) {
fprintf(stderr, "%s is no V4L2 device\\n",
fprintf(stderr, "%s is no V4L2 device\n",
dev_name);
exit(EXIT_FAILURE);
} else {
@ -435,7 +435,7 @@ file: media/v4l/capture.c
}
if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
fprintf(stderr, "%s is no video capture device\\n",
fprintf(stderr, "%s is no video capture device\n",
dev_name);
exit(EXIT_FAILURE);
}
@ -443,7 +443,7 @@ file: media/v4l/capture.c
switch (io) {
case IO_METHOD_READ:
if (!(cap.capabilities & V4L2_CAP_READWRITE)) {
fprintf(stderr, "%s does not support read i/o\\n",
fprintf(stderr, "%s does not support read i/o\n",
dev_name);
exit(EXIT_FAILURE);
}
@ -452,7 +452,7 @@ file: media/v4l/capture.c
case IO_METHOD_MMAP:
case IO_METHOD_USERPTR:
if (!(cap.capabilities & V4L2_CAP_STREAMING)) {
fprintf(stderr, "%s does not support streaming i/o\\n",
fprintf(stderr, "%s does not support streaming i/o\n",
dev_name);
exit(EXIT_FAILURE);
}
@ -541,7 +541,7 @@ file: media/v4l/capture.c
struct stat st;
if (-1 == stat(dev_name, &st)) {
fprintf(stderr, "Cannot identify '%s': %d, %s\\n",
fprintf(stderr, "Cannot identify '%s': %d, %s\n",
dev_name, errno, strerror(errno));
exit(EXIT_FAILURE);
}
@ -554,7 +554,7 @@ file: media/v4l/capture.c
fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0);
if (-1 == fd) {
fprintf(stderr, "Cannot open '%s': %d, %s\\n",
fprintf(stderr, "Cannot open '%s': %d, %s\n",
dev_name, errno, strerror(errno));
exit(EXIT_FAILURE);
}
@ -563,17 +563,17 @@ file: media/v4l/capture.c
static void usage(FILE *fp, int argc, char **argv)
{
fprintf(fp,
"Usage: %s [options]\\n\\n"
"Version 1.3\\n"
"Options:\\n"
"-d | --device name Video device name [%s]n"
"-h | --help Print this messagen"
"-m | --mmap Use memory mapped buffers [default]n"
"-r | --read Use read() callsn"
"-u | --userp Use application allocated buffersn"
"-o | --output Outputs stream to stdoutn"
"-f | --format Force format to 640x480 YUYVn"
"-c | --count Number of frames to grab [%i]n"
"Usage: %s [options]\n\n"
"Version 1.3\n"
"Options:\n"
"-d | --device name Video device name [%s]\n"
"-h | --help Print this message\n"
"-m | --mmap Use memory mapped buffers [default]\n"
"-r | --read Use read() calls\n"
"-u | --userp Use application allocated buffers\n"
"-o | --output Outputs stream to stdout\n"
"-f | --format Force format to 640x480 YUYV\n"
"-c | --count Number of frames to grab [%i]\n"
"",
argv[0], dev_name, frame_count);
}
@ -659,6 +659,6 @@ file: media/v4l/capture.c
stop_capturing();
uninit_device();
close_device();
fprintf(stderr, "\\n");
fprintf(stderr, "\n");
return 0;
}

View File

@ -242,8 +242,17 @@ Control IDs
* - ``V4L2_COLORFX_SET_CBCR``
- The Cb and Cr chroma components are replaced by fixed coefficients
determined by ``V4L2_CID_COLORFX_CBCR`` control.
* - ``V4L2_COLORFX_SET_RGB``
- The RGB components are replaced by the fixed RGB components determined
by ``V4L2_CID_COLORFX_RGB`` control.
``V4L2_CID_COLORFX_RGB`` ``(integer)``
Determines the Red, Green, and Blue coefficients for
``V4L2_COLORFX_SET_RGB`` color effect.
Bits [7:0] of the supplied 32 bit value are interpreted as Blue component,
bits [15:8] as Green component, bits [23:16] as Red component, and
bits [31:24] must be zero.
``V4L2_CID_COLORFX_CBCR`` ``(integer)``
Determines the Cb and Cr coefficients for ``V4L2_COLORFX_SET_CBCR``

View File

@ -752,6 +752,23 @@ available to dequeue. Specifically:
buffers are out-of-order compared to the ``OUTPUT`` buffers): ``CAPTURE``
timestamps will not retain the order of ``OUTPUT`` timestamps.
.. note::
The backing memory of ``CAPTURE`` buffers that are used as reference frames
by the stream may be read by the hardware even after they are dequeued.
Consequently, the client should avoid writing into this memory while the
``CAPTURE`` queue is streaming. Failure to observe this may result in
corruption of decoded frames.
Similarly, when using a memory type other than ``V4L2_MEMORY_MMAP``, the
client should make sure that each ``CAPTURE`` buffer is always queued with
the same backing memory for as long as the ``CAPTURE`` queue is streaming.
The reason for this is that V4L2 buffer indices can be used by drivers to
identify frames. Thus, if the backing memory of a reference frame is
submitted under a different buffer ID, the driver may misidentify it and
decode a new frame into it while it is still in use, resulting in corruption
of the following frames.
During the decoding, the decoder may initiate one of the special sequences, as
listed below. The sequences will result in the decoder returning all the
``CAPTURE`` buffers that originated from all the ``OUTPUT`` buffers processed

View File

@ -1458,3 +1458,576 @@ FWHT Flags
.. raw:: latex
\normalsize
.. _v4l2-codec-stateless-vp9:
``V4L2_CID_STATELESS_VP9_COMPRESSED_HDR (struct)``
Stores VP9 probabilities updates as parsed from the current compressed frame
header. A value of zero in an array element means no update of the relevant
probability. Motion vector-related updates contain a new value or zero. All
other updates contain values translated with inv_map_table[] (see 6.3.5 in
:ref:`vp9`).
.. c:type:: v4l2_ctrl_vp9_compressed_hdr
.. tabularcolumns:: |p{1cm}|p{4.8cm}|p{11.4cm}|
.. cssclass:: longtable
.. flat-table:: struct v4l2_ctrl_vp9_compressed_hdr
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __u8
- ``tx_mode``
- Specifies the TX mode. See :ref:`TX Mode <vp9_tx_mode>` for more details.
* - __u8
- ``tx8[2][1]``
- TX 8x8 probabilities delta.
* - __u8
- ``tx16[2][2]``
- TX 16x16 probabilities delta.
* - __u8
- ``tx32[2][3]``
- TX 32x32 probabilities delta.
* - __u8
- ``coef[4][2][2][6][6][3]``
- Coefficient probabilities delta.
* - __u8
- ``skip[3]``
- Skip probabilities delta.
* - __u8
- ``inter_mode[7][3]``
- Inter prediction mode probabilities delta.
* - __u8
- ``interp_filter[4][2]``
- Interpolation filter probabilities delta.
* - __u8
- ``is_inter[4]``
- Is inter-block probabilities delta.
* - __u8
- ``comp_mode[5]``
- Compound prediction mode probabilities delta.
* - __u8
- ``single_ref[5][2]``
- Single reference probabilities delta.
* - __u8
- ``comp_ref[5]``
- Compound reference probabilities delta.
* - __u8
- ``y_mode[4][9]``
- Y prediction mode probabilities delta.
* - __u8
- ``uv_mode[10][9]``
- UV prediction mode probabilities delta.
* - __u8
- ``partition[16][3]``
- Partition probabilities delta.
* - __u8
- ``mv.joint[3]``
- Motion vector joint probabilities delta.
* - __u8
- ``mv.sign[2]``
- Motion vector sign probabilities delta.
* - __u8
- ``mv.classes[2][10]``
- Motion vector class probabilities delta.
* - __u8
- ``mv.class0_bit[2]``
- Motion vector class0 bit probabilities delta.
* - __u8
- ``mv.bits[2][10]``
- Motion vector bits probabilities delta.
* - __u8
- ``mv.class0_fr[2][2][3]``
- Motion vector class0 fractional bit probabilities delta.
* - __u8
- ``mv.fr[2][3]``
- Motion vector fractional bit probabilities delta.
* - __u8
- ``mv.class0_hp[2]``
- Motion vector class0 high precision fractional bit probabilities delta.
* - __u8
- ``mv.hp[2]``
- Motion vector high precision fractional bit probabilities delta.
.. _vp9_tx_mode:
``TX Mode``
.. tabularcolumns:: |p{6.5cm}|p{0.5cm}|p{10.3cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_VP9_TX_MODE_ONLY_4X4``
- 0
- Transform size is 4x4.
* - ``V4L2_VP9_TX_MODE_ALLOW_8X8``
- 1
- Transform size can be up to 8x8.
* - ``V4L2_VP9_TX_MODE_ALLOW_16X16``
- 2
- Transform size can be up to 16x16.
* - ``V4L2_VP9_TX_MODE_ALLOW_32X32``
- 3
- transform size can be up to 32x32.
* - ``V4L2_VP9_TX_MODE_SELECT``
- 4
- Bitstream contains the transform size for each block.
See section '7.3.1 Tx mode semantics' of the :ref:`vp9` specification for more details.
``V4L2_CID_STATELESS_VP9_FRAME (struct)``
Specifies the frame parameters for the associated VP9 frame decode request.
This includes the necessary parameters for configuring a stateless hardware
decoding pipeline for VP9. The bitstream parameters are defined according
to :ref:`vp9`.
.. c:type:: v4l2_ctrl_vp9_frame
.. raw:: latex
\small
.. tabularcolumns:: |p{4.7cm}|p{5.5cm}|p{7.1cm}|
.. cssclass:: longtable
.. flat-table:: struct v4l2_ctrl_vp9_frame
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - struct :c:type:`v4l2_vp9_loop_filter`
- ``lf``
- Loop filter parameters. See struct :c:type:`v4l2_vp9_loop_filter` for more details.
* - struct :c:type:`v4l2_vp9_quantization`
- ``quant``
- Quantization parameters. See :c:type:`v4l2_vp9_quantization` for more details.
* - struct :c:type:`v4l2_vp9_segmentation`
- ``seg``
- Segmentation parameters. See :c:type:`v4l2_vp9_segmentation` for more details.
* - __u32
- ``flags``
- Combination of V4L2_VP9_FRAME_FLAG_* flags. See :ref:`Frame Flags<vp9_frame_flags>`.
* - __u16
- ``compressed_header_size``
- Compressed header size in bytes.
* - __u16
- ``uncompressed_header_size``
- Uncompressed header size in bytes.
* - __u16
- ``frame_width_minus_1``
- Add 1 to get the frame width expressed in pixels. See section 7.2.3 in :ref:`vp9`.
* - __u16
- ``frame_height_minus_1``
- Add 1 to get the frame height expressed in pixels. See section 7.2.3 in :ref:`vp9`.
* - __u16
- ``render_width_minus_1``
- Add 1 to get the expected render width expressed in pixels. This is
not used during the decoding process but might be used by HW scalers to
prepare a frame that's ready for scanout. See section 7.2.4 in :ref:`vp9`.
* - __u16
- render_height_minus_1
- Add 1 to get the expected render height expressed in pixels. This is
not used during the decoding process but might be used by HW scalers to
prepare a frame that's ready for scanout. See section 7.2.4 in :ref:`vp9`.
* - __u64
- ``last_frame_ts``
- "last" reference buffer timestamp.
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.
* - __u64
- ``golden_frame_ts``
- "golden" reference buffer timestamp.
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.
* - __u64
- ``alt_frame_ts``
- "alt" reference buffer timestamp.
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.
* - __u8
- ``ref_frame_sign_bias``
- a bitfield specifying whether the sign bias is set for a given
reference frame. See :ref:`Reference Frame Sign Bias<vp9_ref_frame_sign_bias>`
for more details.
* - __u8
- ``reset_frame_context``
- specifies whether the frame context should be reset to default values. See
:ref:`Reset Frame Context<vp9_reset_frame_context>` for more details.
* - __u8
- ``frame_context_idx``
- Frame context that should be used/updated.
* - __u8
- ``profile``
- VP9 profile. Can be 0, 1, 2 or 3.
* - __u8
- ``bit_depth``
- Component depth in bits. Can be 8, 10 or 12. Note that not all profiles
support 10 and/or 12 bits depths.
* - __u8
- ``interpolation_filter``
- Specifies the filter selection used for performing inter prediction. See
:ref:`Interpolation Filter<vp9_interpolation_filter>` for more details.
* - __u8
- ``tile_cols_log2``
- Specifies the base 2 logarithm of the width of each tile (where the
width is measured in units of 8x8 blocks). Shall be less than or equal
to 6.
* - __u8
- ``tile_rows_log2``
- Specifies the base 2 logarithm of the height of each tile (where the
height is measured in units of 8x8 blocks).
* - __u8
- ``reference_mode``
- Specifies the type of inter prediction to be used. See
:ref:`Reference Mode<vp9_reference_mode>` for more details.
* - __u8
- ``reserved[7]``
- Applications and drivers must set this to zero.
.. raw:: latex
\normalsize
.. _vp9_frame_flags:
``Frame Flags``
.. tabularcolumns:: |p{10.0cm}|p{1.2cm}|p{6.1cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_VP9_FRAME_FLAG_KEY_FRAME``
- 0x001
- The frame is a key frame.
* - ``V4L2_VP9_FRAME_FLAG_SHOW_FRAME``
- 0x002
- The frame should be displayed.
* - ``V4L2_VP9_FRAME_FLAG_ERROR_RESILIENT``
- 0x004
- The decoding should be error resilient.
* - ``V4L2_VP9_FRAME_FLAG_INTRA_ONLY``
- 0x008
- The frame does not reference other frames.
* - ``V4L2_VP9_FRAME_FLAG_ALLOW_HIGH_PREC_MV``
- 0x010
- The frame can use high precision motion vectors.
* - ``V4L2_VP9_FRAME_FLAG_REFRESH_FRAME_CTX``
- 0x020
- Frame context should be updated after decoding.
* - ``V4L2_VP9_FRAME_FLAG_PARALLEL_DEC_MODE``
- 0x040
- Parallel decoding is used.
* - ``V4L2_VP9_FRAME_FLAG_X_SUBSAMPLING``
- 0x080
- Vertical subsampling is enabled.
* - ``V4L2_VP9_FRAME_FLAG_Y_SUBSAMPLING``
- 0x100
- Horizontal subsampling is enabled.
* - ``V4L2_VP9_FRAME_FLAG_COLOR_RANGE_FULL_SWING``
- 0x200
- The full UV range is used.
.. _vp9_ref_frame_sign_bias:
``Reference Frame Sign Bias``
.. tabularcolumns:: |p{7.0cm}|p{1.2cm}|p{9.1cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_VP9_SIGN_BIAS_LAST``
- 0x1
- Sign bias is set for the last reference frame.
* - ``V4L2_VP9_SIGN_BIAS_GOLDEN``
- 0x2
- Sign bias is set for the golden reference frame.
* - ``V4L2_VP9_SIGN_BIAS_ALT``
- 0x2
- Sign bias is set for the alt reference frame.
.. _vp9_reset_frame_context:
``Reset Frame Context``
.. tabularcolumns:: |p{7.0cm}|p{1.2cm}|p{9.1cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_VP9_RESET_FRAME_CTX_NONE``
- 0
- Do not reset any frame context.
* - ``V4L2_VP9_RESET_FRAME_CTX_SPEC``
- 1
- Reset the frame context pointed to by
:c:type:`v4l2_ctrl_vp9_frame`.frame_context_idx.
* - ``V4L2_VP9_RESET_FRAME_CTX_ALL``
- 2
- Reset all frame contexts.
See section '7.2 Uncompressed header semantics' of the :ref:`vp9` specification
for more details.
.. _vp9_interpolation_filter:
``Interpolation Filter``
.. tabularcolumns:: |p{9.0cm}|p{1.2cm}|p{7.1cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_VP9_INTERP_FILTER_EIGHTTAP``
- 0
- Eight tap filter.
* - ``V4L2_VP9_INTERP_FILTER_EIGHTTAP_SMOOTH``
- 1
- Eight tap smooth filter.
* - ``V4L2_VP9_INTERP_FILTER_EIGHTTAP_SHARP``
- 2
- Eeight tap sharp filter.
* - ``V4L2_VP9_INTERP_FILTER_BILINEAR``
- 3
- Bilinear filter.
* - ``V4L2_VP9_INTERP_FILTER_SWITCHABLE``
- 4
- Filter selection is signaled at the block level.
See section '7.2.7 Interpolation filter semantics' of the :ref:`vp9` specification
for more details.
.. _vp9_reference_mode:
``Reference Mode``
.. tabularcolumns:: |p{9.6cm}|p{0.5cm}|p{7.2cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_VP9_REFERENCE_MODE_SINGLE_REFERENCE``
- 0
- Indicates that all the inter blocks use only a single reference frame
to generate motion compensated prediction.
* - ``V4L2_VP9_REFERENCE_MODE_COMPOUND_REFERENCE``
- 1
- Requires all the inter blocks to use compound mode. Single reference
frame prediction is not allowed.
* - ``V4L2_VP9_REFERENCE_MODE_SELECT``
- 2
- Allows each individual inter block to select between single and
compound prediction modes.
See section '7.3.6 Frame reference mode semantics' of the :ref:`vp9` specification for more details.
.. c:type:: v4l2_vp9_segmentation
Encodes the quantization parameters. See section '7.2.10 Segmentation
params syntax' of the :ref:`vp9` specification for more details.
.. tabularcolumns:: |p{0.8cm}|p{5cm}|p{11.4cm}|
.. cssclass:: longtable
.. flat-table:: struct v4l2_vp9_segmentation
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __u8
- ``feature_data[8][4]``
- Data attached to each feature. Data entry is only valid if the feature
is enabled. The array shall be indexed with segment number as the first dimension
(0..7) and one of V4L2_VP9_SEG_* as the second dimension.
See :ref:`Segment Feature IDs<vp9_segment_feature>`.
* - __u8
- ``feature_enabled[8]``
- Bitmask defining which features are enabled in each segment. The value for each
segment is a combination of V4L2_VP9_SEGMENT_FEATURE_ENABLED(id) values where id is
one of V4L2_VP9_SEG_*. See :ref:`Segment Feature IDs<vp9_segment_feature>`.
* - __u8
- ``tree_probs[7]``
- Specifies the probability values to be used when decoding a Segment-ID.
See '5.15. Segmentation map' section of :ref:`vp9` for more details.
* - __u8
- ``pred_probs[3]``
- Specifies the probability values to be used when decoding a
Predicted-Segment-ID. See '6.4.14. Get segment id syntax'
section of :ref:`vp9` for more details.
* - __u8
- ``flags``
- Combination of V4L2_VP9_SEGMENTATION_FLAG_* flags. See
:ref:`Segmentation Flags<vp9_segmentation_flags>`.
* - __u8
- ``reserved[5]``
- Applications and drivers must set this to zero.
.. _vp9_segment_feature:
``Segment feature IDs``
.. tabularcolumns:: |p{6.0cm}|p{1cm}|p{10.3cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_VP9_SEG_LVL_ALT_Q``
- 0
- Quantizer segment feature.
* - ``V4L2_VP9_SEG_LVL_ALT_L``
- 1
- Loop filter segment feature.
* - ``V4L2_VP9_SEG_LVL_REF_FRAME``
- 2
- Reference frame segment feature.
* - ``V4L2_VP9_SEG_LVL_SKIP``
- 3
- Skip segment feature.
* - ``V4L2_VP9_SEG_LVL_MAX``
- 4
- Number of segment features.
.. _vp9_segmentation_flags:
``Segmentation Flags``
.. tabularcolumns:: |p{10.6cm}|p{0.8cm}|p{5.9cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_VP9_SEGMENTATION_FLAG_ENABLED``
- 0x01
- Indicates that this frame makes use of the segmentation tool.
* - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_MAP``
- 0x02
- Indicates that the segmentation map should be updated during the
decoding of this frame.
* - ``V4L2_VP9_SEGMENTATION_FLAG_TEMPORAL_UPDATE``
- 0x04
- Indicates that the updates to the segmentation map are coded
relative to the existing segmentation map.
* - ``V4L2_VP9_SEGMENTATION_FLAG_UPDATE_DATA``
- 0x08
- Indicates that new parameters are about to be specified for each
segment.
* - ``V4L2_VP9_SEGMENTATION_FLAG_ABS_OR_DELTA_UPDATE``
- 0x10
- Indicates that the segmentation parameters represent the actual values
to be used.
.. c:type:: v4l2_vp9_quantization
Encodes the quantization parameters. See section '7.2.9 Quantization params
syntax' of the VP9 specification for more details.
.. tabularcolumns:: |p{0.8cm}|p{4cm}|p{12.4cm}|
.. cssclass:: longtable
.. flat-table:: struct v4l2_vp9_quantization
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __u8
- ``base_q_idx``
- Indicates the base frame qindex.
* - __s8
- ``delta_q_y_dc``
- Indicates the Y DC quantizer relative to base_q_idx.
* - __s8
- ``delta_q_uv_dc``
- Indicates the UV DC quantizer relative to base_q_idx.
* - __s8
- ``delta_q_uv_ac``
- Indicates the UV AC quantizer relative to base_q_idx.
* - __u8
- ``reserved[4]``
- Applications and drivers must set this to zero.
.. c:type:: v4l2_vp9_loop_filter
This structure contains all loop filter related parameters. See sections
'7.2.8 Loop filter semantics' of the :ref:`vp9` specification for more details.
.. tabularcolumns:: |p{0.8cm}|p{4cm}|p{12.4cm}|
.. cssclass:: longtable
.. flat-table:: struct v4l2_vp9_loop_filter
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - __s8
- ``ref_deltas[4]``
- Contains the adjustment needed for the filter level based on the chosen
reference frame.
* - __s8
- ``mode_deltas[2]``
- Contains the adjustment needed for the filter level based on the chosen
mode.
* - __u8
- ``level``
- Indicates the loop filter strength.
* - __u8
- ``sharpness``
- Indicates the sharpness level.
* - __u8
- ``flags``
- Combination of V4L2_VP9_LOOP_FILTER_FLAG_* flags.
See :ref:`Loop Filter Flags <vp9_loop_filter_flags>`.
* - __u8
- ``reserved[7]``
- Applications and drivers must set this to zero.
.. _vp9_loop_filter_flags:
``Loop Filter Flags``
.. tabularcolumns:: |p{9.6cm}|p{0.5cm}|p{7.2cm}|
.. flat-table::
:header-rows: 0
:stub-columns: 0
:widths: 1 1 2
* - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_ENABLED``
- 0x1
- When set, the filter level depends on the mode and reference frame used
to predict a block.
* - ``V4L2_VP9_LOOP_FILTER_FLAG_DELTA_UPDATE``
- 0x2
- When set, the bitstream contains additional syntax elements that
specify which mode and reference frame deltas are to be updated.

View File

@ -26,7 +26,7 @@ found in V4L2 drivers into a few common RGB and YUY formats.
It currently accepts the following V4L2 driver formats:
:ref:`V4L2_PIX_FMT_BGR24 <V4L2-PIX-FMT-BGR24>`,
:ref:`V4L2_PIX_FMT_HM12 <V4L2-PIX-FMT-HM12>`,
:ref:`V4L2_PIX_FMT_NV12_16L16 <V4L2-PIX-FMT-NV12-16L16>`,
:ref:`V4L2_PIX_FMT_JPEG <V4L2-PIX-FMT-JPEG>`,
:ref:`V4L2_PIX_FMT_MJPEG <V4L2-PIX-FMT-MJPEG>`,
:ref:`V4L2_PIX_FMT_MR97310A <V4L2-PIX-FMT-MR97310A>`,

View File

@ -172,6 +172,21 @@ Compressed Formats
- VP9 compressed video frame. The encoder generates one
compressed frame per buffer, and the decoder requires one
compressed frame per buffer.
* .. _V4L2-PIX-FMT-VP9-FRAME:
- ``V4L2_PIX_FMT_VP9_FRAME``
- 'VP9F'
- VP9 parsed frame, including the frame header, as extracted from the container.
This format is adapted for stateless video decoders that implement a
VP9 pipeline with the :ref:`stateless_decoder`.
Metadata associated with the frame to decode is required to be passed
through the ``V4L2_CID_STATELESS_VP9_FRAME`` and
the ``V4L2_CID_STATELESS_VP9_COMPRESSED_HDR`` controls.
See the :ref:`associated Codec Control IDs <v4l2-codec-stateless-vp9>`.
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.
* .. _V4L2-PIX-FMT-HEVC:
- ``V4L2_PIX_FMT_HEVC``

View File

@ -7833,7 +7833,7 @@ The following table lists existing HSV/HSL formats.
.. raw:: latex
\normalsize
\endgroup
JPEG Compressed Formats

View File

@ -46,7 +46,7 @@ file: media/v4l/v4l2grab.c
} while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
if (r == -1) {
fprintf(stderr, "error %d, %s\\n", errno, strerror(errno));
fprintf(stderr, "error %d, %s\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
}
@ -80,11 +80,11 @@ file: media/v4l/v4l2grab.c
fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
xioctl(fd, VIDIOC_S_FMT, &fmt);
if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) {
printf("Libv4l didn't accept RGB24 format. Can't proceed.\\n");
printf("Libv4l didn't accept RGB24 format. Can't proceed.\n");
exit(EXIT_FAILURE);
}
if ((fmt.fmt.pix.width != 640) || (fmt.fmt.pix.height != 480))
printf("Warning: driver is sending image at %dx%d\\n",
printf("Warning: driver is sending image at %dx%d\n",
fmt.fmt.pix.width, fmt.fmt.pix.height);
CLEAR(req);
@ -151,7 +151,7 @@ file: media/v4l/v4l2grab.c
perror("Cannot open image");
exit(EXIT_FAILURE);
}
fprintf(fout, "P6\\n%d %d 255\\n",
fprintf(fout, "P6\n%d %d 255\n",
fmt.fmt.pix.width, fmt.fmt.pix.height);
fwrite(buffers[buf.index].start, buf.bytesused, 1, fout);
fclose(fout);

View File

@ -233,6 +233,14 @@ still cause this situation.
- ``p_mpeg2_quantisation``
- A pointer to a struct :c:type:`v4l2_ctrl_mpeg2_quantisation`. Valid if this control is
of type ``V4L2_CTRL_TYPE_MPEG2_QUANTISATION``.
* - struct :c:type:`v4l2_ctrl_vp9_compressed_hdr` *
- ``p_vp9_compressed_hdr_probs``
- A pointer to a struct :c:type:`v4l2_ctrl_vp9_compressed_hdr`. Valid if this
control is of type ``V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR``.
* - struct :c:type:`v4l2_ctrl_vp9_frame` *
- ``p_vp9_frame``
- A pointer to a struct :c:type:`v4l2_ctrl_vp9_frame`. Valid if this
control is of type ``V4L2_CTRL_TYPE_VP9_FRAME``.
* - struct :c:type:`v4l2_ctrl_hdr10_cll_info` *
- ``p_hdr10_cll``
- A pointer to a struct :c:type:`v4l2_ctrl_hdr10_cll_info`. Valid if this control is

View File

@ -513,6 +513,18 @@ See also the examples in :ref:`control`.
- n/a
- A struct :c:type:`v4l2_ctrl_hevc_decode_params`, containing HEVC
decoding parameters for stateless video decoders.
* - ``V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR``
- n/a
- n/a
- n/a
- A struct :c:type:`v4l2_ctrl_vp9_compressed_hdr`, containing VP9
probabilities updates for stateless video decoders.
* - ``V4L2_CTRL_TYPE_VP9_FRAME``
- n/a
- n/a
- n/a
- A struct :c:type:`v4l2_ctrl_vp9_frame`, containing VP9
frame decode parameters for stateless video decoders.
.. raw:: latex

View File

@ -149,6 +149,8 @@ replace symbol V4L2_CTRL_TYPE_HEVC_SLICE_PARAMS :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_AREA :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_FWHT_PARAMS :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_VP8_FRAME :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_VP9_COMPRESSED_HDR :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_VP9_FRAME :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_HDR10_CLL_INFO :c:type:`v4l2_ctrl_type`
replace symbol V4L2_CTRL_TYPE_HDR10_MASTERING_DISPLAY :c:type:`v4l2_ctrl_type`

View File

@ -1140,6 +1140,7 @@ ANALOG DEVICES INC ADV748X DRIVER
M: Kieran Bingham <kieran.bingham@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/i2c/adv748x.yaml
F: drivers/media/i2c/adv748x/*
ANALOG DEVICES INC ADV7511 DRIVER
@ -2583,7 +2584,7 @@ N: s3c64xx
N: s5pv210
ARM/SAMSUNG S5P SERIES 2D GRAPHICS ACCELERATION (G2D) SUPPORT
M: Andrzej Hajda <a.hajda@samsung.com>
M: Łukasz Stelmach <l.stelmach@samsung.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-media@vger.kernel.org
S: Maintained
@ -2607,7 +2608,8 @@ S: Maintained
F: drivers/media/platform/s5p-jpeg/
ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
M: Andrzej Hajda <a.hajda@samsung.com>
M: Marek Szyprowski <m.szyprowski@samsung.com>
M: Andrzej Hajda <andrzej.hajda@intel.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-media@vger.kernel.org
S: Maintained
@ -6327,7 +6329,7 @@ F: Documentation/devicetree/bindings/display/atmel/
F: drivers/gpu/drm/atmel-hlcdc/
DRM DRIVERS FOR BRIDGE CHIPS
M: Andrzej Hajda <a.hajda@samsung.com>
M: Andrzej Hajda <andrzej.hajda@intel.com>
M: Neil Armstrong <narmstrong@baylibre.com>
M: Robert Foss <robert.foss@linaro.org>
R: Laurent Pinchart <Laurent.pinchart@ideasonboard.com>
@ -11562,6 +11564,12 @@ S: Maintained
F: Documentation/devicetree/bindings/media/i2c/maxim,max9286.yaml
F: drivers/media/i2c/max9286.c
MAX96712 QUAD GMSL2 DESERIALIZER DRIVER
M: Niklas Söderlund <niklas.soderlund@ragnatech.se>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/staging/media/max96712/max96712.c
MAX9860 MONO AUDIO VOICE CODEC DRIVER
M: Peter Rosin <peda@axentia.se>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
@ -14126,7 +14134,6 @@ F: drivers/media/i2c/ov5647.c
OMNIVISION OV5670 SENSOR DRIVER
M: Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
M: Hyungwoo Yang <hyungwoo.yang@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
@ -14139,6 +14146,13 @@ S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/ov5675.c
OMNIVISION OV5693 SENSOR DRIVER
M: Daniel Scally <djrscally@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/ov5693.c
OMNIVISION OV5695 SENSOR DRIVER
M: Shunqian Zheng <zhengsq@rock-chips.com>
L: linux-media@vger.kernel.org
@ -16866,13 +16880,15 @@ F: Documentation/devicetree/bindings/net/nfc/samsung,s3fwrn5.yaml
F: drivers/nfc/s3fwrn5
SAMSUNG S5C73M3 CAMERA DRIVER
M: Andrzej Hajda <a.hajda@samsung.com>
M: Sylwester Nawrocki <s.nawrocki@samsung.com>
M: Andrzej Hajda <andrzej.hajda@intel.com>
L: linux-media@vger.kernel.org
S: Supported
F: drivers/media/i2c/s5c73m3/*
SAMSUNG S5K5BAF CAMERA DRIVER
M: Andrzej Hajda <a.hajda@samsung.com>
M: Sylwester Nawrocki <s.nawrocki@samsung.com>
M: Andrzej Hajda <andrzej.hajda@intel.com>
L: linux-media@vger.kernel.org
S: Supported
F: drivers/media/i2c/s5k5baf.c

View File

@ -797,6 +797,12 @@ static const char * const acpi_ignore_dep_ids[] = {
NULL
};
/* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */
static const char * const acpi_honor_dep_ids[] = {
"INT3472", /* Camera sensor PMIC / clk and regulator info */
NULL
};
static struct acpi_device *acpi_bus_get_parent(acpi_handle handle)
{
struct acpi_device *device = NULL;
@ -1762,8 +1768,12 @@ static void acpi_scan_dep_init(struct acpi_device *adev)
struct acpi_dep_data *dep;
list_for_each_entry(dep, &acpi_dep_list, node) {
if (dep->consumer == adev->handle)
if (dep->consumer == adev->handle) {
if (dep->honor_dep)
adev->flags.honor_deps = 1;
adev->dep_unmet++;
}
}
}
@ -1967,7 +1977,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
for (count = 0, i = 0; i < dep_devices.count; i++) {
struct acpi_device_info *info;
struct acpi_dep_data *dep;
bool skip;
bool skip, honor_dep;
status = acpi_get_object_info(dep_devices.handles[i], &info);
if (ACPI_FAILURE(status)) {
@ -1976,6 +1986,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
}
skip = acpi_info_matches_ids(info, acpi_ignore_dep_ids);
honor_dep = acpi_info_matches_ids(info, acpi_honor_dep_ids);
kfree(info);
if (skip)
@ -1989,6 +2000,7 @@ static u32 acpi_scan_check_dep(acpi_handle handle, bool check_dep)
dep->supplier = dep_devices.handles[i];
dep->consumer = handle;
dep->honor_dep = honor_dep;
mutex_lock(&acpi_dep_list_lock);
list_add_tail(&dep->node , &acpi_dep_list);
@ -2155,8 +2167,8 @@ static void acpi_bus_attach(struct acpi_device *device, bool first_pass)
register_dock_dependent_device(device, ejd);
acpi_bus_get_status(device);
/* Skip devices that are not present. */
if (!acpi_device_is_present(device)) {
/* Skip devices that are not ready for enumeration (e.g. not present) */
if (!acpi_dev_ready_for_enumeration(device)) {
device->flags.initialized = false;
acpi_device_clear_enumerated(device);
device->flags.power_manageable = 0;
@ -2318,6 +2330,23 @@ void acpi_dev_clear_dependencies(struct acpi_device *supplier)
}
EXPORT_SYMBOL_GPL(acpi_dev_clear_dependencies);
/**
* acpi_dev_ready_for_enumeration - Check if the ACPI device is ready for enumeration
* @device: Pointer to the &struct acpi_device to check
*
* Check if the device is present and has no unmet dependencies.
*
* Return true if the device is ready for enumeratino. Otherwise, return false.
*/
bool acpi_dev_ready_for_enumeration(const struct acpi_device *device)
{
if (device->flags.honor_deps && device->dep_unmet)
return false;
return acpi_device_is_present(device);
}
EXPORT_SYMBOL_GPL(acpi_dev_ready_for_enumeration);
/**
* acpi_dev_get_first_consumer_dev - Return ACPI device dependent on @supplier
* @supplier: Pointer to the dependee device

View File

@ -144,9 +144,12 @@ static int i2c_acpi_do_lookup(struct acpi_device *adev,
struct list_head resource_list;
int ret;
if (acpi_bus_get_status(adev) || !adev->status.present)
if (acpi_bus_get_status(adev))
return -EINVAL;
if (!acpi_dev_ready_for_enumeration(adev))
return -ENODEV;
if (acpi_match_device_ids(adev, i2c_acpi_ignored_device_ids) == 0)
return -ENODEV;
@ -473,8 +476,8 @@ struct notifier_block i2c_acpi_notifier = {
};
/**
* i2c_acpi_new_device - Create i2c-client for the Nth I2cSerialBus resource
* @dev: Device owning the ACPI resources to get the client from
* i2c_acpi_new_device_by_fwnode - Create i2c-client for the Nth I2cSerialBus resource
* @fwnode: fwnode with the ACPI resources to get the client from
* @index: Index of ACPI resource to get
* @info: describes the I2C device; note this is modified (addr gets set)
* Context: can sleep
@ -490,15 +493,20 @@ struct notifier_block i2c_acpi_notifier = {
* Returns a pointer to the new i2c-client, or error pointer in case of failure.
* Specifically, -EPROBE_DEFER is returned if the adapter is not found.
*/
struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
struct i2c_board_info *info)
struct i2c_client *i2c_acpi_new_device_by_fwnode(struct fwnode_handle *fwnode,
int index,
struct i2c_board_info *info)
{
struct acpi_device *adev = ACPI_COMPANION(dev);
struct i2c_acpi_lookup lookup;
struct i2c_adapter *adapter;
struct acpi_device *adev;
LIST_HEAD(resource_list);
int ret;
adev = to_acpi_device_node(fwnode);
if (!adev)
return ERR_PTR(-ENODEV);
memset(&lookup, 0, sizeof(lookup));
lookup.info = info;
lookup.device_handle = acpi_device_handle(adev);
@ -520,7 +528,7 @@ struct i2c_client *i2c_acpi_new_device(struct device *dev, int index,
return i2c_new_client_device(adapter, info);
}
EXPORT_SYMBOL_GPL(i2c_acpi_new_device);
EXPORT_SYMBOL_GPL(i2c_acpi_new_device_by_fwnode);
bool i2c_acpi_waive_d0_probe(struct device *dev)
{

View File

@ -141,10 +141,10 @@ config MEDIA_TEST_SUPPORT
prompt "Test drivers" if MEDIA_SUPPORT_FILTER
default y if !MEDIA_SUPPORT_FILTER
help
Those drivers should not be used on production Kernels, but
can be useful on debug ones. It enables several dummy drivers
that simulate a real hardware. Very useful to test userspace
applications and to validate if the subsystem core is doesn't
These drivers should not be used on production kernels, but
can be useful on debug ones. This option enables several dummy drivers
that simulate real hardware. Very useful to test userspace
applications and to validate if the subsystem core doesn't
have regressions.
Say Y if you want to use some virtual test driver.

View File

@ -161,10 +161,10 @@ static void cec_queue_event(struct cec_adapter *adap,
u64 ts = ktime_get_ns();
struct cec_fh *fh;
mutex_lock(&adap->devnode.lock);
mutex_lock(&adap->devnode.lock_fhs);
list_for_each_entry(fh, &adap->devnode.fhs, list)
cec_queue_event_fh(fh, ev, ts);
mutex_unlock(&adap->devnode.lock);
mutex_unlock(&adap->devnode.lock_fhs);
}
/* Notify userspace that the CEC pin changed state at the given time. */
@ -178,11 +178,12 @@ void cec_queue_pin_cec_event(struct cec_adapter *adap, bool is_high,
};
struct cec_fh *fh;
mutex_lock(&adap->devnode.lock);
list_for_each_entry(fh, &adap->devnode.fhs, list)
mutex_lock(&adap->devnode.lock_fhs);
list_for_each_entry(fh, &adap->devnode.fhs, list) {
if (fh->mode_follower == CEC_MODE_MONITOR_PIN)
cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
mutex_unlock(&adap->devnode.lock);
}
mutex_unlock(&adap->devnode.lock_fhs);
}
EXPORT_SYMBOL_GPL(cec_queue_pin_cec_event);
@ -195,10 +196,10 @@ void cec_queue_pin_hpd_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
};
struct cec_fh *fh;
mutex_lock(&adap->devnode.lock);
mutex_lock(&adap->devnode.lock_fhs);
list_for_each_entry(fh, &adap->devnode.fhs, list)
cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
mutex_unlock(&adap->devnode.lock);
mutex_unlock(&adap->devnode.lock_fhs);
}
EXPORT_SYMBOL_GPL(cec_queue_pin_hpd_event);
@ -211,10 +212,10 @@ void cec_queue_pin_5v_event(struct cec_adapter *adap, bool is_high, ktime_t ts)
};
struct cec_fh *fh;
mutex_lock(&adap->devnode.lock);
mutex_lock(&adap->devnode.lock_fhs);
list_for_each_entry(fh, &adap->devnode.fhs, list)
cec_queue_event_fh(fh, &ev, ktime_to_ns(ts));
mutex_unlock(&adap->devnode.lock);
mutex_unlock(&adap->devnode.lock_fhs);
}
EXPORT_SYMBOL_GPL(cec_queue_pin_5v_event);
@ -286,12 +287,12 @@ static void cec_queue_msg_monitor(struct cec_adapter *adap,
u32 monitor_mode = valid_la ? CEC_MODE_MONITOR :
CEC_MODE_MONITOR_ALL;
mutex_lock(&adap->devnode.lock);
mutex_lock(&adap->devnode.lock_fhs);
list_for_each_entry(fh, &adap->devnode.fhs, list) {
if (fh->mode_follower >= monitor_mode)
cec_queue_msg_fh(fh, msg);
}
mutex_unlock(&adap->devnode.lock);
mutex_unlock(&adap->devnode.lock_fhs);
}
/*
@ -302,12 +303,12 @@ static void cec_queue_msg_followers(struct cec_adapter *adap,
{
struct cec_fh *fh;
mutex_lock(&adap->devnode.lock);
mutex_lock(&adap->devnode.lock_fhs);
list_for_each_entry(fh, &adap->devnode.fhs, list) {
if (fh->mode_follower == CEC_MODE_FOLLOWER)
cec_queue_msg_fh(fh, msg);
}
mutex_unlock(&adap->devnode.lock);
mutex_unlock(&adap->devnode.lock_fhs);
}
/* Notify userspace of an adapter state change. */
@ -342,7 +343,7 @@ static void cec_data_completed(struct cec_data *data)
* Without that we would be referring to a closed filehandle.
*/
if (data->fh)
list_del(&data->xfer_list);
list_del_init(&data->xfer_list);
if (data->blocking) {
/*
@ -898,6 +899,8 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
if (fh)
list_add_tail(&data->xfer_list, &fh->xfer_list);
else
INIT_LIST_HEAD(&data->xfer_list);
list_add_tail(&data->list, &adap->transmit_queue);
adap->transmit_queue_sz++;
@ -923,6 +926,10 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,
/* The transmit completed (possibly with an error) */
*msg = data->msg;
if (WARN_ON(!list_empty(&data->list)))
list_del(&data->list);
if (WARN_ON(!list_empty(&data->xfer_list)))
list_del(&data->xfer_list);
kfree(data);
return 0;
}
@ -1573,6 +1580,7 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
/* Disabling monitor all mode should always succeed */
if (adap->monitor_all_cnt)
WARN_ON(call_op(adap, adap_monitor_all_enable, false));
/* serialize adap_enable */
mutex_lock(&adap->devnode.lock);
if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
WARN_ON(adap->ops->adap_enable(adap, false));
@ -1584,14 +1592,16 @@ void __cec_s_phys_addr(struct cec_adapter *adap, u16 phys_addr, bool block)
return;
}
/* serialize adap_enable */
mutex_lock(&adap->devnode.lock);
adap->last_initiator = 0xff;
adap->transmit_in_progress = false;
if ((adap->needs_hpd || list_empty(&adap->devnode.fhs)) &&
adap->ops->adap_enable(adap, true)) {
mutex_unlock(&adap->devnode.lock);
return;
if (adap->needs_hpd || list_empty(&adap->devnode.fhs)) {
if (adap->ops->adap_enable(adap, true)) {
mutex_unlock(&adap->devnode.lock);
return;
}
}
if (adap->monitor_all_cnt &&

View File

@ -586,6 +586,7 @@ static int cec_open(struct inode *inode, struct file *filp)
return err;
}
/* serialize adap_enable */
mutex_lock(&devnode->lock);
if (list_empty(&devnode->fhs) &&
!adap->needs_hpd &&
@ -624,7 +625,9 @@ static int cec_open(struct inode *inode, struct file *filp)
}
#endif
mutex_lock(&devnode->lock_fhs);
list_add(&fh->list, &devnode->fhs);
mutex_unlock(&devnode->lock_fhs);
mutex_unlock(&devnode->lock);
return 0;
@ -653,8 +656,11 @@ static int cec_release(struct inode *inode, struct file *filp)
cec_monitor_all_cnt_dec(adap);
mutex_unlock(&adap->lock);
/* serialize adap_enable */
mutex_lock(&devnode->lock);
mutex_lock(&devnode->lock_fhs);
list_del(&fh->list);
mutex_unlock(&devnode->lock_fhs);
if (cec_is_registered(adap) && list_empty(&devnode->fhs) &&
!adap->needs_hpd && adap->phys_addr == CEC_PHYS_ADDR_INVALID) {
WARN_ON(adap->ops->adap_enable(adap, false));
@ -669,7 +675,7 @@ static int cec_release(struct inode *inode, struct file *filp)
data->blocking = false;
data->fh = NULL;
list_del(&data->xfer_list);
list_del_init(&data->xfer_list);
}
mutex_unlock(&adap->lock);
while (!list_empty(&fh->msgs)) {

View File

@ -169,8 +169,10 @@ static void cec_devnode_unregister(struct cec_adapter *adap)
devnode->registered = false;
devnode->unregistered = true;
mutex_lock(&devnode->lock_fhs);
list_for_each_entry(fh, &devnode->fhs, list)
wake_up_interruptible(&fh->wait);
mutex_unlock(&devnode->lock_fhs);
mutex_unlock(&devnode->lock);
@ -272,6 +274,7 @@ struct cec_adapter *cec_allocate_adapter(const struct cec_adap_ops *ops,
/* adap->devnode initialization */
INIT_LIST_HEAD(&adap->devnode.fhs);
mutex_init(&adap->devnode.lock_fhs);
mutex_init(&adap->devnode.lock);
adap->kthread = kthread_run(cec_thread_func, adap, "cec-%s", name);

View File

@ -170,7 +170,6 @@ struct cec_pin {
ktime_t ts;
unsigned int wait_usecs;
u16 la_mask;
bool enabled;
bool monitor_all;
bool rx_eom;
bool enable_irq_failed;

View File

@ -1033,6 +1033,7 @@ static int cec_pin_thread_func(void *_adap)
{
struct cec_adapter *adap = _adap;
struct cec_pin *pin = adap->pin;
bool irq_enabled = false;
for (;;) {
wait_event_interruptible(pin->kthread_waitq,
@ -1060,6 +1061,7 @@ static int cec_pin_thread_func(void *_adap)
ns_to_ktime(pin->work_rx_msg.rx_ts));
msg->len = 0;
}
if (pin->work_tx_status) {
unsigned int tx_status = pin->work_tx_status;
@ -1083,27 +1085,39 @@ static int cec_pin_thread_func(void *_adap)
switch (atomic_xchg(&pin->work_irq_change,
CEC_PIN_IRQ_UNCHANGED)) {
case CEC_PIN_IRQ_DISABLE:
pin->ops->disable_irq(adap);
if (irq_enabled) {
pin->ops->disable_irq(adap);
irq_enabled = false;
}
cec_pin_high(pin);
cec_pin_to_idle(pin);
hrtimer_start(&pin->timer, ns_to_ktime(0),
HRTIMER_MODE_REL);
break;
case CEC_PIN_IRQ_ENABLE:
if (irq_enabled)
break;
pin->enable_irq_failed = !pin->ops->enable_irq(adap);
if (pin->enable_irq_failed) {
cec_pin_to_idle(pin);
hrtimer_start(&pin->timer, ns_to_ktime(0),
HRTIMER_MODE_REL);
} else {
irq_enabled = true;
}
break;
default:
break;
}
if (kthread_should_stop())
break;
}
if (pin->ops->disable_irq && irq_enabled)
pin->ops->disable_irq(adap);
hrtimer_cancel(&pin->timer);
cec_pin_read(pin);
cec_pin_to_idle(pin);
pin->state = CEC_ST_OFF;
return 0;
}
@ -1111,7 +1125,6 @@ static int cec_pin_adap_enable(struct cec_adapter *adap, bool enable)
{
struct cec_pin *pin = adap->pin;
pin->enabled = enable;
if (enable) {
atomic_set(&pin->work_pin_num_events, 0);
pin->work_pin_events_rd = pin->work_pin_events_wr = 0;
@ -1130,13 +1143,7 @@ static int cec_pin_adap_enable(struct cec_adapter *adap, bool enable)
hrtimer_start(&pin->timer, ns_to_ktime(0),
HRTIMER_MODE_REL);
} else {
if (pin->ops->disable_irq)
pin->ops->disable_irq(adap);
hrtimer_cancel(&pin->timer);
kthread_stop(pin->kthread);
cec_pin_read(pin);
cec_pin_to_idle(pin);
pin->state = CEC_ST_OFF;
}
return 0;
}
@ -1157,11 +1164,8 @@ void cec_pin_start_timer(struct cec_pin *pin)
if (pin->state != CEC_ST_RX_IRQ)
return;
atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_UNCHANGED);
pin->ops->disable_irq(pin->adap);
cec_pin_high(pin);
cec_pin_to_idle(pin);
hrtimer_start(&pin->timer, ns_to_ktime(0), HRTIMER_MODE_REL);
atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_DISABLE);
wake_up_interruptible(&pin->kthread_waitq);
}
static int cec_pin_adap_transmit(struct cec_adapter *adap, u8 attempts,

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* Linux driver for digital TV devices equipped with B2C2 FlexcopII(b)/III
* flexcop.c - main module part
@ -15,16 +16,6 @@
* Uwe Bugla, uwe.bugla at gmx.de (doing tests, restyling code, writing docu)
* Niklas Peinecke, peinecke at gdv.uni-hannover.de (hardware pid/mac
* filtering)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "flexcop.h"

View File

@ -487,6 +487,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
if (hdl->error) {
err = hdl->error;
v4l2_ctrl_handler_free(hdl);
v4l2_device_unregister(&dev->v4l2_dev);
return err;
}
dev->v4l2_dev.ctrl_handler = hdl;
@ -495,6 +496,7 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
if (vv == NULL) {
ERR("out of memory. aborting.\n");
v4l2_ctrl_handler_free(hdl);
v4l2_device_unregister(&dev->v4l2_dev);
return -ENOMEM;
}
ext_vv->vid_ops = saa7146_video_ioctl_ops;
@ -521,7 +523,8 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
ERR("out of memory. aborting.\n");
kfree(vv);
v4l2_ctrl_handler_free(hdl);
return -1;
v4l2_device_unregister(&dev->v4l2_dev);
return -ENOMEM;
}
saa7146_video_uops.init(dev,vv);

View File

@ -37,6 +37,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
{
struct mm_struct *mm = current->mm;
struct vm_area_struct *vma;
int ret_pin_user_pages_fast = 0;
int ret = 0;
int err;
@ -56,6 +57,7 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
vec->is_pfns = false;
goto out_unlocked;
}
ret_pin_user_pages_fast = ret;
mmap_read_lock(mm);
vec->got_ref = false;
@ -71,7 +73,18 @@ int get_vaddr_frames(unsigned long start, unsigned int nr_frames,
while (ret < nr_frames && start + PAGE_SIZE <= vma->vm_end) {
err = follow_pfn(vma, start, &nums[ret]);
if (err) {
if (ret == 0)
if (ret)
goto out;
// If follow_pfn() returns -EINVAL, then this
// is not an IO mapping or a raw PFN mapping.
// In that case, return the original error from
// pin_user_pages_fast(). Otherwise this
// function would return -EINVAL when
// pin_user_pages_fast() returned -ENOMEM,
// which makes debugging hard.
if (err == -EINVAL && ret_pin_user_pages_fast)
ret = ret_pin_user_pages_fast;
else
ret = err;
goto out;
}

View File

@ -257,7 +257,7 @@ static void *vb2_dc_alloc(struct vb2_buffer *vb,
ret = vb2_dc_alloc_coherent(buf);
if (ret) {
dev_err(dev, "dma alloc of size %ld failed\n", size);
dev_err(dev, "dma alloc of size %lu failed\n", size);
kfree(buf);
return ERR_PTR(-ENOMEM);
}
@ -298,9 +298,9 @@ static int vb2_dc_mmap(void *buf_priv, struct vm_area_struct *vma)
vma->vm_ops->open(vma);
pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %ld\n",
__func__, (unsigned long)buf->dma_addr, vma->vm_start,
buf->size);
pr_debug("%s: mapped dma addr 0x%08lx at 0x%08lx, size %lu\n",
__func__, (unsigned long)buf->dma_addr, vma->vm_start,
buf->size);
return 0;
}

View File

@ -1,19 +1,9 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* dmxdev.c - DVB demultiplexer device
*
* Copyright (C) 2000 Ralph Metzler & Marcus Metzler
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#define pr_fmt(fmt) "dmxdev: " fmt
@ -1413,7 +1403,7 @@ static const struct dvb_device dvbdev_dvr = {
};
int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
{
int i;
int i, ret;
if (dmxdev->demux->open(dmxdev->demux) < 0)
return -EUSERS;
@ -1432,14 +1422,26 @@ int dvb_dmxdev_init(struct dmxdev *dmxdev, struct dvb_adapter *dvb_adapter)
DMXDEV_STATE_FREE);
}
dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
ret = dvb_register_device(dvb_adapter, &dmxdev->dvbdev, &dvbdev_demux, dmxdev,
DVB_DEVICE_DEMUX, dmxdev->filternum);
dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
if (ret < 0)
goto err_register_dvbdev;
ret = dvb_register_device(dvb_adapter, &dmxdev->dvr_dvbdev, &dvbdev_dvr,
dmxdev, DVB_DEVICE_DVR, dmxdev->filternum);
if (ret < 0)
goto err_register_dvr_dvbdev;
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
return 0;
err_register_dvr_dvbdev:
dvb_unregister_device(dmxdev->dvbdev);
err_register_dvbdev:
vfree(dmxdev->filter);
dmxdev->filter = NULL;
return ret;
}
EXPORT_SYMBOL(dvb_dmxdev_init);

View File

@ -1,20 +1,10 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* dvb_demux.c - DVB kernel demux API
*
* Copyright (C) 2000-2001 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#define pr_fmt(fmt) "dvb_demux: " fmt

View File

@ -2554,8 +2554,7 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_DISEQC_SEND_BURST:
if (fe->ops.diseqc_send_burst) {
err = fe->ops.diseqc_send_burst(fe,
(enum fe_sec_mini_cmd)parg);
err = fe->ops.diseqc_send_burst(fe, (long)parg);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
@ -2563,9 +2562,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_SET_TONE:
if (fe->ops.set_tone) {
err = fe->ops.set_tone(fe,
(enum fe_sec_tone_mode)parg);
fepriv->tone = (enum fe_sec_tone_mode)parg;
fepriv->tone = (long)parg;
err = fe->ops.set_tone(fe, fepriv->tone);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
@ -2573,9 +2571,8 @@ static int dvb_frontend_handle_ioctl(struct file *file,
case FE_SET_VOLTAGE:
if (fe->ops.set_voltage) {
err = fe->ops.set_voltage(fe,
(enum fe_sec_voltage)parg);
fepriv->voltage = (enum fe_sec_voltage)parg;
fepriv->voltage = (long)parg;
err = fe->ops.set_voltage(fe, fepriv->voltage);
fepriv->state = FESTATE_DISEQC;
fepriv->status = 0;
}
@ -2935,7 +2932,9 @@ int dvb_frontend_suspend(struct dvb_frontend *fe)
else if (fe->ops.tuner_ops.sleep)
ret = fe->ops.tuner_ops.sleep(fe);
if (fe->ops.sleep)
if (fe->ops.suspend)
ret = fe->ops.suspend(fe);
else if (fe->ops.sleep)
ret = fe->ops.sleep(fe);
return ret;
@ -2951,7 +2950,9 @@ int dvb_frontend_resume(struct dvb_frontend *fe)
fe->id);
fe->exit = DVB_FE_DEVICE_RESUME;
if (fe->ops.init)
if (fe->ops.resume)
ret = fe->ops.resume(fe);
else if (fe->ops.init)
ret = fe->ops.init(fe);
if (fe->ops.tuner_ops.resume)

View File

@ -5,10 +5,6 @@
* Copyright (C) 2015 Samsung Electronics
*
* Author: jh1009.sung@samsung.com
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation.
*/
#include <linux/err.h>

View File

@ -1,20 +1,10 @@
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* dvbdev.c
*
* Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
* & Marcus Metzler <marcus@convergence.de>
* for convergence integrated media GmbH
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#define pr_fmt(fmt) "dvbdev: " fmt

View File

@ -378,7 +378,7 @@ static void cx24113_set_nfr(struct cx24113_state *state, u16 n, s32 f, u8 r)
static int cx24113_set_frequency(struct cx24113_state *state, u32 frequency)
{
u8 r = 1; /* or 2 */
u8 r;
u16 n = 6;
s32 f = 0;

View File

@ -4473,8 +4473,10 @@ static struct dvb_frontend *dib8000_init(struct i2c_adapter *i2c_adap, u8 i2c_ad
state->timf_default = cfg->pll->timf;
if (dib8000_identify(&state->i2c) == 0)
if (dib8000_identify(&state->i2c) == 0) {
kfree(fe);
goto error;
}
dibx000_init_i2c_master(&state->i2c_master, DIB8000, state->i2c.adap, state->i2c.addr);

View File

@ -258,7 +258,7 @@ static int dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 *b, u32
state->i2c_write_buffer[0] |= (1 << 4);
do {
l = len < chunk_size ? len : chunk_size;
l = min(len, chunk_size);
state->msg[1].len = l;
state->msg[1].buf = b;
ret = i2c_transfer(state->i2c.i2c_adap, state->msg, 2) != 2 ? -EREMOTEIO : 0;
@ -342,7 +342,7 @@ static int dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 *
state->i2c_write_buffer[0] |= (1 << 4);
do {
l = len < chunk_size ? len : chunk_size;
l = min(len, chunk_size);
state->msg[0].len = l + 2;
memcpy(&state->i2c_write_buffer[2], buf, l);

View File

@ -914,44 +914,36 @@ static int DownloadMicrocode(struct drxd_state *state,
u32 Address;
u16 nBlocks;
u16 BlockSize;
u32 offset = 0;
int i, status = 0;
pSrc = (u8 *) pMCImage;
/* We're not using Flags */
/* Flags = (pSrc[0] << 8) | pSrc[1]; */
pSrc += sizeof(u16);
offset += sizeof(u16);
nBlocks = (pSrc[0] << 8) | pSrc[1];
pSrc += sizeof(u16);
offset += sizeof(u16);
for (i = 0; i < nBlocks; i++) {
Address = (pSrc[0] << 24) | (pSrc[1] << 16) |
(pSrc[2] << 8) | pSrc[3];
pSrc += sizeof(u32);
offset += sizeof(u32);
BlockSize = ((pSrc[0] << 8) | pSrc[1]) * sizeof(u16);
pSrc += sizeof(u16);
offset += sizeof(u16);
/* We're not using Flags */
/* u16 Flags = (pSrc[0] << 8) | pSrc[1]; */
pSrc += sizeof(u16);
offset += sizeof(u16);
/* We're not using BlockCRC */
/* u16 BlockCRC = (pSrc[0] << 8) | pSrc[1]; */
pSrc += sizeof(u16);
offset += sizeof(u16);
status = WriteBlock(state, Address, BlockSize,
pSrc, DRX_I2C_CLEARCRC);
if (status < 0)
break;
pSrc += BlockSize;
offset += BlockSize;
}
return status;

View File

@ -3720,7 +3720,6 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
{
u16 cmd_result = 0;
u16 transmission_params = 0;
u16 operation_mode = 0;
u32 iqm_rc_rate_ofs = 0;
u32 bandwidth = 0;
u16 param1;
@ -3759,10 +3758,8 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
/* mode */
switch (state->props.transmission_mode) {
case TRANSMISSION_MODE_AUTO:
default:
operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_MODE__M;
fallthrough; /* try first guess DRX_FFTMODE_8K */
case TRANSMISSION_MODE_8K:
default:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_MODE_8K;
break;
case TRANSMISSION_MODE_2K:
@ -3773,9 +3770,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
/* guard */
switch (state->props.guard_interval) {
default:
case GUARD_INTERVAL_AUTO:
operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_GUARD__M;
fallthrough; /* try first guess DRX_GUARD_1DIV4 */
case GUARD_INTERVAL_AUTO: /* try first guess DRX_GUARD_1DIV4 */
case GUARD_INTERVAL_1_4:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_GUARD_4;
break;
@ -3794,11 +3789,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
switch (state->props.hierarchy) {
case HIERARCHY_AUTO:
case HIERARCHY_NONE:
default:
operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_HIER__M;
/* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
/* transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_NO; */
fallthrough;
default: /* try first guess SC_RA_RAM_OP_PARAM_HIER_NO */
case HIERARCHY_1:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_HIER_A1;
break;
@ -3814,9 +3805,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
/* modulation */
switch (state->props.modulation) {
case QAM_AUTO:
default:
operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_CONST__M;
fallthrough; /* try first guess DRX_CONSTELLATION_QAM64 */
default: /* try first guess DRX_CONSTELLATION_QAM64 */
case QAM_64:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_CONST_QAM64;
break;
@ -3857,9 +3846,7 @@ static int set_dvbt(struct drxk_state *state, u16 intermediate_freqk_hz,
/* coderate */
switch (state->props.code_rate_HP) {
case FEC_AUTO:
default:
operation_mode |= OFDM_SC_RA_RAM_OP_AUTO_RATE__M;
fallthrough; /* try first guess DRX_CODERATE_2DIV3 */
default: /* try first guess DRX_CODERATE_2DIV3 */
case FEC_2_3:
transmission_params |= OFDM_SC_RA_RAM_OP_PARAM_RATE_2_3;
break;

View File

@ -451,7 +451,7 @@ static int m88ds3103b_select_mclk(struct m88ds3103_dev *dev)
static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz)
{
u8 reg11 = 0x0A, reg15, reg16, reg1D, reg1E, reg1F, tmp;
u8 reg15, reg16, reg1D, reg1E, reg1F, tmp;
u8 sm, f0 = 0, f1 = 0, f2 = 0, f3 = 0;
u16 pll_div_fb, N;
u32 div;
@ -480,8 +480,6 @@ static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz)
div /= mclk_khz;
if (dev->cfg->ts_mode == M88DS3103_TS_SERIAL) {
reg11 |= 0x02;
if (div <= 32) {
N = 2;
@ -532,8 +530,6 @@ static int m88ds3103b_set_mclk(struct m88ds3103_dev *dev, u32 mclk_khz)
else if ((f3 < 8) && (f3 != 0))
f3 = 8;
} else {
reg11 &= ~0x02;
if (div <= 32) {
N = 2;

View File

@ -150,7 +150,7 @@ static struct vsb_snr_tab {
{ 0x35b, 235, },
{ 0x353, 230, },
{ 0x349, 225, },
{ 0x340, 320, },
{ 0x340, 220, },
{ 0x337, 215, },
{ 0x327, 210, },
{ 0x31b, 205, },

View File

@ -448,23 +448,10 @@ static int si2168_init(struct dvb_frontend *fe)
/* request the firmware, this will block and timeout */
ret = request_firmware(&fw, dev->firmware_name, &client->dev);
if (ret) {
/* fallback mechanism to handle old name for Si2168 B40 fw */
if (dev->chip_id == SI2168_CHIP_ID_B40) {
dev->firmware_name = SI2168_B40_FIRMWARE_FALLBACK;
ret = request_firmware(&fw, dev->firmware_name,
&client->dev);
}
if (ret == 0) {
dev_notice(&client->dev,
"please install firmware file '%s'\n",
SI2168_B40_FIRMWARE);
} else {
dev_err(&client->dev,
"firmware file '%s' not found\n",
dev->firmware_name);
goto err_release_firmware;
}
dev_err(&client->dev,
"firmware file '%s' not found\n",
dev->firmware_name);
goto err_release_firmware;
}
dev_info(&client->dev, "downloading firmware from file '%s'\n",
@ -527,6 +514,7 @@ static int si2168_init(struct dvb_frontend *fe)
goto err;
dev->warm = true;
dev->initialized = true;
warm:
/* Init stats here to indicate which stats are supported */
c->cnr.len = 1;
@ -548,6 +536,26 @@ err:
return ret;
}
static int si2168_resume(struct dvb_frontend *fe)
{
struct i2c_client *client = fe->demodulator_priv;
struct si2168_dev *dev = i2c_get_clientdata(client);
/*
* check whether si2168_init() has been called successfully
* outside of a resume cycle. Only call it (and load firmware)
* in this case. si2168_init() is only called during resume
* once the device has actually been used. Otherwise, leave the
* device untouched.
*/
if (dev->initialized) {
dev_dbg(&client->dev, "previously initialized, call si2168_init()\n");
return si2168_init(fe);
}
dev_dbg(&client->dev, "not initialized yet, skipping init on resume\n");
return 0;
}
static int si2168_sleep(struct dvb_frontend *fe)
{
struct i2c_client *client = fe->demodulator_priv;
@ -657,6 +665,7 @@ static const struct dvb_frontend_ops si2168_ops = {
.init = si2168_init,
.sleep = si2168_sleep,
.resume = si2168_resume,
.set_frontend = si2168_set_frontend,

View File

@ -18,7 +18,6 @@
#define SI2168_A30_FIRMWARE "dvb-demod-si2168-a30-01.fw"
#define SI2168_B40_FIRMWARE "dvb-demod-si2168-b40-01.fw"
#define SI2168_D60_FIRMWARE "dvb-demod-si2168-d60-01.fw"
#define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw"
/* state struct */
struct si2168_dev {
@ -37,6 +36,7 @@ struct si2168_dev {
u8 ts_mode;
unsigned int active:1;
unsigned int warm:1;
unsigned int initialized:1;
unsigned int ts_clock_inv:1;
unsigned int ts_clock_gapped:1;
unsigned int spectral_inversion:1;

View File

@ -711,7 +711,7 @@ static int si21xx_set_frontend(struct dvb_frontend *fe)
int i;
bool inband_interferer_div2[ALLOWABLE_FS_COUNT];
bool inband_interferer_div4[ALLOWABLE_FS_COUNT];
int status;
int status = 0;
/* allowable sample rates for ADC in MHz */
int afs[ALLOWABLE_FS_COUNT] = { 200, 192, 193, 194, 195,
@ -747,8 +747,6 @@ static int si21xx_set_frontend(struct dvb_frontend *fe)
rf_freq = 10 * c->frequency ;
data_rate = c->symbol_rate / 100;
status = PASS;
band_low = (rf_freq - lnb_lo) - ((lnb_uncertanity * 200)
+ (data_rate * 135)) / 200;
@ -832,6 +830,9 @@ static int si21xx_set_frontend(struct dvb_frontend *fe)
state->fs = sample_rate;/*ADC MHz*/
si21xx_setacquire(fe, c->symbol_rate, c->fec_inner);
if (status)
return -EREMOTEIO;
return 0;
}

View File

@ -140,7 +140,7 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
u8 buf [BLOCKSIZE + 2];
int i;
int fw_size = fw->size;
const unsigned char *mem = fw->data;
const unsigned char *mem = fw->data + 10;
dprintk("%s\n", __func__);
@ -148,8 +148,6 @@ static int sp887x_initial_setup (struct dvb_frontend* fe, const struct firmware
if (fw_size < FW_SIZE + 10)
return -ENODEV;
mem = fw->data + 10;
/* soft reset */
sp887x_writereg(state, 0xf1a, 0x000);

View File

@ -110,7 +110,7 @@ static const struct stb6100_regmask stb6100_template[] = {
/*
* Currently unused. Some boards might need it in the future
*/
static inline void stb6100_normalise_regs(u8 regs[])
static __always_unused inline void stb6100_normalise_regs(u8 regs[])
{
int i;

View File

@ -1797,11 +1797,7 @@ static u32 stv0367cab_get_mclk(struct dvb_frontend *fe, u32 ExtClk_Hz)
static u32 stv0367cab_get_adc_freq(struct dvb_frontend *fe, u32 ExtClk_Hz)
{
u32 ADCClk_Hz = ExtClk_Hz;
ADCClk_Hz = stv0367cab_get_mclk(fe, ExtClk_Hz);
return ADCClk_Hz;
return stv0367cab_get_mclk(fe, ExtClk_Hz);
}
static enum stv0367cab_mod stv0367cab_SetQamSize(struct stv0367_state *state,

View File

@ -469,6 +469,7 @@ config VIDEO_VPX3220
config VIDEO_MAX9286
tristate "Maxim MAX9286 GMSL deserializer support"
depends on I2C && I2C_MUX
depends on VIDEO_V4L2
depends on OF_GPIO
select V4L2_FWNODE
select VIDEO_V4L2_SUBDEV_API
@ -1058,6 +1059,17 @@ config VIDEO_OV5675
To compile this driver as a module, choose M here: the
module will be called ov5675.
config VIDEO_OV5693
tristate "OmniVision OV5693 sensor support"
depends on I2C && VIDEO_V4L2
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV5693 camera.
To compile this driver as a module, choose M here: the
module will be called ov5693.
config VIDEO_OV5695
tristate "OmniVision OV5695 sensor support"
depends on I2C && VIDEO_V4L2

View File

@ -75,6 +75,7 @@ obj-$(CONFIG_VIDEO_OV5647) += ov5647.o
obj-$(CONFIG_VIDEO_OV5648) += ov5648.o
obj-$(CONFIG_VIDEO_OV5670) += ov5670.o
obj-$(CONFIG_VIDEO_OV5675) += ov5675.o
obj-$(CONFIG_VIDEO_OV5693) += ov5693.o
obj-$(CONFIG_VIDEO_OV5695) += ov5695.o
obj-$(CONFIG_VIDEO_OV6650) += ov6650.o
obj-$(CONFIG_VIDEO_OV7251) += ov7251.o

View File

@ -270,28 +270,6 @@ static int adv7511_pktmem_rd(struct v4l2_subdev *sd, u8 reg)
return adv_smbus_read_byte_data(state->i2c_pktmem, reg);
}
static int adv7511_pktmem_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv7511_state *state = get_adv7511_state(sd);
int ret;
int i;
for (i = 0; i < 3; i++) {
ret = i2c_smbus_write_byte_data(state->i2c_pktmem, reg, val);
if (ret == 0)
return 0;
}
v4l2_err(sd, "%s: i2c write error\n", __func__);
return ret;
}
/* To set specific bits in the register, a clear-mask is given (to be AND-ed),
and then the value-mask (to be OR-ed). */
static inline void adv7511_pktmem_wr_and_or(struct v4l2_subdev *sd, u8 reg, u8 clr_mask, u8 val_mask)
{
adv7511_pktmem_wr(sd, reg, (adv7511_pktmem_rd(sd, reg) & clr_mask) | val_mask);
}
static inline bool adv7511_have_hotplug(struct v4l2_subdev *sd)
{
return adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT;

View File

@ -398,14 +398,14 @@ static inline int io_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask,
return io_write(sd, reg, (io_read(sd, reg) & ~mask) | val);
}
static inline int avlink_read(struct v4l2_subdev *sd, u8 reg)
static inline int __always_unused avlink_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv76xx_state *state = to_state(sd);
return adv76xx_read_check(state, ADV7604_PAGE_AVLINK, reg);
}
static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val)
static inline int __always_unused avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv76xx_state *state = to_state(sd);
@ -439,14 +439,14 @@ static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
return adv76xx_read_check(state, ADV76XX_PAGE_INFOFRAME, reg);
}
static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
static inline int __always_unused infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv76xx_state *state = to_state(sd);
return regmap_write(state->regmap[ADV76XX_PAGE_INFOFRAME], reg, val);
}
static inline int afe_read(struct v4l2_subdev *sd, u8 reg)
static inline int __always_unused afe_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv76xx_state *state = to_state(sd);
@ -479,14 +479,14 @@ static inline int rep_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8
return rep_write(sd, reg, (rep_read(sd, reg) & ~mask) | val);
}
static inline int edid_read(struct v4l2_subdev *sd, u8 reg)
static inline int __always_unused edid_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv76xx_state *state = to_state(sd);
return adv76xx_read_check(state, ADV76XX_PAGE_EDID, reg);
}
static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
static inline int __always_unused edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv76xx_state *state = to_state(sd);
@ -570,7 +570,7 @@ static inline int hdmi_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8
return hdmi_write(sd, reg, (hdmi_read(sd, reg) & ~mask) | val);
}
static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
static inline int __always_unused test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv76xx_state *state = to_state(sd);
@ -601,14 +601,14 @@ static inline int cp_write_clr_set(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 v
return cp_write(sd, reg, (cp_read(sd, reg) & ~mask) | val);
}
static inline int vdp_read(struct v4l2_subdev *sd, u8 reg)
static inline int __always_unused vdp_read(struct v4l2_subdev *sd, u8 reg)
{
struct adv76xx_state *state = to_state(sd);
return adv76xx_read_check(state, ADV7604_PAGE_VDP, reg);
}
static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
static inline int __always_unused vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{
struct adv76xx_state *state = to_state(sd);

View File

@ -256,21 +256,11 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
return &container_of(ctrl->handler, struct adv7842_state, hdl)->sd;
}
static inline unsigned hblanking(const struct v4l2_bt_timings *t)
{
return V4L2_DV_BT_BLANKING_WIDTH(t);
}
static inline unsigned htotal(const struct v4l2_bt_timings *t)
{
return V4L2_DV_BT_FRAME_WIDTH(t);
}
static inline unsigned vblanking(const struct v4l2_bt_timings *t)
{
return V4L2_DV_BT_BLANKING_HEIGHT(t);
}
static inline unsigned vtotal(const struct v4l2_bt_timings *t)
{
return V4L2_DV_BT_FRAME_HEIGHT(t);

View File

@ -2758,13 +2758,13 @@ ident_show(struct device *dev, struct device_attribute *attr, char *buf)
struct ccs_module_info *minfo = &sensor->minfo;
if (minfo->mipi_manufacturer_id)
return snprintf(buf, PAGE_SIZE, "%4.4x%4.4x%2.2x\n",
minfo->mipi_manufacturer_id, minfo->model_id,
minfo->revision_number) + 1;
return sysfs_emit(buf, "%4.4x%4.4x%2.2x\n",
minfo->mipi_manufacturer_id, minfo->model_id,
minfo->revision_number) + 1;
else
return snprintf(buf, PAGE_SIZE, "%2.2x%4.4x%2.2x\n",
minfo->smia_manufacturer_id, minfo->model_id,
minfo->revision_number) + 1;
return sysfs_emit(buf, "%2.2x%4.4x%2.2x\n",
minfo->smia_manufacturer_id, minfo->model_id,
minfo->revision_number) + 1;
}
static DEVICE_ATTR_RO(ident);

View File

@ -136,19 +136,6 @@ static inline u16 count_to_clock_divider(unsigned int d)
return (u16) d;
}
static inline u16 ns_to_clock_divider(unsigned int ns)
{
return count_to_clock_divider(
DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ / 1000000 * ns, 1000));
}
static inline unsigned int clock_divider_to_ns(unsigned int divider)
{
/* Period of the Rx or Tx clock in ns */
return DIV_ROUND_CLOSEST((divider + 1) * 1000,
CX25840_IR_REFCLK_FREQ / 1000000);
}
static inline u16 carrier_freq_to_clock_divider(unsigned int freq)
{
return count_to_clock_divider(
@ -160,13 +147,6 @@ static inline unsigned int clock_divider_to_carrier_freq(unsigned int divider)
return DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, (divider + 1) * 16);
}
static inline u16 freq_to_clock_divider(unsigned int freq,
unsigned int rollovers)
{
return count_to_clock_divider(
DIV_ROUND_CLOSEST(CX25840_IR_REFCLK_FREQ, freq * rollovers));
}
static inline unsigned int clock_divider_to_freq(unsigned int divider,
unsigned int rollovers)
{

View File

@ -469,6 +469,11 @@ static int dw9768_probe(struct i2c_client *client)
dw9768->sd.entity.function = MEDIA_ENT_F_LENS;
/*
* Device is already turned on by i2c-core with ACPI domain PM.
* Attempt to turn off the device to satisfy the privacy LED concerns.
*/
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
if (!pm_runtime_enabled(dev)) {
ret = dw9768_runtime_resume(dev);
@ -483,6 +488,7 @@ static int dw9768_probe(struct i2c_client *client)
dev_err(dev, "failed to register V4L2 subdev: %d", ret);
goto err_power_off;
}
pm_runtime_idle(dev);
return 0;

View File

@ -495,6 +495,9 @@ struct hi556 {
/* Streaming on/off */
bool streaming;
/* True if the device has been identified */
bool identified;
};
static u64 to_pixel_rate(u32 f_index)
@ -757,12 +760,41 @@ static void hi556_assign_pad_format(const struct hi556_mode *mode,
fmt->field = V4L2_FIELD_NONE;
}
static int hi556_identify_module(struct hi556 *hi556)
{
struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd);
int ret;
u32 val;
if (hi556->identified)
return 0;
ret = hi556_read_reg(hi556, HI556_REG_CHIP_ID,
HI556_REG_VALUE_16BIT, &val);
if (ret)
return ret;
if (val != HI556_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x",
HI556_CHIP_ID, val);
return -ENXIO;
}
hi556->identified = true;
return 0;
}
static int hi556_start_streaming(struct hi556 *hi556)
{
struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd);
const struct hi556_reg_list *reg_list;
int link_freq_index, ret;
ret = hi556_identify_module(hi556);
if (ret)
return ret;
link_freq_index = hi556->cur_mode->link_freq_index;
reg_list = &link_freq_configs[link_freq_index].reg_list;
ret = hi556_write_reg_list(hi556, reg_list);
@ -1001,26 +1033,6 @@ static const struct v4l2_subdev_internal_ops hi556_internal_ops = {
.open = hi556_open,
};
static int hi556_identify_module(struct hi556 *hi556)
{
struct i2c_client *client = v4l2_get_subdevdata(&hi556->sd);
int ret;
u32 val;
ret = hi556_read_reg(hi556, HI556_REG_CHIP_ID,
HI556_REG_VALUE_16BIT, &val);
if (ret)
return ret;
if (val != HI556_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x",
HI556_CHIP_ID, val);
return -ENXIO;
}
return 0;
}
static int hi556_check_hwcfg(struct device *dev)
{
struct fwnode_handle *ep;
@ -1106,6 +1118,7 @@ static int hi556_remove(struct i2c_client *client)
static int hi556_probe(struct i2c_client *client)
{
struct hi556 *hi556;
bool full_power;
int ret;
ret = hi556_check_hwcfg(&client->dev);
@ -1120,10 +1133,14 @@ static int hi556_probe(struct i2c_client *client)
return -ENOMEM;
v4l2_i2c_subdev_init(&hi556->sd, client, &hi556_subdev_ops);
ret = hi556_identify_module(hi556);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
return ret;
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
ret = hi556_identify_module(hi556);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
return ret;
}
}
mutex_init(&hi556->mutex);
@ -1152,7 +1169,9 @@ static int hi556_probe(struct i2c_client *client)
goto probe_error_media_entity_cleanup;
}
pm_runtime_set_active(&client->dev);
/* Set the device's state to active if it's in D0 state. */
if (full_power)
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
pm_runtime_idle(&client->dev);
@ -1189,6 +1208,7 @@ static struct i2c_driver hi556_i2c_driver = {
},
.probe_new = hi556_probe,
.remove = hi556_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
module_i2c_driver(hi556_i2c_driver);

View File

@ -1656,7 +1656,7 @@ err_reg:
return ret;
}
static void hi846_power_off(struct hi846 *hi846)
static int hi846_power_off(struct hi846 *hi846)
{
if (hi846->rst_gpio)
gpiod_set_value_cansleep(hi846->rst_gpio, 1);
@ -1665,7 +1665,7 @@ static void hi846_power_off(struct hi846 *hi846)
gpiod_set_value_cansleep(hi846->shutdown_gpio, 1);
clk_disable_unprepare(hi846->clock);
regulator_bulk_disable(HI846_NUM_SUPPLIES, hi846->supplies);
return regulator_bulk_disable(HI846_NUM_SUPPLIES, hi846->supplies);
}
static int __maybe_unused hi846_suspend(struct device *dev)
@ -1677,9 +1677,7 @@ static int __maybe_unused hi846_suspend(struct device *dev)
if (hi846->streaming)
hi846_stop_streaming(hi846);
hi846_power_off(hi846);
return 0;
return hi846_power_off(hi846);
}
static int __maybe_unused hi846_resume(struct device *dev)
@ -2164,7 +2162,11 @@ static int hi846_remove(struct i2c_client *client)
return 0;
}
static UNIVERSAL_DEV_PM_OPS(hi846_pm_ops, hi846_suspend, hi846_resume, NULL);
static const struct dev_pm_ops hi846_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(hi846_suspend, hi846_resume, NULL)
};
static const struct of_device_id hi846_of_match[] = {
{ .compatible = "hynix,hi846", },

View File

@ -296,6 +296,9 @@ struct imx208 {
/* OTP data */
bool otp_read;
char otp_data[IMX208_OTP_SIZE];
/* True if the device has been identified */
bool identified;
};
static inline struct imx208 *to_imx208(struct v4l2_subdev *_sd)
@ -619,6 +622,34 @@ static int imx208_set_pad_format(struct v4l2_subdev *sd,
return 0;
}
static int imx208_identify_module(struct imx208 *imx208)
{
struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
int ret;
u32 val;
if (imx208->identified)
return 0;
ret = imx208_read_reg(imx208, IMX208_REG_CHIP_ID,
2, &val);
if (ret) {
dev_err(&client->dev, "failed to read chip id %x\n",
IMX208_CHIP_ID);
return ret;
}
if (val != IMX208_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
IMX208_CHIP_ID, val);
return -EIO;
}
imx208->identified = true;
return 0;
}
/* Start streaming */
static int imx208_start_streaming(struct imx208 *imx208)
{
@ -626,6 +657,10 @@ static int imx208_start_streaming(struct imx208 *imx208)
const struct imx208_reg_list *reg_list;
int ret, link_freq_index;
ret = imx208_identify_module(imx208);
if (ret)
return ret;
/* Setup PLL */
link_freq_index = imx208->cur_mode->link_freq_index;
reg_list = &link_freq_configs[link_freq_index].reg_list;
@ -752,29 +787,6 @@ error:
}
/* Verify chip ID */
static int imx208_identify_module(struct imx208 *imx208)
{
struct i2c_client *client = v4l2_get_subdevdata(&imx208->sd);
int ret;
u32 val;
ret = imx208_read_reg(imx208, IMX208_REG_CHIP_ID,
2, &val);
if (ret) {
dev_err(&client->dev, "failed to read chip id %x\n",
IMX208_CHIP_ID);
return ret;
}
if (val != IMX208_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
IMX208_CHIP_ID, val);
return -EIO;
}
return 0;
}
static const struct v4l2_subdev_video_ops imx208_video_ops = {
.s_stream = imx208_set_stream,
};
@ -813,6 +825,10 @@ static int imx208_read_otp(struct imx208 *imx208)
goto out_unlock;
}
ret = imx208_identify_module(imx208);
if (ret)
goto out_pm_put;
/* Write register address */
msgs[0].addr = client->addr;
msgs[0].flags = 0;
@ -831,6 +847,7 @@ static int imx208_read_otp(struct imx208 *imx208)
ret = 0;
}
out_pm_put:
pm_runtime_put(&client->dev);
out_unlock:
@ -961,6 +978,7 @@ static int imx208_probe(struct i2c_client *client)
{
struct imx208 *imx208;
int ret;
bool full_power;
u32 val = 0;
device_property_read_u32(&client->dev, "clock-frequency", &val);
@ -978,11 +996,14 @@ static int imx208_probe(struct i2c_client *client)
/* Initialize subdev */
v4l2_i2c_subdev_init(&imx208->sd, client, &imx208_subdev_ops);
/* Check module identity */
ret = imx208_identify_module(imx208);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
goto error_probe;
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
/* Check module identity */
ret = imx208_identify_module(imx208);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
goto error_probe;
}
}
/* Set default mode to max resolution */
@ -1017,7 +1038,9 @@ static int imx208_probe(struct i2c_client *client)
goto error_async_subdev;
}
pm_runtime_set_active(&client->dev);
/* Set the device's state to active if it's in D0 state. */
if (full_power)
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
pm_runtime_idle(&client->dev);
@ -1077,6 +1100,7 @@ static struct i2c_driver imx208_i2c_driver = {
},
.probe_new = imx208_probe,
.remove = imx208_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
module_i2c_driver(imx208_i2c_driver);

View File

@ -27,6 +27,7 @@
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
/*
@ -1367,6 +1368,10 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd,
int min, max, def;
int ret;
ret = pm_runtime_resume_and_get(&imx274->client->dev);
if (ret < 0)
return ret;
mutex_lock(&imx274->lock);
ret = imx274_set_frame_interval(imx274, fi->interval);
@ -1398,6 +1403,7 @@ static int imx274_s_frame_interval(struct v4l2_subdev *sd,
unlock:
mutex_unlock(&imx274->lock);
pm_runtime_put(&imx274->client->dev);
return ret;
}
@ -1457,7 +1463,7 @@ static int imx274_s_stream(struct v4l2_subdev *sd, int on)
goto fail;
/*
* update frame rate & expsoure. if the last mode is different,
* update frame rate & exposure. if the last mode is different,
* HMAX could be changed. As the result, frame rate & exposure
* are changed.
* gain is not affected.
@ -1494,7 +1500,7 @@ fail:
/*
* imx274_get_frame_length - Function for obtaining current frame length
* @priv: Pointer to device structure
* @val: Pointer to obainted value
* @val: Pointer to obtained value
*
* frame_length = vmax x (svr + 1), in unit of hmax.
*
@ -1904,7 +1910,21 @@ fail:
return err;
}
static int imx274_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
if (code->index > 0)
return -EINVAL;
/* only supported format in the driver is Raw 10 bits SRGGB */
code->code = MEDIA_BUS_FMT_SRGGB10_1X10;
return 0;
}
static const struct v4l2_subdev_pad_ops imx274_pad_ops = {
.enum_mbus_code = imx274_enum_mbus_code,
.get_fmt = imx274_get_fmt,
.set_fmt = imx274_set_fmt,
.get_selection = imx274_get_selection,
@ -1938,27 +1958,66 @@ static const struct i2c_device_id imx274_id[] = {
};
MODULE_DEVICE_TABLE(i2c, imx274_id);
static int imx274_fwnode_parse(struct device *dev)
{
struct fwnode_handle *endpoint;
/* Only CSI2 is supported */
struct v4l2_fwnode_endpoint ep = {
.bus_type = V4L2_MBUS_CSI2_DPHY
};
int ret;
endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
if (!endpoint) {
dev_err(dev, "Endpoint node not found\n");
return -EINVAL;
}
ret = v4l2_fwnode_endpoint_parse(endpoint, &ep);
fwnode_handle_put(endpoint);
if (ret == -ENXIO) {
dev_err(dev, "Unsupported bus type, should be CSI2\n");
return ret;
} else if (ret) {
dev_err(dev, "Parsing endpoint node failed %d\n", ret);
return ret;
}
/* Check number of data lanes, only 4 lanes supported */
if (ep.bus.mipi_csi2.num_data_lanes != 4) {
dev_err(dev, "Invalid data lanes: %d\n",
ep.bus.mipi_csi2.num_data_lanes);
return -EINVAL;
}
return 0;
}
static int imx274_probe(struct i2c_client *client)
{
struct v4l2_subdev *sd;
struct stimx274 *imx274;
struct device *dev = &client->dev;
int ret;
/* initialize imx274 */
imx274 = devm_kzalloc(&client->dev, sizeof(*imx274), GFP_KERNEL);
imx274 = devm_kzalloc(dev, sizeof(*imx274), GFP_KERNEL);
if (!imx274)
return -ENOMEM;
mutex_init(&imx274->lock);
imx274->inck = devm_clk_get_optional(&client->dev, "inck");
ret = imx274_fwnode_parse(dev);
if (ret)
return ret;
imx274->inck = devm_clk_get_optional(dev, "inck");
if (IS_ERR(imx274->inck))
return PTR_ERR(imx274->inck);
ret = imx274_regulators_get(&client->dev, imx274);
ret = imx274_regulators_get(dev, imx274);
if (ret) {
dev_err(&client->dev,
"Failed to get power regulators, err: %d\n", ret);
dev_err(dev, "Failed to get power regulators, err: %d\n", ret);
return ret;
}
@ -1977,7 +2036,7 @@ static int imx274_probe(struct i2c_client *client)
/* initialize regmap */
imx274->regmap = devm_regmap_init_i2c(client, &imx274_regmap_config);
if (IS_ERR(imx274->regmap)) {
dev_err(&client->dev,
dev_err(dev,
"regmap init failed: %ld\n", PTR_ERR(imx274->regmap));
ret = -ENODEV;
goto err_regmap;
@ -1994,34 +2053,32 @@ static int imx274_probe(struct i2c_client *client)
sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;
ret = media_entity_pads_init(&sd->entity, 1, &imx274->pad);
if (ret < 0) {
dev_err(&client->dev,
dev_err(dev,
"%s : media entity init Failed %d\n", __func__, ret);
goto err_regmap;
}
/* initialize sensor reset gpio */
imx274->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
imx274->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(imx274->reset_gpio)) {
if (PTR_ERR(imx274->reset_gpio) != -EPROBE_DEFER)
dev_err(&client->dev, "Reset GPIO not setup in DT");
dev_err(dev, "Reset GPIO not setup in DT");
ret = PTR_ERR(imx274->reset_gpio);
goto err_me;
}
/* power on the sensor */
ret = imx274_power_on(&client->dev);
ret = imx274_power_on(dev);
if (ret < 0) {
dev_err(&client->dev,
"%s : imx274 power on failed\n", __func__);
dev_err(dev, "%s : imx274 power on failed\n", __func__);
goto err_me;
}
/* initialize controls */
ret = v4l2_ctrl_handler_init(&imx274->ctrls.handler, 4);
if (ret < 0) {
dev_err(&client->dev,
"%s : ctrl handler init Failed\n", __func__);
dev_err(dev, "%s : ctrl handler init Failed\n", __func__);
goto err_power_off;
}
@ -2064,23 +2121,22 @@ static int imx274_probe(struct i2c_client *client)
/* register subdevice */
ret = v4l2_async_register_subdev(sd);
if (ret < 0) {
dev_err(&client->dev,
"%s : v4l2_async_register_subdev failed %d\n",
dev_err(dev, "%s : v4l2_async_register_subdev failed %d\n",
__func__, ret);
goto err_ctrls;
}
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
pm_runtime_idle(&client->dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
pm_runtime_idle(dev);
dev_info(&client->dev, "imx274 : imx274 probe success !\n");
dev_info(dev, "imx274 : imx274 probe success !\n");
return 0;
err_ctrls:
v4l2_ctrl_handler_free(&imx274->ctrls.handler);
err_power_off:
imx274_power_off(&client->dev);
imx274_power_off(dev);
err_me:
media_entity_cleanup(&sd->entity);
err_regmap:

View File

@ -363,7 +363,7 @@ static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd)
return container_of(_sd, struct imx290, sd);
}
static inline int imx290_read_reg(struct imx290 *imx290, u16 addr, u8 *value)
static inline int __always_unused imx290_read_reg(struct imx290 *imx290, u16 addr, u8 *value)
{
unsigned int regval;
int ret;

View File

@ -2565,6 +2565,6 @@ module_i2c_driver(imx319_i2c_driver);
MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");
MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
MODULE_AUTHOR("Yang, Hyungwoo <hyungwoo.yang@intel.com>");
MODULE_AUTHOR("Yang, Hyungwoo");
MODULE_DESCRIPTION("Sony imx319 sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -1851,6 +1851,6 @@ module_i2c_driver(imx355_i2c_driver);
MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");
MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
MODULE_AUTHOR("Yang, Hyungwoo <hyungwoo.yang@intel.com>");
MODULE_AUTHOR("Yang, Hyungwoo");
MODULE_DESCRIPTION("Sony imx355 sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -1055,7 +1055,6 @@ static int max9286_register_gpio(struct max9286_priv *priv)
gpio->label = dev_name(dev);
gpio->parent = dev;
gpio->owner = THIS_MODULE;
gpio->of_node = dev->of_node;
gpio->ngpio = 2;
gpio->base = -1;
gpio->set = max9286_gpio_set;
@ -1295,11 +1294,9 @@ static int max9286_probe(struct i2c_client *client)
priv->regulator = devm_regulator_get(&client->dev, "poc");
if (IS_ERR(priv->regulator)) {
if (PTR_ERR(priv->regulator) != -EPROBE_DEFER)
dev_err(&client->dev,
"Unable to get PoC regulator (%ld)\n",
PTR_ERR(priv->regulator));
ret = PTR_ERR(priv->regulator);
dev_err_probe(&client->dev, ret,
"Unable to get PoC regulator\n");
goto err_powerdown;
}

View File

@ -1818,6 +1818,6 @@ module_i2c_driver(ov13858_i2c_driver);
MODULE_AUTHOR("Kan, Chris <chris.kan@intel.com>");
MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
MODULE_AUTHOR("Yang, Hyungwoo <hyungwoo.yang@intel.com>");
MODULE_AUTHOR("Yang, Hyungwoo");
MODULE_DESCRIPTION("Omnivision ov13858 sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -345,6 +345,9 @@ struct ov2740 {
/* NVM data inforamtion */
struct nvm_data *nvm;
/* True if the device has been identified */
bool identified;
};
static inline struct ov2740 *to_ov2740(struct v4l2_subdev *subdev)
@ -440,6 +443,30 @@ static int ov2740_write_reg_list(struct ov2740 *ov2740,
return 0;
}
static int ov2740_identify_module(struct ov2740 *ov2740)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd);
int ret;
u32 val;
if (ov2740->identified)
return 0;
ret = ov2740_read_reg(ov2740, OV2740_REG_CHIP_ID, 3, &val);
if (ret)
return ret;
if (val != OV2740_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x",
OV2740_CHIP_ID, val);
return -ENXIO;
}
ov2740->identified = true;
return 0;
}
static int ov2740_update_digital_gain(struct ov2740 *ov2740, u32 d_gain)
{
int ret = 0;
@ -724,6 +751,10 @@ static int ov2740_start_streaming(struct ov2740 *ov2740)
int link_freq_index;
int ret = 0;
ret = ov2740_identify_module(ov2740);
if (ret)
return ret;
ov2740_load_otp_data(nvm);
link_freq_index = ov2740->cur_mode->link_freq_index;
@ -956,25 +987,6 @@ static const struct v4l2_subdev_internal_ops ov2740_internal_ops = {
.open = ov2740_open,
};
static int ov2740_identify_module(struct ov2740 *ov2740)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd);
int ret;
u32 val;
ret = ov2740_read_reg(ov2740, OV2740_REG_CHIP_ID, 3, &val);
if (ret)
return ret;
if (val != OV2740_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x",
OV2740_CHIP_ID, val);
return -ENXIO;
}
return 0;
}
static int ov2740_check_hwcfg(struct device *dev)
{
struct fwnode_handle *ep;
@ -1137,6 +1149,7 @@ static int ov2740_probe(struct i2c_client *client)
{
struct ov2740 *ov2740;
int ret = 0;
bool full_power;
ret = ov2740_check_hwcfg(&client->dev);
if (ret) {
@ -1149,6 +1162,15 @@ static int ov2740_probe(struct i2c_client *client)
if (!ov2740)
return -ENOMEM;
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
ret = ov2740_identify_module(ov2740);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
return ret;
}
}
v4l2_i2c_subdev_init(&ov2740->sd, client, &ov2740_subdev_ops);
ret = ov2740_identify_module(ov2740);
if (ret) {
@ -1186,11 +1208,9 @@ static int ov2740_probe(struct i2c_client *client)
if (ret)
dev_warn(&client->dev, "register nvmem failed, ret %d\n", ret);
/*
* Device is already turned on by i2c-core with ACPI domain PM.
* Enable runtime PM and turn off the device.
*/
pm_runtime_set_active(&client->dev);
/* Set the device's state to active if it's in D0 state. */
if (full_power)
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
pm_runtime_idle(&client->dev);
@ -1225,6 +1245,7 @@ static struct i2c_driver ov2740_i2c_driver = {
},
.probe_new = ov2740_probe,
.remove = ov2740_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
module_i2c_driver(ov2740_i2c_driver);

View File

@ -1833,6 +1833,8 @@ struct ov5670 {
/* Streaming on/off */
bool streaming;
/* True if the device has been identified */
bool identified;
};
#define to_ov5670(_sd) container_of(_sd, struct ov5670, sd)
@ -2273,6 +2275,32 @@ static int ov5670_get_skip_frames(struct v4l2_subdev *sd, u32 *frames)
return 0;
}
/* Verify chip ID */
static int ov5670_identify_module(struct ov5670 *ov5670)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd);
int ret;
u32 val;
if (ov5670->identified)
return 0;
ret = ov5670_read_reg(ov5670, OV5670_REG_CHIP_ID,
OV5670_REG_VALUE_24BIT, &val);
if (ret)
return ret;
if (val != OV5670_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
OV5670_CHIP_ID, val);
return -ENXIO;
}
ov5670->identified = true;
return 0;
}
/* Prepare streaming by writing default values and customized values */
static int ov5670_start_streaming(struct ov5670 *ov5670)
{
@ -2281,6 +2309,10 @@ static int ov5670_start_streaming(struct ov5670 *ov5670)
int link_freq_index;
int ret;
ret = ov5670_identify_module(ov5670);
if (ret)
return ret;
/* Get out of from software reset */
ret = ov5670_write_reg(ov5670, OV5670_REG_SOFTWARE_RST,
OV5670_REG_VALUE_08BIT, OV5670_SOFTWARE_RST);
@ -2400,27 +2432,6 @@ static int __maybe_unused ov5670_resume(struct device *dev)
return 0;
}
/* Verify chip ID */
static int ov5670_identify_module(struct ov5670 *ov5670)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd);
int ret;
u32 val;
ret = ov5670_read_reg(ov5670, OV5670_REG_CHIP_ID,
OV5670_REG_VALUE_24BIT, &val);
if (ret)
return ret;
if (val != OV5670_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x\n",
OV5670_CHIP_ID, val);
return -ENXIO;
}
return 0;
}
static const struct v4l2_subdev_core_ops ov5670_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status,
.subscribe_event = v4l2_ctrl_subdev_subscribe_event,
@ -2462,6 +2473,7 @@ static int ov5670_probe(struct i2c_client *client)
struct ov5670 *ov5670;
const char *err_msg;
u32 input_clk = 0;
bool full_power;
int ret;
device_property_read_u32(&client->dev, "clock-frequency", &input_clk);
@ -2478,11 +2490,14 @@ static int ov5670_probe(struct i2c_client *client)
/* Initialize subdev */
v4l2_i2c_subdev_init(&ov5670->sd, client, &ov5670_subdev_ops);
/* Check module identity */
ret = ov5670_identify_module(ov5670);
if (ret) {
err_msg = "ov5670_identify_module() error";
goto error_print;
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
/* Check module identity */
ret = ov5670_identify_module(ov5670);
if (ret) {
err_msg = "ov5670_identify_module() error";
goto error_print;
}
}
mutex_init(&ov5670->mutex);
@ -2519,11 +2534,9 @@ static int ov5670_probe(struct i2c_client *client)
ov5670->streaming = false;
/*
* Device is already turned on by i2c-core with ACPI domain PM.
* Enable runtime PM and turn off the device.
*/
pm_runtime_set_active(&client->dev);
/* Set the device's state to active if it's in D0 state. */
if (full_power)
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
pm_runtime_idle(&client->dev);
@ -2565,7 +2578,7 @@ static const struct dev_pm_ops ov5670_pm_ops = {
#ifdef CONFIG_ACPI
static const struct acpi_device_id ov5670_acpi_ids[] = {
{"INT3479"},
{ "INT3479" },
{ /* sentinel */ }
};
@ -2580,11 +2593,12 @@ static struct i2c_driver ov5670_i2c_driver = {
},
.probe_new = ov5670_probe,
.remove = ov5670_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
module_i2c_driver(ov5670_i2c_driver);
MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
MODULE_AUTHOR("Yang, Hyungwoo <hyungwoo.yang@intel.com>");
MODULE_AUTHOR("Yang, Hyungwoo");
MODULE_DESCRIPTION("Omnivision ov5670 sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -493,6 +493,9 @@ struct ov5675 {
/* Streaming on/off */
bool streaming;
/* True if the device has been identified */
bool identified;
};
static u64 to_pixel_rate(u32 f_index)
@ -808,12 +811,41 @@ static void ov5675_update_pad_format(const struct ov5675_mode *mode,
fmt->field = V4L2_FIELD_NONE;
}
static int ov5675_identify_module(struct ov5675 *ov5675)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
int ret;
u32 val;
if (ov5675->identified)
return 0;
ret = ov5675_read_reg(ov5675, OV5675_REG_CHIP_ID,
OV5675_REG_VALUE_24BIT, &val);
if (ret)
return ret;
if (val != OV5675_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x",
OV5675_CHIP_ID, val);
return -ENXIO;
}
ov5675->identified = true;
return 0;
}
static int ov5675_start_streaming(struct ov5675 *ov5675)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
const struct ov5675_reg_list *reg_list;
int link_freq_index, ret;
ret = ov5675_identify_module(ov5675);
if (ret)
return ret;
link_freq_index = ov5675->cur_mode->link_freq_index;
reg_list = &link_freq_configs[link_freq_index].reg_list;
ret = ov5675_write_reg_list(ov5675, reg_list);
@ -1048,26 +1080,6 @@ static const struct v4l2_subdev_internal_ops ov5675_internal_ops = {
.open = ov5675_open,
};
static int ov5675_identify_module(struct ov5675 *ov5675)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
int ret;
u32 val;
ret = ov5675_read_reg(ov5675, OV5675_REG_CHIP_ID,
OV5675_REG_VALUE_24BIT, &val);
if (ret)
return ret;
if (val != OV5675_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x",
OV5675_CHIP_ID, val);
return -ENXIO;
}
return 0;
}
static int ov5675_check_hwcfg(struct device *dev)
{
struct fwnode_handle *ep;
@ -1154,6 +1166,7 @@ static int ov5675_remove(struct i2c_client *client)
static int ov5675_probe(struct i2c_client *client)
{
struct ov5675 *ov5675;
bool full_power;
int ret;
ret = ov5675_check_hwcfg(&client->dev);
@ -1168,10 +1181,14 @@ static int ov5675_probe(struct i2c_client *client)
return -ENOMEM;
v4l2_i2c_subdev_init(&ov5675->sd, client, &ov5675_subdev_ops);
ret = ov5675_identify_module(ov5675);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
return ret;
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
ret = ov5675_identify_module(ov5675);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
return ret;
}
}
mutex_init(&ov5675->mutex);
@ -1204,7 +1221,10 @@ static int ov5675_probe(struct i2c_client *client)
* Device is already turned on by i2c-core with ACPI domain PM.
* Enable runtime PM and turn off the device.
*/
pm_runtime_set_active(&client->dev);
/* Set the device's state to active if it's in D0 state. */
if (full_power)
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
pm_runtime_idle(&client->dev);
@ -1241,6 +1261,7 @@ static struct i2c_driver ov5675_i2c_driver = {
},
.probe_new = ov5675_probe,
.remove = ov5675_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
module_i2c_driver(ov5675_i2c_driver);

1537
drivers/media/i2c/ov5693.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1445,6 +1445,9 @@ struct ov8856 {
const struct ov8856_lane_cfg *priv_lane;
u8 modes_size;
/* True if the device has been identified */
bool identified;
};
struct ov8856_lane_cfg {
@ -1685,6 +1688,71 @@ static int ov8856_write_reg_list(struct ov8856 *ov8856,
return 0;
}
static int ov8856_identify_module(struct ov8856 *ov8856)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd);
int ret;
u32 val;
if (ov8856->identified)
return 0;
ret = ov8856_read_reg(ov8856, OV8856_REG_CHIP_ID,
OV8856_REG_VALUE_24BIT, &val);
if (ret)
return ret;
if (val != OV8856_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x",
OV8856_CHIP_ID, val);
return -ENXIO;
}
ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
OV8856_REG_VALUE_08BIT, OV8856_MODE_STREAMING);
if (ret)
return ret;
ret = ov8856_write_reg(ov8856, OV8856_OTP_MODE_CTRL,
OV8856_REG_VALUE_08BIT, OV8856_OTP_MODE_AUTO);
if (ret) {
dev_err(&client->dev, "failed to set otp mode");
return ret;
}
ret = ov8856_write_reg(ov8856, OV8856_OTP_LOAD_CTRL,
OV8856_REG_VALUE_08BIT,
OV8856_OTP_LOAD_CTRL_ENABLE);
if (ret) {
dev_err(&client->dev, "failed to enable load control");
return ret;
}
ret = ov8856_read_reg(ov8856, OV8856_MODULE_REVISION,
OV8856_REG_VALUE_08BIT, &val);
if (ret) {
dev_err(&client->dev, "failed to read module revision");
return ret;
}
dev_info(&client->dev, "OV8856 revision %x (%s) at address 0x%02x\n",
val,
val == OV8856_2A_MODULE ? "2A" :
val == OV8856_1B_MODULE ? "1B" : "unknown revision",
client->addr);
ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
OV8856_REG_VALUE_08BIT, OV8856_MODE_STANDBY);
if (ret) {
dev_err(&client->dev, "failed to exit streaming mode");
return ret;
}
ov8856->identified = true;
return 0;
}
static int ov8856_update_digital_gain(struct ov8856 *ov8856, u32 d_gain)
{
int ret;
@ -1969,6 +2037,10 @@ static int ov8856_start_streaming(struct ov8856 *ov8856)
const struct ov8856_reg_list *reg_list;
int link_freq_index, ret;
ret = ov8856_identify_module(ov8856);
if (ret)
return ret;
link_freq_index = ov8856->cur_mode->link_freq_index;
reg_list = &ov8856->priv_lane->link_freq_configs[link_freq_index].reg_list;
@ -2276,65 +2348,6 @@ static const struct v4l2_subdev_internal_ops ov8856_internal_ops = {
.open = ov8856_open,
};
static int ov8856_identify_module(struct ov8856 *ov8856)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov8856->sd);
int ret;
u32 val;
ret = ov8856_read_reg(ov8856, OV8856_REG_CHIP_ID,
OV8856_REG_VALUE_24BIT, &val);
if (ret)
return ret;
if (val != OV8856_CHIP_ID) {
dev_err(&client->dev, "chip id mismatch: %x!=%x",
OV8856_CHIP_ID, val);
return -ENXIO;
}
ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
OV8856_REG_VALUE_08BIT, OV8856_MODE_STREAMING);
if (ret)
return ret;
ret = ov8856_write_reg(ov8856, OV8856_OTP_MODE_CTRL,
OV8856_REG_VALUE_08BIT, OV8856_OTP_MODE_AUTO);
if (ret) {
dev_err(&client->dev, "failed to set otp mode");
return ret;
}
ret = ov8856_write_reg(ov8856, OV8856_OTP_LOAD_CTRL,
OV8856_REG_VALUE_08BIT,
OV8856_OTP_LOAD_CTRL_ENABLE);
if (ret) {
dev_err(&client->dev, "failed to enable load control");
return ret;
}
ret = ov8856_read_reg(ov8856, OV8856_MODULE_REVISION,
OV8856_REG_VALUE_08BIT, &val);
if (ret) {
dev_err(&client->dev, "failed to read module revision");
return ret;
}
dev_info(&client->dev, "OV8856 revision %x (%s) at address 0x%02x\n",
val,
val == OV8856_2A_MODULE ? "2A" :
val == OV8856_1B_MODULE ? "1B" : "unknown revision",
client->addr);
ret = ov8856_write_reg(ov8856, OV8856_REG_MODE_SELECT,
OV8856_REG_VALUE_08BIT, OV8856_MODE_STANDBY);
if (ret) {
dev_err(&client->dev, "failed to exit streaming mode");
return ret;
}
return 0;
}
static int ov8856_get_hwcfg(struct ov8856 *ov8856, struct device *dev)
{
@ -2458,6 +2471,7 @@ static int ov8856_probe(struct i2c_client *client)
{
struct ov8856 *ov8856;
int ret;
bool full_power;
ov8856 = devm_kzalloc(&client->dev, sizeof(*ov8856), GFP_KERNEL);
if (!ov8856)
@ -2472,16 +2486,19 @@ static int ov8856_probe(struct i2c_client *client)
v4l2_i2c_subdev_init(&ov8856->sd, client, &ov8856_subdev_ops);
ret = __ov8856_power_on(ov8856);
if (ret) {
dev_err(&client->dev, "failed to power on\n");
return ret;
}
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
ret = __ov8856_power_on(ov8856);
if (ret) {
dev_err(&client->dev, "failed to power on\n");
return ret;
}
ret = ov8856_identify_module(ov8856);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
goto probe_power_off;
ret = ov8856_identify_module(ov8856);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
goto probe_power_off;
}
}
mutex_init(&ov8856->mutex);
@ -2511,11 +2528,9 @@ static int ov8856_probe(struct i2c_client *client)
goto probe_error_media_entity_cleanup;
}
/*
* Device is already turned on by i2c-core with ACPI domain PM.
* Enable runtime PM and turn off the device.
*/
pm_runtime_set_active(&client->dev);
/* Set the device's state to active if it's in D0 state. */
if (full_power)
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
pm_runtime_idle(&client->dev);
@ -2562,6 +2577,7 @@ static struct i2c_driver ov8856_i2c_driver = {
},
.probe_new = ov8856_probe,
.remove = ov8856_remove,
.flags = I2C_DRV_ACPI_WAIVE_D0_PROBE,
};
module_i2c_driver(ov8856_i2c_driver);

View File

@ -9,6 +9,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/pm_runtime.h>
@ -20,10 +21,6 @@
#include <media/v4l2-image-sizes.h>
#include <media/v4l2-mediabus.h>
/* Clock rate */
#define OV8865_EXTCLK_RATE 24000000
/* Register definitions */
/* System */
@ -146,6 +143,7 @@
#define OV8865_EXPOSURE_CTRL_L_REG 0x3502
#define OV8865_EXPOSURE_CTRL_L(v) ((v) & GENMASK(7, 0))
#define OV8865_EXPOSURE_GAIN_MANUAL_REG 0x3503
#define OV8865_INTEGRATION_TIME_MARGIN 8
#define OV8865_GAIN_CTRL_H_REG 0x3508
#define OV8865_GAIN_CTRL_H(v) (((v) & GENMASK(12, 8)) >> 8)
@ -186,6 +184,8 @@
#define OV8865_VTS_H(v) (((v) & GENMASK(11, 8)) >> 8)
#define OV8865_VTS_L_REG 0x380f
#define OV8865_VTS_L(v) ((v) & GENMASK(7, 0))
#define OV8865_TIMING_MAX_VTS 0xffff
#define OV8865_TIMING_MIN_VTS 0x04
#define OV8865_OFFSET_X_H_REG 0x3810
#define OV8865_OFFSET_X_H(v) (((v) & GENMASK(15, 8)) >> 8)
#define OV8865_OFFSET_X_L_REG 0x3811
@ -453,6 +453,15 @@
#define OV8865_PRE_CTRL0_PATTERN_COLOR_SQUARES 2
#define OV8865_PRE_CTRL0_PATTERN_BLACK 3
/* Pixel Array */
#define OV8865_NATIVE_WIDTH 3296
#define OV8865_NATIVE_HEIGHT 2528
#define OV8865_ACTIVE_START_TOP 32
#define OV8865_ACTIVE_START_LEFT 80
#define OV8865_ACTIVE_WIDTH 3264
#define OV8865_ACTIVE_HEIGHT 2448
/* Macros */
#define ov8865_subdev_sensor(s) \
@ -566,6 +575,25 @@ struct ov8865_sclk_config {
unsigned int sclk_div;
};
struct ov8865_pll_configs {
const struct ov8865_pll1_config *pll1_config;
const struct ov8865_pll2_config *pll2_config_native;
const struct ov8865_pll2_config *pll2_config_binning;
};
/* Clock rate */
enum extclk_rate {
OV8865_19_2_MHZ,
OV8865_24_MHZ,
OV8865_NUM_SUPPORTED_RATES
};
static const unsigned long supported_extclk_rates[] = {
[OV8865_19_2_MHZ] = 19200000,
[OV8865_24_MHZ] = 24000000,
};
/*
* General formulas for (array-centered) mode calculation:
* - photo_array_width = 3296
@ -632,11 +660,7 @@ struct ov8865_mode {
unsigned int blc_anchor_right_start;
unsigned int blc_anchor_right_end;
struct v4l2_fract frame_interval;
const struct ov8865_pll1_config *pll1_config;
const struct ov8865_pll2_config *pll2_config;
const struct ov8865_sclk_config *sclk_config;
bool pll2_binning;
const struct ov8865_register_value *register_values;
unsigned int register_values_count;
@ -652,6 +676,9 @@ struct ov8865_state {
struct ov8865_ctrls {
struct v4l2_ctrl *link_freq;
struct v4l2_ctrl *pixel_rate;
struct v4l2_ctrl *hblank;
struct v4l2_ctrl *vblank;
struct v4l2_ctrl *exposure;
struct v4l2_ctrl_handler handler;
};
@ -664,6 +691,9 @@ struct ov8865_sensor {
struct regulator *avdd;
struct regulator *dvdd;
struct regulator *dovdd;
unsigned long extclk_rate;
const struct ov8865_pll_configs *pll_configs;
struct clk *extclk;
struct v4l2_fwnode_endpoint endpoint;
@ -679,43 +709,70 @@ struct ov8865_sensor {
/* Static definitions */
/*
* EXTCLK = 24 MHz
* PHY_SCLK = 720 MHz
* MIPI_PCLK = 90 MHz
*/
static const struct ov8865_pll1_config ov8865_pll1_config_native = {
.pll_pre_div_half = 1,
.pll_pre_div = 0,
.pll_mul = 30,
.m_div = 1,
.mipi_div = 3,
.pclk_div = 1,
.sys_pre_div = 1,
.sys_div = 2,
static const struct ov8865_pll1_config ov8865_pll1_config_native_19_2mhz = {
.pll_pre_div_half = 1,
.pll_pre_div = 2,
.pll_mul = 75,
.m_div = 1,
.mipi_div = 3,
.pclk_div = 1,
.sys_pre_div = 1,
.sys_div = 2,
};
static const struct ov8865_pll1_config ov8865_pll1_config_native_24mhz = {
.pll_pre_div_half = 1,
.pll_pre_div = 0,
.pll_mul = 30,
.m_div = 1,
.mipi_div = 3,
.pclk_div = 1,
.sys_pre_div = 1,
.sys_div = 2,
};
/*
* EXTCLK = 24 MHz
* DAC_CLK = 360 MHz
* SCLK = 144 MHz
*/
static const struct ov8865_pll2_config ov8865_pll2_config_native = {
.pll_pre_div_half = 1,
.pll_pre_div = 0,
.pll_mul = 30,
.dac_div = 2,
.sys_pre_div = 5,
.sys_div = 0,
static const struct ov8865_pll2_config ov8865_pll2_config_native_19_2mhz = {
.pll_pre_div_half = 1,
.pll_pre_div = 5,
.pll_mul = 75,
.dac_div = 1,
.sys_pre_div = 1,
.sys_div = 3,
};
static const struct ov8865_pll2_config ov8865_pll2_config_native_24mhz = {
.pll_pre_div_half = 1,
.pll_pre_div = 0,
.pll_mul = 30,
.dac_div = 2,
.sys_pre_div = 5,
.sys_div = 0,
};
/*
* EXTCLK = 24 MHz
* DAC_CLK = 360 MHz
* SCLK = 80 MHz
* SCLK = 72 MHz
*/
static const struct ov8865_pll2_config ov8865_pll2_config_binning = {
static const struct ov8865_pll2_config ov8865_pll2_config_binning_19_2mhz = {
.pll_pre_div_half = 1,
.pll_pre_div = 2,
.pll_mul = 75,
.dac_div = 2,
.sys_pre_div = 10,
.sys_div = 0,
};
static const struct ov8865_pll2_config ov8865_pll2_config_binning_24mhz = {
.pll_pre_div_half = 1,
.pll_pre_div = 0,
.pll_mul = 30,
@ -724,6 +781,23 @@ static const struct ov8865_pll2_config ov8865_pll2_config_binning = {
.sys_div = 0,
};
static const struct ov8865_pll_configs ov8865_pll_configs_19_2mhz = {
.pll1_config = &ov8865_pll1_config_native_19_2mhz,
.pll2_config_native = &ov8865_pll2_config_native_19_2mhz,
.pll2_config_binning = &ov8865_pll2_config_binning_19_2mhz,
};
static const struct ov8865_pll_configs ov8865_pll_configs_24mhz = {
.pll1_config = &ov8865_pll1_config_native_24mhz,
.pll2_config_native = &ov8865_pll2_config_native_24mhz,
.pll2_config_binning = &ov8865_pll2_config_binning_24mhz,
};
static const struct ov8865_pll_configs *ov8865_pll_configs[] = {
&ov8865_pll_configs_19_2mhz,
&ov8865_pll_configs_24mhz,
};
static const struct ov8865_sclk_config ov8865_sclk_config_native = {
.sys_sel = 1,
.sclk_sel = 0,
@ -890,7 +964,7 @@ static const struct ov8865_mode ov8865_modes[] = {
{
/* Horizontal */
.output_size_x = 3264,
.hts = 1944,
.hts = 3888,
/* Vertical */
.output_size_y = 2448,
@ -929,13 +1003,8 @@ static const struct ov8865_mode ov8865_modes[] = {
.blc_anchor_right_start = 1984,
.blc_anchor_right_end = 2239,
/* Frame Interval */
.frame_interval = { 1, 30 },
/* PLL */
.pll1_config = &ov8865_pll1_config_native,
.pll2_config = &ov8865_pll2_config_native,
.sclk_config = &ov8865_sclk_config_native,
.pll2_binning = false,
/* Registers */
.register_values = ov8865_register_values_native,
@ -946,11 +1015,11 @@ static const struct ov8865_mode ov8865_modes[] = {
{
/* Horizontal */
.output_size_x = 3264,
.hts = 2582,
.hts = 3888,
/* Vertical */
.output_size_y = 1836,
.vts = 2002,
.vts = 2470,
.size_auto = true,
.size_auto_boundary_x = 8,
@ -985,13 +1054,8 @@ static const struct ov8865_mode ov8865_modes[] = {
.blc_anchor_right_start = 1984,
.blc_anchor_right_end = 2239,
/* Frame Interval */
.frame_interval = { 1, 30 },
/* PLL */
.pll1_config = &ov8865_pll1_config_native,
.pll2_config = &ov8865_pll2_config_native,
.sclk_config = &ov8865_sclk_config_native,
.pll2_binning = false,
/* Registers */
.register_values = ov8865_register_values_native,
@ -1045,13 +1109,8 @@ static const struct ov8865_mode ov8865_modes[] = {
.blc_anchor_right_start = 992,
.blc_anchor_right_end = 1119,
/* Frame Interval */
.frame_interval = { 1, 30 },
/* PLL */
.pll1_config = &ov8865_pll1_config_native,
.pll2_config = &ov8865_pll2_config_binning,
.sclk_config = &ov8865_sclk_config_native,
.pll2_binning = true,
/* Registers */
.register_values = ov8865_register_values_binning,
@ -1111,13 +1170,8 @@ static const struct ov8865_mode ov8865_modes[] = {
.blc_anchor_right_start = 992,
.blc_anchor_right_end = 1119,
/* Frame Interval */
.frame_interval = { 1, 90 },
/* PLL */
.pll1_config = &ov8865_pll1_config_native,
.pll2_config = &ov8865_pll2_config_binning,
.sclk_config = &ov8865_sclk_config_native,
.pll2_binning = true,
/* Registers */
.register_values = ov8865_register_values_binning,
@ -1512,12 +1566,11 @@ static int ov8865_isp_configure(struct ov8865_sensor *sensor)
static unsigned long ov8865_mode_pll1_rate(struct ov8865_sensor *sensor,
const struct ov8865_mode *mode)
{
const struct ov8865_pll1_config *config = mode->pll1_config;
unsigned long extclk_rate;
const struct ov8865_pll1_config *config;
unsigned long pll1_rate;
extclk_rate = clk_get_rate(sensor->extclk);
pll1_rate = extclk_rate * config->pll_mul / config->pll_pre_div_half;
config = sensor->pll_configs->pll1_config;
pll1_rate = sensor->extclk_rate * config->pll_mul / config->pll_pre_div_half;
switch (config->pll_pre_div) {
case 0:
@ -1551,10 +1604,12 @@ static int ov8865_mode_pll1_configure(struct ov8865_sensor *sensor,
const struct ov8865_mode *mode,
u32 mbus_code)
{
const struct ov8865_pll1_config *config = mode->pll1_config;
const struct ov8865_pll1_config *config;
u8 value;
int ret;
config = sensor->pll_configs->pll1_config;
switch (mbus_code) {
case MEDIA_BUS_FMT_SBGGR10_1X10:
value = OV8865_MIPI_BIT_SEL(10);
@ -1621,9 +1676,12 @@ static int ov8865_mode_pll1_configure(struct ov8865_sensor *sensor,
static int ov8865_mode_pll2_configure(struct ov8865_sensor *sensor,
const struct ov8865_mode *mode)
{
const struct ov8865_pll2_config *config = mode->pll2_config;
const struct ov8865_pll2_config *config;
int ret;
config = mode->pll2_binning ? sensor->pll_configs->pll2_config_binning :
sensor->pll_configs->pll2_config_native;
ret = ov8865_write(sensor, OV8865_PLL_CTRL12_REG,
OV8865_PLL_CTRL12_PRE_DIV_HALF(config->pll_pre_div_half) |
OV8865_PLL_CTRL12_DAC_DIV(config->dac_div));
@ -1657,7 +1715,7 @@ static int ov8865_mode_pll2_configure(struct ov8865_sensor *sensor,
static int ov8865_mode_sclk_configure(struct ov8865_sensor *sensor,
const struct ov8865_mode *mode)
{
const struct ov8865_sclk_config *config = mode->sclk_config;
const struct ov8865_sclk_config *config = &ov8865_sclk_config_native;
int ret;
ret = ov8865_write(sensor, OV8865_CLK_SEL0_REG,
@ -2052,9 +2110,11 @@ static int ov8865_mode_configure(struct ov8865_sensor *sensor,
static unsigned long ov8865_mode_mipi_clk_rate(struct ov8865_sensor *sensor,
const struct ov8865_mode *mode)
{
const struct ov8865_pll1_config *config = mode->pll1_config;
const struct ov8865_pll1_config *config;
unsigned long pll1_rate;
config = sensor->pll_configs->pll1_config;
pll1_rate = ov8865_mode_pll1_rate(sensor, mode);
return pll1_rate / config->m_div / 2;
@ -2066,6 +2126,9 @@ static int ov8865_exposure_configure(struct ov8865_sensor *sensor, u32 exposure)
{
int ret;
/* The sensor stores exposure in units of 1/16th of a line */
exposure *= 16;
ret = ov8865_write(sensor, OV8865_EXPOSURE_CTRL_HH_REG,
OV8865_EXPOSURE_CTRL_HH(exposure));
if (ret)
@ -2082,7 +2145,7 @@ static int ov8865_exposure_configure(struct ov8865_sensor *sensor, u32 exposure)
/* Gain */
static int ov8865_gain_configure(struct ov8865_sensor *sensor, u32 gain)
static int ov8865_analog_gain_configure(struct ov8865_sensor *sensor, u32 gain)
{
int ret;
@ -2157,6 +2220,20 @@ static int ov8865_test_pattern_configure(struct ov8865_sensor *sensor,
ov8865_test_pattern_bits[index]);
}
/* Blanking */
static int ov8865_vts_configure(struct ov8865_sensor *sensor, u32 vblank)
{
u16 vts = sensor->state.mode->output_size_y + vblank;
int ret;
ret = ov8865_write(sensor, OV8865_VTS_H_REG, OV8865_VTS_H(vts));
if (ret)
return ret;
return ov8865_write(sensor, OV8865_VTS_L_REG, OV8865_VTS_L(vts));
}
/* State */
static int ov8865_state_mipi_configure(struct ov8865_sensor *sensor,
@ -2330,27 +2407,27 @@ static int ov8865_sensor_power(struct ov8865_sensor *sensor, bool on)
if (ret) {
dev_err(sensor->dev,
"failed to enable DOVDD regulator\n");
goto disable;
return ret;
}
ret = regulator_enable(sensor->avdd);
if (ret) {
dev_err(sensor->dev,
"failed to enable AVDD regulator\n");
goto disable;
goto disable_dovdd;
}
ret = regulator_enable(sensor->dvdd);
if (ret) {
dev_err(sensor->dev,
"failed to enable DVDD regulator\n");
goto disable;
goto disable_avdd;
}
ret = clk_prepare_enable(sensor->extclk);
if (ret) {
dev_err(sensor->dev, "failed to enable EXTCLK clock\n");
goto disable;
goto disable_dvdd;
}
gpiod_set_value_cansleep(sensor->reset, 0);
@ -2359,14 +2436,16 @@ static int ov8865_sensor_power(struct ov8865_sensor *sensor, bool on)
/* Time to enter streaming mode according to power timings. */
usleep_range(10000, 12000);
} else {
disable:
gpiod_set_value_cansleep(sensor->powerdown, 1);
gpiod_set_value_cansleep(sensor->reset, 1);
clk_disable_unprepare(sensor->extclk);
disable_dvdd:
regulator_disable(sensor->dvdd);
disable_avdd:
regulator_disable(sensor->avdd);
disable_dovdd:
regulator_disable(sensor->dovdd);
}
@ -2382,6 +2461,20 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl)
unsigned int index;
int ret;
/* If VBLANK is altered we need to update exposure to compensate */
if (ctrl->id == V4L2_CID_VBLANK) {
int exposure_max;
exposure_max = sensor->state.mode->output_size_y + ctrl->val -
OV8865_INTEGRATION_TIME_MARGIN;
__v4l2_ctrl_modify_range(sensor->ctrls.exposure,
sensor->ctrls.exposure->minimum,
exposure_max,
sensor->ctrls.exposure->step,
min(sensor->ctrls.exposure->val,
exposure_max));
}
/* Wait for the sensor to be on before setting controls. */
if (pm_runtime_suspended(sensor->dev))
return 0;
@ -2392,8 +2485,8 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl)
if (ret)
return ret;
break;
case V4L2_CID_GAIN:
ret = ov8865_gain_configure(sensor, ctrl->val);
case V4L2_CID_ANALOGUE_GAIN:
ret = ov8865_analog_gain_configure(sensor, ctrl->val);
if (ret)
return ret;
break;
@ -2408,6 +2501,8 @@ static int ov8865_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_TEST_PATTERN:
index = (unsigned int)ctrl->val;
return ov8865_test_pattern_configure(sensor, index);
case V4L2_CID_VBLANK:
return ov8865_vts_configure(sensor, ctrl->val);
default:
return -EINVAL;
}
@ -2424,6 +2519,10 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor)
struct ov8865_ctrls *ctrls = &sensor->ctrls;
struct v4l2_ctrl_handler *handler = &ctrls->handler;
const struct v4l2_ctrl_ops *ops = &ov8865_ctrl_ops;
const struct ov8865_mode *mode = &ov8865_modes[0];
struct v4l2_fwnode_device_properties props;
unsigned int vblank_max, vblank_def;
unsigned int hblank;
int ret;
v4l2_ctrl_handler_init(handler, 32);
@ -2433,12 +2532,13 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor)
/* Exposure */
v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 16, 1048575, 16,
512);
ctrls->exposure = v4l2_ctrl_new_std(handler, ops, V4L2_CID_EXPOSURE, 2,
65535, 1, 32);
/* Gain */
v4l2_ctrl_new_std(handler, ops, V4L2_CID_GAIN, 128, 8191, 128, 128);
v4l2_ctrl_new_std(handler, ops, V4L2_CID_ANALOGUE_GAIN, 128, 2048, 128,
128);
/* White Balance */
@ -2459,6 +2559,20 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor)
ARRAY_SIZE(ov8865_test_pattern_menu) - 1,
0, 0, ov8865_test_pattern_menu);
/* Blanking */
hblank = mode->hts - mode->output_size_x;
ctrls->hblank = v4l2_ctrl_new_std(handler, ops, V4L2_CID_HBLANK, hblank,
hblank, 1, hblank);
if (ctrls->hblank)
ctrls->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
vblank_max = OV8865_TIMING_MAX_VTS - mode->output_size_y;
vblank_def = mode->vts - mode->output_size_y;
ctrls->vblank = v4l2_ctrl_new_std(handler, ops, V4L2_CID_VBLANK,
OV8865_TIMING_MIN_VTS, vblank_max, 1,
vblank_def);
/* MIPI CSI-2 */
ctrls->link_freq =
@ -2470,6 +2584,15 @@ static int ov8865_ctrls_init(struct ov8865_sensor *sensor)
v4l2_ctrl_new_std(handler, NULL, V4L2_CID_PIXEL_RATE, 1,
INT_MAX, 1, 1);
/* set properties from fwnode (e.g. rotation, orientation) */
ret = v4l2_fwnode_device_parse(sensor->dev, &props);
if (ret)
goto error_ctrls;
ret = v4l2_ctrl_new_fwnode_properties(handler, ops, &props);
if (ret)
goto error_ctrls;
if (handler->error) {
ret = handler->error;
goto error_ctrls;
@ -2522,11 +2645,18 @@ static int ov8865_g_frame_interval(struct v4l2_subdev *subdev,
{
struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);
const struct ov8865_mode *mode;
unsigned int framesize;
unsigned int fps;
mutex_lock(&sensor->mutex);
mode = sensor->state.mode;
interval->interval = mode->frame_interval;
framesize = mode->hts * (mode->output_size_y +
sensor->ctrls.vblank->val);
fps = DIV_ROUND_CLOSEST(sensor->ctrls.pixel_rate->val, framesize);
interval->interval.numerator = 1;
interval->interval.denominator = fps;
mutex_unlock(&sensor->mutex);
@ -2599,7 +2729,9 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev,
struct v4l2_mbus_framefmt *mbus_format = &format->format;
const struct ov8865_mode *mode;
u32 mbus_code = 0;
unsigned int hblank;
unsigned int index;
int exposure_max;
int ret = 0;
mutex_lock(&sensor->mutex);
@ -2639,6 +2771,21 @@ static int ov8865_set_fmt(struct v4l2_subdev *subdev,
sensor->state.mbus_code != mbus_code)
ret = ov8865_state_configure(sensor, mode, mbus_code);
__v4l2_ctrl_modify_range(sensor->ctrls.vblank, OV8865_TIMING_MIN_VTS,
OV8865_TIMING_MAX_VTS - mode->output_size_y,
1, mode->vts - mode->output_size_y);
hblank = mode->hts - mode->output_size_x;
__v4l2_ctrl_modify_range(sensor->ctrls.hblank, hblank, hblank, 1,
hblank);
exposure_max = mode->vts - OV8865_INTEGRATION_TIME_MARGIN;
__v4l2_ctrl_modify_range(sensor->ctrls.exposure,
sensor->ctrls.exposure->minimum, exposure_max,
sensor->ctrls.exposure->step,
min(sensor->ctrls.exposure->val,
exposure_max));
complete:
mutex_unlock(&sensor->mutex);
@ -2662,37 +2809,55 @@ static int ov8865_enum_frame_size(struct v4l2_subdev *subdev,
return 0;
}
static int ov8865_enum_frame_interval(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_frame_interval_enum *interval_enum)
static void
__ov8865_get_pad_crop(struct ov8865_sensor *sensor,
struct v4l2_subdev_state *state, unsigned int pad,
enum v4l2_subdev_format_whence which, struct v4l2_rect *r)
{
const struct ov8865_mode *mode = NULL;
unsigned int mode_index;
unsigned int interval_index;
const struct ov8865_mode *mode = sensor->state.mode;
if (interval_enum->index > 0)
return -EINVAL;
/*
* Multiple modes with the same dimensions may have different frame
* intervals, so look up each relevant mode.
*/
for (mode_index = 0, interval_index = 0;
mode_index < ARRAY_SIZE(ov8865_modes); mode_index++) {
mode = &ov8865_modes[mode_index];
if (mode->output_size_x == interval_enum->width &&
mode->output_size_y == interval_enum->height) {
if (interval_index == interval_enum->index)
break;
interval_index++;
}
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
*r = *v4l2_subdev_get_try_crop(&sensor->subdev, state, pad);
break;
case V4L2_SUBDEV_FORMAT_ACTIVE:
r->height = mode->output_size_y;
r->width = mode->output_size_x;
r->top = (OV8865_NATIVE_HEIGHT - mode->output_size_y) / 2;
r->left = (OV8865_NATIVE_WIDTH - mode->output_size_x) / 2;
break;
}
}
if (mode_index == ARRAY_SIZE(ov8865_modes))
static int ov8865_get_selection(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *state,
struct v4l2_subdev_selection *sel)
{
struct ov8865_sensor *sensor = ov8865_subdev_sensor(subdev);
switch (sel->target) {
case V4L2_SEL_TGT_CROP:
mutex_lock(&sensor->mutex);
__ov8865_get_pad_crop(sensor, state, sel->pad,
sel->which, &sel->r);
mutex_unlock(&sensor->mutex);
break;
case V4L2_SEL_TGT_NATIVE_SIZE:
sel->r.top = 0;
sel->r.left = 0;
sel->r.width = OV8865_NATIVE_WIDTH;
sel->r.height = OV8865_NATIVE_HEIGHT;
break;
case V4L2_SEL_TGT_CROP_BOUNDS:
case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.top = OV8865_ACTIVE_START_TOP;
sel->r.left = OV8865_ACTIVE_START_LEFT;
sel->r.width = OV8865_ACTIVE_WIDTH;
sel->r.height = OV8865_ACTIVE_HEIGHT;
break;
default:
return -EINVAL;
interval_enum->interval = mode->frame_interval;
}
return 0;
}
@ -2702,7 +2867,8 @@ static const struct v4l2_subdev_pad_ops ov8865_subdev_pad_ops = {
.get_fmt = ov8865_get_fmt,
.set_fmt = ov8865_set_fmt,
.enum_frame_size = ov8865_enum_frame_size,
.enum_frame_interval = ov8865_enum_frame_interval,
.get_selection = ov8865_get_selection,
.set_selection = ov8865_get_selection,
};
static const struct v4l2_subdev_ops ov8865_subdev_ops = {
@ -2782,7 +2948,8 @@ static int ov8865_probe(struct i2c_client *client)
struct ov8865_sensor *sensor;
struct v4l2_subdev *subdev;
struct media_pad *pad;
unsigned long rate;
unsigned int rate = 0;
unsigned int i;
int ret;
sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
@ -2792,13 +2959,31 @@ static int ov8865_probe(struct i2c_client *client)
sensor->dev = dev;
sensor->i2c_client = client;
/* Regulators */
/* DVDD: digital core */
sensor->dvdd = devm_regulator_get(dev, "dvdd");
if (IS_ERR(sensor->dvdd))
return dev_err_probe(dev, PTR_ERR(sensor->dvdd),
"cannot get DVDD regulator\n");
/* DOVDD: digital I/O */
sensor->dovdd = devm_regulator_get(dev, "dovdd");
if (IS_ERR(sensor->dovdd))
return dev_err_probe(dev, PTR_ERR(sensor->dovdd),
"cannot get DOVDD regulator\n");
/* AVDD: analog */
sensor->avdd = devm_regulator_get(dev, "avdd");
if (IS_ERR(sensor->avdd))
return dev_err_probe(dev, PTR_ERR(sensor->avdd),
"cannot get AVDD (analog) regulator\n");
/* Graph Endpoint */
handle = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
if (!handle) {
dev_err(dev, "unable to find endpoint node\n");
return -EINVAL;
}
if (!handle)
return -EPROBE_DEFER;
sensor->endpoint.bus_type = V4L2_MBUS_CSI2_DPHY;
@ -2824,48 +3009,54 @@ static int ov8865_probe(struct i2c_client *client)
goto error_endpoint;
}
/* Regulators */
/* DVDD: digital core */
sensor->dvdd = devm_regulator_get(dev, "dvdd");
if (IS_ERR(sensor->dvdd)) {
dev_err(dev, "cannot get DVDD (digital core) regulator\n");
ret = PTR_ERR(sensor->dvdd);
goto error_endpoint;
}
/* DOVDD: digital I/O */
sensor->dovdd = devm_regulator_get(dev, "dovdd");
if (IS_ERR(sensor->dovdd)) {
dev_err(dev, "cannot get DOVDD (digital I/O) regulator\n");
ret = PTR_ERR(sensor->dovdd);
goto error_endpoint;
}
/* AVDD: analog */
sensor->avdd = devm_regulator_get(dev, "avdd");
if (IS_ERR(sensor->avdd)) {
dev_err(dev, "cannot get AVDD (analog) regulator\n");
ret = PTR_ERR(sensor->avdd);
goto error_endpoint;
}
/* External Clock */
sensor->extclk = devm_clk_get(dev, NULL);
if (IS_ERR(sensor->extclk)) {
if (PTR_ERR(sensor->extclk) == -ENOENT) {
dev_info(dev, "no external clock found, continuing...\n");
sensor->extclk = NULL;
} else if (IS_ERR(sensor->extclk)) {
dev_err(dev, "failed to get external clock\n");
ret = PTR_ERR(sensor->extclk);
goto error_endpoint;
}
rate = clk_get_rate(sensor->extclk);
if (rate != OV8865_EXTCLK_RATE) {
dev_err(dev, "clock rate %lu Hz is unsupported\n", rate);
/*
* We could have either a 24MHz or 19.2MHz clock rate from either dt or
* ACPI...but we also need to support the weird IPU3 case which will
* have an external clock AND a clock-frequency property. Check for the
* clock-frequency property and if found, set that rate if we managed
* to acquire a clock. This should cover the ACPI case. If the system
* uses devicetree then the configured rate should already be set, so
* we can just read it.
*/
ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
&rate);
if (!ret && sensor->extclk) {
ret = clk_set_rate(sensor->extclk, rate);
if (ret)
return dev_err_probe(dev, ret,
"failed to set clock rate\n");
} else if (ret && !sensor->extclk) {
return dev_err_probe(dev, ret, "invalid clock config\n");
}
sensor->extclk_rate = rate ? rate : clk_get_rate(sensor->extclk);
for (i = 0; i < ARRAY_SIZE(supported_extclk_rates); i++) {
if (sensor->extclk_rate == supported_extclk_rates[i])
break;
}
if (i == ARRAY_SIZE(supported_extclk_rates)) {
dev_err(dev, "clock rate %lu Hz is unsupported\n",
sensor->extclk_rate);
ret = -EINVAL;
goto error_endpoint;
}
sensor->pll_configs = ov8865_pll_configs[i];
/* Subdev, entity and pad */
subdev = &sensor->subdev;
@ -2891,14 +3082,16 @@ static int ov8865_probe(struct i2c_client *client)
if (ret)
goto error_mutex;
mutex_lock(&sensor->mutex);
ret = ov8865_state_init(sensor);
mutex_unlock(&sensor->mutex);
if (ret)
goto error_ctrls;
/* Runtime PM */
pm_runtime_enable(sensor->dev);
pm_runtime_set_suspended(sensor->dev);
pm_runtime_enable(sensor->dev);
/* V4L2 subdev register */
@ -2946,6 +3139,12 @@ static const struct dev_pm_ops ov8865_pm_ops = {
SET_RUNTIME_PM_OPS(ov8865_suspend, ov8865_resume, NULL)
};
static const struct acpi_device_id ov8865_acpi_match[] = {
{"INT347A"},
{ }
};
MODULE_DEVICE_TABLE(acpi, ov8865_acpi_match);
static const struct of_device_id ov8865_of_match[] = {
{ .compatible = "ovti,ov8865" },
{ }
@ -2956,6 +3155,7 @@ static struct i2c_driver ov8865_driver = {
.driver = {
.name = "ov8865",
.of_match_table = ov8865_of_match,
.acpi_match_table = ov8865_acpi_match,
.pm = &ov8865_pm_ops,
},
.probe_new = ov8865_probe,

View File

@ -130,16 +130,10 @@ static int s5c73m3_spi_probe(struct spi_device *spi)
return 0;
}
static int s5c73m3_spi_remove(struct spi_device *spi)
{
return 0;
}
int s5c73m3_register_spi_driver(struct s5c73m3 *state)
{
struct spi_driver *spidrv = &state->spidrv;
spidrv->remove = s5c73m3_spi_remove;
spidrv->probe = s5c73m3_spi_probe;
spidrv->driver.name = S5C73M3_SPI_DRV_NAME;
spidrv->driver.of_match_table = s5c73m3_spi_ids;

View File

@ -14,22 +14,6 @@
#include <media/media-entity.h>
#include <media/media-device.h>
static inline const char *gobj_type(enum media_gobj_type type)
{
switch (type) {
case MEDIA_GRAPH_ENTITY:
return "entity";
case MEDIA_GRAPH_PAD:
return "pad";
case MEDIA_GRAPH_LINK:
return "link";
case MEDIA_GRAPH_INTF_DEVNODE:
return "intf-devnode";
default:
return "unknown";
}
}
static inline const char *intf_type(struct media_interface *intf)
{
switch (intf->type) {
@ -64,12 +48,10 @@ __must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,
int idx_max)
{
idx_max = ALIGN(idx_max, BITS_PER_LONG);
ent_enum->bmap = kcalloc(idx_max / BITS_PER_LONG, sizeof(long),
GFP_KERNEL);
ent_enum->bmap = bitmap_zalloc(idx_max, GFP_KERNEL);
if (!ent_enum->bmap)
return -ENOMEM;
bitmap_zero(ent_enum->bmap, idx_max);
ent_enum->idx_max = idx_max;
return 0;
@ -78,7 +60,7 @@ EXPORT_SYMBOL_GPL(__media_entity_enum_init);
void media_entity_enum_cleanup(struct media_entity_enum *ent_enum)
{
kfree(ent_enum->bmap);
bitmap_free(ent_enum->bmap);
}
EXPORT_SYMBOL_GPL(media_entity_enum_cleanup);

View File

@ -185,6 +185,8 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
dma_addr_t cur_addr =
fc->read_ibi_reg(fc,dma1_008).dma_0x8.dma_cur_addr << 2;
u32 cur_pos = cur_addr - fc_pci->dma[0].dma_addr0;
if (cur_pos > fc_pci->dma[0].size * 2)
goto error;
deb_irq("%u irq: %08x cur_addr: %llx: cur_pos: %08x, last_cur_pos: %08x ",
jiffies_to_usecs(jiffies - fc_pci->last_irq),
@ -225,6 +227,7 @@ static irqreturn_t flexcop_pci_isr(int irq, void *dev_id)
ret = IRQ_NONE;
}
error:
spin_unlock_irqrestore(&fc_pci->irq_lock, flags);
return ret;
}

View File

@ -170,14 +170,14 @@ MODULE_VERSION(BTTV_VERSION);
/* ----------------------------------------------------------------------- */
/* sysfs */
static ssize_t show_card(struct device *cd,
static ssize_t card_show(struct device *cd,
struct device_attribute *attr, char *buf)
{
struct video_device *vfd = to_video_device(cd);
struct bttv *btv = video_get_drvdata(vfd);
return sprintf(buf, "%d\n", btv ? btv->c.type : UNSET);
}
static DEVICE_ATTR(card, S_IRUGO, show_card, NULL);
static DEVICE_ATTR_RO(card);
/* ----------------------------------------------------------------------- */
/* dvb auto-load setup */

View File

@ -236,7 +236,6 @@ bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned f_out)
u8 n1, hsdiv;
u8 regs[6];
int found = 0;
u16 clock_ctrl;
int retries = 3;
for (i = 0; i < ARRAY_SIZE(multipliers); i++) {
@ -260,9 +259,7 @@ bool cobalt_cpld_set_freq(struct cobalt *cobalt, unsigned f_out)
hsdiv = multipliers[i_best].hsdiv - 4;
rfreq = div_u64(dco << 28, f_xtal);
clock_ctrl = cpld_read(cobalt, SI570_CLOCK_CTRL);
clock_ctrl |= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_FPGA_CTRL;
clock_ctrl |= S01755_REG_CLOCK_CTRL_BITMAP_CLKHSMA_EN;
cpld_read(cobalt, SI570_CLOCK_CTRL);
regs[0] = (hsdiv << 5) | (n1 >> 2);
regs[1] = ((n1 & 0x3) << 6) | (rfreq >> 32);

View File

@ -51,12 +51,6 @@ struct snd_cx18_card *to_snd_cx18_card(struct v4l2_device *v4l2_dev)
return to_cx18(v4l2_dev)->alsa;
}
static inline
struct snd_cx18_card *p_to_snd_cx18_card(struct v4l2_device **v4l2_dev)
{
return container_of(v4l2_dev, struct snd_cx18_card, v4l2_dev);
}
static void snd_cx18_card_free(struct snd_cx18_card *cxsc)
{
if (cxsc == NULL)

View File

@ -337,13 +337,6 @@ static int cx25821_risc_decode(u32 risc)
return incr[risc >> 28] ? incr[risc >> 28] : 1;
}
static inline int i2c_slave_did_ack(struct i2c_adapter *i2c_adap)
{
struct cx25821_i2c *bus = i2c_adap->algo_data;
struct cx25821_dev *dev = bus->dev;
return cx_read(bus->reg_stat) & 0x01;
}
static void cx25821_registers_init(struct cx25821_dev *dev)
{
u32 tmp;

View File

@ -3,6 +3,7 @@
#include <linux/acpi.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/pci.h>
#include <linux/property.h>
#include <media/v4l2-fwnode.h>
@ -21,7 +22,9 @@
*/
static const struct cio2_sensor_config cio2_supported_sensors[] = {
/* Omnivision OV5693 */
CIO2_SENSOR_CONFIG("INT33BE", 0),
CIO2_SENSOR_CONFIG("INT33BE", 1, 419200000),
/* Omnivision OV8865 */
CIO2_SENSOR_CONFIG("INT347A", 1, 360000000),
/* Omnivision OV2680 */
CIO2_SENSOR_CONFIG("OVTI2680", 0),
};
@ -36,6 +39,18 @@ static const struct cio2_property_names prop_names = {
.link_frequencies = "link-frequencies",
};
static const char * const cio2_vcm_types[] = {
"ad5823",
"dw9714",
"ad5816",
"dw9719",
"dw9718",
"dw9806b",
"wv517s",
"lc898122xa",
"lc898212axb",
};
static int cio2_bridge_read_acpi_buffer(struct acpi_device *adev, char *id,
void *data, u32 size)
{
@ -132,6 +147,12 @@ static void cio2_bridge_create_fwnode_properties(
sensor->dev_properties[2] = PROPERTY_ENTRY_U32(
sensor->prop_names.orientation,
orientation);
if (sensor->ssdb.vcmtype) {
sensor->vcm_ref[0] =
SOFTWARE_NODE_REFERENCE(&sensor->swnodes[SWNODE_VCM]);
sensor->dev_properties[3] =
PROPERTY_ENTRY_REF_ARRAY("lens-focus", sensor->vcm_ref);
}
sensor->ep_properties[0] = PROPERTY_ENTRY_U32(
sensor->prop_names.bus_type,
@ -193,6 +214,33 @@ static void cio2_bridge_create_connection_swnodes(struct cio2_bridge *bridge,
sensor->node_names.endpoint,
&nodes[SWNODE_CIO2_PORT],
sensor->cio2_properties);
if (sensor->ssdb.vcmtype)
nodes[SWNODE_VCM] =
NODE_VCM(cio2_vcm_types[sensor->ssdb.vcmtype - 1]);
}
static void cio2_bridge_instantiate_vcm_i2c_client(struct cio2_sensor *sensor)
{
struct i2c_board_info board_info = { };
char name[16];
if (!sensor->ssdb.vcmtype)
return;
snprintf(name, sizeof(name), "%s-VCM", acpi_dev_name(sensor->adev));
board_info.dev_name = name;
strscpy(board_info.type, cio2_vcm_types[sensor->ssdb.vcmtype - 1],
ARRAY_SIZE(board_info.type));
board_info.swnode = &sensor->swnodes[SWNODE_VCM];
sensor->vcm_i2c_client =
i2c_acpi_new_device_by_fwnode(acpi_fwnode_handle(sensor->adev),
1, &board_info);
if (IS_ERR(sensor->vcm_i2c_client)) {
dev_warn(&sensor->adev->dev, "Error instantiation VCM i2c-client: %ld\n",
PTR_ERR(sensor->vcm_i2c_client));
sensor->vcm_i2c_client = NULL;
}
}
static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
@ -205,6 +253,7 @@ static void cio2_bridge_unregister_sensors(struct cio2_bridge *bridge)
software_node_unregister_nodes(sensor->swnodes);
ACPI_FREE(sensor->pld);
acpi_dev_put(sensor->adev);
i2c_unregister_device(sensor->vcm_i2c_client);
}
}
@ -237,9 +286,17 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
if (ret)
goto err_put_adev;
if (sensor->ssdb.vcmtype > ARRAY_SIZE(cio2_vcm_types)) {
dev_warn(&adev->dev, "Unknown VCM type %d\n",
sensor->ssdb.vcmtype);
sensor->ssdb.vcmtype = 0;
}
status = acpi_get_physical_device_location(adev->handle, &sensor->pld);
if (ACPI_FAILURE(status))
if (ACPI_FAILURE(status)) {
ret = -ENODEV;
goto err_put_adev;
}
if (sensor->ssdb.lanes > CIO2_MAX_LANES) {
dev_err(&adev->dev,
@ -265,6 +322,8 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
sensor->adev = acpi_dev_get(adev);
adev->fwnode.secondary = fwnode;
cio2_bridge_instantiate_vcm_i2c_client(sensor);
dev_info(&cio2->dev, "Found supported sensor %s\n",
acpi_dev_name(adev));
@ -304,6 +363,40 @@ err_unregister_sensors:
return ret;
}
/*
* The VCM cannot be probed until the PMIC is completely setup. We cannot rely
* on -EPROBE_DEFER for this, since the consumer<->supplier relations between
* the VCM and regulators/clks are not described in ACPI, instead they are
* passed as board-data to the PMIC drivers. Since -PROBE_DEFER does not work
* for the clks/regulators the VCM i2c-clients must not be instantiated until
* the PMIC is fully setup.
*
* The sensor/VCM ACPI device has an ACPI _DEP on the PMIC, check this using the
* acpi_dev_ready_for_enumeration() helper, like the i2c-core-acpi code does
* for the sensors.
*/
static int cio2_bridge_sensors_are_ready(void)
{
struct acpi_device *adev;
bool ready = true;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(cio2_supported_sensors); i++) {
const struct cio2_sensor_config *cfg =
&cio2_supported_sensors[i];
for_each_acpi_dev_match(adev, cfg->hid, NULL, -1) {
if (!adev->status.enabled)
continue;
if (!acpi_dev_ready_for_enumeration(adev))
ready = false;
}
}
return ready;
}
int cio2_bridge_init(struct pci_dev *cio2)
{
struct device *dev = &cio2->dev;
@ -312,6 +405,9 @@ int cio2_bridge_init(struct pci_dev *cio2)
unsigned int i;
int ret;
if (!cio2_bridge_sensors_are_ready())
return -EPROBE_DEFER;
bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
if (!bridge)
return -ENOMEM;

View File

@ -8,6 +8,8 @@
#include "ipu3-cio2.h"
struct i2c_client;
#define CIO2_HID "INT343E"
#define CIO2_MAX_LANES 4
#define MAX_NUM_LINK_FREQS 3
@ -42,12 +44,19 @@
.properties = _PROPS, \
}
#define NODE_VCM(_TYPE) \
(const struct software_node) { \
.name = _TYPE, \
}
enum cio2_sensor_swnodes {
SWNODE_SENSOR_HID,
SWNODE_SENSOR_PORT,
SWNODE_SENSOR_ENDPOINT,
SWNODE_CIO2_PORT,
SWNODE_CIO2_ENDPOINT,
/* Must be last because it is optional / maybe empty */
SWNODE_VCM,
SWNODE_COUNT
};
@ -106,8 +115,10 @@ struct cio2_sensor_config {
struct cio2_sensor {
char name[ACPI_ID_LEN];
struct acpi_device *adev;
struct i2c_client *vcm_i2c_client;
struct software_node swnodes[6];
/* SWNODE_COUNT + 1 for terminating empty node */
struct software_node swnodes[SWNODE_COUNT + 1];
struct cio2_node_names node_names;
struct cio2_sensor_ssdb ssdb;
@ -115,10 +126,11 @@ struct cio2_sensor {
struct cio2_property_names prop_names;
struct property_entry ep_properties[5];
struct property_entry dev_properties[4];
struct property_entry dev_properties[5];
struct property_entry cio2_properties[3];
struct software_node_ref_args local_ref[1];
struct software_node_ref_args remote_ref[1];
struct software_node_ref_args vcm_ref[1];
};
struct cio2_bridge {

View File

@ -1713,11 +1713,6 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
struct cio2_device *cio2;
int r;
cio2 = devm_kzalloc(dev, sizeof(*cio2), GFP_KERNEL);
if (!cio2)
return -ENOMEM;
cio2->pci_dev = pci_dev;
/*
* On some platforms no connections to sensors are defined in firmware,
* if the device has no endpoints then we can try to build those as
@ -1735,6 +1730,11 @@ static int cio2_pci_probe(struct pci_dev *pci_dev,
return r;
}
cio2 = devm_kzalloc(dev, sizeof(*cio2), GFP_KERNEL);
if (!cio2)
return -ENOMEM;
cio2->pci_dev = pci_dev;
r = pcim_enable_device(pci_dev);
if (r) {
dev_err(dev, "failed to enable device (%d)\n", r);
@ -1966,12 +1966,19 @@ static int __maybe_unused cio2_suspend(struct device *dev)
struct pci_dev *pci_dev = to_pci_dev(dev);
struct cio2_device *cio2 = pci_get_drvdata(pci_dev);
struct cio2_queue *q = cio2->cur_queue;
int r;
dev_dbg(dev, "cio2 suspend\n");
if (!cio2->streaming)
return 0;
/* Stop stream */
r = v4l2_subdev_call(q->sensor, video, s_stream, 0);
if (r) {
dev_err(dev, "failed to stop sensor streaming\n");
return r;
}
cio2_hw_exit(cio2, q);
synchronize_irq(pci_dev->irq);
@ -2005,8 +2012,16 @@ static int __maybe_unused cio2_resume(struct device *dev)
}
r = cio2_hw_init(cio2, q);
if (r)
if (r) {
dev_err(dev, "fail to init cio2 hw\n");
return r;
}
r = v4l2_subdev_call(q->sensor, video, s_stream, 1);
if (r) {
dev_err(dev, "fail to start sensor streaming\n");
cio2_hw_exit(cio2, q);
}
return r;
}

View File

@ -48,12 +48,6 @@ struct snd_ivtv_card *to_snd_ivtv_card(struct v4l2_device *v4l2_dev)
return to_ivtv(v4l2_dev)->alsa;
}
static inline
struct snd_ivtv_card *p_to_snd_ivtv_card(struct v4l2_device **v4l2_dev)
{
return container_of(v4l2_dev, struct snd_ivtv_card, v4l2_dev);
}
static void snd_ivtv_card_free(struct snd_ivtv_card *itvsc)
{
if (itvsc == NULL)

View File

@ -42,7 +42,7 @@
/* card parameters */
static int ivtvfb_card_id = -1;
static int ivtvfb_debug = 0;
static int ivtvfb_debug;
static bool ivtvfb_force_pat = IS_ENABLED(CONFIG_VIDEO_FB_IVTV_FORCE_PAT);
static bool osd_laced;
static int osd_depth;

View File

@ -685,12 +685,6 @@ static void pt3_remove(struct pci_dev *pdev)
for (i = PT3_NUM_FE - 1; i >= 0; i--)
pt3_cleanup_adapter(pt3, i);
i2c_del_adapter(&pt3->i2c_adap);
kfree(pt3->i2c_buf);
pci_iounmap(pt3->pdev, pt3->regs[0]);
pci_iounmap(pt3->pdev, pt3->regs[1]);
pci_release_regions(pdev);
pci_disable_device(pdev);
kfree(pt3);
}
static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@ -704,14 +698,14 @@ static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (pci_read_config_byte(pdev, PCI_REVISION_ID, &rev) || rev != 1)
return -ENODEV;
ret = pci_enable_device(pdev);
ret = pcim_enable_device(pdev);
if (ret < 0)
return -ENODEV;
pci_set_master(pdev);
ret = pci_request_regions(pdev, DRV_NAME);
ret = pcim_iomap_regions(pdev, BIT(0) | BIT(2), DRV_NAME);
if (ret < 0)
goto err_disable_device;
return ret;
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
if (ret == 0)
@ -722,42 +716,32 @@ static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
else {
dev_err(&pdev->dev, "Failed to set DMA mask\n");
goto err_release_regions;
return ret;
}
dev_info(&pdev->dev, "Use 32bit DMA\n");
}
pt3 = kzalloc(sizeof(*pt3), GFP_KERNEL);
if (!pt3) {
ret = -ENOMEM;
goto err_release_regions;
}
pt3 = devm_kzalloc(&pdev->dev, sizeof(*pt3), GFP_KERNEL);
if (!pt3)
return -ENOMEM;
pci_set_drvdata(pdev, pt3);
pt3->pdev = pdev;
mutex_init(&pt3->lock);
pt3->regs[0] = pci_ioremap_bar(pdev, 0);
pt3->regs[1] = pci_ioremap_bar(pdev, 2);
if (pt3->regs[0] == NULL || pt3->regs[1] == NULL) {
dev_err(&pdev->dev, "Failed to ioremap\n");
ret = -ENOMEM;
goto err_kfree;
}
pt3->regs[0] = pcim_iomap_table(pdev)[0];
pt3->regs[1] = pcim_iomap_table(pdev)[2];
ver = ioread32(pt3->regs[0] + REG_VERSION);
if ((ver >> 16) != 0x0301) {
dev_warn(&pdev->dev, "PT%d, I/F-ver.:%d not supported\n",
ver >> 24, (ver & 0x00ff0000) >> 16);
ret = -ENODEV;
goto err_iounmap;
return -ENODEV;
}
pt3->num_bufs = clamp_val(num_bufs, MIN_DATA_BUFS, MAX_DATA_BUFS);
pt3->i2c_buf = kmalloc(sizeof(*pt3->i2c_buf), GFP_KERNEL);
if (pt3->i2c_buf == NULL) {
ret = -ENOMEM;
goto err_iounmap;
}
pt3->i2c_buf = devm_kmalloc(&pdev->dev, sizeof(*pt3->i2c_buf), GFP_KERNEL);
if (!pt3->i2c_buf)
return -ENOMEM;
i2c = &pt3->i2c_adap;
i2c->owner = THIS_MODULE;
i2c->algo = &pt3_i2c_algo;
@ -767,7 +751,7 @@ static int pt3_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
i2c_set_adapdata(i2c, pt3);
ret = i2c_add_adapter(i2c);
if (ret < 0)
goto err_i2cbuf;
return ret;
for (i = 0; i < PT3_NUM_FE; i++) {
ret = pt3_alloc_adapter(pt3, i);
@ -799,21 +783,7 @@ err_cleanup_adapters:
while (i >= 0)
pt3_cleanup_adapter(pt3, i--);
i2c_del_adapter(i2c);
err_i2cbuf:
kfree(pt3->i2c_buf);
err_iounmap:
if (pt3->regs[0])
pci_iounmap(pdev, pt3->regs[0]);
if (pt3->regs[1])
pci_iounmap(pdev, pt3->regs[1]);
err_kfree:
kfree(pt3);
err_release_regions:
pci_release_regions(pdev);
err_disable_device:
pci_disable_device(pdev);
return ret;
}
static const struct pci_device_id pt3_id_table[] = {

View File

@ -56,11 +56,6 @@ struct saa7134_go7007 {
dma_addr_t bottom_dma;
};
static inline struct saa7134_go7007 *to_state(struct v4l2_subdev *sd)
{
return container_of(sd, struct saa7134_go7007, sd);
}
static const struct go7007_board_info board_voyager = {
.flags = 0,
.sensor_flags = GO7007_SENSOR_656 |
@ -385,7 +380,7 @@ MODULE_FIRMWARE("go7007/go7007tv.bin");
static int saa7134_go7007_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
{
#if 0
struct saa7134_go7007 *saa = to_state(sd);
struct saa7134_go7007 *saa = container_of(sd, struct saa7134_go7007, sd);
struct saa7134_dev *dev = saa->dev;
return saa7134_s_std_internal(dev, NULL, norm);

View File

@ -284,7 +284,12 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d
hexium_set_input(hexium, 0);
hexium->cur_input = 0;
saa7146_vv_init(dev, &vv_data);
ret = saa7146_vv_init(dev, &vv_data);
if (ret) {
i2c_del_adapter(&hexium->i2c_adapter);
kfree(hexium);
return ret;
}
vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
vv_data.vid_ops.vidioc_g_input = vidioc_g_input;

View File

@ -355,10 +355,16 @@ static struct saa7146_ext_vv vv_data;
static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
{
struct hexium *hexium = (struct hexium *) dev->ext_priv;
int ret;
DEB_EE("\n");
saa7146_vv_init(dev, &vv_data);
ret = saa7146_vv_init(dev, &vv_data);
if (ret) {
pr_err("Error in saa7146_vv_init()\n");
return ret;
}
vv_data.vid_ops.vidioc_enum_input = vidioc_enum_input;
vv_data.vid_ops.vidioc_g_input = vidioc_g_input;
vv_data.vid_ops.vidioc_s_input = vidioc_s_input;

View File

@ -340,7 +340,7 @@ static int mxb_init_done(struct saa7146_dev* dev)
struct tuner_setup tun_setup;
v4l2_std_id std = V4L2_STD_PAL_BG;
int i = 0, err = 0;
int i, err = 0;
/* mute audio on tea6420s */
tea6420_route(mxb, 6);
@ -349,7 +349,6 @@ static int mxb_init_done(struct saa7146_dev* dev)
saa7111a_call(mxb, video, s_std, std);
/* select tuner-output on saa7111a */
i = 0;
saa7111a_call(mxb, video, s_routing, SAA7115_COMPOSITE0,
SAA7111_FMT_CCIR, 0);
@ -683,10 +682,16 @@ static struct saa7146_ext_vv vv_data;
static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info)
{
struct mxb *mxb;
int ret;
DEB_EE("dev:%p\n", dev);
saa7146_vv_init(dev, &vv_data);
ret = saa7146_vv_init(dev, &vv_data);
if (ret) {
ERR("Error in saa7146_vv_init()");
return ret;
}
if (mxb_probe(dev)) {
saa7146_vv_release(dev);
return -1;

View File

@ -391,12 +391,12 @@ static int solo_send_desc(struct solo_enc_dev *solo_enc, int skip,
}
/* Extract values from VOP header - VE_STATUSxx */
static inline int vop_interlaced(const vop_header *vh)
static inline __always_unused int vop_interlaced(const vop_header *vh)
{
return (__le32_to_cpu((*vh)[0]) >> 30) & 1;
}
static inline u8 vop_channel(const vop_header *vh)
static inline __always_unused u8 vop_channel(const vop_header *vh)
{
return (__le32_to_cpu((*vh)[0]) >> 24) & 0x1F;
}
@ -411,12 +411,12 @@ static inline u32 vop_mpeg_size(const vop_header *vh)
return __le32_to_cpu((*vh)[0]) & 0xFFFFF;
}
static inline u8 vop_hsize(const vop_header *vh)
static inline u8 __always_unused vop_hsize(const vop_header *vh)
{
return (__le32_to_cpu((*vh)[1]) >> 8) & 0xFF;
}
static inline u8 vop_vsize(const vop_header *vh)
static inline u8 __always_unused vop_vsize(const vop_header *vh)
{
return __le32_to_cpu((*vh)[1]) & 0xFF;
}
@ -436,12 +436,12 @@ static inline u32 vop_jpeg_size(const vop_header *vh)
return __le32_to_cpu((*vh)[4]) & 0xFFFFF;
}
static inline u32 vop_sec(const vop_header *vh)
static inline u32 __always_unused vop_sec(const vop_header *vh)
{
return __le32_to_cpu((*vh)[5]);
}
static inline u32 vop_usec(const vop_header *vh)
static inline __always_unused u32 vop_usec(const vop_header *vh)
{
return __le32_to_cpu((*vh)[6]);
}

View File

@ -333,11 +333,10 @@ static void tw5864_finidev(struct pci_dev *pci_dev)
/* release resources */
iounmap(dev->mmio);
release_mem_region(pci_resource_start(pci_dev, 0),
pci_resource_len(pci_dev, 0));
pci_release_regions(pci_dev);
pci_disable_device(pci_dev);
v4l2_device_unregister(&dev->v4l2_dev);
devm_kfree(&pci_dev->dev, dev);
}
static struct pci_driver tw5864_pci_driver = {

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