forked from Minki/linux
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:
commit
9bcbf894b6
1
.mailmap
1
.mailmap
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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>;
|
||||
};
|
||||
|
||||
...
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
212
Documentation/devicetree/bindings/media/i2c/adv748x.yaml
Normal file
212
Documentation/devicetree/bindings/media/i2c/adv748x.yaml
Normal 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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -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>;
|
||||
};
|
65
Documentation/devicetree/bindings/media/renesas,jpu.yaml
Normal file
65
Documentation/devicetree/bindings/media/renesas,jpu.yaml
Normal 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>;
|
||||
};
|
71
Documentation/devicetree/bindings/media/st,stm32-dma2d.yaml
Normal file
71
Documentation/devicetree/bindings/media/st,stm32-dma2d.yaml
Normal 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";
|
||||
};
|
||||
|
||||
...
|
@ -21,6 +21,7 @@ Video4Linux (V4L) drivers
|
||||
pvrusb2
|
||||
pxa_camera
|
||||
radiotrack
|
||||
rkisp1
|
||||
saa7134-devel
|
||||
sh_mobile_ceu_camera
|
||||
tuners
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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``
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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>`,
|
||||
|
@ -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``
|
||||
|
@ -7833,7 +7833,7 @@ The following table lists existing HSV/HSL formats.
|
||||
|
||||
.. raw:: latex
|
||||
|
||||
\normalsize
|
||||
\endgroup
|
||||
|
||||
|
||||
JPEG Compressed Formats
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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`
|
||||
|
||||
|
28
MAINTAINERS
28
MAINTAINERS
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
|
@ -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 &&
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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, },
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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", },
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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);
|
||||
|
@ -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");
|
||||
|
@ -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
1537
drivers/media/i2c/ov5693.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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[] = {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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]);
|
||||
}
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user