media updates for v5.12-rc1
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAmAtJ+IACgkQCF8+vY7k 4RX8eBAAhTzVFopTBMAW2+FjBTtUGwn+LnrIG9O1HrFp4yjTfe/MnZWXkVRZXjqo cYZehdab0j8636aLTs86Y6mEMHGPdm6V0hQhgvXoy7FqQqLq52K1bpXL+4a0lNYx HE8OLbOvSM49RlP9ZU978NuUzfWLCW+dGlXuGxdJDU/fmbKdaSjvelRjjfNFhBo3 ENK2LXVnebvtttjq4uSQ5LjeJEBBsIldK947/lvu7zJnnfDlXXdtrsuonkWvRp+s 8M1+AQ0F/edKX1atXSCZZqLNhUNaswHWc6lMmIL8qGvMZjZffWi4KwfcB0XXvrAW IJYfaLQ9kvEaFaSLZ3E5dCPO5CQLUkR4YOmSSUdK16fpyb1WzVjWsKPUjxsk5IeB IitjX5KkP5T+uA8pmzQE9dX2Do7no9A/765f2uqpaQxYbze1IT+6qWMisLrlguZe NV10Fah2dSehmqqfnnIjDE40rP3iff6xKheTeLzF1e4j8JiNDPCRI8z1i8M2OJ1e jIEC4Pq4/mGmn+InJOzxPloel1CnCL+d0bU/wrAhEyg0Ss+M95/+KgK6LCEzgyei /+2II2tABxtanO8mxp4jts3jPduqVuV9EEpWquzf9bPqFy5mBFD3NbOJNn/5ZVlx /DhvjRxiEedQihQ9Pt0OQxiJm6InopaeTihAvMQrMH3nLBsF2/Y= =/wKL -----END PGP SIGNATURE----- Merge tag 'media/v5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media Pull media updates from Mauro Carvalho Chehab: - some core fixes in VB2 mem2mem support - some improvements and cleanups in V4L2 async kAPI - newer controls in V4L2 API for H-264 and HEVC codecs - allegro-dvt driver was promoted from staging - new i2c sendor drivers: imx334, ov5648, ov8865 - new automobile camera module: rdacm21 - ipu3 cio2 driver started gained support for some ACPI BIOSes - new ATSC frontend: MaxLinear mxl692 VSB tuner/demod - the SMIA/CCS driver gained more support for CSS standard - several driver fixes, updates and improvements * tag 'media/v5.12-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (362 commits) media: v4l: async: Fix kerneldoc documentation for async functions media: i2c: max9271: Add MODULE_* macros media: i2c: Kconfig: Make MAX9271 a module media: imx334: 'ret' is uninitialized, should have been PTR_ERR() media: i2c: Add imx334 camera sensor driver media: dt-bindings: media: Add bindings for imx334 media: ov8856: Configure sensor for GRBG Bayer for all modes media: i2c: imx219: Implement V4L2_CID_LINK_FREQ control media: ov5675: fix vflip/hflip control media: ipu3-cio2: Build bridge only if ACPI is enabled media: Remove the legacy v4l2-clk API media: ov6650: Use the generic clock framework media: mt9m111: Use the generic clock framework media: ov9640: Use the generic clock framework media: pxa_camera: Drop the v4l2-clk clock register media: mach-pxa: Register the camera sensor fixed-rate clock media: i2c: imx258: get clock from device properties and enable it via runtime PM media: i2c: imx258: simplify getting state container media: i2c: imx258: add support for binding via device tree media: dt-bindings: media: imx258: add bindings for IMX258 sensor ...
This commit is contained in:
commit
de16175788
@ -111,8 +111,8 @@ of the following host1x client modules:
|
||||
|
||||
endpoint (required node)
|
||||
Required properties:
|
||||
- data-lanes: an array of data lane from 1 to 4. Valid array
|
||||
lengths are 1/2/4.
|
||||
- data-lanes: an array of data lane from 1 to 8. Valid array
|
||||
lengths are 1/2/4/8.
|
||||
- remote-endpoint: phandle to sensor 'endpoint' node.
|
||||
|
||||
port@1 (required node)
|
||||
|
105
Documentation/devicetree/bindings/media/allegro,al5e.yaml
Normal file
105
Documentation/devicetree/bindings/media/allegro,al5e.yaml
Normal file
@ -0,0 +1,105 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/allegro,al5e.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Allegro DVT Video IP Codecs Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Michael Tretter <m.tretter@pengutronix.de>
|
||||
|
||||
description: |-
|
||||
Allegro DVT video IP codecs present in the Xilinx ZynqMP SoC. The IP core may
|
||||
either be a H.264/H.265 encoder or H.264/H.265 decoder ip core.
|
||||
|
||||
Each actual codec engine is controlled by a microcontroller (MCU). Host
|
||||
software uses a provided mailbox interface to communicate with the MCU. The
|
||||
MCUs share an interrupt.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: allegro,al5e-1.1
|
||||
- const: allegro,al5e
|
||||
- items:
|
||||
- const: allegro,al5d-1.1
|
||||
- const: allegro,al5d
|
||||
|
||||
reg:
|
||||
items:
|
||||
- description: The registers
|
||||
- description: The SRAM
|
||||
|
||||
reg-names:
|
||||
items:
|
||||
- const: regs
|
||||
- const: sram
|
||||
|
||||
interrupts:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: Core clock
|
||||
- description: MCU clock
|
||||
- description: Core AXI master port clock
|
||||
- description: MCU AXI master port clock
|
||||
- description: AXI4-Lite slave port clock
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: core_clk
|
||||
- const: mcu_clk
|
||||
- const: m_axi_core_aclk
|
||||
- const: m_axi_mcu_aclk
|
||||
- const: s_axi_lite_aclk
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- reg-names
|
||||
- interrupts
|
||||
- clocks
|
||||
- clock-names
|
||||
|
||||
additionalProperties: False
|
||||
|
||||
examples:
|
||||
- |
|
||||
fpga {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
al5e: video-codec@a0009000 {
|
||||
compatible = "allegro,al5e-1.1", "allegro,al5e";
|
||||
reg = <0 0xa0009000 0 0x1000>,
|
||||
<0 0xa0000000 0 0x8000>;
|
||||
reg-names = "regs", "sram";
|
||||
interrupts = <0 96 4>;
|
||||
clocks = <&xlnx_vcu 0>, <&xlnx_vcu 1>,
|
||||
<&clkc 71>, <&clkc 71>, <&clkc 71>;
|
||||
clock-names = "core_clk", "mcu_clk", "m_axi_core_aclk",
|
||||
"m_axi_mcu_aclk", "s_axi_lite_aclk";
|
||||
};
|
||||
};
|
||||
- |
|
||||
fpga {
|
||||
#address-cells = <2>;
|
||||
#size-cells = <2>;
|
||||
|
||||
al5d: video-codec@a0029000 {
|
||||
compatible = "allegro,al5d-1.1", "allegro,al5d";
|
||||
reg = <0 0xa0029000 0 0x1000>,
|
||||
<0 0xa0020000 0 0x8000>;
|
||||
reg-names = "regs", "sram";
|
||||
interrupts = <0 96 4>;
|
||||
clocks = <&xlnx_vcu 2>, <&xlnx_vcu 3>,
|
||||
<&clkc 71>, <&clkc 71>, <&clkc 71>;
|
||||
clock-names = "core_clk", "mcu_clk", "m_axi_core_aclk",
|
||||
"m_axi_mcu_aclk", "s_axi_lite_aclk";
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -1,43 +0,0 @@
|
||||
Device-tree bindings for the Allegro DVT video IP codecs present in the Xilinx
|
||||
ZynqMP SoC. The IP core may either be a H.264/H.265 encoder or H.264/H.265
|
||||
decoder ip core.
|
||||
|
||||
Each actual codec engines is controlled by a microcontroller (MCU). Host
|
||||
software uses a provided mailbox interface to communicate with the MCU. The
|
||||
MCU share an interrupt.
|
||||
|
||||
Required properties:
|
||||
- compatible: value should be one of the following
|
||||
"allegro,al5e-1.1", "allegro,al5e": encoder IP core
|
||||
"allegro,al5d-1.1", "allegro,al5d": decoder IP core
|
||||
- reg: base and length of the memory mapped register region and base and
|
||||
length of the memory mapped sram
|
||||
- reg-names: must include "regs" and "sram"
|
||||
- interrupts: shared interrupt from the MCUs to the processing system
|
||||
- clocks: must contain an entry for each entry in clock-names
|
||||
- clock-names: must include "core_clk", "mcu_clk", "m_axi_core_aclk",
|
||||
"m_axi_mcu_aclk", "s_axi_lite_aclk"
|
||||
|
||||
Example:
|
||||
al5e: video-codec@a0009000 {
|
||||
compatible = "allegro,al5e-1.1", "allegro,al5e";
|
||||
reg = <0 0xa0009000 0 0x1000>,
|
||||
<0 0xa0000000 0 0x8000>;
|
||||
reg-names = "regs", "sram";
|
||||
interrupts = <0 96 4>;
|
||||
clocks = <&xlnx_vcu 0>, <&xlnx_vcu 1>,
|
||||
<&clkc 71>, <&clkc 71>, <&clkc 71>;
|
||||
clock-names = "core_clk", "mcu_clk", "m_axi_core_aclk",
|
||||
"m_axi_mcu_aclk", "s_axi_lite_aclk"
|
||||
};
|
||||
al5d: video-codec@a0029000 {
|
||||
compatible = "allegro,al5d-1.1", "allegro,al5d";
|
||||
reg = <0 0xa0029000 0 0x1000>,
|
||||
<0 0xa0020000 0 0x8000>;
|
||||
reg-names = "regs", "sram";
|
||||
interrupts = <0 96 4>;
|
||||
clocks = <&xlnx_vcu 2>, <&xlnx_vcu 3>,
|
||||
<&clkc 71>, <&clkc 71>, <&clkc 71>;
|
||||
clock-names = "core_clk", "mcu_clk", "m_axi_core_aclk",
|
||||
"m_axi_mcu_aclk", "s_axi_lite_aclk"
|
||||
};
|
@ -67,14 +67,14 @@ properties:
|
||||
interconnect-names:
|
||||
const: dma-mem
|
||||
|
||||
# See ./video-interfaces.txt for details
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
bus-width:
|
||||
@ -83,7 +83,6 @@ properties:
|
||||
data-active: true
|
||||
hsync-active: true
|
||||
pclk-sample: true
|
||||
remote-endpoint: true
|
||||
vsync-active: true
|
||||
|
||||
required:
|
||||
@ -91,12 +90,8 @@ properties:
|
||||
- data-active
|
||||
- hsync-active
|
||||
- pclk-sample
|
||||
- remote-endpoint
|
||||
- vsync-active
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -40,17 +40,15 @@ properties:
|
||||
resets:
|
||||
maxItems: 1
|
||||
|
||||
# See ./video-interfaces.txt for details
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
remote-endpoint: true
|
||||
|
||||
bus-width:
|
||||
enum: [ 8, 10, 12, 16 ]
|
||||
|
||||
@ -60,10 +58,6 @@ properties:
|
||||
|
||||
required:
|
||||
- bus-width
|
||||
- remote-endpoint
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
|
@ -36,17 +36,9 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
type: object
|
||||
description:
|
||||
A node containing a single endpoint as doucmented in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
ports:
|
||||
type: object
|
||||
description:
|
||||
A node containing input and output port nodes with endpoint definitions
|
||||
as documented in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
ports: true
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
@ -80,25 +72,20 @@ allOf:
|
||||
then:
|
||||
properties:
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
'#size-cells':
|
||||
const: 0
|
||||
port@3:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Output port
|
||||
|
||||
patternProperties:
|
||||
"^port@[0-2]$":
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Input port
|
||||
|
||||
required:
|
||||
- port@3
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- ports
|
||||
|
||||
@ -110,25 +97,20 @@ allOf:
|
||||
then:
|
||||
properties:
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
'#size-cells':
|
||||
const: 0
|
||||
port@6:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Output port
|
||||
|
||||
patternProperties:
|
||||
"^port@[0-5]$":
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Input port
|
||||
|
||||
required:
|
||||
- port@6
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- ports
|
||||
|
||||
|
@ -64,16 +64,12 @@ properties:
|
||||
description:
|
||||
Select which input is selected after reset.
|
||||
|
||||
ports:
|
||||
type: object
|
||||
description:
|
||||
A node containing input and output port nodes with endpoint definitions
|
||||
as documented in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
ports: true
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- ports
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
@ -86,26 +82,19 @@ allOf:
|
||||
then:
|
||||
properties:
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
'#size-cells':
|
||||
const: 0
|
||||
port@0:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Input port
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Output port
|
||||
|
||||
required:
|
||||
- port@1
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- ports
|
||||
|
||||
- if:
|
||||
properties:
|
||||
compatible:
|
||||
@ -114,28 +103,20 @@ allOf:
|
||||
then:
|
||||
properties:
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
'#size-cells':
|
||||
const: 0
|
||||
port@2:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Output port
|
||||
|
||||
patternProperties:
|
||||
"^port@[0-1]$":
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Input port
|
||||
|
||||
required:
|
||||
- port@2
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- ports
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
@ -41,9 +41,9 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: |
|
||||
Output video port. See ../video-interfaces.txt.
|
||||
Output video port.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
@ -86,33 +86,9 @@ properties:
|
||||
maxItems: 3
|
||||
|
||||
port:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
description: -|
|
||||
Connection to the remote GMSL endpoint are modelled using the OF graph
|
||||
bindings in accordance with the video interface bindings defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
|
||||
The device node contains a single "port" child node with a single
|
||||
"endpoint" sub-device.
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
remote-endpoint:
|
||||
description: -|
|
||||
phandle to the remote GMSL endpoint sub-node in the remote node
|
||||
port.
|
||||
maxItems: 1
|
||||
|
||||
required:
|
||||
- remote-endpoint
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Connection to the remote GMSL endpoint.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
@ -44,12 +44,15 @@ properties:
|
||||
Reference to the GPIO connected to the xclr pin, if any.
|
||||
Must be released (set high) after all supplies are applied.
|
||||
|
||||
# See ../video-interfaces.txt for more details
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes:
|
||||
description: |-
|
||||
@ -60,16 +63,8 @@ properties:
|
||||
- const: 1
|
||||
- const: 2
|
||||
|
||||
clock-noncontinuous:
|
||||
type: boolean
|
||||
description: |-
|
||||
MIPI CSI-2 clock is non-continuous if this property is present,
|
||||
otherwise it's continuous.
|
||||
|
||||
link-frequencies:
|
||||
$ref: /schemas/types.yaml#/definitions/uint64-array
|
||||
description:
|
||||
Allowed data bus frequencies.
|
||||
clock-noncontinuous: true
|
||||
link-frequencies: true
|
||||
|
||||
required:
|
||||
- link-frequencies
|
||||
|
134
Documentation/devicetree/bindings/media/i2c/imx258.yaml
Normal file
134
Documentation/devicetree/bindings/media/i2c/imx258.yaml
Normal file
@ -0,0 +1,134 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/i2c/imx258.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sony IMX258 13 Mpixel CMOS Digital Image Sensor
|
||||
|
||||
maintainers:
|
||||
- Krzysztof Kozlowski <krzk@kernel.org>
|
||||
|
||||
description: |-
|
||||
IMX258 is a diagonal 5.867mm (Type 1/3.06) 13 Mega-pixel CMOS active pixel
|
||||
type stacked image sensor with a square pixel array of size 4208 x 3120. It
|
||||
is programmable through I2C interface. Image data is sent through MIPI
|
||||
CSI-2.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sony,imx258
|
||||
|
||||
assigned-clocks: true
|
||||
assigned-clock-parents: true
|
||||
assigned-clock-rates: true
|
||||
|
||||
clocks:
|
||||
description:
|
||||
Clock frequency from 6 to 27 MHz.
|
||||
maxItems: 1
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: |-
|
||||
Reference to the GPIO connected to the XCLR pin, if any.
|
||||
|
||||
vana-supply:
|
||||
description:
|
||||
Analog voltage (VANA) supply, 2.7 V
|
||||
|
||||
vdig-supply:
|
||||
description:
|
||||
Digital I/O voltage (VDIG) supply, 1.2 V
|
||||
|
||||
vif-supply:
|
||||
description:
|
||||
Interface voltage (VIF) supply, 1.8 V
|
||||
|
||||
# See ../video-interfaces.txt for more details
|
||||
port:
|
||||
type: object
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
properties:
|
||||
data-lanes:
|
||||
oneOf:
|
||||
- items:
|
||||
- const: 1
|
||||
- const: 2
|
||||
- const: 3
|
||||
- const: 4
|
||||
- items:
|
||||
- const: 1
|
||||
- const: 2
|
||||
|
||||
link-frequencies:
|
||||
allOf:
|
||||
- $ref: /schemas/types.yaml#/definitions/uint64-array
|
||||
description:
|
||||
Allowed data bus frequencies.
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
- link-frequencies
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sensor@6c {
|
||||
compatible = "sony,imx258";
|
||||
reg = <0x6c>;
|
||||
clocks = <&imx258_clk>;
|
||||
|
||||
port {
|
||||
endpoint {
|
||||
remote-endpoint = <&csi1_ep>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
link-frequencies = /bits/ 64 <320000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/* Oscillator on the camera board */
|
||||
imx258_clk: clk {
|
||||
compatible = "fixed-clock";
|
||||
#clock-cells = <0>;
|
||||
clock-frequency = <19200000>;
|
||||
};
|
||||
|
||||
- |
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
sensor@6c {
|
||||
compatible = "sony,imx258";
|
||||
reg = <0x6c>;
|
||||
clocks = <&imx258_clk>;
|
||||
|
||||
assigned-clocks = <&imx258_clk>;
|
||||
assigned-clock-rates = <19200000>;
|
||||
|
||||
port {
|
||||
endpoint {
|
||||
remote-endpoint = <&csi1_ep>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
link-frequencies = /bits/ 64 <633600000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -50,82 +50,62 @@ properties:
|
||||
'#gpio-cells':
|
||||
const: 2
|
||||
|
||||
ports:
|
||||
type: object
|
||||
maxim,reverse-channel-microvolt:
|
||||
minimum: 30000
|
||||
maximum: 200000
|
||||
default: 170000
|
||||
description: |
|
||||
The connections to the MAX9286 GMSL and its endpoint nodes are modelled
|
||||
using the OF graph bindings in accordance with the video interface
|
||||
bindings defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
Initial amplitude of the reverse control channel, in micro volts.
|
||||
|
||||
The following table lists the port number corresponding to each device
|
||||
port.
|
||||
The initial amplitude shall be adjusted to a value compatible with the
|
||||
configuration of the connected remote serializer.
|
||||
|
||||
Port Description
|
||||
----------------------------------------
|
||||
Port 0 GMSL Input 0
|
||||
Port 1 GMSL Input 1
|
||||
Port 2 GMSL Input 2
|
||||
Port 3 GMSL Input 3
|
||||
Port 4 CSI-2 Output
|
||||
Some camera modules (for example RDACM20) include an on-board MCU that
|
||||
pre-programs the embedded serializer with power supply noise immunity
|
||||
(high-threshold) enabled. A typical value of the deserializer's reverse
|
||||
channel amplitude to communicate with pre-programmed serializers is
|
||||
170000 micro volts.
|
||||
|
||||
A typical value for the reverse channel amplitude to communicate with
|
||||
a remote serializer whose high-threshold noise immunity is not enabled
|
||||
is 100000 micro volts
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
port@0:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: GMSL Input 0
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
port@1:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: GMSL Input 1
|
||||
|
||||
port@[0-3]:
|
||||
type: object
|
||||
properties:
|
||||
reg:
|
||||
enum: [ 0, 1, 2, 3 ]
|
||||
port@2:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: GMSL Input 2
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
remote-endpoint:
|
||||
description: |
|
||||
phandle to the remote GMSL source endpoint subnode in the
|
||||
remote node port.
|
||||
|
||||
required:
|
||||
- remote-endpoint
|
||||
|
||||
required:
|
||||
- reg
|
||||
- endpoint
|
||||
|
||||
additionalProperties: false
|
||||
port@3:
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: GMSL Input 3
|
||||
|
||||
port@4:
|
||||
type: object
|
||||
properties:
|
||||
reg:
|
||||
const: 4
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: CSI-2 Output
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
remote-endpoint:
|
||||
description: phandle to the remote CSI-2 sink endpoint.
|
||||
|
||||
data-lanes:
|
||||
description: array of physical CSI-2 data lane indexes.
|
||||
data-lanes: true
|
||||
|
||||
required:
|
||||
- remote-endpoint
|
||||
- data-lanes
|
||||
|
||||
required:
|
||||
- reg
|
||||
- endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- port@4
|
||||
|
||||
@ -183,25 +163,8 @@ properties:
|
||||
requirements of the currently connected remote device.
|
||||
|
||||
port:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
remote-endpoint:
|
||||
description: phandle to the MAX9286 sink endpoint.
|
||||
|
||||
required:
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
additionalProperties: false
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: Connection to the MAX9286 sink.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
@ -242,6 +205,8 @@ examples:
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
|
||||
maxim,reverse-channel-microvolt = <170000>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
@ -71,19 +71,18 @@ properties:
|
||||
enum: [ 0, 180 ]
|
||||
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
link-frequencies:
|
||||
$ref: /schemas/types.yaml#/definitions/uint64-array
|
||||
description: List of allowed data link frequencies.
|
||||
data-lanes:
|
||||
minItems: 1
|
||||
maxItems: 8
|
||||
link-frequencies: true
|
||||
data-lanes: true
|
||||
bus-type:
|
||||
description: The type of the data bus.
|
||||
oneOf:
|
||||
- const: 1 # CSI-2 C-PHY
|
||||
- const: 3 # CCP2
|
||||
|
@ -57,16 +57,13 @@ properties:
|
||||
active low.
|
||||
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
additionalProperties: false
|
||||
description:
|
||||
A node containing an output port node with an endpoint definition
|
||||
as documented in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes:
|
||||
@ -79,18 +76,14 @@ properties:
|
||||
- const: 4
|
||||
|
||||
link-frequencies:
|
||||
$ref: /schemas/types.yaml#/definitions/uint64-array
|
||||
description:
|
||||
Allowed data bus frequencies. 360000000, 180000000 Hz or both
|
||||
are supported by the driver.
|
||||
|
||||
description: Frequencies listed are driver, not h/w limitations.
|
||||
maxItems: 2
|
||||
items:
|
||||
enum: [ 360000000, 180000000 ]
|
||||
|
||||
required:
|
||||
- link-frequencies
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
@ -139,4 +132,3 @@ examples:
|
||||
};
|
||||
};
|
||||
...
|
||||
|
||||
|
@ -17,6 +17,9 @@ description: |-
|
||||
@ 1600x1200 (UXGA) resolution transferred over a 1-lane MIPI interface. The
|
||||
sensor output is available via CSI-2 serial data output.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/media/video-interface-devices.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ovti,ov02a10
|
||||
@ -66,42 +69,34 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
rotation:
|
||||
description:
|
||||
Definition of the sensor's placement.
|
||||
allOf:
|
||||
- $ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
- enum:
|
||||
- 0 # Sensor Mounted Upright
|
||||
- 180 # Sensor Mounted Upside Down
|
||||
default: 0
|
||||
enum:
|
||||
- 0 # Sensor Mounted Upright
|
||||
- 180 # Sensor Mounted Upside Down
|
||||
default: 0
|
||||
|
||||
# See ../video-interfaces.txt for details
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
additionalProperties: false
|
||||
description:
|
||||
Output port node, single endpoint describing the CSI-2 transmitter.
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
link-frequencies: true
|
||||
ovti,mipi-clock-voltage:
|
||||
allOf:
|
||||
- $ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
$ref: "/schemas/types.yaml#/definitions/uint32"
|
||||
description:
|
||||
Definition of MIPI clock voltage unit. This entry corresponds to
|
||||
the link speed defined by the 'link-frequencies' property.
|
||||
If present, the value shall be in the range of 0-4.
|
||||
default: 4
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- link-frequencies
|
||||
- remote-endpoint
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
@ -50,11 +50,9 @@ properties:
|
||||
Definition of the regulator used as digital power supply.
|
||||
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
A node containing an output port node with an endpoint definition
|
||||
as documented in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
A node containing an output port node.
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/i2c/ov5647.yaml#
|
||||
$id: http://devicetree.org/schemas/media/i2c/ovti,ov5647.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Omnivision OV5647 raw image sensor
|
||||
@ -31,27 +31,15 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
type: object
|
||||
description: |-
|
||||
Should contain one endpoint sub-node used to model connection to the
|
||||
video receiver according to the specification defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
remote-endpoint:
|
||||
description: |-
|
||||
phandle to the video receiver input port.
|
||||
|
||||
clock-noncontinuous:
|
||||
type: boolean
|
||||
description: |-
|
||||
Set to true to allow MIPI CSI-2 non-continuous clock operations.
|
||||
|
||||
additionalProperties: false
|
||||
clock-noncontinuous: true
|
||||
|
||||
additionalProperties: false
|
||||
|
115
Documentation/devicetree/bindings/media/i2c/ovti,ov5648.yaml
Normal file
115
Documentation/devicetree/bindings/media/i2c/ovti,ov5648.yaml
Normal file
@ -0,0 +1,115 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/i2c/ovti,ov5648.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: OmniVision OV5648 Image Sensor Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Paul Kocialkowski <paul.kocialkowski@bootlin.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ovti,ov5648
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: XVCLK Clock
|
||||
|
||||
assigned-clocks:
|
||||
maxItems: 1
|
||||
|
||||
assigned-clock-rates:
|
||||
maxItems: 1
|
||||
|
||||
dvdd-supply:
|
||||
description: Digital Domain Power Supply
|
||||
|
||||
avdd-supply:
|
||||
description: Analog Domain Power Supply (internal AVDD is used if missing)
|
||||
|
||||
dovdd-supply:
|
||||
description: I/O Domain Power Supply
|
||||
|
||||
powerdown-gpios:
|
||||
maxItems: 1
|
||||
description: Power Down Pin GPIO Control (active low)
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description: Reset Pin GPIO Control (active low)
|
||||
|
||||
port:
|
||||
type: object
|
||||
description: MIPI CSI-2 transmitter port
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
remote-endpoint: true
|
||||
|
||||
link-frequencies:
|
||||
$ref: /schemas/types.yaml#/definitions/uint64-array
|
||||
description: Allowed MIPI CSI-2 link frequencies
|
||||
|
||||
data-lanes:
|
||||
minItems: 1
|
||||
maxItems: 2
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
- link-frequencies
|
||||
- remote-endpoint
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- assigned-clocks
|
||||
- assigned-clock-rates
|
||||
- dvdd-supply
|
||||
- dovdd-supply
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/sun8i-v3s-ccu.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ov5648: camera@36 {
|
||||
compatible = "ovti,ov5648";
|
||||
reg = <0x36>;
|
||||
|
||||
dvdd-supply = <&ov5648_dvdd>;
|
||||
avdd-supply = <&ov5648_avdd>;
|
||||
dovdd-supply = <&ov5648_dovdd>;
|
||||
clocks = <&ov5648_xvclk 0>;
|
||||
assigned-clocks = <&ov5648_xvclk 0>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
|
||||
ov5648_out: port {
|
||||
ov5648_out_mipi_csi2: endpoint {
|
||||
data-lanes = <1 2>;
|
||||
link-frequencies = /bits/ 64 <210000000 168000000>;
|
||||
|
||||
remote-endpoint = <&mipi_csi2_in_ov5648>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
@ -37,13 +37,14 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
description: |
|
||||
Video output port. See ../video-interfaces.txt.
|
||||
Video output port.
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
bus-type:
|
||||
@ -91,8 +92,6 @@ properties:
|
||||
required:
|
||||
- bus-type
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
|
124
Documentation/devicetree/bindings/media/i2c/ovti,ov8865.yaml
Normal file
124
Documentation/devicetree/bindings/media/i2c/ovti,ov8865.yaml
Normal file
@ -0,0 +1,124 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/i2c/ovti,ov8865.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: OmniVision OV8865 Image Sensor Device Tree Bindings
|
||||
|
||||
maintainers:
|
||||
- Paul Kocialkowski <paul.kocialkowski@bootlin.com>
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: ovti,ov8865
|
||||
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
clocks:
|
||||
items:
|
||||
- description: EXTCLK Clock
|
||||
|
||||
assigned-clocks:
|
||||
maxItems: 1
|
||||
|
||||
assigned-clock-rates:
|
||||
maxItems: 1
|
||||
|
||||
dvdd-supply:
|
||||
description: Digital Domain Power Supply
|
||||
|
||||
avdd-supply:
|
||||
description: Analog Domain Power Supply
|
||||
|
||||
dovdd-supply:
|
||||
description: I/O Domain Power Supply
|
||||
|
||||
powerdown-gpios:
|
||||
maxItems: 1
|
||||
description: Power Down Pin GPIO Control (active low)
|
||||
|
||||
reset-gpios:
|
||||
maxItems: 1
|
||||
description: Reset Pin GPIO Control (active low)
|
||||
|
||||
port:
|
||||
type: object
|
||||
description: MIPI CSI-2 transmitter port
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
remote-endpoint: true
|
||||
|
||||
link-frequencies:
|
||||
$ref: /schemas/types.yaml#/definitions/uint64-array
|
||||
description: Allowed MIPI CSI-2 link frequencies
|
||||
|
||||
data-lanes:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
- link-frequencies
|
||||
- remote-endpoint
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- assigned-clocks
|
||||
- assigned-clock-rates
|
||||
- dvdd-supply
|
||||
- avdd-supply
|
||||
- dovdd-supply
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
#include <dt-bindings/clock/sun8i-a83t-ccu.h>
|
||||
#include <dt-bindings/gpio/gpio.h>
|
||||
|
||||
i2c2 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
ov8865: camera@36 {
|
||||
compatible = "ovti,ov8865";
|
||||
reg = <0x36>;
|
||||
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&csi_mclk_pin>;
|
||||
|
||||
clocks = <&ccu CLK_CSI_MCLK>;
|
||||
assigned-clocks = <&ccu CLK_CSI_MCLK>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
avdd-supply = <®_ov8865_avdd>;
|
||||
dovdd-supply = <®_ov8865_dovdd>;
|
||||
dvdd-supply = <®_ov8865_dvdd>;
|
||||
|
||||
powerdown-gpios = <&pio 4 17 GPIO_ACTIVE_LOW>; /* PE17 */
|
||||
reset-gpios = <&pio 4 16 GPIO_ACTIVE_LOW>; /* PE16 */
|
||||
|
||||
port {
|
||||
ov8865_out_mipi_csi2: endpoint {
|
||||
data-lanes = <1 2 3 4>;
|
||||
link-frequencies = /bits/ 64 <360000000>;
|
||||
|
||||
remote-endpoint = <&mipi_csi2_in_ov8865>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -15,6 +15,9 @@ description: |
|
||||
interface. Image data is sent through MIPI CSI-2, through 2 or 4 lanes at a
|
||||
maximum throughput of 1.2Gbps/lane.
|
||||
|
||||
allOf:
|
||||
- $ref: ../video-interface-devices.yaml#
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sony,imx214
|
||||
@ -44,25 +47,21 @@ properties:
|
||||
vddd-supply:
|
||||
description: Chip digital core regulator (1.12V).
|
||||
|
||||
flash-leds:
|
||||
description: See ../video-interfaces.txt
|
||||
|
||||
lens-focus:
|
||||
description: See ../video-interfaces.txt
|
||||
flash-leds: true
|
||||
lens-focus: true
|
||||
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
description: |
|
||||
Video output port. See ../video-interfaces.txt.
|
||||
Video output port.
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: See ../video-interfaces.txt
|
||||
anyOf:
|
||||
- items:
|
||||
- const: 1
|
||||
@ -73,16 +72,12 @@ properties:
|
||||
- const: 3
|
||||
- const: 4
|
||||
|
||||
link-frequencies:
|
||||
$ref: /schemas/types.yaml#/definitions/uint64-array
|
||||
description: See ../video-interfaces.txt
|
||||
link-frequencies: true
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
- link-frequencies
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
|
@ -41,8 +41,7 @@ properties:
|
||||
description: Sensor digital IO 1.2 V supply.
|
||||
|
||||
port:
|
||||
type: object
|
||||
description: Output video port. See ../video-interfaces.txt.
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
91
Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
Normal file
91
Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
Normal file
@ -0,0 +1,91 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
# Copyright (C) 2021 Intel Corporation
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/i2c/sony,imx334.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sony IMX334 Sensor
|
||||
|
||||
maintainers:
|
||||
- Paul J. Murphy <paul.j.murphy@intel.com>
|
||||
- Daniele Alessandrelli <daniele.alessandrelli@intel.com>
|
||||
|
||||
description:
|
||||
IMX334 sensor is a Sony CMOS active pixel digital image sensor with an active
|
||||
array size of 3864H x 2202V. It is programmable through I2C interface. The
|
||||
I2C client address is fixed to 0x1a as per sensor data sheet. Image data is
|
||||
sent through MIPI CSI-2.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sony,imx334
|
||||
reg:
|
||||
description: I2C address
|
||||
maxItems: 1
|
||||
|
||||
assigned-clocks: true
|
||||
assigned-clock-parents: true
|
||||
assigned-clock-rates: true
|
||||
|
||||
clocks:
|
||||
description: Clock frequency from 6 to 27 MHz, 37.125MHz, 74.25MHz
|
||||
maxItems: 1
|
||||
|
||||
reset-gpios:
|
||||
description: Reference to the GPIO connected to the XCLR pin, if any.
|
||||
|
||||
port:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
properties:
|
||||
data-lanes:
|
||||
$ref: ../video-interfaces.yaml#/properties/data-lanes
|
||||
link-frequencies:
|
||||
$ref: ../video-interfaces.yaml#/properties/link-frequencies
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
- link-frequencies
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- clocks
|
||||
- port
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
examples:
|
||||
- |
|
||||
i2c0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
camera@1a {
|
||||
compatible = "sony,imx334";
|
||||
reg = <0x1a>;
|
||||
clocks = <&imx334_clk>;
|
||||
|
||||
assigned-clocks = <&imx334_clk>;
|
||||
assigned-clock-parents = <&imx334_clk_parent>;
|
||||
assigned-clock-rates = <24000000>;
|
||||
|
||||
port {
|
||||
imx334: endpoint {
|
||||
remote-endpoint = <&cam>;
|
||||
data-lanes = <1 2 3 4>;
|
||||
link-frequencies = /bits/ 64 <891000000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
@ -27,29 +27,20 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
# Properties described in
|
||||
# Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
properties:
|
||||
remote-endpoint: true
|
||||
hsync-active: true
|
||||
vsync-active: true
|
||||
pclk-sample: true
|
||||
bus-type: true
|
||||
|
||||
required:
|
||||
- remote-endpoint
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
clocks:
|
||||
minItems: 1
|
||||
maxItems: 3
|
||||
|
@ -33,10 +33,7 @@ properties:
|
||||
- const: mclk
|
||||
|
||||
port:
|
||||
type: object
|
||||
description:
|
||||
A node containing input port nodes with endpoint definitions as documented
|
||||
in Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
@ -58,35 +58,22 @@ properties:
|
||||
Differential receiver (HS-RX) settle time
|
||||
|
||||
ports:
|
||||
type: object
|
||||
description:
|
||||
A node containing input and output port nodes with endpoint definitions
|
||||
as documented in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
port@0:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description:
|
||||
Input port node, single endpoint describing the CSI-2 transmitter.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 0
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
data-lanes:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
description: See ../video-interfaces.txt
|
||||
oneOf:
|
||||
- items:
|
||||
- const: 1
|
||||
@ -94,18 +81,11 @@ properties:
|
||||
- const: 1
|
||||
- const: 2
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Output port node
|
||||
|
||||
|
@ -34,18 +34,15 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
# Properties described in
|
||||
# Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
properties:
|
||||
remote-endpoint: true
|
||||
hsync-active: true
|
||||
vsync-active: true
|
||||
field-even-active: false
|
||||
@ -53,12 +50,6 @@ properties:
|
||||
enum: [8, 16]
|
||||
default: 8
|
||||
|
||||
required:
|
||||
- remote-endpoint
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -46,24 +46,19 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
type: object
|
||||
description:
|
||||
A node containing input and output port nodes with endpoint definitions
|
||||
as documented in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description:
|
||||
Input port node, single endpoint describing the CSI-2 transmitter.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 0
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
clock-lanes:
|
||||
@ -72,50 +67,19 @@ properties:
|
||||
data-lanes:
|
||||
maxItems: 1
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- clock-lanes
|
||||
- data-lanes
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Output port node, multiple endpoints describing all the R-Car VIN
|
||||
modules connected the CSI-2 receiver.
|
||||
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
reg:
|
||||
const: 1
|
||||
|
||||
patternProperties:
|
||||
"^endpoint@[0-9a-f]$":
|
||||
type: object
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
required:
|
||||
- port@0
|
||||
- port@1
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
@ -69,15 +69,15 @@ properties:
|
||||
|
||||
#The per-board settings for Gen2 and RZ/G1 platforms:
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description:
|
||||
A node containing a parallel input with a single endpoint definitions as
|
||||
documented in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
A node containing a parallel input
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
hsync-active:
|
||||
@ -106,15 +106,6 @@ properties:
|
||||
|
||||
data-active: true
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
#The per-board settings for Gen3 and RZ/G2 platforms:
|
||||
renesas,id:
|
||||
description: VIN channel number
|
||||
@ -123,23 +114,18 @@ properties:
|
||||
maximum: 15
|
||||
|
||||
ports:
|
||||
type: object
|
||||
description:
|
||||
A node containing input nodes with endpoint definitions as documented in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Input port node, single endpoint describing a parallel input source.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 0
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
hsync-active:
|
||||
@ -168,98 +154,29 @@ properties:
|
||||
|
||||
data-active: true
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description:
|
||||
Input port node, multiple endpoints describing all the R-Car CSI-2
|
||||
modules connected the VIN.
|
||||
|
||||
properties:
|
||||
'#address-cells':
|
||||
const: 1
|
||||
|
||||
'#size-cells':
|
||||
const: 0
|
||||
|
||||
reg:
|
||||
const: 1
|
||||
|
||||
endpoint@0:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/endpoint
|
||||
description: Endpoint connected to CSI20.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 0
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
endpoint@1:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/endpoint
|
||||
description: Endpoint connected to CSI21.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 1
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
endpoint@2:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/endpoint
|
||||
description: Endpoint connected to CSI40.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 2
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
endpoint@3:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/endpoint
|
||||
description: Endpoint connected to CSI41.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 3
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
anyOf:
|
||||
- required:
|
||||
- endpoint@0
|
||||
@ -270,8 +187,6 @@ properties:
|
||||
- required:
|
||||
- endpoint@3
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -56,56 +56,26 @@ properties:
|
||||
power-domains:
|
||||
maxItems: 1
|
||||
|
||||
# See ./video-interfaces.txt for details
|
||||
ports:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
port@0:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: connection point for sensors at MIPI-DPHY RX0
|
||||
additionalProperties: false
|
||||
|
||||
properties:
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
reg:
|
||||
const: 0
|
||||
|
||||
patternProperties:
|
||||
endpoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
reg:
|
||||
maxItems: 1
|
||||
|
||||
data-lanes:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
|
||||
required:
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- port@0
|
||||
|
||||
required:
|
||||
|
@ -37,16 +37,15 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
port:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description:
|
||||
DCMI supports a single port node with parallel bus. It should contain
|
||||
one 'port' child node with child 'endpoint' node. Please refer to the
|
||||
bindings defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
DCMI supports a single port node with parallel bus.
|
||||
|
||||
properties:
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
bus-type:
|
||||
@ -57,8 +56,6 @@ properties:
|
||||
enum: [8, 10, 12, 14]
|
||||
default: 8
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
allOf:
|
||||
- if:
|
||||
properties:
|
||||
@ -73,14 +70,9 @@ properties:
|
||||
enum: [8]
|
||||
|
||||
required:
|
||||
- remote-endpoint
|
||||
- bus-type
|
||||
- pclk-sample
|
||||
|
||||
unevaluatedProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -15,10 +15,7 @@ description: |-
|
||||
processing capability to connect CSI2 image-sensor modules to the
|
||||
DRA72x device.
|
||||
|
||||
CAL supports 2 camera port nodes on MIPI bus. Each CSI2 camera port nodes
|
||||
should contain a 'port' child node with child 'endpoint' node. Please
|
||||
refer to the bindings defined in
|
||||
Documentation/devicetree/bindings/media/video-interfaces.txt.
|
||||
CAL supports 2 camera port nodes on MIPI bus.
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
@ -67,31 +64,19 @@ properties:
|
||||
Documentation/devicetree/bindings/power/power_domain.txt
|
||||
maxItems: 1
|
||||
|
||||
# See ./video-interfaces.txt for details
|
||||
ports:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
"#address-cells":
|
||||
const: 1
|
||||
|
||||
"#size-cells":
|
||||
const: 0
|
||||
|
||||
port@0:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: CSI2 Port #0
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 0
|
||||
description: CSI2 Port #0
|
||||
|
||||
patternProperties:
|
||||
endpoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
clock-lanes:
|
||||
@ -101,24 +86,15 @@ properties:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
unevaluatedProperties: false
|
||||
description: CSI2 Port #1
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 1
|
||||
description: CSI2 Port #1
|
||||
|
||||
patternProperties:
|
||||
endpoint:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
$ref: video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
clock-lanes:
|
||||
@ -128,14 +104,7 @@ properties:
|
||||
minItems: 1
|
||||
maxItems: 4
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- reg
|
||||
|
||||
required:
|
||||
- "#address-cells"
|
||||
- "#size-cells"
|
||||
- port@0
|
||||
|
||||
required:
|
||||
|
@ -0,0 +1,406 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/video-interface-devices.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Common bindings for video receiver and transmitter devices
|
||||
|
||||
maintainers:
|
||||
- Jacopo Mondi <jacopo@jmondi.org>
|
||||
- Sakari Ailus <sakari.ailus@linux.intel.com>
|
||||
|
||||
properties:
|
||||
flash-leds:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||
description:
|
||||
An array of phandles, each referring to a flash LED, a sub-node of the LED
|
||||
driver device node.
|
||||
|
||||
lens-focus:
|
||||
$ref: /schemas/types.yaml#/definitions/phandle
|
||||
description:
|
||||
A phandle to the node of the focus lens controller.
|
||||
|
||||
rotation:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 90, 180, 270 ]
|
||||
description: |
|
||||
The camera rotation is expressed as the angular difference in degrees
|
||||
between two reference systems, one relative to the camera module, and one
|
||||
defined on the external world scene to be captured when projected on the
|
||||
image sensor pixel array.
|
||||
|
||||
A camera sensor has a 2-dimensional reference system 'Rc' defined by its
|
||||
pixel array read-out order. The origin is set to the first pixel being
|
||||
read out, the X-axis points along the column read-out direction towards
|
||||
the last columns, and the Y-axis along the row read-out direction towards
|
||||
the last row.
|
||||
|
||||
A typical example for a sensor with a 2592x1944 pixel array matrix
|
||||
observed from the front is:
|
||||
|
||||
2591 X-axis 0
|
||||
<------------------------+ 0
|
||||
.......... ... ..........!
|
||||
.......... ... ..........! Y-axis
|
||||
... !
|
||||
.......... ... ..........!
|
||||
.......... ... ..........! 1943
|
||||
V
|
||||
|
||||
The external world scene reference system 'Rs' is a 2-dimensional
|
||||
reference system on the focal plane of the camera module. The origin is
|
||||
placed on the top-left corner of the visible scene, the X-axis points
|
||||
towards the right, and the Y-axis points towards the bottom of the scene.
|
||||
The top, bottom, left and right directions are intentionally not defined
|
||||
and depend on the environment in which the camera is used.
|
||||
|
||||
A typical example of a (very common) picture of a shark swimming from left
|
||||
to right, as seen from the camera, is:
|
||||
|
||||
0 X-axis
|
||||
0 +------------------------------------->
|
||||
!
|
||||
!
|
||||
!
|
||||
! |\____)\___
|
||||
! ) _____ __`<
|
||||
! |/ )/
|
||||
!
|
||||
!
|
||||
!
|
||||
V
|
||||
Y-axis
|
||||
|
||||
with the reference system 'Rs' placed on the camera focal plane:
|
||||
|
||||
¸.·˙!
|
||||
¸.·˙ !
|
||||
_ ¸.·˙ !
|
||||
+-/ \-+¸.·˙ !
|
||||
| (o) | ! Camera focal plane
|
||||
+-----+˙·.¸ !
|
||||
˙·.¸ !
|
||||
˙·.¸ !
|
||||
˙·.¸!
|
||||
|
||||
When projected on the sensor's pixel array, the image and the associated
|
||||
reference system 'Rs' are typically (but not always) inverted, due to the
|
||||
camera module's lens optical inversion effect.
|
||||
|
||||
Assuming the above represented scene of the swimming shark, the lens
|
||||
inversion projects the scene and its reference system onto the sensor
|
||||
pixel array, seen from the front of the camera sensor, as follows:
|
||||
|
||||
Y-axis
|
||||
^
|
||||
!
|
||||
!
|
||||
!
|
||||
! |\_____)\__
|
||||
! ) ____ ___.<
|
||||
! |/ )/
|
||||
!
|
||||
!
|
||||
!
|
||||
0 +------------------------------------->
|
||||
0 X-axis
|
||||
|
||||
Note the shark being upside-down.
|
||||
|
||||
The resulting projected reference system is named 'Rp'.
|
||||
|
||||
The camera rotation property is then defined as the angular difference in
|
||||
the counter-clockwise direction between the camera reference system 'Rc'
|
||||
and the projected scene reference system 'Rp'. It is expressed in degrees
|
||||
as a number in the range [0, 360[.
|
||||
|
||||
Examples
|
||||
|
||||
0 degrees camera rotation:
|
||||
|
||||
|
||||
Y-Rp
|
||||
^
|
||||
Y-Rc !
|
||||
^ !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! 0 +------------------------------------->
|
||||
! 0 X-Rp
|
||||
0 +------------------------------------->
|
||||
0 X-Rc
|
||||
|
||||
|
||||
X-Rc 0
|
||||
<------------------------------------+ 0
|
||||
X-Rp 0 !
|
||||
<------------------------------------+ 0 !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! V
|
||||
! Y-Rc
|
||||
V
|
||||
Y-Rp
|
||||
|
||||
90 degrees camera rotation:
|
||||
|
||||
0 Y-Rc
|
||||
0 +-------------------->
|
||||
! Y-Rp
|
||||
! ^
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! 0 +------------------------------------->
|
||||
! 0 X-Rp
|
||||
!
|
||||
!
|
||||
!
|
||||
!
|
||||
V
|
||||
X-Rc
|
||||
|
||||
180 degrees camera rotation:
|
||||
|
||||
0
|
||||
<------------------------------------+ 0
|
||||
X-Rc !
|
||||
Y-Rp !
|
||||
^ !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! V
|
||||
! Y-Rc
|
||||
0 +------------------------------------->
|
||||
0 X-Rp
|
||||
|
||||
270 degrees camera rotation:
|
||||
|
||||
0 Y-Rc
|
||||
0 +-------------------->
|
||||
! 0
|
||||
! <-----------------------------------+ 0
|
||||
! X-Rp !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! V
|
||||
! Y-Rp
|
||||
!
|
||||
!
|
||||
!
|
||||
!
|
||||
V
|
||||
X-Rc
|
||||
|
||||
|
||||
Example one - Webcam
|
||||
|
||||
A camera module installed on the user facing part of a laptop screen
|
||||
casing used for video calls. The captured images are meant to be displayed
|
||||
in landscape mode (width > height) on the laptop screen.
|
||||
|
||||
The camera is typically mounted upside-down to compensate the lens optical
|
||||
inversion effect:
|
||||
|
||||
Y-Rp
|
||||
Y-Rc ^
|
||||
^ !
|
||||
! !
|
||||
! ! |\_____)\__
|
||||
! ! ) ____ ___.<
|
||||
! ! |/ )/
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! 0 +------------------------------------->
|
||||
! 0 X-Rp
|
||||
0 +------------------------------------->
|
||||
0 X-Rc
|
||||
|
||||
The two reference systems are aligned, the resulting camera rotation is
|
||||
0 degrees, no rotation correction needs to be applied to the resulting
|
||||
image once captured to memory buffers to correctly display it to users:
|
||||
|
||||
+--------------------------------------+
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! |\____)\___ !
|
||||
! ) _____ __`< !
|
||||
! |/ )/ !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
+--------------------------------------+
|
||||
|
||||
If the camera sensor is not mounted upside-down to compensate for the lens
|
||||
optical inversion, the two reference systems will not be aligned, with
|
||||
'Rp' being rotated 180 degrees relatively to 'Rc':
|
||||
|
||||
|
||||
X-Rc 0
|
||||
<------------------------------------+ 0
|
||||
!
|
||||
Y-Rp !
|
||||
^ !
|
||||
! !
|
||||
! |\_____)\__ !
|
||||
! ) ____ ___.< !
|
||||
! |/ )/ !
|
||||
! !
|
||||
! !
|
||||
! V
|
||||
! Y-Rc
|
||||
0 +------------------------------------->
|
||||
0 X-Rp
|
||||
|
||||
The image once captured to memory will then be rotated by 180 degrees:
|
||||
|
||||
+--------------------------------------+
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! __/(_____/| !
|
||||
! >.___ ____ ( !
|
||||
! \( \| !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
+--------------------------------------+
|
||||
|
||||
A software rotation correction of 180 degrees should be applied to
|
||||
correctly display the image:
|
||||
|
||||
+--------------------------------------+
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! |\____)\___ !
|
||||
! ) _____ __`< !
|
||||
! |/ )/ !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
+--------------------------------------+
|
||||
|
||||
Example two - Phone camera
|
||||
|
||||
A camera installed on the back side of a mobile device facing away from
|
||||
the user. The captured images are meant to be displayed in portrait mode
|
||||
(height > width) to match the device screen orientation and the device
|
||||
usage orientation used when taking the picture.
|
||||
|
||||
The camera sensor is typically mounted with its pixel array longer side
|
||||
aligned to the device longer side, upside-down mounted to compensate for
|
||||
the lens optical inversion effect:
|
||||
|
||||
0 Y-Rc
|
||||
0 +-------------------->
|
||||
! Y-Rp
|
||||
! ^
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! ! |\_____)\__
|
||||
! ! ) ____ ___.<
|
||||
! ! |/ )/
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! 0 +------------------------------------->
|
||||
! 0 X-Rp
|
||||
!
|
||||
!
|
||||
!
|
||||
!
|
||||
V
|
||||
X-Rc
|
||||
|
||||
The two reference systems are not aligned and the 'Rp' reference system is
|
||||
rotated by 90 degrees in the counter-clockwise direction relatively to the
|
||||
'Rc' reference system.
|
||||
|
||||
The image once captured to memory will be rotated:
|
||||
|
||||
+-------------------------------------+
|
||||
| _ _ |
|
||||
| \ / |
|
||||
| | | |
|
||||
| | | |
|
||||
| | > |
|
||||
| < | |
|
||||
| | | |
|
||||
| . |
|
||||
| V |
|
||||
+-------------------------------------+
|
||||
|
||||
A correction of 90 degrees in counter-clockwise direction has to be
|
||||
applied to correctly display the image in portrait mode on the device
|
||||
screen:
|
||||
|
||||
+--------------------+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |\____)\___ |
|
||||
| ) _____ __`< |
|
||||
| |/ )/ |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
+--------------------+
|
||||
|
||||
orientation:
|
||||
description:
|
||||
The orientation of a device (typically an image sensor or a flash LED)
|
||||
describing its mounting position relative to the usage orientation of the
|
||||
system where the device is installed on.
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
# Front. The device is mounted on the front facing side of the system. For
|
||||
# mobile devices such as smartphones, tablets and laptops the front side
|
||||
# is the user facing side.
|
||||
- 0
|
||||
# Back. The device is mounted on the back side of the system, which is
|
||||
# defined as the opposite side of the front facing one.
|
||||
- 1
|
||||
# External. The device is not attached directly to the system but is
|
||||
# attached in a way that allows it to move freely.
|
||||
- 2
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
...
|
@ -1,639 +1 @@
|
||||
Common bindings for video receiver and transmitter interfaces
|
||||
|
||||
General concept
|
||||
---------------
|
||||
|
||||
Video data pipelines usually consist of external devices, e.g. camera sensors,
|
||||
controlled over an I2C, SPI or UART bus, and SoC internal IP blocks, including
|
||||
video DMA engines and video data processors.
|
||||
|
||||
SoC internal blocks are described by DT nodes, placed similarly to other SoC
|
||||
blocks. External devices are represented as child nodes of their respective
|
||||
bus controller nodes, e.g. I2C.
|
||||
|
||||
Data interfaces on all video devices are described by their child 'port' nodes.
|
||||
Configuration of a port depends on other devices participating in the data
|
||||
transfer and is described by 'endpoint' subnodes.
|
||||
|
||||
device {
|
||||
...
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
...
|
||||
endpoint@0 { ... };
|
||||
endpoint@1 { ... };
|
||||
};
|
||||
port@1 { ... };
|
||||
};
|
||||
};
|
||||
|
||||
If a port can be configured to work with more than one remote device on the same
|
||||
bus, an 'endpoint' child node must be provided for each of them. If more than
|
||||
one port is present in a device node or there is more than one endpoint at a
|
||||
port, or port node needs to be associated with a selected hardware interface,
|
||||
a common scheme using '#address-cells', '#size-cells' and 'reg' properties is
|
||||
used.
|
||||
|
||||
All 'port' nodes can be grouped under optional 'ports' node, which allows to
|
||||
specify #address-cells, #size-cells properties independently for the 'port'
|
||||
and 'endpoint' nodes and any child device nodes a device might have.
|
||||
|
||||
Two 'endpoint' nodes are linked with each other through their 'remote-endpoint'
|
||||
phandles. An endpoint subnode of a device contains all properties needed for
|
||||
configuration of this device for data exchange with other device. In most
|
||||
cases properties at the peer 'endpoint' nodes will be identical, however they
|
||||
might need to be different when there is any signal modifications on the bus
|
||||
between two devices, e.g. there are logic signal inverters on the lines.
|
||||
|
||||
It is allowed for multiple endpoints at a port to be active simultaneously,
|
||||
where supported by a device. For example, in case where a data interface of
|
||||
a device is partitioned into multiple data busses, e.g. 16-bit input port
|
||||
divided into two separate ITU-R BT.656 8-bit busses. In such case bus-width
|
||||
and data-shift properties can be used to assign physical data lines to each
|
||||
endpoint node (logical bus).
|
||||
|
||||
Documenting bindings for devices
|
||||
--------------------------------
|
||||
|
||||
All required and optional bindings the device supports shall be explicitly
|
||||
documented in device DT binding documentation. This also includes port and
|
||||
endpoint nodes for the device, including unit-addresses and reg properties where
|
||||
relevant.
|
||||
|
||||
Please also see Documentation/devicetree/bindings/graph.txt .
|
||||
|
||||
Required properties
|
||||
-------------------
|
||||
|
||||
If there is more than one 'port' or more than one 'endpoint' node or 'reg'
|
||||
property is present in port and/or endpoint nodes the following properties
|
||||
are required in a relevant parent node:
|
||||
|
||||
- #address-cells : number of cells required to define port/endpoint
|
||||
identifier, should be 1.
|
||||
- #size-cells : should be zero.
|
||||
|
||||
|
||||
Optional properties
|
||||
-------------------
|
||||
|
||||
- flash-leds: An array of phandles, each referring to a flash LED, a sub-node
|
||||
of the LED driver device node.
|
||||
|
||||
- lens-focus: A phandle to the node of the focus lens controller.
|
||||
|
||||
- rotation: The camera rotation is expressed as the angular difference in
|
||||
degrees between two reference systems, one relative to the camera module, and
|
||||
one defined on the external world scene to be captured when projected on the
|
||||
image sensor pixel array.
|
||||
|
||||
A camera sensor has a 2-dimensional reference system 'Rc' defined by
|
||||
its pixel array read-out order. The origin is set to the first pixel
|
||||
being read out, the X-axis points along the column read-out direction
|
||||
towards the last columns, and the Y-axis along the row read-out
|
||||
direction towards the last row.
|
||||
|
||||
A typical example for a sensor with a 2592x1944 pixel array matrix
|
||||
observed from the front is:
|
||||
|
||||
2591 X-axis 0
|
||||
<------------------------+ 0
|
||||
.......... ... ..........!
|
||||
.......... ... ..........! Y-axis
|
||||
... !
|
||||
.......... ... ..........!
|
||||
.......... ... ..........! 1943
|
||||
V
|
||||
|
||||
The external world scene reference system 'Rs' is a 2-dimensional
|
||||
reference system on the focal plane of the camera module. The origin is
|
||||
placed on the top-left corner of the visible scene, the X-axis points
|
||||
towards the right, and the Y-axis points towards the bottom of the
|
||||
scene. The top, bottom, left and right directions are intentionally not
|
||||
defined and depend on the environment in which the camera is used.
|
||||
|
||||
A typical example of a (very common) picture of a shark swimming from
|
||||
left to right, as seen from the camera, is:
|
||||
|
||||
0 X-axis
|
||||
0 +------------------------------------->
|
||||
!
|
||||
!
|
||||
!
|
||||
! |\____)\___
|
||||
! ) _____ __`<
|
||||
! |/ )/
|
||||
!
|
||||
!
|
||||
!
|
||||
V
|
||||
Y-axis
|
||||
|
||||
with the reference system 'Rs' placed on the camera focal plane:
|
||||
|
||||
¸.·˙!
|
||||
¸.·˙ !
|
||||
_ ¸.·˙ !
|
||||
+-/ \-+¸.·˙ !
|
||||
| (o) | ! Camera focal plane
|
||||
+-----+˙·.¸ !
|
||||
˙·.¸ !
|
||||
˙·.¸ !
|
||||
˙·.¸!
|
||||
|
||||
When projected on the sensor's pixel array, the image and the associated
|
||||
reference system 'Rs' are typically (but not always) inverted, due to
|
||||
the camera module's lens optical inversion effect.
|
||||
|
||||
Assuming the above represented scene of the swimming shark, the lens
|
||||
inversion projects the scene and its reference system onto the sensor
|
||||
pixel array, seen from the front of the camera sensor, as follows:
|
||||
|
||||
Y-axis
|
||||
^
|
||||
!
|
||||
!
|
||||
!
|
||||
! |\_____)\__
|
||||
! ) ____ ___.<
|
||||
! |/ )/
|
||||
!
|
||||
!
|
||||
!
|
||||
0 +------------------------------------->
|
||||
0 X-axis
|
||||
|
||||
Note the shark being upside-down.
|
||||
|
||||
The resulting projected reference system is named 'Rp'.
|
||||
|
||||
The camera rotation property is then defined as the angular difference
|
||||
in the counter-clockwise direction between the camera reference system
|
||||
'Rc' and the projected scene reference system 'Rp'. It is expressed in
|
||||
degrees as a number in the range [0, 360[.
|
||||
|
||||
Examples
|
||||
|
||||
0 degrees camera rotation:
|
||||
|
||||
|
||||
Y-Rp
|
||||
^
|
||||
Y-Rc !
|
||||
^ !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! 0 +------------------------------------->
|
||||
! 0 X-Rp
|
||||
0 +------------------------------------->
|
||||
0 X-Rc
|
||||
|
||||
|
||||
X-Rc 0
|
||||
<------------------------------------+ 0
|
||||
X-Rp 0 !
|
||||
<------------------------------------+ 0 !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! V
|
||||
! Y-Rc
|
||||
V
|
||||
Y-Rp
|
||||
|
||||
90 degrees camera rotation:
|
||||
|
||||
0 Y-Rc
|
||||
0 +-------------------->
|
||||
! Y-Rp
|
||||
! ^
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! 0 +------------------------------------->
|
||||
! 0 X-Rp
|
||||
!
|
||||
!
|
||||
!
|
||||
!
|
||||
V
|
||||
X-Rc
|
||||
|
||||
180 degrees camera rotation:
|
||||
|
||||
0
|
||||
<------------------------------------+ 0
|
||||
X-Rc !
|
||||
Y-Rp !
|
||||
^ !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! V
|
||||
! Y-Rc
|
||||
0 +------------------------------------->
|
||||
0 X-Rp
|
||||
|
||||
270 degrees camera rotation:
|
||||
|
||||
0 Y-Rc
|
||||
0 +-------------------->
|
||||
! 0
|
||||
! <-----------------------------------+ 0
|
||||
! X-Rp !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! V
|
||||
! Y-Rp
|
||||
!
|
||||
!
|
||||
!
|
||||
!
|
||||
V
|
||||
X-Rc
|
||||
|
||||
|
||||
Example one - Webcam
|
||||
|
||||
A camera module installed on the user facing part of a laptop screen
|
||||
casing used for video calls. The captured images are meant to be
|
||||
displayed in landscape mode (width > height) on the laptop screen.
|
||||
|
||||
The camera is typically mounted upside-down to compensate the lens
|
||||
optical inversion effect:
|
||||
|
||||
Y-Rp
|
||||
Y-Rc ^
|
||||
^ !
|
||||
! !
|
||||
! ! |\_____)\__
|
||||
! ! ) ____ ___.<
|
||||
! ! |/ )/
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! 0 +------------------------------------->
|
||||
! 0 X-Rp
|
||||
0 +------------------------------------->
|
||||
0 X-Rc
|
||||
|
||||
The two reference systems are aligned, the resulting camera rotation is
|
||||
0 degrees, no rotation correction needs to be applied to the resulting
|
||||
image once captured to memory buffers to correctly display it to users:
|
||||
|
||||
+--------------------------------------+
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! |\____)\___ !
|
||||
! ) _____ __`< !
|
||||
! |/ )/ !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
+--------------------------------------+
|
||||
|
||||
If the camera sensor is not mounted upside-down to compensate for the
|
||||
lens optical inversion, the two reference systems will not be aligned,
|
||||
with 'Rp' being rotated 180 degrees relatively to 'Rc':
|
||||
|
||||
|
||||
X-Rc 0
|
||||
<------------------------------------+ 0
|
||||
!
|
||||
Y-Rp !
|
||||
^ !
|
||||
! !
|
||||
! |\_____)\__ !
|
||||
! ) ____ ___.< !
|
||||
! |/ )/ !
|
||||
! !
|
||||
! !
|
||||
! V
|
||||
! Y-Rc
|
||||
0 +------------------------------------->
|
||||
0 X-Rp
|
||||
|
||||
The image once captured to memory will then be rotated by 180 degrees:
|
||||
|
||||
+--------------------------------------+
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! __/(_____/| !
|
||||
! >.___ ____ ( !
|
||||
! \( \| !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
+--------------------------------------+
|
||||
|
||||
A software rotation correction of 180 degrees should be applied to
|
||||
correctly display the image:
|
||||
|
||||
+--------------------------------------+
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! |\____)\___ !
|
||||
! ) _____ __`< !
|
||||
! |/ )/ !
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
+--------------------------------------+
|
||||
|
||||
Example two - Phone camera
|
||||
|
||||
A camera installed on the back side of a mobile device facing away from
|
||||
the user. The captured images are meant to be displayed in portrait mode
|
||||
(height > width) to match the device screen orientation and the device
|
||||
usage orientation used when taking the picture.
|
||||
|
||||
The camera sensor is typically mounted with its pixel array longer side
|
||||
aligned to the device longer side, upside-down mounted to compensate for
|
||||
the lens optical inversion effect:
|
||||
|
||||
0 Y-Rc
|
||||
0 +-------------------->
|
||||
! Y-Rp
|
||||
! ^
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! ! |\_____)\__
|
||||
! ! ) ____ ___.<
|
||||
! ! |/ )/
|
||||
! !
|
||||
! !
|
||||
! !
|
||||
! 0 +------------------------------------->
|
||||
! 0 X-Rp
|
||||
!
|
||||
!
|
||||
!
|
||||
!
|
||||
V
|
||||
X-Rc
|
||||
|
||||
The two reference systems are not aligned and the 'Rp' reference
|
||||
system is rotated by 90 degrees in the counter-clockwise direction
|
||||
relatively to the 'Rc' reference system.
|
||||
|
||||
The image once captured to memory will be rotated:
|
||||
|
||||
+-------------------------------------+
|
||||
| _ _ |
|
||||
| \ / |
|
||||
| | | |
|
||||
| | | |
|
||||
| | > |
|
||||
| < | |
|
||||
| | | |
|
||||
| . |
|
||||
| V |
|
||||
+-------------------------------------+
|
||||
|
||||
A correction of 90 degrees in counter-clockwise direction has to be
|
||||
applied to correctly display the image in portrait mode on the device
|
||||
screen:
|
||||
|
||||
+--------------------+
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |\____)\___ |
|
||||
| ) _____ __`< |
|
||||
| |/ )/ |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
| |
|
||||
+--------------------+
|
||||
|
||||
- orientation: The orientation of a device (typically an image sensor or a flash
|
||||
LED) describing its mounting position relative to the usage orientation of the
|
||||
system where the device is installed on.
|
||||
Possible values are:
|
||||
0 - Front. The device is mounted on the front facing side of the system.
|
||||
For mobile devices such as smartphones, tablets and laptops the front side is
|
||||
the user facing side.
|
||||
1 - Back. The device is mounted on the back side of the system, which is
|
||||
defined as the opposite side of the front facing one.
|
||||
2 - External. The device is not attached directly to the system but is
|
||||
attached in a way that allows it to move freely.
|
||||
|
||||
Optional endpoint properties
|
||||
----------------------------
|
||||
|
||||
- remote-endpoint: phandle to an 'endpoint' subnode of a remote device node.
|
||||
- slave-mode: a boolean property indicating that the link is run in slave mode.
|
||||
The default when this property is not specified is master mode. In the slave
|
||||
mode horizontal and vertical synchronization signals are provided to the
|
||||
slave device (data source) by the master device (data sink). In the master
|
||||
mode the data source device is also the source of the synchronization signals.
|
||||
- bus-type: data bus type. Possible values are:
|
||||
1 - MIPI CSI-2 C-PHY
|
||||
2 - MIPI CSI1
|
||||
3 - CCP2
|
||||
4 - MIPI CSI-2 D-PHY
|
||||
5 - Parallel
|
||||
6 - Bt.656
|
||||
- bus-width: number of data lines actively used, valid for the parallel busses.
|
||||
- data-shift: on the parallel data busses, if bus-width is used to specify the
|
||||
number of data lines, data-shift can be used to specify which data lines are
|
||||
used, e.g. "bus-width=<8>; data-shift=<2>;" means, that lines 9:2 are used.
|
||||
- hsync-active: active state of the HSYNC signal, 0/1 for LOW/HIGH respectively.
|
||||
- vsync-active: active state of the VSYNC signal, 0/1 for LOW/HIGH respectively.
|
||||
Note, that if HSYNC and VSYNC polarities are not specified, embedded
|
||||
synchronization may be required, where supported.
|
||||
- data-active: similar to HSYNC and VSYNC, specifies data line polarity.
|
||||
- data-enable-active: similar to HSYNC and VSYNC, specifies the data enable
|
||||
signal polarity.
|
||||
- field-even-active: field signal level during the even field data transmission.
|
||||
- pclk-sample: sample data on rising (1) or falling (0) edge of the pixel clock
|
||||
signal.
|
||||
- sync-on-green-active: active state of Sync-on-green (SoG) signal, 0/1 for
|
||||
LOW/HIGH respectively.
|
||||
- data-lanes: an array of physical data lane indexes. Position of an entry
|
||||
determines the logical lane number, while the value of an entry indicates
|
||||
physical lane, e.g. for 2-lane MIPI CSI-2 bus we could have
|
||||
"data-lanes = <1 2>;", assuming the clock lane is on hardware lane 0.
|
||||
If the hardware does not support lane reordering, monotonically
|
||||
incremented values shall be used from 0 or 1 onwards, depending on
|
||||
whether or not there is also a clock lane. This property is valid for
|
||||
serial busses only (e.g. MIPI CSI-2).
|
||||
- clock-lanes: an array of physical clock lane indexes. Position of an entry
|
||||
determines the logical lane number, while the value of an entry indicates
|
||||
physical lane, e.g. for a MIPI CSI-2 bus we could have "clock-lanes = <0>;",
|
||||
which places the clock lane on hardware lane 0. This property is valid for
|
||||
serial busses only (e.g. MIPI CSI-2). Note that for the MIPI CSI-2 bus this
|
||||
array contains only one entry.
|
||||
- clock-noncontinuous: a boolean property to allow MIPI CSI-2 non-continuous
|
||||
clock mode.
|
||||
- link-frequencies: Allowed data bus frequencies. For MIPI CSI-2, for
|
||||
instance, this is the actual frequency of the bus, not bits per clock per
|
||||
lane value. An array of 64-bit unsigned integers.
|
||||
- lane-polarities: an array of polarities of the lanes starting from the clock
|
||||
lane and followed by the data lanes in the same order as in data-lanes.
|
||||
Valid values are 0 (normal) and 1 (inverted). The length of the array
|
||||
should be the combined length of data-lanes and clock-lanes properties.
|
||||
If the lane-polarities property is omitted, the value must be interpreted
|
||||
as 0 (normal). This property is valid for serial busses only.
|
||||
- strobe: Whether the clock signal is used as clock (0) or strobe (1). Used
|
||||
with CCP2, for instance.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
The example snippet below describes two data pipelines. ov772x and imx074 are
|
||||
camera sensors with a parallel and serial (MIPI CSI-2) video bus respectively.
|
||||
Both sensors are on the I2C control bus corresponding to the i2c0 controller
|
||||
node. ov772x sensor is linked directly to the ceu0 video host interface.
|
||||
imx074 is linked to ceu0 through the MIPI CSI-2 receiver (csi2). ceu0 has a
|
||||
(single) DMA engine writing captured data to memory. ceu0 node has a single
|
||||
'port' node which may indicate that at any time only one of the following data
|
||||
pipelines can be active: ov772x -> ceu0 or imx074 -> csi2 -> ceu0.
|
||||
|
||||
ceu0: ceu@fe910000 {
|
||||
compatible = "renesas,sh-mobile-ceu";
|
||||
reg = <0xfe910000 0xa0>;
|
||||
interrupts = <0x880>;
|
||||
|
||||
mclk: master_clock {
|
||||
compatible = "renesas,ceu-clock";
|
||||
#clock-cells = <1>;
|
||||
clock-frequency = <50000000>; /* Max clock frequency */
|
||||
clock-output-names = "mclk";
|
||||
};
|
||||
|
||||
port {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* Parallel bus endpoint */
|
||||
ceu0_1: endpoint@1 {
|
||||
reg = <1>; /* Local endpoint # */
|
||||
remote = <&ov772x_1_1>; /* Remote phandle */
|
||||
bus-width = <8>; /* Used data lines */
|
||||
data-shift = <2>; /* Lines 9:2 are used */
|
||||
|
||||
/* If hsync-active/vsync-active are missing,
|
||||
embedded BT.656 sync is used */
|
||||
hsync-active = <0>; /* Active low */
|
||||
vsync-active = <0>; /* Active low */
|
||||
data-active = <1>; /* Active high */
|
||||
pclk-sample = <1>; /* Rising */
|
||||
};
|
||||
|
||||
/* MIPI CSI-2 bus endpoint */
|
||||
ceu0_0: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote = <&csi2_2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c0: i2c@fff20000 {
|
||||
...
|
||||
ov772x_1: camera@21 {
|
||||
compatible = "ovti,ov772x";
|
||||
reg = <0x21>;
|
||||
vddio-supply = <®ulator1>;
|
||||
vddcore-supply = <®ulator2>;
|
||||
|
||||
clock-frequency = <20000000>;
|
||||
clocks = <&mclk 0>;
|
||||
clock-names = "xclk";
|
||||
|
||||
port {
|
||||
/* With 1 endpoint per port no need for addresses. */
|
||||
ov772x_1_1: endpoint {
|
||||
bus-width = <8>;
|
||||
remote-endpoint = <&ceu0_1>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <0>; /* Who came up with an
|
||||
inverter here ?... */
|
||||
data-active = <1>;
|
||||
pclk-sample = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
imx074: camera@1a {
|
||||
compatible = "sony,imx074";
|
||||
reg = <0x1a>;
|
||||
vddio-supply = <®ulator1>;
|
||||
vddcore-supply = <®ulator2>;
|
||||
|
||||
clock-frequency = <30000000>; /* Shared clock with ov772x_1 */
|
||||
clocks = <&mclk 0>;
|
||||
clock-names = "sysclk"; /* Assuming this is the
|
||||
name in the datasheet */
|
||||
port {
|
||||
imx074_1: endpoint {
|
||||
clock-lanes = <0>;
|
||||
data-lanes = <1 2>;
|
||||
remote-endpoint = <&csi2_1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
csi2: csi2@ffc90000 {
|
||||
compatible = "renesas,sh-mobile-csi2";
|
||||
reg = <0xffc90000 0x1000>;
|
||||
interrupts = <0x17a0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@1 {
|
||||
compatible = "renesas,csi2c"; /* One of CSI2I and CSI2C. */
|
||||
reg = <1>; /* CSI-2 PHY #1 of 2: PHY_S,
|
||||
PHY_M has port address 0,
|
||||
is unused. */
|
||||
csi2_1: endpoint {
|
||||
clock-lanes = <0>;
|
||||
data-lanes = <2 1>;
|
||||
remote-endpoint = <&imx074_1>;
|
||||
};
|
||||
};
|
||||
port@2 {
|
||||
reg = <2>; /* port 2: link to the CEU */
|
||||
|
||||
csi2_2: endpoint {
|
||||
remote-endpoint = <&ceu0_0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
This file has moved to video-interfaces.yaml and video-interface-devices.yaml.
|
||||
|
344
Documentation/devicetree/bindings/media/video-interfaces.yaml
Normal file
344
Documentation/devicetree/bindings/media/video-interfaces.yaml
Normal file
@ -0,0 +1,344 @@
|
||||
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||
%YAML 1.2
|
||||
---
|
||||
$id: http://devicetree.org/schemas/media/video-interfaces.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Common bindings for video receiver and transmitter interface endpoints
|
||||
|
||||
maintainers:
|
||||
- Sakari Ailus <sakari.ailus@linux.intel.com>
|
||||
- Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
|
||||
description: |
|
||||
Video data pipelines usually consist of external devices, e.g. camera sensors,
|
||||
controlled over an I2C, SPI or UART bus, and SoC internal IP blocks, including
|
||||
video DMA engines and video data processors.
|
||||
|
||||
SoC internal blocks are described by DT nodes, placed similarly to other SoC
|
||||
blocks. External devices are represented as child nodes of their respective
|
||||
bus controller nodes, e.g. I2C.
|
||||
|
||||
Data interfaces on all video devices are described by their child 'port' nodes.
|
||||
Configuration of a port depends on other devices participating in the data
|
||||
transfer and is described by 'endpoint' subnodes.
|
||||
|
||||
device {
|
||||
...
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@0 {
|
||||
...
|
||||
endpoint@0 { ... };
|
||||
endpoint@1 { ... };
|
||||
};
|
||||
port@1 { ... };
|
||||
};
|
||||
};
|
||||
|
||||
If a port can be configured to work with more than one remote device on the same
|
||||
bus, an 'endpoint' child node must be provided for each of them. If more than
|
||||
one port is present in a device node or there is more than one endpoint at a
|
||||
port, or port node needs to be associated with a selected hardware interface,
|
||||
a common scheme using '#address-cells', '#size-cells' and 'reg' properties is
|
||||
used.
|
||||
|
||||
All 'port' nodes can be grouped under optional 'ports' node, which allows to
|
||||
specify #address-cells, #size-cells properties independently for the 'port'
|
||||
and 'endpoint' nodes and any child device nodes a device might have.
|
||||
|
||||
Two 'endpoint' nodes are linked with each other through their 'remote-endpoint'
|
||||
phandles. An endpoint subnode of a device contains all properties needed for
|
||||
configuration of this device for data exchange with other device. In most
|
||||
cases properties at the peer 'endpoint' nodes will be identical, however they
|
||||
might need to be different when there is any signal modifications on the bus
|
||||
between two devices, e.g. there are logic signal inverters on the lines.
|
||||
|
||||
It is allowed for multiple endpoints at a port to be active simultaneously,
|
||||
where supported by a device. For example, in case where a data interface of
|
||||
a device is partitioned into multiple data busses, e.g. 16-bit input port
|
||||
divided into two separate ITU-R BT.656 8-bit busses. In such case bus-width
|
||||
and data-shift properties can be used to assign physical data lines to each
|
||||
endpoint node (logical bus).
|
||||
|
||||
Documenting bindings for devices
|
||||
--------------------------------
|
||||
|
||||
All required and optional bindings the device supports shall be explicitly
|
||||
documented in device DT binding documentation. This also includes port and
|
||||
endpoint nodes for the device, including unit-addresses and reg properties
|
||||
where relevant.
|
||||
|
||||
allOf:
|
||||
- $ref: /schemas/graph.yaml#/$defs/endpoint-base
|
||||
|
||||
properties:
|
||||
slave-mode:
|
||||
type: boolean
|
||||
description:
|
||||
Indicates that the link is run in slave mode. The default when this
|
||||
property is not specified is master mode. In the slave mode horizontal and
|
||||
vertical synchronization signals are provided to the slave device (data
|
||||
source) by the master device (data sink). In the master mode the data
|
||||
source device is also the source of the synchronization signals.
|
||||
|
||||
bus-type:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum:
|
||||
- 1 # MIPI CSI-2 C-PHY
|
||||
- 2 # MIPI CSI1
|
||||
- 3 # CCP2
|
||||
- 4 # MIPI CSI-2 D-PHY
|
||||
- 5 # Parallel
|
||||
- 6 # BT.656
|
||||
description:
|
||||
Data bus type.
|
||||
|
||||
bus-width:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
maximum: 64
|
||||
description:
|
||||
Number of data lines actively used, valid for the parallel busses.
|
||||
|
||||
data-shift:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
maximum: 64
|
||||
description:
|
||||
On the parallel data busses, if bus-width is used to specify the number of
|
||||
data lines, data-shift can be used to specify which data lines are used,
|
||||
e.g. "bus-width=<8>; data-shift=<2>;" means, that lines 9:2 are used.
|
||||
|
||||
hsync-active:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
description:
|
||||
Active state of the HSYNC signal, 0/1 for LOW/HIGH respectively.
|
||||
|
||||
vsync-active:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
description:
|
||||
Active state of the VSYNC signal, 0/1 for LOW/HIGH respectively. Note,
|
||||
that if HSYNC and VSYNC polarities are not specified, embedded
|
||||
synchronization may be required, where supported.
|
||||
|
||||
data-active:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
description:
|
||||
Similar to HSYNC and VSYNC, specifies data line polarity.
|
||||
|
||||
data-enable-active:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
description:
|
||||
Similar to HSYNC and VSYNC, specifies the data enable signal polarity.
|
||||
|
||||
field-even-active:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
description:
|
||||
Field signal level during the even field data transmission.
|
||||
|
||||
pclk-sample:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
description:
|
||||
Sample data on rising (1) or falling (0) edge of the pixel clock signal.
|
||||
|
||||
sync-on-green-active:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
description:
|
||||
Active state of Sync-on-green (SoG) signal, 0/1 for LOW/HIGH respectively.
|
||||
|
||||
data-lanes:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 1
|
||||
maxItems: 8
|
||||
items:
|
||||
# Assume up to 9 physical lane indices
|
||||
maximum: 8
|
||||
description:
|
||||
An array of physical data lane indexes. Position of an entry determines
|
||||
the logical lane number, while the value of an entry indicates physical
|
||||
lane, e.g. for 2-lane MIPI CSI-2 bus we could have "data-lanes = <1 2>;",
|
||||
assuming the clock lane is on hardware lane 0. If the hardware does not
|
||||
support lane reordering, monotonically incremented values shall be used
|
||||
from 0 or 1 onwards, depending on whether or not there is also a clock
|
||||
lane. This property is valid for serial busses only (e.g. MIPI CSI-2).
|
||||
|
||||
clock-lanes:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
# Assume up to 9 physical lane indices
|
||||
maximum: 8
|
||||
description:
|
||||
Physical clock lane index. Position of an entry determines the logical
|
||||
lane number, while the value of an entry indicates physical lane, e.g. for
|
||||
a MIPI CSI-2 bus we could have "clock-lanes = <0>;", which places the
|
||||
clock lane on hardware lane 0. This property is valid for serial busses
|
||||
only (e.g. MIPI CSI-2).
|
||||
|
||||
clock-noncontinuous:
|
||||
type: boolean
|
||||
description:
|
||||
Allow MIPI CSI-2 non-continuous clock mode.
|
||||
|
||||
link-frequencies:
|
||||
$ref: /schemas/types.yaml#/definitions/uint64-array
|
||||
description:
|
||||
Allowed data bus frequencies. For MIPI CSI-2, for instance, this is the
|
||||
actual frequency of the bus, not bits per clock per lane value. An array
|
||||
of 64-bit unsigned integers.
|
||||
|
||||
lane-polarities:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32-array
|
||||
minItems: 1
|
||||
maxItems: 9
|
||||
items:
|
||||
enum: [ 0, 1 ]
|
||||
description:
|
||||
An array of polarities of the lanes starting from the clock lane and
|
||||
followed by the data lanes in the same order as in data-lanes. Valid
|
||||
values are 0 (normal) and 1 (inverted). The length of the array should be
|
||||
the combined length of data-lanes and clock-lanes properties. If the
|
||||
lane-polarities property is omitted, the value must be interpreted as 0
|
||||
(normal). This property is valid for serial busses only.
|
||||
|
||||
strobe:
|
||||
$ref: /schemas/types.yaml#/definitions/uint32
|
||||
enum: [ 0, 1 ]
|
||||
description:
|
||||
Whether the clock signal is used as clock (0) or strobe (1). Used with
|
||||
CCP2, for instance.
|
||||
|
||||
additionalProperties: true
|
||||
|
||||
examples:
|
||||
# The example snippet below describes two data pipelines. ov772x and imx074
|
||||
# are camera sensors with a parallel and serial (MIPI CSI-2) video bus
|
||||
# respectively. Both sensors are on the I2C control bus corresponding to the
|
||||
# i2c0 controller node. ov772x sensor is linked directly to the ceu0 video
|
||||
# host interface. imx074 is linked to ceu0 through the MIPI CSI-2 receiver
|
||||
# (csi2). ceu0 has a (single) DMA engine writing captured data to memory.
|
||||
# ceu0 node has a single 'port' node which may indicate that at any time
|
||||
# only one of the following data pipelines can be active:
|
||||
# ov772x -> ceu0 or imx074 -> csi2 -> ceu0.
|
||||
- |
|
||||
ceu@fe910000 {
|
||||
compatible = "renesas,sh-mobile-ceu";
|
||||
reg = <0xfe910000 0xa0>;
|
||||
interrupts = <0x880>;
|
||||
|
||||
mclk: master_clock {
|
||||
compatible = "renesas,ceu-clock";
|
||||
#clock-cells = <1>;
|
||||
clock-frequency = <50000000>; /* Max clock frequency */
|
||||
clock-output-names = "mclk";
|
||||
};
|
||||
|
||||
port {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
/* Parallel bus endpoint */
|
||||
ceu0_1: endpoint@1 {
|
||||
reg = <1>; /* Local endpoint # */
|
||||
remote-endpoint = <&ov772x_1_1>; /* Remote phandle */
|
||||
bus-width = <8>; /* Used data lines */
|
||||
data-shift = <2>; /* Lines 9:2 are used */
|
||||
|
||||
/* If hsync-active/vsync-active are missing,
|
||||
embedded BT.656 sync is used */
|
||||
hsync-active = <0>; /* Active low */
|
||||
vsync-active = <0>; /* Active low */
|
||||
data-active = <1>; /* Active high */
|
||||
pclk-sample = <1>; /* Rising */
|
||||
};
|
||||
|
||||
/* MIPI CSI-2 bus endpoint */
|
||||
ceu0_0: endpoint@0 {
|
||||
reg = <0>;
|
||||
remote-endpoint = <&csi2_2>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
i2c {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
camera@21 {
|
||||
compatible = "ovti,ov772x";
|
||||
reg = <0x21>;
|
||||
vddio-supply = <®ulator1>;
|
||||
vddcore-supply = <®ulator2>;
|
||||
|
||||
clock-frequency = <20000000>;
|
||||
clocks = <&mclk 0>;
|
||||
clock-names = "xclk";
|
||||
|
||||
port {
|
||||
/* With 1 endpoint per port no need for addresses. */
|
||||
ov772x_1_1: endpoint {
|
||||
bus-width = <8>;
|
||||
remote-endpoint = <&ceu0_1>;
|
||||
hsync-active = <1>;
|
||||
vsync-active = <0>; /* Who came up with an
|
||||
inverter here ?... */
|
||||
data-active = <1>;
|
||||
pclk-sample = <1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
camera@1a {
|
||||
compatible = "sony,imx074";
|
||||
reg = <0x1a>;
|
||||
vddio-supply = <®ulator1>;
|
||||
vddcore-supply = <®ulator2>;
|
||||
|
||||
clock-frequency = <30000000>; /* Shared clock with ov772x_1 */
|
||||
clocks = <&mclk 0>;
|
||||
clock-names = "sysclk"; /* Assuming this is the
|
||||
name in the datasheet */
|
||||
port {
|
||||
imx074_1: endpoint {
|
||||
clock-lanes = <0>;
|
||||
data-lanes = <1 2>;
|
||||
remote-endpoint = <&csi2_1>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
csi2: csi2@ffc90000 {
|
||||
compatible = "renesas,sh-mobile-csi2";
|
||||
reg = <0xffc90000 0x1000>;
|
||||
interrupts = <0x17a0>;
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
port@1 {
|
||||
compatible = "renesas,csi2c"; /* One of CSI2I and CSI2C. */
|
||||
reg = <1>; /* CSI-2 PHY #1 of 2: PHY_S,
|
||||
PHY_M has port address 0,
|
||||
is unused. */
|
||||
csi2_1: endpoint {
|
||||
clock-lanes = <0>;
|
||||
data-lanes = <2 1>;
|
||||
remote-endpoint = <&imx074_1>;
|
||||
};
|
||||
};
|
||||
port@2 {
|
||||
reg = <2>; /* port 2: link to the CEU */
|
||||
|
||||
csi2_2: endpoint {
|
||||
remote-endpoint = <&ceu0_0>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
@ -97,24 +97,21 @@ properties:
|
||||
maxItems: 1
|
||||
|
||||
ports:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
properties:
|
||||
port@0:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/$defs/port-base
|
||||
description: |
|
||||
Input / sink port node, single endpoint describing the
|
||||
CSI-2 transmitter.
|
||||
|
||||
properties:
|
||||
reg:
|
||||
const: 0
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
$ref: /schemas/media/video-interfaces.yaml#
|
||||
unevaluatedProperties: false
|
||||
|
||||
properties:
|
||||
|
||||
data-lanes:
|
||||
description: |
|
||||
This is required only in the sink port 0 endpoint which
|
||||
@ -130,41 +127,17 @@ properties:
|
||||
- const: 3
|
||||
- const: 4
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- data-lanes
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
unevaluatedProperties: false
|
||||
|
||||
port@1:
|
||||
type: object
|
||||
$ref: /schemas/graph.yaml#/properties/port
|
||||
description: |
|
||||
Output / source port node, endpoint describing modules
|
||||
connected the CSI-2 receiver.
|
||||
|
||||
properties:
|
||||
|
||||
reg:
|
||||
const: 1
|
||||
|
||||
endpoint:
|
||||
type: object
|
||||
|
||||
properties:
|
||||
|
||||
remote-endpoint: true
|
||||
|
||||
required:
|
||||
- remote-endpoint
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
additionalProperties: false
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
@ -15,7 +15,7 @@ Camera sensors have an internal clock tree including a PLL and a number of
|
||||
divisors. The clock tree is generally configured by the driver based on a few
|
||||
input parameters that are specific to the hardware:: the external clock frequency
|
||||
and the link frequency. The two parameters generally are obtained from system
|
||||
firmware. No other frequencies should be used in any circumstances.
|
||||
firmware. **No other frequencies should be used in any circumstances.**
|
||||
|
||||
The reason why the clock frequencies are so important is that the clock signals
|
||||
come out of the SoC, and in many cases a specific frequency is designed to be
|
||||
@ -23,6 +23,24 @@ used in the system. Using another frequency may cause harmful effects
|
||||
elsewhere. Therefore only the pre-determined frequencies are configurable by the
|
||||
user.
|
||||
|
||||
ACPI
|
||||
~~~~
|
||||
|
||||
Read the "clock-frequency" _DSD property to denote the frequency. The driver can
|
||||
rely on this frequency being used.
|
||||
|
||||
Devicetree
|
||||
~~~~~~~~~~
|
||||
|
||||
The currently preferred way to achieve this is using "assigned-clock-rates"
|
||||
property. See Documentation/devicetree/bindings/clock/clock-bindings.txt for
|
||||
more information. The driver then gets the frequency using clk_get_rate().
|
||||
|
||||
This approach has the drawback that there's no guarantee that the frequency
|
||||
hasn't been modified directly or indirectly by another driver, or supported by
|
||||
the board's clock tree to begin with. Changes to the Common Clock Framework API
|
||||
are required to ensure reliability.
|
||||
|
||||
Frame size
|
||||
----------
|
||||
|
||||
|
@ -26,7 +26,7 @@ It is documented in the HDMI 1.4 specification with the new 2.0 bits documented
|
||||
in the HDMI 2.0 specification. But for most of the features the freely available
|
||||
HDMI 1.3a specification is sufficient:
|
||||
|
||||
http://www.microprocessor.org/HDMISpecification13a.pdf
|
||||
https://www.hdmi.org/spec/index
|
||||
|
||||
|
||||
CEC Adapter Interface
|
||||
|
@ -35,7 +35,7 @@ ability to start and stop the stream.
|
||||
|
||||
The value of the V4L2_CID_PIXEL_RATE is calculated as follows::
|
||||
|
||||
pixel_rate = link_freq * 2 * nr_of_lanes / bits_per_sample
|
||||
pixel_rate = link_freq * 2 * nr_of_lanes * 16 / k / bits_per_sample
|
||||
|
||||
where
|
||||
|
||||
@ -53,6 +53,8 @@ where
|
||||
- Two bits are transferred per clock cycle per lane.
|
||||
* - bits_per_sample
|
||||
- Number of bits per sample.
|
||||
* - k
|
||||
- 16 for D-PHY and 7 for C-PHY
|
||||
|
||||
The transmitter drivers must, if possible, configure the CSI-2
|
||||
transmitter to *LP-11 mode* whenever the transmitter is powered on but
|
||||
|
@ -79,4 +79,17 @@ definitions:
|
||||
-l drivers/media/i2c/ccs/ccs-limits.c \
|
||||
-c Documentation/driver-api/media/drivers/ccs/ccs-regs.asc
|
||||
|
||||
CCS PLL calculator
|
||||
==================
|
||||
|
||||
The CCS PLL calculator is used to compute the PLL configuration, given sensor's
|
||||
capabilities as well as board configuration and user specified configuration. As
|
||||
the configuration space that encompasses all these configurations is vast, the
|
||||
PLL calculator isn't entirely trivial. Yet it is relatively simple to use for a
|
||||
driver.
|
||||
|
||||
The PLL model implemented by the PLL calculator corresponds to MIPI CCS 1.1.
|
||||
|
||||
.. kernel-doc:: drivers/media/i2c/ccs-pll.h
|
||||
|
||||
**Copyright** |copy| 2020 Intel Corporation
|
||||
|
@ -1,31 +0,0 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
V4L2 clocks
|
||||
-----------
|
||||
|
||||
.. attention::
|
||||
|
||||
This is a temporary API and it shall be replaced by the generic
|
||||
clock API, when the latter becomes widely available.
|
||||
|
||||
Many subdevices, like camera sensors, TV decoders and encoders, need a clock
|
||||
signal to be supplied by the system. Often this clock is supplied by the
|
||||
respective bridge device. The Linux kernel provides a Common Clock Framework for
|
||||
this purpose. However, it is not (yet) available on all architectures. Besides,
|
||||
the nature of the multi-functional (clock, data + synchronisation, I2C control)
|
||||
connection of subdevices to the system might impose special requirements on the
|
||||
clock API usage. E.g. V4L2 has to support clock provider driver unregistration
|
||||
while a subdevice driver is holding a reference to the clock. For these reasons
|
||||
a V4L2 clock helper API has been developed and is provided to bridge and
|
||||
subdevice drivers.
|
||||
|
||||
The API consists of two parts: two functions to register and unregister a V4L2
|
||||
clock source: v4l2_clk_register() and v4l2_clk_unregister() and calls to control
|
||||
a clock object, similar to the respective generic clock API calls:
|
||||
v4l2_clk_get(), v4l2_clk_put(), v4l2_clk_enable(), v4l2_clk_disable(),
|
||||
v4l2_clk_get_rate(), and v4l2_clk_set_rate(). Clock suppliers have to provide
|
||||
clock operations that will be called when clock users invoke respective API
|
||||
methods.
|
||||
|
||||
It is expected that once the CCF becomes available on all relevant
|
||||
architectures this API will be removed.
|
@ -15,7 +15,6 @@ Video4Linux devices
|
||||
v4l2-controls
|
||||
v4l2-videobuf
|
||||
v4l2-videobuf2
|
||||
v4l2-clocks
|
||||
v4l2-dv-timings
|
||||
v4l2-flash-led-class
|
||||
v4l2-mc
|
||||
|
@ -122,15 +122,12 @@ Don't forget to cleanup the media entity before the sub-device is destroyed:
|
||||
|
||||
media_entity_cleanup(&sd->entity);
|
||||
|
||||
If the subdev driver intends to process video and integrate with the media
|
||||
framework, it must implement format related functionality using
|
||||
:c:type:`v4l2_subdev_pad_ops` instead of :c:type:`v4l2_subdev_video_ops`.
|
||||
|
||||
In that case, the subdev driver may set the link_validate field to provide
|
||||
its own link validation function. The link validation function is called for
|
||||
every link in the pipeline where both of the ends of the links are V4L2
|
||||
sub-devices. The driver is still responsible for validating the correctness
|
||||
of the format configuration between sub-devices and video nodes.
|
||||
If a sub-device driver implements sink pads, the subdev driver may set the
|
||||
link_validate field in :c:type:`v4l2_subdev_pad_ops` to provide its own link
|
||||
validation function. For every link in the pipeline, the link_validate pad
|
||||
operation of the sink end of the link is called. In both cases the driver is
|
||||
still responsible for validating the correctness of the format configuration
|
||||
between sub-devices and video nodes.
|
||||
|
||||
If link_validate op is not set, the default function
|
||||
:c:func:`v4l2_subdev_link_validate_default` is used instead. This function
|
||||
@ -200,15 +197,45 @@ unregister the notifier the driver has to call
|
||||
takes two arguments: a pointer to struct :c:type:`v4l2_device` and a
|
||||
pointer to struct :c:type:`v4l2_async_notifier`.
|
||||
|
||||
Before registering the notifier, bridge drivers must do two things:
|
||||
first, the notifier must be initialized using the
|
||||
:c:func:`v4l2_async_notifier_init`. Second, bridge drivers can then
|
||||
begin to form a list of subdevice descriptors that the bridge device
|
||||
needs for its operation. Subdevice descriptors are added to the notifier
|
||||
using the :c:func:`v4l2_async_notifier_add_subdev` call. This function
|
||||
takes two arguments: a pointer to struct :c:type:`v4l2_async_notifier`,
|
||||
and a pointer to the subdevice descripter, which is of type struct
|
||||
:c:type:`v4l2_async_subdev`.
|
||||
Before registering the notifier, bridge drivers must do two things: first, the
|
||||
notifier must be initialized using the :c:func:`v4l2_async_notifier_init`.
|
||||
Second, bridge drivers can then begin to form a list of subdevice descriptors
|
||||
that the bridge device needs for its operation. Several functions are available
|
||||
to add subdevice descriptors to a notifier, depending on the type of device and
|
||||
the needs of the driver.
|
||||
|
||||
:c:func:`v4l2_async_notifier_add_fwnode_remote_subdev` and
|
||||
:c:func:`v4l2_async_notifier_add_i2c_subdev` are for bridge and ISP drivers for
|
||||
registering their async sub-devices with the notifier.
|
||||
|
||||
:c:func:`v4l2_async_register_subdev_sensor_common` is a helper function for
|
||||
sensor drivers registering their own async sub-device, but it also registers a
|
||||
notifier and further registers async sub-devices for lens and flash devices
|
||||
found in firmware. The notifier for the sub-device is unregistered with the
|
||||
async sub-device.
|
||||
|
||||
These functions allocate an async sub-device descriptor which is of type struct
|
||||
:c:type:`v4l2_async_subdev` embedded in a driver-specific struct. The &struct
|
||||
:c:type:`v4l2_async_subdev` shall be the first member of this struct:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct my_async_subdev {
|
||||
struct v4l2_async_subdev asd;
|
||||
...
|
||||
};
|
||||
|
||||
struct my_async_subdev *my_asd;
|
||||
struct fwnode_handle *ep;
|
||||
|
||||
...
|
||||
|
||||
my_asd = v4l2_async_notifier_add_fwnode_remote_subdev(¬ifier, ep,
|
||||
struct my_async_subdev);
|
||||
fwnode_handle_put(ep);
|
||||
|
||||
if (IS_ERR(asd))
|
||||
return PTR_ERR(asd);
|
||||
|
||||
The V4L2 core will then use these descriptors to match asynchronously
|
||||
registered subdevices to them. If a match is detected the ``.bound()``
|
||||
|
110
Documentation/userspace-api/media/drivers/ccs.rst
Normal file
110
Documentation/userspace-api/media/drivers/ccs.rst
Normal file
@ -0,0 +1,110 @@
|
||||
.. SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
.. include:: <isonum.txt>
|
||||
|
||||
MIPI CCS camera sensor driver
|
||||
=============================
|
||||
|
||||
The MIPI CCS camera sensor driver is a generic driver for `MIPI CCS
|
||||
<https://www.mipi.org/specifications/camera-command-set>`_ compliant
|
||||
camera sensors. It exposes three sub-devices representing the pixel array,
|
||||
the binner and the scaler.
|
||||
|
||||
As the capabilities of individual devices vary, the driver exposes
|
||||
interfaces based on the capabilities that exist in hardware.
|
||||
|
||||
Pixel Array sub-device
|
||||
----------------------
|
||||
|
||||
The pixel array sub-device represents the camera sensor's pixel matrix, as well
|
||||
as analogue crop functionality present in many compliant devices. The analogue
|
||||
crop is configured using the ``V4L2_SEL_TGT_CROP`` on the source pad (0) of the
|
||||
entity. The size of the pixel matrix can be obtained by getting the
|
||||
``V4L2_SEL_TGT_NATIVE_SIZE`` target.
|
||||
|
||||
Binner
|
||||
------
|
||||
|
||||
The binner sub-device represents the binning functionality on the sensor. For
|
||||
that purpose, selection target ``V4L2_SEL_TGT_COMPOSE`` is supported on the
|
||||
sink pad (0).
|
||||
|
||||
Additionally, if a device has no scaler or digital crop functionality, the
|
||||
source pad (1) expses another digital crop selection rectangle that can only
|
||||
crop at the end of the lines and frames.
|
||||
|
||||
Scaler
|
||||
------
|
||||
|
||||
The scaler sub-device represents the digital crop and scaling functionality of
|
||||
the sensor. The V4L2 selection target ``V4L2_SEL_TGT_CROP`` is used to
|
||||
configure the digital crop on the sink pad (0) when digital crop is supported.
|
||||
Scaling is configured using selection target ``V4L2_SEL_TGT_COMPOSE`` on the
|
||||
sink pad (0) as well.
|
||||
|
||||
Additionally, if the scaler sub-device exists, its source pad (1) exposes
|
||||
another digital crop selection rectangle that can only crop at the end of the
|
||||
lines and frames.
|
||||
|
||||
Digital and analogue crop
|
||||
-------------------------
|
||||
|
||||
Digital crop functionality is referred to as cropping that effectively works by
|
||||
dropping some data on the floor. Analogue crop, on the other hand, means that
|
||||
the cropped information is never retrieved. In case of camera sensors, the
|
||||
analogue data is never read from the pixel matrix that are outside the
|
||||
configured selection rectangle that designates crop. The difference has an
|
||||
effect in device timing and likely also in power consumption.
|
||||
|
||||
Private controls
|
||||
----------------
|
||||
|
||||
The MIPI CCS driver implements a number of private controls under
|
||||
``V4L2_CID_USER_BASE_CCS`` to control the MIPI CCS compliant camera sensors.
|
||||
|
||||
Analogue gain model
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The CCS defines an analogue gain model where the gain can be calculated using
|
||||
the following formula:
|
||||
|
||||
gain = m0 * x + c0 / (m1 * x + c1)
|
||||
|
||||
Either m0 or c0 will be zero. The constants that are device specific, can be
|
||||
obtained from the following controls:
|
||||
|
||||
V4L2_CID_CCS_ANALOGUE_GAIN_M0
|
||||
V4L2_CID_CCS_ANALOGUE_GAIN_M1
|
||||
V4L2_CID_CCS_ANALOGUE_GAIN_C0
|
||||
V4L2_CID_CCS_ANALOGUE_GAIN_C1
|
||||
|
||||
The analogue gain (``x`` in the formula) is controlled through
|
||||
``V4L2_CID_ANALOGUE_GAIN`` in this case.
|
||||
|
||||
Alternate analogue gain model
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The CCS defines another analogue gain model called alternate analogue gain. In
|
||||
this case, the formula to calculate actual gain consists of linear and
|
||||
exponential parts:
|
||||
|
||||
gain = linear * 2 ^ exponent
|
||||
|
||||
The ``linear`` and ``exponent`` factors can be set using the
|
||||
``V4L2_CID_CCS_ANALOGUE_LINEAR_GAIN`` and
|
||||
``V4L2_CID_CCS_ANALOGUE_EXPONENTIAL_GAIN`` controls, respectively
|
||||
|
||||
Shading correction
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The CCS standard supports lens shading correction. The feature can be controlled
|
||||
using ``V4L2_CID_CCS_SHADING_CORRECTION``. Additionally, the luminance
|
||||
correction level may be changed using
|
||||
``V4L2_CID_CCS_LUMINANCE_CORRECTION_LEVEL``, where value 0 indicates no
|
||||
correction and 128 indicates correcting the luminance in corners to 10 % less
|
||||
than in the centre.
|
||||
|
||||
Shading correction needs to be enabled for luminance correction level to have an
|
||||
effect.
|
||||
|
||||
**Copyright** |copy| 2020 Intel Corporation
|
@ -31,6 +31,7 @@ For more details see the file COPYING in the source distribution of Linux.
|
||||
:maxdepth: 5
|
||||
:numbered:
|
||||
|
||||
ccs
|
||||
cx2341x-uapi
|
||||
imx-uapi
|
||||
max2175
|
||||
|
@ -2,7 +2,7 @@
|
||||
<!-- SPDX-License-Identifier: GPL-2.0 OR GFDL-1.1-no-invariants-or-later -->
|
||||
<svg id="svg2" width="15.847cm" height="8.4187cm" fill-rule="evenodd" stroke-linejoin="round" stroke-width="28.222" preserveAspectRatio="xMidYMid" version="1.2" viewBox="0 0 23770.123 12628.122" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"><defs id="defs142"><marker id="Arrow1Lend" overflow="visible" orient="auto"><path id="path954" transform="matrix(-.8 0 0 -.8 -10 0)" d="m0 0 5-5-17.5 5 17.5 5z" fill-rule="evenodd" stroke="#000" stroke-width="1pt"/></marker><marker id="marker1243" overflow="visible" orient="auto"><path id="path1241" transform="matrix(-.8 0 0 -.8 -10 0)" d="m0 0 5-5-17.5 5 17.5 5z" fill-rule="evenodd" stroke="#000" stroke-width="1pt"/></marker></defs><metadata id="metadata519"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title/></cc:Work></rdf:RDF></metadata><rect id="rect197" class="BoundingBox" x="5355.1" y="13.122" width="18403" height="9603" fill="none"/><path id="path199" d="m14556 9614.1h-9200v-9600h18400v9600z" fill="#fff"/><path id="path201" d="m14556 9614.1h-9200v-9600h18400v9600z" fill="none" stroke="#000"/><rect id="rect206" class="BoundingBox" x="13.122" y="4013.1" width="4544" height="2403" fill="none"/><path id="path208" d="m2285.1 6414.1h-2271v-2400h4541v2400z" fill="#fff"/><path id="path210" d="m2285.1 6414.1h-2271v-2400h4541v2400z" fill="none" stroke="#000"/><text id="text212" class="TextShape" x="-2443.8779" y="-4585.8779"><tspan id="tspan214" class="TextParagraph" font-family="sans-serif" font-size="635px" font-weight="400"><tspan id="tspan216" class="TextPosition"
|
||||
x="1281.1219" y="5435.1221"><tspan id="tspan218" fill="#000000">Antena</tspan></tspan></tspan></text>
|
||||
x="1013.1317" y="5435.1221"><tspan id="tspan218" fill="#000000">Antenna</tspan></tspan></tspan></text>
|
||||
<rect id="rect223" class="BoundingBox" x="6213.1" y="1813.1" width="4544" height="2403" fill="none"/><path id="path225" d="m8485.1 4214.1h-2271v-2400h4541v2400z" fill="#fff"/><path id="path227" d="m8485.1 4214.1h-2271v-2400h4541v2400z" fill="none" stroke="#000"/><text id="text229" class="TextShape" x="-2443.8779" y="-4585.8779"><tspan id="tspan231" class="TextParagraph" font-family="sans-serif" font-size="635px" font-weight="400"><tspan id="tspan233" class="TextPosition" x="7217.1221" y="3235.1221"><tspan id="tspan235" fill="#000000">Frontend</tspan></tspan></tspan></text>
|
||||
<rect id="rect240" class="BoundingBox" x="12113" y="1813.1" width="4544" height="2403" fill="none"/><path id="path242" d="m14385 4214.1h-2271v-2400h4541v2400z" fill="#fff"/><path id="path244" d="m14385 4214.1h-2271v-2400h4541v2400z" fill="none" stroke="#000"/><text id="text246" class="TextShape" x="-2443.8779" y="-4585.8779"><tspan id="tspan248" class="TextParagraph" font-family="sans-serif" font-size="635px" font-weight="400"><tspan id="tspan250" class="TextPosition" x="13944.122" y="3235.1221"><tspan id="tspan252" fill="#000000">CA</tspan></tspan></tspan></text>
|
||||
<rect id="rect257" class="BoundingBox" x="18113" y="1813.1" width="4544" height="2403" fill="none"/><path id="path259" d="m20385 4214.1h-2271v-2400h4541v2400z" fill="#fff"/><path id="path261" d="m20385 4214.1h-2271v-2400h4541v2400z" fill="none" stroke="#000"/><text id="text263" class="TextShape" x="-2443.8779" y="-4585.8779"><tspan id="tspan265" class="TextParagraph" font-family="sans-serif" font-size="635px" font-weight="400"><tspan id="tspan267" class="TextPosition" x="19384.123" y="3235.1221"><tspan id="tspan269" fill="#000000">Demux</tspan></tspan></tspan></text>
|
||||
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 8.9 KiB |
@ -39,6 +39,7 @@ Types and flags used to represent the media graph elements
|
||||
.. _MEDIA-ENT-F-PROC-VIDEO-STATISTICS:
|
||||
.. _MEDIA-ENT-F-PROC-VIDEO-ENCODER:
|
||||
.. _MEDIA-ENT-F-PROC-VIDEO-DECODER:
|
||||
.. _MEDIA-ENT-F-PROC-VIDEO-ISP:
|
||||
.. _MEDIA-ENT-F-VID-MUX:
|
||||
.. _MEDIA-ENT-F-VID-IF-BRIDGE:
|
||||
.. _MEDIA-ENT-F-DV-DECODER:
|
||||
@ -201,6 +202,12 @@ Types and flags used to represent the media graph elements
|
||||
decompressing a compressed video stream into uncompressed video
|
||||
frames. Must have one sink pad and at least one source pad.
|
||||
|
||||
* - ``MEDIA_ENT_F_PROC_VIDEO_ISP``
|
||||
- An Image Signal Processor (ISP) device. ISPs generally are one of a
|
||||
kind devices that have their specific control interfaces using a
|
||||
combination of custom V4L2 controls and IOCTLs, and parameters
|
||||
supplied in a metadata buffer.
|
||||
|
||||
* - ``MEDIA_ENT_F_VID_MUX``
|
||||
- Video multiplexer. An entity capable of multiplexing must have at
|
||||
least two sink pads and one source pad, and must pass the video
|
||||
|
@ -1182,6 +1182,18 @@ enum v4l2_mpeg_video_h264_entropy_mode -
|
||||
V4L2_CID_MPEG_VIDEO_H264_MAX_QP is also set, the quantization parameter
|
||||
should be chosen to meet both requirements.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MIN_QP (integer)``
|
||||
Minimum quantization parameter for the H264 B frame to limit B frame
|
||||
quality to a range. Valid range: from 0 to 51. If
|
||||
V4L2_CID_MPEG_VIDEO_H264_MIN_QP is also set, the quantization parameter
|
||||
should be chosen to meet both requirements.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_H264_B_FRAME_MAX_QP (integer)``
|
||||
Maximum quantization parameter for the H264 B frame to limit B frame
|
||||
quality to a range. Valid range: from 0 to 51. If
|
||||
V4L2_CID_MPEG_VIDEO_H264_MAX_QP is also set, the quantization parameter
|
||||
should be chosen to meet both requirements.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP (integer)``
|
||||
Quantization parameter for an I frame for MPEG4. Valid range: from 1
|
||||
to 31.
|
||||
@ -1501,6 +1513,26 @@ enum v4l2_mpeg_video_h264_hierarchical_coding_type -
|
||||
* - Bit 16:32
|
||||
- Layer number
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L0_BR (integer)``
|
||||
Indicates bit rate (bps) for hierarchical coding layer 0 for H264 encoder.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L1_BR (integer)``
|
||||
Indicates bit rate (bps) for hierarchical coding layer 1 for H264 encoder.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L2_BR (integer)``
|
||||
Indicates bit rate (bps) for hierarchical coding layer 2 for H264 encoder.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L3_BR (integer)``
|
||||
Indicates bit rate (bps) for hierarchical coding layer 3 for H264 encoder.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L4_BR (integer)``
|
||||
Indicates bit rate (bps) for hierarchical coding layer 4 for H264 encoder.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L5_BR (integer)``
|
||||
Indicates bit rate (bps) for hierarchical coding layer 5 for H264 encoder.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_H264_HIER_CODING_L6_BR (integer)``
|
||||
Indicates bit rate (bps) for hierarchical coding layer 6 for H264 encoder.
|
||||
|
||||
.. _v4l2-mpeg-mpeg2:
|
||||
|
||||
@ -2628,11 +2660,11 @@ HEVC/H.265 Control IDs
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP (integer)``
|
||||
Minimum quantization parameter for HEVC.
|
||||
Valid range: from 0 to 51.
|
||||
Valid range: from 0 to 51 for 8 bit and from 0 to 63 for 10 bit.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP (integer)``
|
||||
Maximum quantization parameter for HEVC.
|
||||
Valid range: from 0 to 51.
|
||||
Valid range: from 0 to 51 for 8 bit and from 0 to 63 for 10 bit.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_QP (integer)``
|
||||
Quantization parameter for an I frame for HEVC.
|
||||
@ -2649,6 +2681,42 @@ HEVC/H.265 Control IDs
|
||||
Valid range: [V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP,
|
||||
V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP].
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MIN_QP (integer)``
|
||||
Minimum quantization parameter for the HEVC I frame to limit I frame
|
||||
quality to a range. Valid range: from 0 to 51 for 8 bit and from 0 to 63 for 10 bit.
|
||||
If V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP is also set, the quantization parameter
|
||||
should be chosen to meet both requirements.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_HEVC_I_FRAME_MAX_QP (integer)``
|
||||
Maximum quantization parameter for the HEVC I frame to limit I frame
|
||||
quality to a range. Valid range: from 0 to 51 for 8 bit and from 0 to 63 for 10 bit.
|
||||
If V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP is also set, the quantization parameter
|
||||
should be chosen to meet both requirements.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MIN_QP (integer)``
|
||||
Minimum quantization parameter for the HEVC P frame to limit P frame
|
||||
quality to a range. Valid range: from 0 to 51 for 8 bit and from 0 to 63 for 10 bit.
|
||||
If V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP is also set, the quantization parameter
|
||||
should be chosen to meet both requirements.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_HEVC_P_FRAME_MAX_QP (integer)``
|
||||
Maximum quantization parameter for the HEVC P frame to limit P frame
|
||||
quality to a range. Valid range: from 0 to 51 for 8 bit and from 0 to 63 for 10 bit.
|
||||
If V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP is also set, the quantization parameter
|
||||
should be chosen to meet both requirements.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MIN_QP (integer)``
|
||||
Minimum quantization parameter for the HEVC B frame to limit B frame
|
||||
quality to a range. Valid range: from 0 to 51 for 8 bit and from 0 to 63 for 10 bit.
|
||||
If V4L2_CID_MPEG_VIDEO_HEVC_MIN_QP is also set, the quantization parameter
|
||||
should be chosen to meet both requirements.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_HEVC_B_FRAME_MAX_QP (integer)``
|
||||
Maximum quantization parameter for the HEVC B frame to limit B frame
|
||||
quality to a range. Valid range: from 0 to 51 for 8 bit and from 0 to 63 for 10 bit.
|
||||
If V4L2_CID_MPEG_VIDEO_HEVC_MAX_QP is also set, the quantization parameter
|
||||
should be chosen to meet both requirements.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_HEVC_HIER_QP (boolean)``
|
||||
HIERARCHICAL_QP allows the host to specify the quantization parameter
|
||||
values for each temporal layer through HIERARCHICAL_QP_LAYER. This is
|
||||
@ -3569,3 +3637,12 @@ enum v4l2_mpeg_video_hevc_size_of_length_field -
|
||||
- Selecting this value specifies that HEVC slices are expected
|
||||
to be prefixed by Annex B start codes. According to :ref:`hevc`
|
||||
valid start codes can be 3-bytes 0x000001 or 4-bytes 0x00000001.
|
||||
|
||||
``V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID (integer)``
|
||||
Specifies a priority identifier for the NAL unit, which will be applied to
|
||||
the base layer. By default this value is set to 0 for the base layer,
|
||||
and the next layer will have the priority ID assigned as 1, 2, 3 and so on.
|
||||
The video encoder can't decide the priority id to be applied to a layer,
|
||||
so this has to come from client.
|
||||
This is applicable to H264 and valid Range is from 0 to 63.
|
||||
Source Rec. ITU-T H.264 (06/2019); G.7.4.1.1, G.8.8.1.
|
||||
|
@ -396,9 +396,9 @@ number of lines as the luma plane.
|
||||
NV24 and NV42
|
||||
-------------
|
||||
|
||||
Semi-planar YUV 4:4:4 formats. The chroma plane is subsampled by 2 in the
|
||||
horizontal direction. Chroma lines contain half the number of pixels and the
|
||||
same number of bytes as luma lines, and the chroma plane contains the same
|
||||
Semi-planar YUV 4:4:4 formats. The chroma plane is not subsampled.
|
||||
Chroma lines contain the same number of pixels and twice the
|
||||
number of bytes as luma lines, and the chroma plane contains the same
|
||||
number of lines as the luma plane.
|
||||
|
||||
.. flat-table:: Sample 4x4 NV24 Image
|
||||
|
33
MAINTAINERS
33
MAINTAINERS
@ -699,7 +699,8 @@ M: Michael Tretter <m.tretter@pengutronix.de>
|
||||
R: Pengutronix Kernel Team <kernel@pengutronix.de>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: drivers/staging/media/allegro-dvt/
|
||||
F: Documentation/devicetree/bindings/media/allegro,al5e.yaml
|
||||
F: drivers/media/platform/allegro-dvt/
|
||||
|
||||
ALLWINNER A10 CSI DRIVER
|
||||
M: Maxime Ripard <mripard@kernel.org>
|
||||
@ -8979,9 +8980,11 @@ INTEL IPU3 CSI-2 CIO2 DRIVER
|
||||
M: Yong Zhi <yong.zhi@intel.com>
|
||||
M: Sakari Ailus <sakari.ailus@linux.intel.com>
|
||||
M: Bingbu Cao <bingbu.cao@intel.com>
|
||||
M: Dan Scally <djrscally@gmail.com>
|
||||
R: Tianshu Qiu <tian.shu.qiu@intel.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/userspace-api/media/v4l/pixfmt-srggb10-ipu3.rst
|
||||
F: drivers/media/pci/intel/ipu3/
|
||||
|
||||
@ -11528,7 +11531,7 @@ L: linux-amlogic@lists.infradead.org
|
||||
S: Supported
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/amlogic,axg-ge2d.yaml
|
||||
F: drivers/media/meson/ge2d/
|
||||
F: drivers/media/platform/meson/ge2d/
|
||||
|
||||
MESON NAND CONTROLLER DRIVER FOR AMLOGIC SOCS
|
||||
M: Liang Yang <liang.yang@amlogic.com>
|
||||
@ -11811,9 +11814,11 @@ L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/media/i2c/mipi-ccs.yaml
|
||||
F: Documentation/driver-api/media/drivers/ccs/
|
||||
F: Documentation/userspace-api/media/drivers/ccs.rst
|
||||
F: drivers/media/i2c/ccs-pll.c
|
||||
F: drivers/media/i2c/ccs-pll.h
|
||||
F: drivers/media/i2c/ccs/
|
||||
F: include/uapi/linux/ccs.h
|
||||
F: include/uapi/linux/smiapp.h
|
||||
|
||||
MIPS
|
||||
@ -13095,7 +13100,7 @@ M: Jacopo Mondi <jacopo@jmondi.org>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/ov5647.yaml
|
||||
F: Documentation/devicetree/bindings/media/i2c/ovti,ov5647.yaml
|
||||
F: drivers/media/i2c/ov5647.c
|
||||
|
||||
OMNIVISION OV5670 SENSOR DRIVER
|
||||
@ -14941,6 +14946,18 @@ F: drivers/media/i2c/max9271.c
|
||||
F: drivers/media/i2c/max9271.h
|
||||
F: drivers/media/i2c/rdacm20.c
|
||||
|
||||
RDACM21 Camera Sensor
|
||||
M: Jacopo Mondi <jacopo+renesas@jmondi.org>
|
||||
M: Kieran Bingham <kieran.bingham+renesas@ideasonboard.com>
|
||||
M: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
|
||||
M: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
F: Documentation/devicetree/bindings/media/i2c/rdacm2x-gmsl.yaml
|
||||
F: drivers/media/i2c/max9271.c
|
||||
F: drivers/media/i2c/max9271.h
|
||||
F: drivers/media/i2c/rdacm21.c
|
||||
|
||||
RDC R-321X SoC
|
||||
M: Florian Fainelli <florian@openwrt.org>
|
||||
S: Maintained
|
||||
@ -16517,6 +16534,7 @@ M: Sakari Ailus <sakari.ailus@linux.intel.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/imx258.yaml
|
||||
F: drivers/media/i2c/imx258.c
|
||||
|
||||
SONY IMX274 SENSOR DRIVER
|
||||
@ -16542,6 +16560,15 @@ S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: drivers/media/i2c/imx319.c
|
||||
|
||||
SONY IMX334 SENSOR DRIVER
|
||||
M: Paul J. Murphy <paul.j.murphy@intel.com>
|
||||
M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
S: Maintained
|
||||
T: git git://linuxtv.org/media_tree.git
|
||||
F: Documentation/devicetree/bindings/media/i2c/sony,imx334.yaml
|
||||
F: drivers/media/i2c/imx334.c
|
||||
|
||||
SONY IMX355 SENSOR DRIVER
|
||||
M: Tianshu Qiu <tian.shu.qiu@intel.com>
|
||||
L: linux-media@vger.kernel.org
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/spi/pxa2xx_spi.h>
|
||||
@ -634,6 +635,13 @@ static struct platform_device pxa27x_device_camera = {
|
||||
|
||||
void __init pxa_set_camera_info(struct pxacamera_platform_data *info)
|
||||
{
|
||||
struct clk *mclk;
|
||||
|
||||
/* Register a fixed-rate clock for camera sensors. */
|
||||
mclk = clk_register_fixed_rate(NULL, "pxa_camera_clk", NULL, 0,
|
||||
info->mclk_10khz * 10000);
|
||||
if (!IS_ERR(mclk))
|
||||
clkdev_create(mclk, "mclk", NULL);
|
||||
pxa_register_device(&pxa27x_device_camera, info);
|
||||
}
|
||||
|
||||
|
@ -822,6 +822,36 @@ bool acpi_dev_present(const char *hid, const char *uid, s64 hrv)
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_dev_present);
|
||||
|
||||
/**
|
||||
* acpi_dev_get_next_match_dev - Return the next match of ACPI device
|
||||
* @adev: Pointer to the previous acpi_device matching this @hid, @uid and @hrv
|
||||
* @hid: Hardware ID of the device.
|
||||
* @uid: Unique ID of the device, pass NULL to not check _UID
|
||||
* @hrv: Hardware Revision of the device, pass -1 to not check _HRV
|
||||
*
|
||||
* Return the next match of ACPI device if another matching device was present
|
||||
* at the moment of invocation, or NULL otherwise.
|
||||
*
|
||||
* The caller is responsible to call put_device() on the returned device.
|
||||
*
|
||||
* See additional information in acpi_dev_present() as well.
|
||||
*/
|
||||
struct acpi_device *
|
||||
acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const char *uid, s64 hrv)
|
||||
{
|
||||
struct device *start = adev ? &adev->dev : NULL;
|
||||
struct acpi_dev_match_info match = {};
|
||||
struct device *dev;
|
||||
|
||||
strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
|
||||
match.uid = uid;
|
||||
match.hrv = hrv;
|
||||
|
||||
dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
|
||||
return dev ? to_acpi_device(dev) : NULL;
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_dev_get_next_match_dev);
|
||||
|
||||
/**
|
||||
* acpi_dev_get_first_match_dev - Return the first match of ACPI device
|
||||
* @hid: Hardware ID of the device.
|
||||
@ -838,15 +868,7 @@ EXPORT_SYMBOL(acpi_dev_present);
|
||||
struct acpi_device *
|
||||
acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv)
|
||||
{
|
||||
struct acpi_dev_match_info match = {};
|
||||
struct device *dev;
|
||||
|
||||
strlcpy(match.hid[0].id, hid, sizeof(match.hid[0].id));
|
||||
match.uid = uid;
|
||||
match.hrv = hrv;
|
||||
|
||||
dev = bus_find_device(&acpi_bus_type, NULL, &match, acpi_dev_match_cb);
|
||||
return dev ? to_acpi_device(dev) : NULL;
|
||||
return acpi_dev_get_next_match_dev(NULL, hid, uid, hrv);
|
||||
}
|
||||
EXPORT_SYMBOL(acpi_dev_get_first_match_dev);
|
||||
|
||||
|
@ -837,9 +837,15 @@ EXPORT_SYMBOL_GPL(fwnode_handle_put);
|
||||
/**
|
||||
* fwnode_device_is_available - check if a device is available for use
|
||||
* @fwnode: Pointer to the fwnode of the device.
|
||||
*
|
||||
* For fwnode node types that don't implement the .device_is_available()
|
||||
* operation, this function returns true.
|
||||
*/
|
||||
bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
|
||||
{
|
||||
if (!fwnode_has_op(fwnode, device_is_available))
|
||||
return true;
|
||||
|
||||
return fwnode_call_bool_op(fwnode, device_is_available);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_device_is_available);
|
||||
@ -1209,7 +1215,14 @@ fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
|
||||
best_ep_id = fwnode_ep.id;
|
||||
}
|
||||
|
||||
return best_ep;
|
||||
if (best_ep)
|
||||
return best_ep;
|
||||
|
||||
if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
|
||||
return fwnode_graph_get_endpoint_by_id(fwnode->secondary, port,
|
||||
endpoint, flags);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id);
|
||||
|
||||
|
@ -457,14 +457,18 @@ software_node_get_next_child(const struct fwnode_handle *fwnode,
|
||||
struct swnode *c = to_swnode(child);
|
||||
|
||||
if (!p || list_empty(&p->children) ||
|
||||
(c && list_is_last(&c->entry, &p->children)))
|
||||
(c && list_is_last(&c->entry, &p->children))) {
|
||||
fwnode_handle_put(child);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (c)
|
||||
c = list_next_entry(c, entry);
|
||||
else
|
||||
c = list_first_entry(&p->children, struct swnode, entry);
|
||||
return &c->fwnode;
|
||||
|
||||
fwnode_handle_put(child);
|
||||
return fwnode_handle_get(&c->fwnode);
|
||||
}
|
||||
|
||||
static struct fwnode_handle *
|
||||
@ -550,6 +554,115 @@ software_node_get_reference_args(const struct fwnode_handle *fwnode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct fwnode_handle *
|
||||
swnode_graph_find_next_port(const struct fwnode_handle *parent,
|
||||
struct fwnode_handle *port)
|
||||
{
|
||||
struct fwnode_handle *old = port;
|
||||
|
||||
while ((port = software_node_get_next_child(parent, old))) {
|
||||
/*
|
||||
* fwnode ports have naming style "port@", so we search for any
|
||||
* children that follow that convention.
|
||||
*/
|
||||
if (!strncmp(to_swnode(port)->node->name, "port@",
|
||||
strlen("port@")))
|
||||
return port;
|
||||
old = port;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct fwnode_handle *
|
||||
software_node_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
|
||||
struct fwnode_handle *endpoint)
|
||||
{
|
||||
struct swnode *swnode = to_swnode(fwnode);
|
||||
struct fwnode_handle *parent;
|
||||
struct fwnode_handle *port;
|
||||
|
||||
if (!swnode)
|
||||
return NULL;
|
||||
|
||||
if (endpoint) {
|
||||
port = software_node_get_parent(endpoint);
|
||||
parent = software_node_get_parent(port);
|
||||
} else {
|
||||
parent = software_node_get_named_child_node(fwnode, "ports");
|
||||
if (!parent)
|
||||
parent = software_node_get(&swnode->fwnode);
|
||||
|
||||
port = swnode_graph_find_next_port(parent, NULL);
|
||||
}
|
||||
|
||||
for (; port; port = swnode_graph_find_next_port(parent, port)) {
|
||||
endpoint = software_node_get_next_child(port, endpoint);
|
||||
if (endpoint) {
|
||||
fwnode_handle_put(port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fwnode_handle_put(parent);
|
||||
|
||||
return endpoint;
|
||||
}
|
||||
|
||||
static struct fwnode_handle *
|
||||
software_node_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct swnode *swnode = to_swnode(fwnode);
|
||||
const struct software_node_ref_args *ref;
|
||||
const struct property_entry *prop;
|
||||
|
||||
if (!swnode)
|
||||
return NULL;
|
||||
|
||||
prop = property_entry_get(swnode->node->properties, "remote-endpoint");
|
||||
if (!prop || prop->type != DEV_PROP_REF || prop->is_inline)
|
||||
return NULL;
|
||||
|
||||
ref = prop->pointer;
|
||||
|
||||
return software_node_get(software_node_fwnode(ref[0].node));
|
||||
}
|
||||
|
||||
static struct fwnode_handle *
|
||||
software_node_graph_get_port_parent(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct swnode *swnode = to_swnode(fwnode);
|
||||
|
||||
swnode = swnode->parent;
|
||||
if (swnode && !strcmp(swnode->node->name, "ports"))
|
||||
swnode = swnode->parent;
|
||||
|
||||
return swnode ? software_node_get(&swnode->fwnode) : NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
software_node_graph_parse_endpoint(const struct fwnode_handle *fwnode,
|
||||
struct fwnode_endpoint *endpoint)
|
||||
{
|
||||
struct swnode *swnode = to_swnode(fwnode);
|
||||
const char *parent_name = swnode->parent->node->name;
|
||||
int ret;
|
||||
|
||||
if (strlen("port@") >= strlen(parent_name) ||
|
||||
strncmp(parent_name, "port@", strlen("port@")))
|
||||
return -EINVAL;
|
||||
|
||||
/* Ports have naming style "port@n", we need to select the n */
|
||||
ret = kstrtou32(parent_name + strlen("port@"), 10, &endpoint->port);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
endpoint->id = swnode->id;
|
||||
endpoint->local_fwnode = fwnode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct fwnode_operations software_node_ops = {
|
||||
.get = software_node_get,
|
||||
.put = software_node_put,
|
||||
@ -561,7 +674,11 @@ static const struct fwnode_operations software_node_ops = {
|
||||
.get_parent = software_node_get_parent,
|
||||
.get_next_child_node = software_node_get_next_child,
|
||||
.get_named_child_node = software_node_get_named_child_node,
|
||||
.get_reference_args = software_node_get_reference_args
|
||||
.get_reference_args = software_node_get_reference_args,
|
||||
.graph_get_next_endpoint = software_node_graph_get_next_endpoint,
|
||||
.graph_get_remote_endpoint = software_node_graph_get_remote_endpoint,
|
||||
.graph_get_port_parent = software_node_graph_get_port_parent,
|
||||
.graph_parse_endpoint = software_node_graph_parse_endpoint,
|
||||
};
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
@ -702,7 +819,11 @@ out_err:
|
||||
* software_node_register_nodes - Register an array of software nodes
|
||||
* @nodes: Zero terminated array of software nodes to be registered
|
||||
*
|
||||
* Register multiple software nodes at once.
|
||||
* Register multiple software nodes at once. If any node in the array
|
||||
* has its .parent pointer set (which can only be to another software_node),
|
||||
* then its parent **must** have been registered before it is; either outside
|
||||
* of this function or by ordering the array such that parent comes before
|
||||
* child.
|
||||
*/
|
||||
int software_node_register_nodes(const struct software_node *nodes)
|
||||
{
|
||||
@ -710,14 +831,23 @@ int software_node_register_nodes(const struct software_node *nodes)
|
||||
int i;
|
||||
|
||||
for (i = 0; nodes[i].name; i++) {
|
||||
ret = software_node_register(&nodes[i]);
|
||||
if (ret) {
|
||||
software_node_unregister_nodes(nodes);
|
||||
return ret;
|
||||
const struct software_node *parent = nodes[i].parent;
|
||||
|
||||
if (parent && !software_node_to_swnode(parent)) {
|
||||
ret = -EINVAL;
|
||||
goto err_unregister_nodes;
|
||||
}
|
||||
|
||||
ret = software_node_register(&nodes[i]);
|
||||
if (ret)
|
||||
goto err_unregister_nodes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_unregister_nodes:
|
||||
software_node_unregister_nodes(nodes);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(software_node_register_nodes);
|
||||
|
||||
@ -725,18 +855,23 @@ EXPORT_SYMBOL_GPL(software_node_register_nodes);
|
||||
* software_node_unregister_nodes - Unregister an array of software nodes
|
||||
* @nodes: Zero terminated array of software nodes to be unregistered
|
||||
*
|
||||
* Unregister multiple software nodes at once.
|
||||
* Unregister multiple software nodes at once. If parent pointers are set up
|
||||
* in any of the software nodes then the array **must** be ordered such that
|
||||
* parents come before their children.
|
||||
*
|
||||
* NOTE: Be careful using this call if the nodes had parent pointers set up in
|
||||
* them before registering. If so, it is wiser to remove the nodes
|
||||
* individually, in the correct order (child before parent) instead of relying
|
||||
* on the sequential order of the list of nodes in the array.
|
||||
* NOTE: If you are uncertain whether the array is ordered such that
|
||||
* parents will be unregistered before their children, it is wiser to
|
||||
* remove the nodes individually, in the correct order (child before
|
||||
* parent).
|
||||
*/
|
||||
void software_node_unregister_nodes(const struct software_node *nodes)
|
||||
{
|
||||
int i;
|
||||
unsigned int i = 0;
|
||||
|
||||
for (i = 0; nodes[i].name; i++)
|
||||
while (nodes[i].name)
|
||||
i++;
|
||||
|
||||
while (i--)
|
||||
software_node_unregister(&nodes[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(software_node_unregister_nodes);
|
||||
@ -771,16 +906,23 @@ EXPORT_SYMBOL_GPL(software_node_register_node_group);
|
||||
* software_node_unregister_node_group - Unregister a group of software nodes
|
||||
* @node_group: NULL terminated array of software node pointers to be unregistered
|
||||
*
|
||||
* Unregister multiple software nodes at once.
|
||||
* Unregister multiple software nodes at once. The array will be unwound in
|
||||
* reverse order (i.e. last entry first) and thus if any members of the array are
|
||||
* children of another member then the children must appear later in the list such
|
||||
* that they are unregistered first.
|
||||
*/
|
||||
void software_node_unregister_node_group(const struct software_node **node_group)
|
||||
void software_node_unregister_node_group(
|
||||
const struct software_node **node_group)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int i = 0;
|
||||
|
||||
if (!node_group)
|
||||
return;
|
||||
|
||||
for (i = 0; node_group[i]; i++)
|
||||
while (node_group[i])
|
||||
i++;
|
||||
|
||||
while (i--)
|
||||
software_node_unregister(node_group[i]);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(software_node_unregister_node_group);
|
||||
|
@ -1296,7 +1296,7 @@ static int cec_config_log_addr(struct cec_adapter *adap,
|
||||
/*
|
||||
* If we are unable to get an OK or a NACK after max_retries attempts
|
||||
* (and note that each attempt already consists of four polls), then
|
||||
* then we assume that something is really weird and that it is not a
|
||||
* we assume that something is really weird and that it is not a
|
||||
* good idea to try and claim this logical address.
|
||||
*/
|
||||
if (i == max_retries)
|
||||
@ -1735,7 +1735,7 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
|
||||
const u8 feature_sz = ARRAY_SIZE(log_addrs->features[0]);
|
||||
u8 *features = log_addrs->features[i];
|
||||
bool op_is_dev_features = false;
|
||||
unsigned j;
|
||||
unsigned int j;
|
||||
|
||||
log_addrs->log_addr[i] = CEC_LOG_ADDR_INVALID;
|
||||
if (log_addrs->log_addr_type[i] > CEC_LOG_ADDR_TYPE_UNREGISTERED) {
|
||||
|
@ -40,7 +40,7 @@ static __poll_t cec_poll(struct file *filp,
|
||||
|
||||
poll_wait(filp, &fh->wait, poll);
|
||||
if (!cec_is_registered(adap))
|
||||
return EPOLLERR | EPOLLHUP;
|
||||
return EPOLLERR | EPOLLHUP | EPOLLPRI;
|
||||
mutex_lock(&adap->lock);
|
||||
if (adap->is_configured &&
|
||||
adap->transmit_queue_sz < CEC_MAX_MSG_TX_QUEUE_SZ)
|
||||
|
@ -2374,13 +2374,20 @@ __poll_t vb2_core_poll(struct vb2_queue *q, struct file *file,
|
||||
struct vb2_buffer *vb = NULL;
|
||||
unsigned long flags;
|
||||
|
||||
/*
|
||||
* poll_wait() MUST be called on the first invocation on all the
|
||||
* potential queues of interest, even if we are not interested in their
|
||||
* events during this first call. Failure to do so will result in
|
||||
* queue's events to be ignored because the poll_table won't be capable
|
||||
* of adding new wait queues thereafter.
|
||||
*/
|
||||
poll_wait(file, &q->done_wq, wait);
|
||||
|
||||
if (!q->is_output && !(req_events & (EPOLLIN | EPOLLRDNORM)))
|
||||
return 0;
|
||||
if (q->is_output && !(req_events & (EPOLLOUT | EPOLLWRNORM)))
|
||||
return 0;
|
||||
|
||||
poll_wait(file, &q->done_wq, wait);
|
||||
|
||||
/*
|
||||
* Start file I/O emulator only if streaming API has not been used yet.
|
||||
*/
|
||||
|
@ -487,11 +487,6 @@ static int vb2_queue_or_prepare_buf(struct vb2_queue *q, struct media_device *md
|
||||
!q->ops->buf_out_validate))
|
||||
return -EINVAL;
|
||||
|
||||
if (b->request_fd < 0) {
|
||||
dprintk(q, 1, "%s: request_fd < 0\n", opname);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
req = media_request_get_by_fd(mdev, b->request_fd);
|
||||
if (IS_ERR(req)) {
|
||||
dprintk(q, 1, "%s: invalid request_fd\n", opname);
|
||||
|
@ -984,6 +984,7 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
|
||||
fe->ops.info.symbol_rate_max);
|
||||
return -EINVAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -515,7 +515,7 @@ config DVB_RTL2830
|
||||
config DVB_RTL2832
|
||||
tristate "Realtek RTL2832 DVB-T"
|
||||
depends on DVB_CORE && I2C && I2C_MUX
|
||||
select REGMAP
|
||||
select REGMAP_I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
Say Y when you want to support this frontend.
|
||||
@ -708,6 +708,15 @@ config DVB_S5H1411
|
||||
An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
|
||||
to support this frontend.
|
||||
|
||||
config DVB_MXL692
|
||||
tristate "MaxLinear MXL692 based"
|
||||
depends on DVB_CORE && I2C
|
||||
default m if !MEDIA_SUBDRV_AUTOSELECT
|
||||
help
|
||||
MaxLinear MxL692 is a combo tuner-demodulator that
|
||||
supports ATSC 8VSB and QAM modes. Say Y when you want to
|
||||
support this frontend.
|
||||
|
||||
comment "ISDB-T (terrestrial) frontends"
|
||||
depends on DVB_CORE
|
||||
|
||||
|
@ -55,6 +55,7 @@ obj-$(CONFIG_DVB_S5H1420) += s5h1420.o
|
||||
obj-$(CONFIG_DVB_LGDT330X) += lgdt330x.o
|
||||
obj-$(CONFIG_DVB_LGDT3305) += lgdt3305.o
|
||||
obj-$(CONFIG_DVB_LGDT3306A) += lgdt3306a.o
|
||||
obj-$(CONFIG_DVB_MXL692) += mxl692.o
|
||||
obj-$(CONFIG_DVB_LG2160) += lg2160.o
|
||||
obj-$(CONFIG_DVB_CX24123) += cx24123.o
|
||||
obj-$(CONFIG_DVB_LNBH25) += lnbh25.o
|
||||
|
@ -125,6 +125,7 @@ static int af9033_init(struct dvb_frontend *fe)
|
||||
if (i == ARRAY_SIZE(clock_adc_lut)) {
|
||||
dev_err(&client->dev, "Couldn't find ADC config for clock %d\n",
|
||||
dev->cfg.clock);
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
@ -852,6 +853,7 @@ static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr)
|
||||
*snr = *snr * 0xffff / 32;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
@ -363,6 +363,7 @@ static void cx24120_check_cmd(struct cx24120_state *state, u8 id)
|
||||
case CMD_DISEQC_BURST:
|
||||
cx24120_msg_mpeg_output_global_config(state, 0);
|
||||
/* Old driver would do a msleep(100) here */
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -3338,7 +3338,7 @@ static int cxd2841er_set_frontend_s(struct dvb_frontend *fe)
|
||||
cxd2841er_tuner_set(fe);
|
||||
|
||||
cxd2841er_tune_done(priv);
|
||||
timeout = ((3000000 + (symbol_rate - 1)) / symbol_rate) + 150;
|
||||
timeout = DIV_ROUND_UP(3000000, symbol_rate) + 150;
|
||||
|
||||
i = 0;
|
||||
do {
|
||||
|
@ -1765,6 +1765,8 @@ static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum front
|
||||
dib0090_write_reg(state, 0x1f, 0x7);
|
||||
*tune_state = CT_TUNER_START; /* reset done -> real tuning can now begin */
|
||||
state->calibrate &= ~DC_CAL;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -3294,6 +3294,7 @@ static int dvbt_sc_command(struct drxk_state *state,
|
||||
case OFDM_SC_RA_RAM_CMD_USER_IO:
|
||||
case OFDM_SC_RA_RAM_CMD_GET_OP_PARAM:
|
||||
status = read16(state, OFDM_SC_RA_RAM_PARAM0__A, &(param0));
|
||||
break;
|
||||
/* All commands yielding 0 results */
|
||||
case OFDM_SC_RA_RAM_CMD_SET_ECHO_TIMING:
|
||||
case OFDM_SC_RA_RAM_CMD_SET_TIMER:
|
||||
|
@ -390,6 +390,7 @@ static int m88rs2000_tab_set(struct m88rs2000_state *state,
|
||||
case 0xff:
|
||||
if (tab[i].reg == 0xaa && tab[i].val == 0xff)
|
||||
return 0;
|
||||
break;
|
||||
case 0x00:
|
||||
break;
|
||||
default:
|
||||
|
1378
drivers/media/dvb-frontends/mxl692.c
Normal file
1378
drivers/media/dvb-frontends/mxl692.c
Normal file
File diff suppressed because it is too large
Load Diff
38
drivers/media/dvb-frontends/mxl692.h
Normal file
38
drivers/media/dvb-frontends/mxl692.h
Normal file
@ -0,0 +1,38 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Driver for the MaxLinear MxL69x family of tuners/demods
|
||||
*
|
||||
* Copyright (C) 2020 Brad Love <brad@nextdimension.cc>
|
||||
*
|
||||
* based on code:
|
||||
* Copyright (c) 2016 MaxLinear, Inc. All rights reserved
|
||||
* which was released under GPL V2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _MXL692_H_
|
||||
#define _MXL692_H_
|
||||
|
||||
#include <media/dvb_frontend.h>
|
||||
|
||||
#define MXL692_FIRMWARE "dvb-demod-mxl692.fw"
|
||||
|
||||
struct mxl692_config {
|
||||
unsigned char id;
|
||||
u8 i2c_addr;
|
||||
/*
|
||||
* frontend
|
||||
* returned by driver
|
||||
*/
|
||||
struct dvb_frontend **fe;
|
||||
};
|
||||
|
||||
#endif /* _MXL692_H_ */
|
548
drivers/media/dvb-frontends/mxl692_defs.h
Normal file
548
drivers/media/dvb-frontends/mxl692_defs.h
Normal file
@ -0,0 +1,548 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Driver for the MaxLinear MxL69x family of combo tuners/demods
|
||||
*
|
||||
* Copyright (C) 2020 Brad Love <brad@nextdimension.cc>
|
||||
*
|
||||
* based on code:
|
||||
* Copyright (c) 2016 MaxLinear, Inc. All rights reserved
|
||||
* which was released under GPL V2
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*****************************************************************************
|
||||
* Defines
|
||||
*****************************************************************************
|
||||
*/
|
||||
#define MXL_EAGLE_HOST_MSG_HEADER_SIZE 8
|
||||
#define MXL_EAGLE_FW_MAX_SIZE_IN_KB 76
|
||||
#define MXL_EAGLE_QAM_FFE_TAPS_LENGTH 16
|
||||
#define MXL_EAGLE_QAM_SPUR_TAPS_LENGTH 32
|
||||
#define MXL_EAGLE_QAM_DFE_TAPS_LENGTH 72
|
||||
#define MXL_EAGLE_ATSC_FFE_TAPS_LENGTH 4096
|
||||
#define MXL_EAGLE_ATSC_DFE_TAPS_LENGTH 384
|
||||
#define MXL_EAGLE_VERSION_SIZE 5 /* A.B.C.D-RCx */
|
||||
#define MXL_EAGLE_FW_LOAD_TIME 50
|
||||
|
||||
#define MXL_EAGLE_FW_MAX_SIZE_IN_KB 76
|
||||
#define MXL_EAGLE_FW_HEADER_SIZE 16
|
||||
#define MXL_EAGLE_FW_SEGMENT_HEADER_SIZE 8
|
||||
#define MXL_EAGLE_MAX_I2C_PACKET_SIZE 58
|
||||
#define MXL_EAGLE_I2C_MHEADER_SIZE 6
|
||||
#define MXL_EAGLE_I2C_PHEADER_SIZE 2
|
||||
|
||||
/* Enum of Eagle family devices */
|
||||
enum MXL_EAGLE_DEVICE_E {
|
||||
MXL_EAGLE_DEVICE_691 = 1, /* Device Mxl691 */
|
||||
MXL_EAGLE_DEVICE_248 = 2, /* Device Mxl248 */
|
||||
MXL_EAGLE_DEVICE_692 = 3, /* Device Mxl692 */
|
||||
MXL_EAGLE_DEVICE_MAX, /* No such device */
|
||||
};
|
||||
|
||||
#define VER_A 1
|
||||
#define VER_B 1
|
||||
#define VER_C 1
|
||||
#define VER_D 3
|
||||
#define VER_E 6
|
||||
|
||||
/* Enum of Host to Eagle I2C protocol opcodes */
|
||||
enum MXL_EAGLE_OPCODE_E {
|
||||
/* DEVICE */
|
||||
MXL_EAGLE_OPCODE_DEVICE_DEMODULATOR_TYPE_SET,
|
||||
MXL_EAGLE_OPCODE_DEVICE_MPEG_OUT_PARAMS_SET,
|
||||
MXL_EAGLE_OPCODE_DEVICE_POWERMODE_SET,
|
||||
MXL_EAGLE_OPCODE_DEVICE_GPIO_DIRECTION_SET,
|
||||
MXL_EAGLE_OPCODE_DEVICE_GPO_LEVEL_SET,
|
||||
MXL_EAGLE_OPCODE_DEVICE_INTR_MASK_SET,
|
||||
MXL_EAGLE_OPCODE_DEVICE_IO_MUX_SET,
|
||||
MXL_EAGLE_OPCODE_DEVICE_VERSION_GET,
|
||||
MXL_EAGLE_OPCODE_DEVICE_STATUS_GET,
|
||||
MXL_EAGLE_OPCODE_DEVICE_GPI_LEVEL_GET,
|
||||
|
||||
/* TUNER */
|
||||
MXL_EAGLE_OPCODE_TUNER_CHANNEL_TUNE_SET,
|
||||
MXL_EAGLE_OPCODE_TUNER_LOCK_STATUS_GET,
|
||||
MXL_EAGLE_OPCODE_TUNER_AGC_STATUS_GET,
|
||||
|
||||
/* ATSC */
|
||||
MXL_EAGLE_OPCODE_ATSC_INIT_SET,
|
||||
MXL_EAGLE_OPCODE_ATSC_ACQUIRE_CARRIER_SET,
|
||||
MXL_EAGLE_OPCODE_ATSC_STATUS_GET,
|
||||
MXL_EAGLE_OPCODE_ATSC_ERROR_COUNTERS_GET,
|
||||
MXL_EAGLE_OPCODE_ATSC_EQUALIZER_FILTER_DFE_TAPS_GET,
|
||||
MXL_EAGLE_OPCODE_ATSC_EQUALIZER_FILTER_FFE_TAPS_GET,
|
||||
|
||||
/* QAM */
|
||||
MXL_EAGLE_OPCODE_QAM_PARAMS_SET,
|
||||
MXL_EAGLE_OPCODE_QAM_RESTART_SET,
|
||||
MXL_EAGLE_OPCODE_QAM_STATUS_GET,
|
||||
MXL_EAGLE_OPCODE_QAM_ERROR_COUNTERS_GET,
|
||||
MXL_EAGLE_OPCODE_QAM_CONSTELLATION_VALUE_GET,
|
||||
MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_FFE_GET,
|
||||
MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_SPUR_START_GET,
|
||||
MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_SPUR_END_GET,
|
||||
MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_TAPS_NUMBER_GET,
|
||||
MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_START_GET,
|
||||
MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_MIDDLE_GET,
|
||||
MXL_EAGLE_OPCODE_QAM_EQUALIZER_FILTER_DFE_END_GET,
|
||||
|
||||
/* OOB */
|
||||
MXL_EAGLE_OPCODE_OOB_PARAMS_SET,
|
||||
MXL_EAGLE_OPCODE_OOB_RESTART_SET,
|
||||
MXL_EAGLE_OPCODE_OOB_ERROR_COUNTERS_GET,
|
||||
MXL_EAGLE_OPCODE_OOB_STATUS_GET,
|
||||
|
||||
/* SMA */
|
||||
MXL_EAGLE_OPCODE_SMA_INIT_SET,
|
||||
MXL_EAGLE_OPCODE_SMA_PARAMS_SET,
|
||||
MXL_EAGLE_OPCODE_SMA_TRANSMIT_SET,
|
||||
MXL_EAGLE_OPCODE_SMA_RECEIVE_GET,
|
||||
|
||||
/* DEBUG */
|
||||
MXL_EAGLE_OPCODE_INTERNAL,
|
||||
|
||||
MXL_EAGLE_OPCODE_MAX = 70,
|
||||
};
|
||||
|
||||
/* Enum of Host to Eagle I2C protocol opcodes */
|
||||
static const char * const MXL_EAGLE_OPCODE_STRING[] = {
|
||||
/* DEVICE */
|
||||
"DEVICE_DEMODULATOR_TYPE_SET",
|
||||
"DEVICE_MPEG_OUT_PARAMS_SET",
|
||||
"DEVICE_POWERMODE_SET",
|
||||
"DEVICE_GPIO_DIRECTION_SET",
|
||||
"DEVICE_GPO_LEVEL_SET",
|
||||
"DEVICE_INTR_MASK_SET",
|
||||
"DEVICE_IO_MUX_SET",
|
||||
"DEVICE_VERSION_GET",
|
||||
"DEVICE_STATUS_GET",
|
||||
"DEVICE_GPI_LEVEL_GET",
|
||||
|
||||
/* TUNER */
|
||||
"TUNER_CHANNEL_TUNE_SET",
|
||||
"TUNER_LOCK_STATUS_GET",
|
||||
"TUNER_AGC_STATUS_GET",
|
||||
|
||||
/* ATSC */
|
||||
"ATSC_INIT_SET",
|
||||
"ATSC_ACQUIRE_CARRIER_SET",
|
||||
"ATSC_STATUS_GET",
|
||||
"ATSC_ERROR_COUNTERS_GET",
|
||||
"ATSC_EQUALIZER_FILTER_DFE_TAPS_GET",
|
||||
"ATSC_EQUALIZER_FILTER_FFE_TAPS_GET",
|
||||
|
||||
/* QAM */
|
||||
"QAM_PARAMS_SET",
|
||||
"QAM_RESTART_SET",
|
||||
"QAM_STATUS_GET",
|
||||
"QAM_ERROR_COUNTERS_GET",
|
||||
"QAM_CONSTELLATION_VALUE_GET",
|
||||
"QAM_EQUALIZER_FILTER_FFE_GET",
|
||||
"QAM_EQUALIZER_FILTER_SPUR_START_GET",
|
||||
"QAM_EQUALIZER_FILTER_SPUR_END_GET",
|
||||
"QAM_EQUALIZER_FILTER_DFE_TAPS_NUMBER_GET",
|
||||
"QAM_EQUALIZER_FILTER_DFE_START_GET",
|
||||
"QAM_EQUALIZER_FILTER_DFE_MIDDLE_GET",
|
||||
"QAM_EQUALIZER_FILTER_DFE_END_GET",
|
||||
|
||||
/* OOB */
|
||||
"OOB_PARAMS_SET",
|
||||
"OOB_RESTART_SET",
|
||||
"OOB_ERROR_COUNTERS_GET",
|
||||
"OOB_STATUS_GET",
|
||||
|
||||
/* SMA */
|
||||
"SMA_INIT_SET",
|
||||
"SMA_PARAMS_SET",
|
||||
"SMA_TRANSMIT_SET",
|
||||
"SMA_RECEIVE_GET",
|
||||
|
||||
/* DEBUG */
|
||||
"INTERNAL",
|
||||
};
|
||||
|
||||
/* Enum of Callabck function types */
|
||||
enum MXL_EAGLE_CB_TYPE_E {
|
||||
MXL_EAGLE_CB_FW_DOWNLOAD = 0,
|
||||
};
|
||||
|
||||
/* Enum of power supply types */
|
||||
enum MXL_EAGLE_POWER_SUPPLY_SOURCE_E {
|
||||
MXL_EAGLE_POWER_SUPPLY_SOURCE_SINGLE, /* Single supply of 3.3V */
|
||||
MXL_EAGLE_POWER_SUPPLY_SOURCE_DUAL, /* Dual supply, 1.8V & 3.3V */
|
||||
};
|
||||
|
||||
/* Enum of I/O pad drive modes */
|
||||
enum MXL_EAGLE_IO_MUX_DRIVE_MODE_E {
|
||||
MXL_EAGLE_IO_MUX_DRIVE_MODE_1X,
|
||||
MXL_EAGLE_IO_MUX_DRIVE_MODE_2X,
|
||||
MXL_EAGLE_IO_MUX_DRIVE_MODE_3X,
|
||||
MXL_EAGLE_IO_MUX_DRIVE_MODE_4X,
|
||||
MXL_EAGLE_IO_MUX_DRIVE_MODE_5X,
|
||||
MXL_EAGLE_IO_MUX_DRIVE_MODE_6X,
|
||||
MXL_EAGLE_IO_MUX_DRIVE_MODE_7X,
|
||||
MXL_EAGLE_IO_MUX_DRIVE_MODE_8X,
|
||||
};
|
||||
|
||||
/* Enum of demodulator types. Used for selection of demodulator
|
||||
* type in relevant devices, e.g. ATSC vs. QAM in Mxl691
|
||||
*/
|
||||
enum MXL_EAGLE_DEMOD_TYPE_E {
|
||||
MXL_EAGLE_DEMOD_TYPE_QAM, /* Mxl248 or Mxl692 */
|
||||
MXL_EAGLE_DEMOD_TYPE_OOB, /* Mxl248 only */
|
||||
MXL_EAGLE_DEMOD_TYPE_ATSC /* Mxl691 or Mxl692 */
|
||||
};
|
||||
|
||||
/* Enum of power modes. Used for initial
|
||||
* activation, or for activating sleep mode
|
||||
*/
|
||||
enum MXL_EAGLE_POWER_MODE_E {
|
||||
MXL_EAGLE_POWER_MODE_SLEEP,
|
||||
MXL_EAGLE_POWER_MODE_ACTIVE
|
||||
};
|
||||
|
||||
/* Enum of GPIOs, used in device GPIO APIs */
|
||||
enum MXL_EAGLE_GPIO_NUMBER_E {
|
||||
MXL_EAGLE_GPIO_NUMBER_0,
|
||||
MXL_EAGLE_GPIO_NUMBER_1,
|
||||
MXL_EAGLE_GPIO_NUMBER_2,
|
||||
MXL_EAGLE_GPIO_NUMBER_3,
|
||||
MXL_EAGLE_GPIO_NUMBER_4,
|
||||
MXL_EAGLE_GPIO_NUMBER_5,
|
||||
MXL_EAGLE_GPIO_NUMBER_6
|
||||
};
|
||||
|
||||
/* Enum of GPIO directions, used in GPIO direction configuration API */
|
||||
enum MXL_EAGLE_GPIO_DIRECTION_E {
|
||||
MXL_EAGLE_GPIO_DIRECTION_INPUT,
|
||||
MXL_EAGLE_GPIO_DIRECTION_OUTPUT
|
||||
};
|
||||
|
||||
/* Enum of GPIO level, used in device GPIO APIs */
|
||||
enum MXL_EAGLE_GPIO_LEVEL_E {
|
||||
MXL_EAGLE_GPIO_LEVEL_LOW,
|
||||
MXL_EAGLE_GPIO_LEVEL_HIGH,
|
||||
};
|
||||
|
||||
/* Enum of I/O Mux function, used in device I/O mux configuration API */
|
||||
enum MXL_EAGLE_IOMUX_FUNCTION_E {
|
||||
MXL_EAGLE_IOMUX_FUNC_FEC_LOCK,
|
||||
MXL_EAGLE_IOMUX_FUNC_MERR,
|
||||
};
|
||||
|
||||
/* Enum of MPEG Data format, used in MPEG and OOB output configuration */
|
||||
enum MXL_EAGLE_MPEG_DATA_FORMAT_E {
|
||||
MXL_EAGLE_DATA_SERIAL_LSB_1ST = 0,
|
||||
MXL_EAGLE_DATA_SERIAL_MSB_1ST,
|
||||
|
||||
MXL_EAGLE_DATA_SYNC_WIDTH_BIT = 0,
|
||||
MXL_EAGLE_DATA_SYNC_WIDTH_BYTE
|
||||
};
|
||||
|
||||
/* Enum of MPEG Clock format, used in MPEG and OOB output configuration */
|
||||
enum MXL_EAGLE_MPEG_CLOCK_FORMAT_E {
|
||||
MXL_EAGLE_CLOCK_ACTIVE_HIGH = 0,
|
||||
MXL_EAGLE_CLOCK_ACTIVE_LOW,
|
||||
|
||||
MXL_EAGLE_CLOCK_POSITIVE = 0,
|
||||
MXL_EAGLE_CLOCK_NEGATIVE,
|
||||
|
||||
MXL_EAGLE_CLOCK_IN_PHASE = 0,
|
||||
MXL_EAGLE_CLOCK_INVERTED,
|
||||
};
|
||||
|
||||
/* Enum of MPEG Clock speeds, used in MPEG output configuration */
|
||||
enum MXL_EAGLE_MPEG_CLOCK_RATE_E {
|
||||
MXL_EAGLE_MPEG_CLOCK_54MHZ,
|
||||
MXL_EAGLE_MPEG_CLOCK_40_5MHZ,
|
||||
MXL_EAGLE_MPEG_CLOCK_27MHZ,
|
||||
MXL_EAGLE_MPEG_CLOCK_13_5MHZ,
|
||||
};
|
||||
|
||||
/* Enum of Interrupt mask bit, used in host interrupt configuration */
|
||||
enum MXL_EAGLE_INTR_MASK_BITS_E {
|
||||
MXL_EAGLE_INTR_MASK_DEMOD = 0,
|
||||
MXL_EAGLE_INTR_MASK_SMA_RX = 1,
|
||||
MXL_EAGLE_INTR_MASK_WDOG = 31
|
||||
};
|
||||
|
||||
/* Enum of QAM Demodulator type, used in QAM configuration */
|
||||
enum MXL_EAGLE_QAM_DEMOD_ANNEX_TYPE_E {
|
||||
MXL_EAGLE_QAM_DEMOD_ANNEX_B, /* J.83B */
|
||||
MXL_EAGLE_QAM_DEMOD_ANNEX_A, /* DVB-C */
|
||||
};
|
||||
|
||||
/* Enum of QAM Demodulator modulation, used in QAM configuration and status */
|
||||
enum MXL_EAGLE_QAM_DEMOD_QAM_TYPE_E {
|
||||
MXL_EAGLE_QAM_DEMOD_QAM16,
|
||||
MXL_EAGLE_QAM_DEMOD_QAM64,
|
||||
MXL_EAGLE_QAM_DEMOD_QAM256,
|
||||
MXL_EAGLE_QAM_DEMOD_QAM1024,
|
||||
MXL_EAGLE_QAM_DEMOD_QAM32,
|
||||
MXL_EAGLE_QAM_DEMOD_QAM128,
|
||||
MXL_EAGLE_QAM_DEMOD_QPSK,
|
||||
MXL_EAGLE_QAM_DEMOD_AUTO,
|
||||
};
|
||||
|
||||
/* Enum of Demodulator IQ setup, used in QAM, OOB configuration and status */
|
||||
enum MXL_EAGLE_IQ_FLIP_E {
|
||||
MXL_EAGLE_DEMOD_IQ_NORMAL,
|
||||
MXL_EAGLE_DEMOD_IQ_FLIPPED,
|
||||
MXL_EAGLE_DEMOD_IQ_AUTO,
|
||||
};
|
||||
|
||||
/* Enum of OOB Demodulator symbol rates, used in OOB configuration */
|
||||
enum MXL_EAGLE_OOB_DEMOD_SYMB_RATE_E {
|
||||
MXL_EAGLE_OOB_DEMOD_SYMB_RATE_0_772MHZ, /* ANSI/SCTE 55-2 0.772 MHz */
|
||||
MXL_EAGLE_OOB_DEMOD_SYMB_RATE_1_024MHZ, /* ANSI/SCTE 55-1 1.024 MHz */
|
||||
MXL_EAGLE_OOB_DEMOD_SYMB_RATE_1_544MHZ, /* ANSI/SCTE 55-2 1.544 MHz */
|
||||
};
|
||||
|
||||
/* Enum of tuner channel tuning mode */
|
||||
enum MXL_EAGLE_TUNER_CHANNEL_TUNE_MODE_E {
|
||||
MXL_EAGLE_TUNER_CHANNEL_TUNE_MODE_VIEW, /* Normal "view" mode */
|
||||
MXL_EAGLE_TUNER_CHANNEL_TUNE_MODE_SCAN, /* Fast "scan" mode */
|
||||
};
|
||||
|
||||
/* Enum of tuner bandwidth */
|
||||
enum MXL_EAGLE_TUNER_BW_E {
|
||||
MXL_EAGLE_TUNER_BW_6MHZ,
|
||||
MXL_EAGLE_TUNER_BW_7MHZ,
|
||||
MXL_EAGLE_TUNER_BW_8MHZ,
|
||||
};
|
||||
|
||||
/* Enum of tuner bandwidth */
|
||||
enum MXL_EAGLE_JUNCTION_TEMPERATURE_E {
|
||||
MXL_EAGLE_JUNCTION_TEMPERATURE_BELOW_0_CELSIUS = 0,
|
||||
MXL_EAGLE_JUNCTION_TEMPERATURE_BETWEEN_0_TO_14_CELSIUS = 1,
|
||||
MXL_EAGLE_JUNCTION_TEMPERATURE_BETWEEN_14_TO_28_CELSIUS = 3,
|
||||
MXL_EAGLE_JUNCTION_TEMPERATURE_BETWEEN_28_TO_42_CELSIUS = 2,
|
||||
MXL_EAGLE_JUNCTION_TEMPERATURE_BETWEEN_42_TO_57_CELSIUS = 6,
|
||||
MXL_EAGLE_JUNCTION_TEMPERATURE_BETWEEN_57_TO_71_CELSIUS = 7,
|
||||
MXL_EAGLE_JUNCTION_TEMPERATURE_BETWEEN_71_TO_85_CELSIUS = 5,
|
||||
MXL_EAGLE_JUNCTION_TEMPERATURE_ABOVE_85_CELSIUS = 4,
|
||||
};
|
||||
|
||||
/* Struct passed in optional callback used during FW download */
|
||||
struct MXL_EAGLE_FW_DOWNLOAD_CB_PAYLOAD_T {
|
||||
u32 total_len;
|
||||
u32 downloaded_len;
|
||||
};
|
||||
|
||||
/* Struct used of I2C protocol between host and Eagle, internal use only */
|
||||
struct __packed MXL_EAGLE_HOST_MSG_HEADER_T {
|
||||
u8 opcode;
|
||||
u8 seqnum;
|
||||
u8 payload_size;
|
||||
u8 status;
|
||||
u32 checksum;
|
||||
};
|
||||
|
||||
/* Device version information struct */
|
||||
struct __packed MXL_EAGLE_DEV_VER_T {
|
||||
u8 chip_id;
|
||||
u8 firmware_ver[MXL_EAGLE_VERSION_SIZE];
|
||||
u8 mxlware_ver[MXL_EAGLE_VERSION_SIZE];
|
||||
};
|
||||
|
||||
/* Xtal configuration struct */
|
||||
struct __packed MXL_EAGLE_DEV_XTAL_T {
|
||||
u8 xtal_cap; /* accepted range is 1..31 pF. Default is 26 */
|
||||
u8 clk_out_enable;
|
||||
u8 clk_out_div_enable; /* clock out freq is xtal freq / 6 */
|
||||
u8 xtal_sharing_enable; /* if enabled set xtal_cap to 25 pF */
|
||||
u8 xtal_calibration_enable; /* enable for master, disable for slave */
|
||||
};
|
||||
|
||||
/* GPIO direction struct, internally used in GPIO configuration API */
|
||||
struct __packed MXL_EAGLE_DEV_GPIO_DIRECTION_T {
|
||||
u8 gpio_number;
|
||||
u8 gpio_direction;
|
||||
};
|
||||
|
||||
/* GPO level struct, internally used in GPIO configuration API */
|
||||
struct __packed MXL_EAGLE_DEV_GPO_LEVEL_T {
|
||||
u8 gpio_number;
|
||||
u8 gpo_level;
|
||||
};
|
||||
|
||||
/* Device Status struct */
|
||||
struct MXL_EAGLE_DEV_STATUS_T {
|
||||
u8 temperature;
|
||||
u8 demod_type;
|
||||
u8 power_mode;
|
||||
u8 cpu_utilization_percent;
|
||||
};
|
||||
|
||||
/* Device interrupt configuration struct */
|
||||
struct __packed MXL_EAGLE_DEV_INTR_CFG_T {
|
||||
u32 intr_mask;
|
||||
u8 edge_trigger;
|
||||
u8 positive_trigger;
|
||||
u8 global_enable_interrupt;
|
||||
};
|
||||
|
||||
/* MPEG pad drive parameters, used on MPEG output configuration */
|
||||
/* See MXL_EAGLE_IO_MUX_DRIVE_MODE_E */
|
||||
struct MXL_EAGLE_MPEG_PAD_DRIVE_T {
|
||||
u8 pad_drv_mpeg_syn;
|
||||
u8 pad_drv_mpeg_dat;
|
||||
u8 pad_drv_mpeg_val;
|
||||
u8 pad_drv_mpeg_clk;
|
||||
};
|
||||
|
||||
/* MPEGOUT parameter struct, used in MPEG output configuration */
|
||||
struct MXL_EAGLE_MPEGOUT_PARAMS_T {
|
||||
u8 mpeg_parallel;
|
||||
u8 msb_first;
|
||||
u8 mpeg_sync_pulse_width; /* See MXL_EAGLE_MPEG_DATA_FORMAT_E */
|
||||
u8 mpeg_valid_pol;
|
||||
u8 mpeg_sync_pol;
|
||||
u8 mpeg_clk_pol;
|
||||
u8 mpeg3wire_mode_enable;
|
||||
u8 mpeg_clk_freq;
|
||||
struct MXL_EAGLE_MPEG_PAD_DRIVE_T mpeg_pad_drv;
|
||||
};
|
||||
|
||||
/* QAM Demodulator parameters struct, used in QAM params configuration */
|
||||
struct __packed MXL_EAGLE_QAM_DEMOD_PARAMS_T {
|
||||
u8 annex_type;
|
||||
u8 qam_type;
|
||||
u8 iq_flip;
|
||||
u8 search_range_idx;
|
||||
u8 spur_canceller_enable;
|
||||
u32 symbol_rate_hz;
|
||||
u32 symbol_rate_256qam_hz;
|
||||
};
|
||||
|
||||
/* QAM Demodulator status */
|
||||
struct MXL_EAGLE_QAM_DEMOD_STATUS_T {
|
||||
u8 annex_type;
|
||||
u8 qam_type;
|
||||
u8 iq_flip;
|
||||
u8 interleaver_depth_i;
|
||||
u8 interleaver_depth_j;
|
||||
u8 qam_locked;
|
||||
u8 fec_locked;
|
||||
u8 mpeg_locked;
|
||||
u16 snr_db_tenths;
|
||||
s16 timing_offset;
|
||||
s32 carrier_offset_hz;
|
||||
};
|
||||
|
||||
/* QAM Demodulator error counters */
|
||||
struct MXL_EAGLE_QAM_DEMOD_ERROR_COUNTERS_T {
|
||||
u32 corrected_code_words;
|
||||
u32 uncorrected_code_words;
|
||||
u32 total_code_words_received;
|
||||
u32 corrected_bits;
|
||||
u32 error_mpeg_frames;
|
||||
u32 mpeg_frames_received;
|
||||
u32 erasures;
|
||||
};
|
||||
|
||||
/* QAM Demodulator constellation point */
|
||||
struct MXL_EAGLE_QAM_DEMOD_CONSTELLATION_VAL_T {
|
||||
s16 i_value[12];
|
||||
s16 q_value[12];
|
||||
};
|
||||
|
||||
/* QAM Demodulator equalizer filter taps */
|
||||
struct MXL_EAGLE_QAM_DEMOD_EQU_FILTER_T {
|
||||
s16 ffe_taps[MXL_EAGLE_QAM_FFE_TAPS_LENGTH];
|
||||
s16 spur_taps[MXL_EAGLE_QAM_SPUR_TAPS_LENGTH];
|
||||
s16 dfe_taps[MXL_EAGLE_QAM_DFE_TAPS_LENGTH];
|
||||
u8 ffe_leading_tap_index;
|
||||
u8 dfe_taps_number;
|
||||
};
|
||||
|
||||
/* OOB Demodulator parameters struct, used in OOB params configuration */
|
||||
struct __packed MXL_EAGLE_OOB_DEMOD_PARAMS_T {
|
||||
u8 symbol_rate;
|
||||
u8 iq_flip;
|
||||
u8 clk_pol;
|
||||
};
|
||||
|
||||
/* OOB Demodulator error counters */
|
||||
struct MXL_EAGLE_OOB_DEMOD_ERROR_COUNTERS_T {
|
||||
u32 corrected_packets;
|
||||
u32 uncorrected_packets;
|
||||
u32 total_packets_received;
|
||||
};
|
||||
|
||||
/* OOB status */
|
||||
struct __packed MXL_EAGLE_OOB_DEMOD_STATUS_T {
|
||||
u16 snr_db_tenths;
|
||||
s16 timing_offset;
|
||||
s32 carrier_offsetHz;
|
||||
u8 qam_locked;
|
||||
u8 fec_locked;
|
||||
u8 mpeg_locked;
|
||||
u8 retune_required;
|
||||
u8 iq_flip;
|
||||
};
|
||||
|
||||
/* ATSC Demodulator status */
|
||||
struct __packed MXL_EAGLE_ATSC_DEMOD_STATUS_T {
|
||||
s16 snr_db_tenths;
|
||||
s16 timing_offset;
|
||||
s32 carrier_offset_hz;
|
||||
u8 frame_lock;
|
||||
u8 atsc_lock;
|
||||
u8 fec_lock;
|
||||
};
|
||||
|
||||
/* ATSC Demodulator error counters */
|
||||
struct MXL_EAGLE_ATSC_DEMOD_ERROR_COUNTERS_T {
|
||||
u32 error_packets;
|
||||
u32 total_packets;
|
||||
u32 error_bytes;
|
||||
};
|
||||
|
||||
/* ATSC Demodulator equalizers filter taps */
|
||||
struct __packed MXL_EAGLE_ATSC_DEMOD_EQU_FILTER_T {
|
||||
s16 ffe_taps[MXL_EAGLE_ATSC_FFE_TAPS_LENGTH];
|
||||
s8 dfe_taps[MXL_EAGLE_ATSC_DFE_TAPS_LENGTH];
|
||||
};
|
||||
|
||||
/* Tuner AGC Status */
|
||||
struct __packed MXL_EAGLE_TUNER_AGC_STATUS_T {
|
||||
u8 locked;
|
||||
u16 raw_agc_gain; /* AGC gain [dB] = rawAgcGain / 2^6 */
|
||||
s16 rx_power_db_hundredths;
|
||||
};
|
||||
|
||||
/* Tuner channel tune parameters */
|
||||
struct __packed MXL_EAGLE_TUNER_CHANNEL_PARAMS_T {
|
||||
u32 freq_hz;
|
||||
u8 tune_mode;
|
||||
u8 bandwidth;
|
||||
};
|
||||
|
||||
/* Tuner channel lock indications */
|
||||
struct __packed MXL_EAGLE_TUNER_LOCK_STATUS_T {
|
||||
u8 rf_pll_locked;
|
||||
u8 ref_pll_locked;
|
||||
};
|
||||
|
||||
/* Smart antenna parameters used in Smart antenna params configuration */
|
||||
struct __packed MXL_EAGLE_SMA_PARAMS_T {
|
||||
u8 full_duplex_enable;
|
||||
u8 rx_disable;
|
||||
u8 idle_logic_high;
|
||||
};
|
||||
|
||||
/* Smart antenna message format */
|
||||
struct __packed MXL_EAGLE_SMA_MESSAGE_T {
|
||||
u32 payload_bits;
|
||||
u8 total_num_bits;
|
||||
};
|
||||
|
@ -698,6 +698,7 @@ static int rtl2832_read_status(struct dvb_frontend *fe, enum fe_status *status)
|
||||
goto err;
|
||||
|
||||
constellation = (u8tmp >> 2) & 0x03; /* [3:2] */
|
||||
ret = -EINVAL;
|
||||
if (constellation > CONSTELLATION_NUM - 1)
|
||||
goto err;
|
||||
|
||||
|
@ -813,6 +813,20 @@ config VIDEO_IMX319
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx319.
|
||||
|
||||
config VIDEO_IMX334
|
||||
tristate "Sony IMX334 sensor support"
|
||||
depends on OF_GPIO
|
||||
depends on I2C && VIDEO_V4L2
|
||||
select VIDEO_V4L2_SUBDEV_API
|
||||
select MEDIA_CONTROLLER
|
||||
select V4L2_FWNODE
|
||||
help
|
||||
This is a Video4Linux2 sensor driver for the Sony
|
||||
IMX334 camera.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called imx334.
|
||||
|
||||
config VIDEO_IMX355
|
||||
tristate "Sony IMX355 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
@ -936,6 +950,19 @@ config VIDEO_OV5647
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov5647.
|
||||
|
||||
config VIDEO_OV5648
|
||||
tristate "OmniVision OV5648 sensor support"
|
||||
depends on I2C && PM && VIDEO_V4L2
|
||||
select MEDIA_CONTROLLER
|
||||
select VIDEO_V4L2_SUBDEV_API
|
||||
select V4L2_FWNODE
|
||||
help
|
||||
This is a Video4Linux2 sensor driver for the OmniVision
|
||||
OV5648 camera.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov5648.
|
||||
|
||||
config VIDEO_OV6650
|
||||
tristate "OmniVision OV6650 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
@ -1000,6 +1027,7 @@ config VIDEO_OV772X
|
||||
tristate "OmniVision OV772x sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
select REGMAP_SCCB
|
||||
select V4L2_FWNODE
|
||||
help
|
||||
This is a Video4Linux2 sensor driver for the OmniVision
|
||||
OV772x camera.
|
||||
@ -1047,6 +1075,19 @@ config VIDEO_OV8856
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov8856.
|
||||
|
||||
config VIDEO_OV8865
|
||||
tristate "OmniVision OV8865 sensor support"
|
||||
depends on I2C && PM && VIDEO_V4L2
|
||||
select MEDIA_CONTROLLER
|
||||
select VIDEO_V4L2_SUBDEV_API
|
||||
select V4L2_FWNODE
|
||||
help
|
||||
This is a Video4Linux2 sensor driver for OmniVision
|
||||
OV8865 camera sensor.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called ov8865.
|
||||
|
||||
config VIDEO_OV9640
|
||||
tristate "OmniVision OV9640 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
@ -1199,12 +1240,16 @@ config VIDEO_NOON010PC30
|
||||
|
||||
source "drivers/media/i2c/m5mols/Kconfig"
|
||||
|
||||
config VIDEO_MAX9271_LIB
|
||||
tristate
|
||||
|
||||
config VIDEO_RDACM20
|
||||
tristate "IMI RDACM20 camera support"
|
||||
depends on I2C
|
||||
select V4L2_FWNODE
|
||||
select VIDEO_V4L2_SUBDEV_API
|
||||
select MEDIA_CONTROLLER
|
||||
select VIDEO_MAX9271_LIB
|
||||
help
|
||||
This driver supports the IMI RDACM20 GMSL camera, used in
|
||||
ADAS systems.
|
||||
@ -1212,6 +1257,20 @@ config VIDEO_RDACM20
|
||||
This camera should be used in conjunction with a GMSL
|
||||
deserialiser such as the MAX9286.
|
||||
|
||||
config VIDEO_RDACM21
|
||||
tristate "IMI RDACM21 camera support"
|
||||
depends on I2C
|
||||
select V4L2_FWNODE
|
||||
select VIDEO_V4L2_SUBDEV_API
|
||||
select MEDIA_CONTROLLER
|
||||
select VIDEO_MAX9271_LIB
|
||||
help
|
||||
This driver supports the IMI RDACM21 GMSL camera, used in
|
||||
ADAS systems.
|
||||
|
||||
This camera should be used in conjunction with a GMSL
|
||||
deserialiser such as the MAX9286.
|
||||
|
||||
config VIDEO_RJ54N1
|
||||
tristate "Sharp RJ54N1CB0C sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
|
@ -72,6 +72,7 @@ obj-$(CONFIG_VIDEO_OV2740) += ov2740.o
|
||||
obj-$(CONFIG_VIDEO_OV5640) += ov5640.o
|
||||
obj-$(CONFIG_VIDEO_OV5645) += ov5645.o
|
||||
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_OV5695) += ov5695.o
|
||||
@ -82,6 +83,7 @@ obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
|
||||
obj-$(CONFIG_VIDEO_OV772X) += ov772x.o
|
||||
obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
|
||||
obj-$(CONFIG_VIDEO_OV8856) += ov8856.o
|
||||
obj-$(CONFIG_VIDEO_OV8865) += ov8865.o
|
||||
obj-$(CONFIG_VIDEO_OV9640) += ov9640.o
|
||||
obj-$(CONFIG_VIDEO_OV9650) += ov9650.o
|
||||
obj-$(CONFIG_VIDEO_OV9734) += ov9734.o
|
||||
@ -120,10 +122,12 @@ obj-$(CONFIG_VIDEO_IMX258) += imx258.o
|
||||
obj-$(CONFIG_VIDEO_IMX274) += imx274.o
|
||||
obj-$(CONFIG_VIDEO_IMX290) += imx290.o
|
||||
obj-$(CONFIG_VIDEO_IMX319) += imx319.o
|
||||
obj-$(CONFIG_VIDEO_IMX334) += imx334.o
|
||||
obj-$(CONFIG_VIDEO_IMX355) += imx355.o
|
||||
obj-$(CONFIG_VIDEO_MAX9286) += max9286.o
|
||||
rdacm20-camera_module-objs := rdacm20.o max9271.o
|
||||
obj-$(CONFIG_VIDEO_RDACM20) += rdacm20-camera_module.o
|
||||
obj-$(CONFIG_VIDEO_MAX9271_LIB) += max9271.o
|
||||
obj-$(CONFIG_VIDEO_RDACM20) += rdacm20.o
|
||||
obj-$(CONFIG_VIDEO_RDACM21) += rdacm21.o
|
||||
obj-$(CONFIG_VIDEO_ST_MIPID02) += st-mipid02.o
|
||||
|
||||
obj-$(CONFIG_SDR_MAX2175) += max2175.o
|
||||
|
@ -17,20 +17,20 @@
|
||||
#include "ccs-pll.h"
|
||||
|
||||
/* Return an even number or one. */
|
||||
static inline uint32_t clk_div_even(uint32_t a)
|
||||
static inline u32 clk_div_even(u32 a)
|
||||
{
|
||||
return max_t(uint32_t, 1, a & ~1);
|
||||
return max_t(u32, 1, a & ~1);
|
||||
}
|
||||
|
||||
/* Return an even number or one. */
|
||||
static inline uint32_t clk_div_even_up(uint32_t a)
|
||||
static inline u32 clk_div_even_up(u32 a)
|
||||
{
|
||||
if (a == 1)
|
||||
return 1;
|
||||
return (a + 1) & ~1;
|
||||
}
|
||||
|
||||
static inline uint32_t is_one_or_even(uint32_t a)
|
||||
static inline u32 is_one_or_even(u32 a)
|
||||
{
|
||||
if (a == 1)
|
||||
return 1;
|
||||
@ -40,13 +40,13 @@ static inline uint32_t is_one_or_even(uint32_t a)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline uint32_t one_or_more(uint32_t a)
|
||||
static inline u32 one_or_more(u32 a)
|
||||
{
|
||||
return a ?: 1;
|
||||
}
|
||||
|
||||
static int bounds_check(struct device *dev, uint32_t val,
|
||||
uint32_t min, uint32_t max, const char *prefix,
|
||||
static int bounds_check(struct device *dev, u32 val,
|
||||
u32 min, u32 max, const char *prefix,
|
||||
char *str)
|
||||
{
|
||||
if (val >= min && val <= max)
|
||||
@ -138,12 +138,12 @@ static void print_pll(struct device *dev, struct ccs_pll *pll)
|
||||
pll->flags & PLL_FL(OP_PIX_DDR) ? " op-pix-ddr" : "");
|
||||
}
|
||||
|
||||
static uint32_t op_sys_ddr(uint32_t flags)
|
||||
static u32 op_sys_ddr(u32 flags)
|
||||
{
|
||||
return flags & CCS_PLL_FLAG_OP_SYS_DDR ? 1 : 0;
|
||||
}
|
||||
|
||||
static uint32_t op_pix_ddr(uint32_t flags)
|
||||
static u32 op_pix_ddr(u32 flags)
|
||||
{
|
||||
return flags & CCS_PLL_FLAG_OP_PIX_DDR ? 1 : 0;
|
||||
}
|
||||
@ -250,8 +250,8 @@ static int check_ext_bounds(struct device *dev, struct ccs_pll *pll)
|
||||
static void
|
||||
ccs_pll_find_vt_sys_div(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
struct ccs_pll *pll, struct ccs_pll_branch_fr *pll_fr,
|
||||
uint16_t min_vt_div, uint16_t max_vt_div,
|
||||
uint16_t *min_sys_div, uint16_t *max_sys_div)
|
||||
u16 min_vt_div, u16 max_vt_div,
|
||||
u16 *min_sys_div, u16 *max_sys_div)
|
||||
{
|
||||
/*
|
||||
* Find limits for sys_clk_div. Not all values are possible with all
|
||||
@ -259,11 +259,11 @@ ccs_pll_find_vt_sys_div(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
*/
|
||||
*min_sys_div = lim->vt_bk.min_sys_clk_div;
|
||||
dev_dbg(dev, "min_sys_div: %u\n", *min_sys_div);
|
||||
*min_sys_div = max_t(uint16_t, *min_sys_div,
|
||||
*min_sys_div = max_t(u16, *min_sys_div,
|
||||
DIV_ROUND_UP(min_vt_div,
|
||||
lim->vt_bk.max_pix_clk_div));
|
||||
dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", *min_sys_div);
|
||||
*min_sys_div = max_t(uint16_t, *min_sys_div,
|
||||
*min_sys_div = max_t(u16, *min_sys_div,
|
||||
pll_fr->pll_op_clk_freq_hz
|
||||
/ lim->vt_bk.max_sys_clk_freq_hz);
|
||||
dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", *min_sys_div);
|
||||
@ -272,11 +272,11 @@ ccs_pll_find_vt_sys_div(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
|
||||
*max_sys_div = lim->vt_bk.max_sys_clk_div;
|
||||
dev_dbg(dev, "max_sys_div: %u\n", *max_sys_div);
|
||||
*max_sys_div = min_t(uint16_t, *max_sys_div,
|
||||
*max_sys_div = min_t(u16, *max_sys_div,
|
||||
DIV_ROUND_UP(max_vt_div,
|
||||
lim->vt_bk.min_pix_clk_div));
|
||||
dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", *max_sys_div);
|
||||
*max_sys_div = min_t(uint16_t, *max_sys_div,
|
||||
*max_sys_div = min_t(u16, *max_sys_div,
|
||||
DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz,
|
||||
lim->vt_bk.min_pix_clk_freq_hz));
|
||||
dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", *max_sys_div);
|
||||
@ -289,15 +289,15 @@ ccs_pll_find_vt_sys_div(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
static inline int
|
||||
__ccs_pll_calculate_vt_tree(struct device *dev,
|
||||
const struct ccs_pll_limits *lim,
|
||||
struct ccs_pll *pll, uint32_t mul, uint32_t div)
|
||||
struct ccs_pll *pll, u32 mul, u32 div)
|
||||
{
|
||||
const struct ccs_pll_branch_limits_fr *lim_fr = &lim->vt_fr;
|
||||
const struct ccs_pll_branch_limits_bk *lim_bk = &lim->vt_bk;
|
||||
struct ccs_pll_branch_fr *pll_fr = &pll->vt_fr;
|
||||
struct ccs_pll_branch_bk *pll_bk = &pll->vt_bk;
|
||||
uint32_t more_mul;
|
||||
uint16_t best_pix_div = SHRT_MAX >> 1, best_div;
|
||||
uint16_t vt_div, min_sys_div, max_sys_div, sys_div;
|
||||
u32 more_mul;
|
||||
u16 best_pix_div = SHRT_MAX >> 1, best_div;
|
||||
u16 vt_div, min_sys_div, max_sys_div, sys_div;
|
||||
|
||||
pll_fr->pll_ip_clk_freq_hz =
|
||||
pll->ext_clk_freq_hz / pll_fr->pre_pll_clk_div;
|
||||
@ -331,7 +331,7 @@ __ccs_pll_calculate_vt_tree(struct device *dev,
|
||||
|
||||
for (sys_div = min_sys_div; sys_div <= max_sys_div;
|
||||
sys_div += 2 - (sys_div & 1)) {
|
||||
uint16_t pix_div;
|
||||
u16 pix_div;
|
||||
|
||||
if (vt_div % sys_div)
|
||||
continue;
|
||||
@ -379,9 +379,9 @@ static int ccs_pll_calculate_vt_tree(struct device *dev,
|
||||
{
|
||||
const struct ccs_pll_branch_limits_fr *lim_fr = &lim->vt_fr;
|
||||
struct ccs_pll_branch_fr *pll_fr = &pll->vt_fr;
|
||||
uint16_t min_pre_pll_clk_div = lim_fr->min_pre_pll_clk_div;
|
||||
uint16_t max_pre_pll_clk_div = lim_fr->max_pre_pll_clk_div;
|
||||
uint32_t pre_mul, pre_div;
|
||||
u16 min_pre_pll_clk_div = lim_fr->min_pre_pll_clk_div;
|
||||
u16 max_pre_pll_clk_div = lim_fr->max_pre_pll_clk_div;
|
||||
u32 pre_mul, pre_div;
|
||||
|
||||
pre_div = gcd(pll->pixel_rate_csi,
|
||||
pll->ext_clk_freq_hz * pll->vt_lanes);
|
||||
@ -390,11 +390,11 @@ static int ccs_pll_calculate_vt_tree(struct device *dev,
|
||||
|
||||
/* Make sure PLL input frequency is within limits */
|
||||
max_pre_pll_clk_div =
|
||||
min_t(uint16_t, max_pre_pll_clk_div,
|
||||
min_t(u16, max_pre_pll_clk_div,
|
||||
DIV_ROUND_UP(pll->ext_clk_freq_hz,
|
||||
lim_fr->min_pll_ip_clk_freq_hz));
|
||||
|
||||
min_pre_pll_clk_div = max_t(uint16_t, min_pre_pll_clk_div,
|
||||
min_pre_pll_clk_div = max_t(u16, min_pre_pll_clk_div,
|
||||
pll->ext_clk_freq_hz /
|
||||
lim_fr->max_pll_ip_clk_freq_hz);
|
||||
|
||||
@ -406,7 +406,7 @@ static int ccs_pll_calculate_vt_tree(struct device *dev,
|
||||
pll_fr->pre_pll_clk_div +=
|
||||
(pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 :
|
||||
2 - (pll_fr->pre_pll_clk_div & 1)) {
|
||||
uint32_t mul, div;
|
||||
u32 mul, div;
|
||||
int rval;
|
||||
|
||||
div = gcd(pre_mul * pll_fr->pre_pll_clk_div, pre_div);
|
||||
@ -440,13 +440,13 @@ ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
const struct ccs_pll_branch_limits_bk *op_lim_bk,
|
||||
struct ccs_pll *pll, struct ccs_pll_branch_fr *pll_fr,
|
||||
struct ccs_pll_branch_bk *op_pll_bk, bool cphy,
|
||||
uint32_t phy_const)
|
||||
u32 phy_const)
|
||||
{
|
||||
uint16_t sys_div;
|
||||
uint16_t best_pix_div = SHRT_MAX >> 1;
|
||||
uint16_t vt_op_binning_div;
|
||||
uint16_t min_vt_div, max_vt_div, vt_div;
|
||||
uint16_t min_sys_div, max_sys_div;
|
||||
u16 sys_div;
|
||||
u16 best_pix_div = SHRT_MAX >> 1;
|
||||
u16 vt_op_binning_div;
|
||||
u16 min_vt_div, max_vt_div, vt_div;
|
||||
u16 min_sys_div, max_sys_div;
|
||||
|
||||
if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS)
|
||||
goto out_calc_pixel_rate;
|
||||
@ -500,18 +500,18 @@ ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
|
||||
/* Find smallest and biggest allowed vt divisor. */
|
||||
dev_dbg(dev, "min_vt_div: %u\n", min_vt_div);
|
||||
min_vt_div = max_t(uint16_t, min_vt_div,
|
||||
min_vt_div = max_t(u16, min_vt_div,
|
||||
DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz,
|
||||
lim->vt_bk.max_pix_clk_freq_hz));
|
||||
dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %u\n",
|
||||
min_vt_div);
|
||||
min_vt_div = max_t(uint16_t, min_vt_div, lim->vt_bk.min_pix_clk_div
|
||||
* lim->vt_bk.min_sys_clk_div);
|
||||
min_vt_div = max_t(u16, min_vt_div, lim->vt_bk.min_pix_clk_div
|
||||
* lim->vt_bk.min_sys_clk_div);
|
||||
dev_dbg(dev, "min_vt_div: min_vt_clk_div: %u\n", min_vt_div);
|
||||
|
||||
max_vt_div = lim->vt_bk.max_sys_clk_div * lim->vt_bk.max_pix_clk_div;
|
||||
dev_dbg(dev, "max_vt_div: %u\n", max_vt_div);
|
||||
max_vt_div = min_t(uint16_t, max_vt_div,
|
||||
max_vt_div = min_t(u16, max_vt_div,
|
||||
DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz,
|
||||
lim->vt_bk.min_pix_clk_freq_hz));
|
||||
dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n",
|
||||
@ -526,12 +526,12 @@ ccs_pll_calculate_vt(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
* divisor.
|
||||
*/
|
||||
for (vt_div = min_vt_div; vt_div <= max_vt_div; vt_div++) {
|
||||
uint16_t __max_sys_div = vt_div & 1 ? 1 : max_sys_div;
|
||||
u16 __max_sys_div = vt_div & 1 ? 1 : max_sys_div;
|
||||
|
||||
for (sys_div = min_sys_div; sys_div <= __max_sys_div;
|
||||
sys_div += 2 - (sys_div & 1)) {
|
||||
uint16_t pix_div;
|
||||
uint16_t rounded_div;
|
||||
u16 pix_div;
|
||||
u16 rounded_div;
|
||||
|
||||
pix_div = DIV_ROUND_UP(vt_div, sys_div);
|
||||
|
||||
@ -588,9 +588,9 @@ ccs_pll_calculate_op(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
const struct ccs_pll_branch_limits_fr *op_lim_fr,
|
||||
const struct ccs_pll_branch_limits_bk *op_lim_bk,
|
||||
struct ccs_pll *pll, struct ccs_pll_branch_fr *op_pll_fr,
|
||||
struct ccs_pll_branch_bk *op_pll_bk, uint32_t mul,
|
||||
uint32_t div, uint32_t op_sys_clk_freq_hz_sdr, uint32_t l,
|
||||
bool cphy, uint32_t phy_const)
|
||||
struct ccs_pll_branch_bk *op_pll_bk, u32 mul,
|
||||
u32 div, u32 op_sys_clk_freq_hz_sdr, u32 l,
|
||||
bool cphy, u32 phy_const)
|
||||
{
|
||||
/*
|
||||
* Higher multipliers (and divisors) are often required than
|
||||
@ -598,9 +598,9 @@ ccs_pll_calculate_op(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
* There are limits for all values in the clock tree. These
|
||||
* are the minimum and maximum multiplier for mul.
|
||||
*/
|
||||
uint32_t more_mul_min, more_mul_max;
|
||||
uint32_t more_mul_factor;
|
||||
uint32_t i;
|
||||
u32 more_mul_min, more_mul_max;
|
||||
u32 more_mul_factor;
|
||||
u32 i;
|
||||
|
||||
/*
|
||||
* Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
|
||||
@ -614,7 +614,7 @@ ccs_pll_calculate_op(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
more_mul_max);
|
||||
/* Don't go above max pll op frequency. */
|
||||
more_mul_max =
|
||||
min_t(uint32_t,
|
||||
min_t(u32,
|
||||
more_mul_max,
|
||||
op_lim_fr->max_pll_op_clk_freq_hz
|
||||
/ (pll->ext_clk_freq_hz /
|
||||
@ -706,14 +706,14 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
struct ccs_pll_branch_fr *op_pll_fr;
|
||||
struct ccs_pll_branch_bk *op_pll_bk;
|
||||
bool cphy = pll->bus_type == CCS_PLL_BUS_TYPE_CSI2_CPHY;
|
||||
uint32_t phy_const = cphy ? CPHY_CONST : DPHY_CONST;
|
||||
uint32_t op_sys_clk_freq_hz_sdr;
|
||||
uint16_t min_op_pre_pll_clk_div;
|
||||
uint16_t max_op_pre_pll_clk_div;
|
||||
uint32_t mul, div;
|
||||
uint32_t l = (!pll->op_bits_per_lane ||
|
||||
pll->op_bits_per_lane >= pll->bits_per_pixel) ? 1 : 2;
|
||||
uint32_t i;
|
||||
u32 phy_const = cphy ? CPHY_CONST : DPHY_CONST;
|
||||
u32 op_sys_clk_freq_hz_sdr;
|
||||
u16 min_op_pre_pll_clk_div;
|
||||
u16 max_op_pre_pll_clk_div;
|
||||
u32 mul, div;
|
||||
u32 l = (!pll->op_bits_per_lane ||
|
||||
pll->op_bits_per_lane >= pll->bits_per_pixel) ? 1 : 2;
|
||||
u32 i;
|
||||
int rval = -EINVAL;
|
||||
|
||||
if (!(pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL)) {
|
||||
@ -791,11 +791,11 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
dev_dbg(dev, "min / max op_pre_pll_clk_div: %u / %u\n",
|
||||
op_lim_fr->min_pre_pll_clk_div, op_lim_fr->max_pre_pll_clk_div);
|
||||
max_op_pre_pll_clk_div =
|
||||
min_t(uint16_t, op_lim_fr->max_pre_pll_clk_div,
|
||||
min_t(u16, op_lim_fr->max_pre_pll_clk_div,
|
||||
clk_div_even(pll->ext_clk_freq_hz /
|
||||
op_lim_fr->min_pll_ip_clk_freq_hz));
|
||||
min_op_pre_pll_clk_div =
|
||||
max_t(uint16_t, op_lim_fr->min_pre_pll_clk_div,
|
||||
max_t(u16, op_lim_fr->min_pre_pll_clk_div,
|
||||
clk_div_even_up(
|
||||
DIV_ROUND_UP(pll->ext_clk_freq_hz,
|
||||
op_lim_fr->max_pll_ip_clk_freq_hz)));
|
||||
@ -809,7 +809,7 @@ int ccs_pll_calculate(struct device *dev, const struct ccs_pll_limits *lim,
|
||||
dev_dbg(dev, "mul %u / div %u\n", mul, div);
|
||||
|
||||
min_op_pre_pll_clk_div =
|
||||
max_t(uint16_t, min_op_pre_pll_clk_div,
|
||||
max_t(u16, min_op_pre_pll_clk_div,
|
||||
clk_div_even_up(
|
||||
mul /
|
||||
one_or_more(
|
||||
@ -877,4 +877,4 @@ EXPORT_SYMBOL_GPL(ccs_pll_calculate);
|
||||
|
||||
MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
|
||||
MODULE_DESCRIPTION("Generic MIPI CCS/SMIA/SMIA++ PLL calculator");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
@ -44,10 +44,10 @@
|
||||
* @pll_op_clk_freq_hz: PLL output clock frequency
|
||||
*/
|
||||
struct ccs_pll_branch_fr {
|
||||
uint16_t pre_pll_clk_div;
|
||||
uint16_t pll_multiplier;
|
||||
uint32_t pll_ip_clk_freq_hz;
|
||||
uint32_t pll_op_clk_freq_hz;
|
||||
u16 pre_pll_clk_div;
|
||||
u16 pll_multiplier;
|
||||
u32 pll_ip_clk_freq_hz;
|
||||
u32 pll_op_clk_freq_hz;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -61,10 +61,10 @@ struct ccs_pll_branch_fr {
|
||||
* @pix_clk_freq_hz: Pixel clock frequency
|
||||
*/
|
||||
struct ccs_pll_branch_bk {
|
||||
uint16_t sys_clk_div;
|
||||
uint16_t pix_clk_div;
|
||||
uint32_t sys_clk_freq_hz;
|
||||
uint32_t pix_clk_freq_hz;
|
||||
u16 sys_clk_div;
|
||||
u16 pix_clk_div;
|
||||
u32 sys_clk_freq_hz;
|
||||
u32 pix_clk_freq_hz;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -97,21 +97,21 @@ struct ccs_pll_branch_bk {
|
||||
*/
|
||||
struct ccs_pll {
|
||||
/* input values */
|
||||
uint8_t bus_type;
|
||||
uint8_t op_lanes;
|
||||
uint8_t vt_lanes;
|
||||
u8 bus_type;
|
||||
u8 op_lanes;
|
||||
u8 vt_lanes;
|
||||
struct {
|
||||
uint8_t lanes;
|
||||
u8 lanes;
|
||||
} csi2;
|
||||
uint8_t binning_horizontal;
|
||||
uint8_t binning_vertical;
|
||||
uint8_t scale_m;
|
||||
uint8_t scale_n;
|
||||
uint8_t bits_per_pixel;
|
||||
uint8_t op_bits_per_lane;
|
||||
uint16_t flags;
|
||||
uint32_t link_freq;
|
||||
uint32_t ext_clk_freq_hz;
|
||||
u8 binning_horizontal;
|
||||
u8 binning_vertical;
|
||||
u8 scale_m;
|
||||
u8 scale_n;
|
||||
u8 bits_per_pixel;
|
||||
u8 op_bits_per_lane;
|
||||
u16 flags;
|
||||
u32 link_freq;
|
||||
u32 ext_clk_freq_hz;
|
||||
|
||||
/* output values */
|
||||
struct ccs_pll_branch_fr vt_fr;
|
||||
@ -119,8 +119,8 @@ struct ccs_pll {
|
||||
struct ccs_pll_branch_fr op_fr;
|
||||
struct ccs_pll_branch_bk op_bk;
|
||||
|
||||
uint32_t pixel_rate_csi;
|
||||
uint32_t pixel_rate_pixel_array;
|
||||
u32 pixel_rate_csi;
|
||||
u32 pixel_rate_pixel_array;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -136,14 +136,14 @@ struct ccs_pll {
|
||||
* @max_pll_op_clk_freq_hz: Maximum PLL output clock frequency
|
||||
*/
|
||||
struct ccs_pll_branch_limits_fr {
|
||||
uint16_t min_pre_pll_clk_div;
|
||||
uint16_t max_pre_pll_clk_div;
|
||||
uint32_t min_pll_ip_clk_freq_hz;
|
||||
uint32_t max_pll_ip_clk_freq_hz;
|
||||
uint16_t min_pll_multiplier;
|
||||
uint16_t max_pll_multiplier;
|
||||
uint32_t min_pll_op_clk_freq_hz;
|
||||
uint32_t max_pll_op_clk_freq_hz;
|
||||
u16 min_pre_pll_clk_div;
|
||||
u16 max_pre_pll_clk_div;
|
||||
u32 min_pll_ip_clk_freq_hz;
|
||||
u32 max_pll_ip_clk_freq_hz;
|
||||
u16 min_pll_multiplier;
|
||||
u16 max_pll_multiplier;
|
||||
u32 min_pll_op_clk_freq_hz;
|
||||
u32 max_pll_op_clk_freq_hz;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -159,14 +159,14 @@ struct ccs_pll_branch_limits_fr {
|
||||
* @max_pix_clk_freq_hz: Maximum pixel clock frequency
|
||||
*/
|
||||
struct ccs_pll_branch_limits_bk {
|
||||
uint16_t min_sys_clk_div;
|
||||
uint16_t max_sys_clk_div;
|
||||
uint32_t min_sys_clk_freq_hz;
|
||||
uint32_t max_sys_clk_freq_hz;
|
||||
uint16_t min_pix_clk_div;
|
||||
uint16_t max_pix_clk_div;
|
||||
uint32_t min_pix_clk_freq_hz;
|
||||
uint32_t max_pix_clk_freq_hz;
|
||||
u16 min_sys_clk_div;
|
||||
u16 max_sys_clk_div;
|
||||
u32 min_sys_clk_freq_hz;
|
||||
u32 max_sys_clk_freq_hz;
|
||||
u16 min_pix_clk_div;
|
||||
u16 max_pix_clk_div;
|
||||
u32 min_pix_clk_freq_hz;
|
||||
u32 max_pix_clk_freq_hz;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -183,8 +183,8 @@ struct ccs_pll_branch_limits_bk {
|
||||
*/
|
||||
struct ccs_pll_limits {
|
||||
/* Strict PLL limits */
|
||||
uint32_t min_ext_clk_freq_hz;
|
||||
uint32_t max_ext_clk_freq_hz;
|
||||
u32 min_ext_clk_freq_hz;
|
||||
u32 max_ext_clk_freq_hz;
|
||||
|
||||
struct ccs_pll_branch_limits_fr vt_fr;
|
||||
struct ccs_pll_branch_limits_bk vt_bk;
|
||||
@ -192,8 +192,8 @@ struct ccs_pll_limits {
|
||||
struct ccs_pll_branch_limits_bk op_bk;
|
||||
|
||||
/* Other relevant limits */
|
||||
uint32_t min_line_length_pck_bin;
|
||||
uint32_t min_line_length_pck;
|
||||
u32 min_line_length_pck_bin;
|
||||
u32 min_line_length_pck;
|
||||
};
|
||||
|
||||
struct device;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <linux/v4l2-mediabus.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <uapi/linux/ccs.h>
|
||||
|
||||
#include "ccs.h"
|
||||
|
||||
@ -382,15 +383,22 @@ static int ccs_pll_configure(struct ccs_sensor *sensor)
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
|
||||
/* Lane op clock ratio does not apply here. */
|
||||
rval = ccs_write(sensor, REQUESTED_LINK_RATE,
|
||||
DIV_ROUND_UP(pll->op_bk.sys_clk_freq_hz,
|
||||
1000000 / 256 / 256) *
|
||||
(pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ?
|
||||
sensor->pll.csi2.lanes : 1) <<
|
||||
(pll->flags & CCS_PLL_FLAG_OP_SYS_DDR ? 1 : 0));
|
||||
if (rval < 0 || sensor->pll.flags & CCS_PLL_FLAG_NO_OP_CLOCKS)
|
||||
return rval;
|
||||
if (!(CCS_LIM(sensor, PHY_CTRL_CAPABILITY) &
|
||||
CCS_PHY_CTRL_CAPABILITY_AUTO_PHY_CTL)) {
|
||||
/* Lane op clock ratio does not apply here. */
|
||||
rval = ccs_write(sensor, REQUESTED_LINK_RATE,
|
||||
DIV_ROUND_UP(pll->op_bk.sys_clk_freq_hz,
|
||||
1000000 / 256 / 256) *
|
||||
(pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ?
|
||||
sensor->pll.csi2.lanes : 1) <<
|
||||
(pll->flags & CCS_PLL_FLAG_OP_SYS_DDR ?
|
||||
1 : 0));
|
||||
if (rval < 0)
|
||||
return rval;
|
||||
}
|
||||
|
||||
if (sensor->pll.flags & CCS_PLL_FLAG_NO_OP_CLOCKS)
|
||||
return 0;
|
||||
|
||||
rval = ccs_write(sensor, OP_PIX_CLK_DIV, pll->op_bk.pix_clk_div);
|
||||
if (rval < 0)
|
||||
@ -671,6 +679,49 @@ static int ccs_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
rval = ccs_write(sensor, ANALOG_GAIN_CODE_GLOBAL, ctrl->val);
|
||||
|
||||
break;
|
||||
|
||||
case V4L2_CID_CCS_ANALOGUE_LINEAR_GAIN:
|
||||
rval = ccs_write(sensor, ANALOG_LINEAR_GAIN_GLOBAL, ctrl->val);
|
||||
|
||||
break;
|
||||
|
||||
case V4L2_CID_CCS_ANALOGUE_EXPONENTIAL_GAIN:
|
||||
rval = ccs_write(sensor, ANALOG_EXPONENTIAL_GAIN_GLOBAL,
|
||||
ctrl->val);
|
||||
|
||||
break;
|
||||
|
||||
case V4L2_CID_DIGITAL_GAIN:
|
||||
if (CCS_LIM(sensor, DIGITAL_GAIN_CAPABILITY) ==
|
||||
CCS_DIGITAL_GAIN_CAPABILITY_GLOBAL) {
|
||||
rval = ccs_write(sensor, DIGITAL_GAIN_GLOBAL,
|
||||
ctrl->val);
|
||||
break;
|
||||
}
|
||||
|
||||
rval = ccs_write_addr(sensor,
|
||||
SMIAPP_REG_U16_DIGITAL_GAIN_GREENR,
|
||||
ctrl->val);
|
||||
if (rval)
|
||||
break;
|
||||
|
||||
rval = ccs_write_addr(sensor,
|
||||
SMIAPP_REG_U16_DIGITAL_GAIN_RED,
|
||||
ctrl->val);
|
||||
if (rval)
|
||||
break;
|
||||
|
||||
rval = ccs_write_addr(sensor,
|
||||
SMIAPP_REG_U16_DIGITAL_GAIN_BLUE,
|
||||
ctrl->val);
|
||||
if (rval)
|
||||
break;
|
||||
|
||||
rval = ccs_write_addr(sensor,
|
||||
SMIAPP_REG_U16_DIGITAL_GAIN_GREENB,
|
||||
ctrl->val);
|
||||
|
||||
break;
|
||||
case V4L2_CID_EXPOSURE:
|
||||
rval = ccs_write(sensor, COARSE_INTEGRATION_TIME, ctrl->val);
|
||||
|
||||
@ -712,6 +763,19 @@ static int ccs_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
case V4L2_CID_TEST_PATTERN_GREENB:
|
||||
rval = ccs_write(sensor, TEST_DATA_GREENB, ctrl->val);
|
||||
|
||||
break;
|
||||
case V4L2_CID_CCS_SHADING_CORRECTION:
|
||||
rval = ccs_write(sensor, SHADING_CORRECTION_EN,
|
||||
ctrl->val ? CCS_SHADING_CORRECTION_EN_ENABLE :
|
||||
0);
|
||||
|
||||
if (!rval && sensor->luminance_level)
|
||||
v4l2_ctrl_activate(sensor->luminance_level, ctrl->val);
|
||||
|
||||
break;
|
||||
case V4L2_CID_CCS_LUMINANCE_CORRECTION_LEVEL:
|
||||
rval = ccs_write(sensor, LUMINANCE_CORRECTION_LEVEL, ctrl->val);
|
||||
|
||||
break;
|
||||
case V4L2_CID_PIXEL_RATE:
|
||||
/* For v4l2_ctrl_s_ctrl_int64() used internally. */
|
||||
@ -739,19 +803,144 @@ static int ccs_init_controls(struct ccs_sensor *sensor)
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||
int rval;
|
||||
|
||||
rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 12);
|
||||
rval = v4l2_ctrl_handler_init(&sensor->pixel_array->ctrl_handler, 17);
|
||||
if (rval)
|
||||
return rval;
|
||||
|
||||
sensor->pixel_array->ctrl_handler.lock = &sensor->mutex;
|
||||
|
||||
sensor->analog_gain = v4l2_ctrl_new_std(
|
||||
&sensor->pixel_array->ctrl_handler, &ccs_ctrl_ops,
|
||||
V4L2_CID_ANALOGUE_GAIN,
|
||||
CCS_LIM(sensor, ANALOG_GAIN_CODE_MIN),
|
||||
CCS_LIM(sensor, ANALOG_GAIN_CODE_MAX),
|
||||
max(CCS_LIM(sensor, ANALOG_GAIN_CODE_STEP), 1U),
|
||||
CCS_LIM(sensor, ANALOG_GAIN_CODE_MIN));
|
||||
switch (CCS_LIM(sensor, ANALOG_GAIN_CAPABILITY)) {
|
||||
case CCS_ANALOG_GAIN_CAPABILITY_GLOBAL: {
|
||||
struct {
|
||||
const char *name;
|
||||
u32 id;
|
||||
s32 value;
|
||||
} const gain_ctrls[] = {
|
||||
{ "Analogue Gain m0", V4L2_CID_CCS_ANALOGUE_GAIN_M0,
|
||||
CCS_LIM(sensor, ANALOG_GAIN_M0), },
|
||||
{ "Analogue Gain c0", V4L2_CID_CCS_ANALOGUE_GAIN_C0,
|
||||
CCS_LIM(sensor, ANALOG_GAIN_C0), },
|
||||
{ "Analogue Gain m1", V4L2_CID_CCS_ANALOGUE_GAIN_M1,
|
||||
CCS_LIM(sensor, ANALOG_GAIN_M1), },
|
||||
{ "Analogue Gain c1", V4L2_CID_CCS_ANALOGUE_GAIN_C1,
|
||||
CCS_LIM(sensor, ANALOG_GAIN_C1), },
|
||||
};
|
||||
struct v4l2_ctrl_config ctrl_cfg = {
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.ops = &ccs_ctrl_ops,
|
||||
.flags = V4L2_CTRL_FLAG_READ_ONLY,
|
||||
.step = 1,
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gain_ctrls); i++) {
|
||||
ctrl_cfg.name = gain_ctrls[i].name;
|
||||
ctrl_cfg.id = gain_ctrls[i].id;
|
||||
ctrl_cfg.min = ctrl_cfg.max = ctrl_cfg.def =
|
||||
gain_ctrls[i].value;
|
||||
|
||||
v4l2_ctrl_new_custom(&sensor->pixel_array->ctrl_handler,
|
||||
&ctrl_cfg, NULL);
|
||||
}
|
||||
|
||||
v4l2_ctrl_new_std(&sensor->pixel_array->ctrl_handler,
|
||||
&ccs_ctrl_ops, V4L2_CID_ANALOGUE_GAIN,
|
||||
CCS_LIM(sensor, ANALOG_GAIN_CODE_MIN),
|
||||
CCS_LIM(sensor, ANALOG_GAIN_CODE_MAX),
|
||||
max(CCS_LIM(sensor, ANALOG_GAIN_CODE_STEP),
|
||||
1U),
|
||||
CCS_LIM(sensor, ANALOG_GAIN_CODE_MIN));
|
||||
}
|
||||
break;
|
||||
|
||||
case CCS_ANALOG_GAIN_CAPABILITY_ALTERNATE_GLOBAL: {
|
||||
struct {
|
||||
const char *name;
|
||||
u32 id;
|
||||
u16 min, max, step;
|
||||
} const gain_ctrls[] = {
|
||||
{
|
||||
"Analogue Linear Gain",
|
||||
V4L2_CID_CCS_ANALOGUE_LINEAR_GAIN,
|
||||
CCS_LIM(sensor, ANALOG_LINEAR_GAIN_MIN),
|
||||
CCS_LIM(sensor, ANALOG_LINEAR_GAIN_MAX),
|
||||
max(CCS_LIM(sensor,
|
||||
ANALOG_LINEAR_GAIN_STEP_SIZE),
|
||||
1U),
|
||||
},
|
||||
{
|
||||
"Analogue Exponential Gain",
|
||||
V4L2_CID_CCS_ANALOGUE_EXPONENTIAL_GAIN,
|
||||
CCS_LIM(sensor, ANALOG_EXPONENTIAL_GAIN_MIN),
|
||||
CCS_LIM(sensor, ANALOG_EXPONENTIAL_GAIN_MAX),
|
||||
max(CCS_LIM(sensor,
|
||||
ANALOG_EXPONENTIAL_GAIN_STEP_SIZE),
|
||||
1U),
|
||||
},
|
||||
};
|
||||
struct v4l2_ctrl_config ctrl_cfg = {
|
||||
.type = V4L2_CTRL_TYPE_INTEGER,
|
||||
.ops = &ccs_ctrl_ops,
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(gain_ctrls); i++) {
|
||||
ctrl_cfg.name = gain_ctrls[i].name;
|
||||
ctrl_cfg.min = ctrl_cfg.def = gain_ctrls[i].min;
|
||||
ctrl_cfg.max = gain_ctrls[i].max;
|
||||
ctrl_cfg.step = gain_ctrls[i].step;
|
||||
ctrl_cfg.id = gain_ctrls[i].id;
|
||||
|
||||
v4l2_ctrl_new_custom(&sensor->pixel_array->ctrl_handler,
|
||||
&ctrl_cfg, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CCS_LIM(sensor, SHADING_CORRECTION_CAPABILITY) &
|
||||
(CCS_SHADING_CORRECTION_CAPABILITY_COLOR_SHADING |
|
||||
CCS_SHADING_CORRECTION_CAPABILITY_LUMINANCE_CORRECTION)) {
|
||||
const struct v4l2_ctrl_config ctrl_cfg = {
|
||||
.name = "Shading Correction",
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.id = V4L2_CID_CCS_SHADING_CORRECTION,
|
||||
.ops = &ccs_ctrl_ops,
|
||||
.max = 1,
|
||||
.step = 1,
|
||||
};
|
||||
|
||||
v4l2_ctrl_new_custom(&sensor->pixel_array->ctrl_handler,
|
||||
&ctrl_cfg, NULL);
|
||||
}
|
||||
|
||||
if (CCS_LIM(sensor, SHADING_CORRECTION_CAPABILITY) &
|
||||
CCS_SHADING_CORRECTION_CAPABILITY_LUMINANCE_CORRECTION) {
|
||||
const struct v4l2_ctrl_config ctrl_cfg = {
|
||||
.name = "Luminance Correction Level",
|
||||
.type = V4L2_CTRL_TYPE_BOOLEAN,
|
||||
.id = V4L2_CID_CCS_LUMINANCE_CORRECTION_LEVEL,
|
||||
.ops = &ccs_ctrl_ops,
|
||||
.max = 255,
|
||||
.step = 1,
|
||||
.def = 128,
|
||||
};
|
||||
|
||||
sensor->luminance_level =
|
||||
v4l2_ctrl_new_custom(&sensor->pixel_array->ctrl_handler,
|
||||
&ctrl_cfg, NULL);
|
||||
}
|
||||
|
||||
if (CCS_LIM(sensor, DIGITAL_GAIN_CAPABILITY) ==
|
||||
CCS_DIGITAL_GAIN_CAPABILITY_GLOBAL ||
|
||||
CCS_LIM(sensor, DIGITAL_GAIN_CAPABILITY) ==
|
||||
SMIAPP_DIGITAL_GAIN_CAPABILITY_PER_CHANNEL)
|
||||
v4l2_ctrl_new_std(&sensor->pixel_array->ctrl_handler,
|
||||
&ccs_ctrl_ops, V4L2_CID_DIGITAL_GAIN,
|
||||
CCS_LIM(sensor, DIGITAL_GAIN_MIN),
|
||||
CCS_LIM(sensor, DIGITAL_GAIN_MAX),
|
||||
max(CCS_LIM(sensor, DIGITAL_GAIN_STEP_SIZE),
|
||||
1U),
|
||||
0x100);
|
||||
|
||||
/* Exposure limits will be updated soon, use just something here. */
|
||||
sensor->exposure = v4l2_ctrl_new_std(
|
||||
@ -1001,7 +1190,7 @@ static void ccs_update_blanking(struct ccs_sensor *sensor)
|
||||
{
|
||||
struct v4l2_ctrl *vblank = sensor->vblank;
|
||||
struct v4l2_ctrl *hblank = sensor->hblank;
|
||||
uint16_t min_fll, max_fll, min_llp, max_llp, min_lbp;
|
||||
u16 min_fll, max_fll, min_llp, max_llp, min_lbp;
|
||||
int min, max;
|
||||
|
||||
if (sensor->binning_vertical > 1 || sensor->binning_horizontal > 1) {
|
||||
@ -1322,6 +1511,28 @@ static int ccs_write_msr_regs(struct ccs_sensor *sensor)
|
||||
sensor->mdata.num_module_manufacturer_regs);
|
||||
}
|
||||
|
||||
static int ccs_update_phy_ctrl(struct ccs_sensor *sensor)
|
||||
{
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
|
||||
u8 val;
|
||||
|
||||
if (!sensor->ccs_limits)
|
||||
return 0;
|
||||
|
||||
if (CCS_LIM(sensor, PHY_CTRL_CAPABILITY) &
|
||||
CCS_PHY_CTRL_CAPABILITY_AUTO_PHY_CTL) {
|
||||
val = CCS_PHY_CTRL_AUTO;
|
||||
} else if (CCS_LIM(sensor, PHY_CTRL_CAPABILITY) &
|
||||
CCS_PHY_CTRL_CAPABILITY_UI_PHY_CTL) {
|
||||
val = CCS_PHY_CTRL_UI;
|
||||
} else {
|
||||
dev_err(&client->dev, "manual PHY control not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ccs_write(sensor, PHY_CTRL, val);
|
||||
}
|
||||
|
||||
static int ccs_power_on(struct device *dev)
|
||||
{
|
||||
struct v4l2_subdev *subdev = dev_get_drvdata(dev);
|
||||
@ -1333,7 +1544,6 @@ static int ccs_power_on(struct device *dev)
|
||||
struct ccs_sensor *sensor =
|
||||
container_of(ssd, struct ccs_sensor, ssds[0]);
|
||||
const struct ccs_device *ccsdev = device_get_match_data(dev);
|
||||
unsigned int sleep;
|
||||
int rval;
|
||||
|
||||
rval = regulator_bulk_enable(ARRAY_SIZE(ccs_regulators),
|
||||
@ -1343,22 +1553,26 @@ static int ccs_power_on(struct device *dev)
|
||||
return rval;
|
||||
}
|
||||
|
||||
rval = clk_prepare_enable(sensor->ext_clk);
|
||||
if (rval < 0) {
|
||||
dev_dbg(dev, "failed to enable xclk\n");
|
||||
goto out_xclk_fail;
|
||||
if (sensor->reset || sensor->xshutdown || sensor->ext_clk) {
|
||||
unsigned int sleep;
|
||||
|
||||
rval = clk_prepare_enable(sensor->ext_clk);
|
||||
if (rval < 0) {
|
||||
dev_dbg(dev, "failed to enable xclk\n");
|
||||
goto out_xclk_fail;
|
||||
}
|
||||
|
||||
gpiod_set_value(sensor->reset, 0);
|
||||
gpiod_set_value(sensor->xshutdown, 1);
|
||||
|
||||
if (ccsdev->flags & CCS_DEVICE_FLAG_IS_SMIA)
|
||||
sleep = SMIAPP_RESET_DELAY(sensor->hwcfg.ext_clk);
|
||||
else
|
||||
sleep = 5000;
|
||||
|
||||
usleep_range(sleep, sleep);
|
||||
}
|
||||
|
||||
gpiod_set_value(sensor->reset, 0);
|
||||
gpiod_set_value(sensor->xshutdown, 1);
|
||||
|
||||
if (ccsdev->flags & CCS_DEVICE_FLAG_IS_SMIA)
|
||||
sleep = SMIAPP_RESET_DELAY(sensor->hwcfg.ext_clk);
|
||||
else
|
||||
sleep = 5000;
|
||||
|
||||
usleep_range(sleep, sleep);
|
||||
|
||||
/*
|
||||
* Failures to respond to the address change command have been noticed.
|
||||
* Those failures seem to be caused by the sensor requiring a longer
|
||||
@ -1370,18 +1584,27 @@ static int ccs_power_on(struct device *dev)
|
||||
* is found.
|
||||
*/
|
||||
|
||||
if (sensor->hwcfg.i2c_addr_alt) {
|
||||
rval = ccs_change_cci_addr(sensor);
|
||||
if (rval) {
|
||||
dev_err(dev, "cci address change error\n");
|
||||
if (!sensor->reset && !sensor->xshutdown) {
|
||||
u8 retry = 100;
|
||||
u32 reset;
|
||||
|
||||
rval = ccs_write(sensor, SOFTWARE_RESET, CCS_SOFTWARE_RESET_ON);
|
||||
if (rval < 0) {
|
||||
dev_err(dev, "software reset failed\n");
|
||||
goto out_cci_addr_fail;
|
||||
}
|
||||
}
|
||||
|
||||
rval = ccs_write(sensor, SOFTWARE_RESET, CCS_SOFTWARE_RESET_ON);
|
||||
if (rval < 0) {
|
||||
dev_err(dev, "software reset failed\n");
|
||||
goto out_cci_addr_fail;
|
||||
do {
|
||||
rval = ccs_read(sensor, SOFTWARE_RESET, &reset);
|
||||
reset = !rval && reset == CCS_SOFTWARE_RESET_OFF;
|
||||
if (reset)
|
||||
break;
|
||||
|
||||
usleep_range(1000, 2000);
|
||||
} while (--retry);
|
||||
|
||||
if (!reset)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (sensor->hwcfg.i2c_addr_alt) {
|
||||
@ -1426,8 +1649,7 @@ static int ccs_power_on(struct device *dev)
|
||||
goto out_cci_addr_fail;
|
||||
}
|
||||
|
||||
/* DPHY control done by sensor based on requested link rate */
|
||||
rval = ccs_write(sensor, PHY_CTRL, CCS_PHY_CTRL_UI);
|
||||
rval = ccs_update_phy_ctrl(sensor);
|
||||
if (rval < 0)
|
||||
goto out_cci_addr_fail;
|
||||
|
||||
@ -2908,7 +3130,8 @@ static int ccs_get_hwconfig(struct ccs_sensor *sensor, struct device *dev)
|
||||
int i;
|
||||
int rval;
|
||||
|
||||
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
|
||||
ep = fwnode_graph_get_endpoint_by_id(fwnode, 0, 0,
|
||||
FWNODE_GRAPH_ENDPOINT_NEXT);
|
||||
if (!ep)
|
||||
return -ENODEV;
|
||||
|
||||
@ -3080,6 +3303,11 @@ static int ccs_probe(struct i2c_client *client)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!sensor->hwcfg.ext_clk) {
|
||||
dev_err(&client->dev, "cannot work with xclk frequency 0\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
sensor->reset = devm_gpiod_get_optional(&client->dev, "reset",
|
||||
GPIOD_OUT_HIGH);
|
||||
if (IS_ERR(sensor->reset))
|
||||
@ -3148,6 +3376,10 @@ static int ccs_probe(struct i2c_client *client)
|
||||
goto out_free_ccs_limits;
|
||||
}
|
||||
|
||||
rval = ccs_update_phy_ctrl(sensor);
|
||||
if (rval < 0)
|
||||
goto out_free_ccs_limits;
|
||||
|
||||
/*
|
||||
* Handle Sensor Module orientation on the board.
|
||||
*
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include <linux/limits.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
|
||||
#include "ccs-data-defs.h"
|
||||
|
||||
@ -215,7 +214,7 @@ static int ccs_data_parse_regs(struct bin_container *bin,
|
||||
size_t *__num_regs, const void *payload,
|
||||
const void *endp, struct device *dev)
|
||||
{
|
||||
struct ccs_reg *regs_base, *regs;
|
||||
struct ccs_reg *regs_base = NULL, *regs = NULL;
|
||||
size_t num_regs = 0;
|
||||
u16 addr = 0;
|
||||
|
||||
@ -286,6 +285,9 @@ static int ccs_data_parse_regs(struct bin_container *bin,
|
||||
if (!bin->base) {
|
||||
bin_reserve(bin, len);
|
||||
} else if (__regs) {
|
||||
if (!regs)
|
||||
return -EIO;
|
||||
|
||||
regs->addr = addr;
|
||||
regs->len = len;
|
||||
regs->value = bin_alloc(bin, len);
|
||||
@ -306,8 +308,12 @@ static int ccs_data_parse_regs(struct bin_container *bin,
|
||||
if (__num_regs)
|
||||
*__num_regs = num_regs;
|
||||
|
||||
if (bin->base && __regs)
|
||||
if (bin->base && __regs) {
|
||||
if (!regs_base)
|
||||
return -EIO;
|
||||
|
||||
*__regs = regs_base;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -426,7 +432,7 @@ static int ccs_data_parse_rules(struct bin_container *bin,
|
||||
size_t *__num_rules, const void *payload,
|
||||
const void *endp, struct device *dev)
|
||||
{
|
||||
struct ccs_rule *rules_base, *rules = NULL, *next_rule;
|
||||
struct ccs_rule *rules_base = NULL, *rules = NULL, *next_rule = NULL;
|
||||
size_t num_rules = 0;
|
||||
const void *__next_rule = payload;
|
||||
int rval;
|
||||
@ -484,6 +490,9 @@ static int ccs_data_parse_rules(struct bin_container *bin,
|
||||
} else {
|
||||
unsigned int i;
|
||||
|
||||
if (!next_rule)
|
||||
return -EIO;
|
||||
|
||||
rules = next_rule;
|
||||
next_rule++;
|
||||
|
||||
@ -556,6 +565,9 @@ static int ccs_data_parse_rules(struct bin_container *bin,
|
||||
bin_reserve(bin, sizeof(*rules) * num_rules);
|
||||
*__num_rules = num_rules;
|
||||
} else {
|
||||
if (!rules_base)
|
||||
return -EIO;
|
||||
|
||||
*__rules = rules_base;
|
||||
}
|
||||
|
||||
@ -691,7 +703,7 @@ static int ccs_data_parse_pdaf(struct bin_container *bin, struct ccs_pdaf_pix_lo
|
||||
}
|
||||
|
||||
for (i = 0; i < max_block_type_id; i++) {
|
||||
struct ccs_pdaf_pix_loc_pixel_desc_group *pdgroup;
|
||||
struct ccs_pdaf_pix_loc_pixel_desc_group *pdgroup = NULL;
|
||||
unsigned int j;
|
||||
|
||||
if (!is_contained(__num_pixel_descs, endp))
|
||||
@ -722,6 +734,9 @@ static int ccs_data_parse_pdaf(struct bin_container *bin, struct ccs_pdaf_pix_lo
|
||||
if (!bin->base)
|
||||
continue;
|
||||
|
||||
if (!pdgroup)
|
||||
return -EIO;
|
||||
|
||||
pdesc = &pdgroup->descs[j];
|
||||
pdesc->pixel_type = __pixel_desc->pixel_type;
|
||||
pdesc->small_offset_x = __pixel_desc->small_offset_x;
|
||||
|
@ -10,6 +10,8 @@
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct device;
|
||||
|
||||
/**
|
||||
* struct ccs_data_block_version - CCS static data version
|
||||
* @version_major: Major version number
|
||||
|
@ -17,11 +17,10 @@
|
||||
#include "ccs.h"
|
||||
#include "ccs-limits.h"
|
||||
|
||||
static uint32_t float_to_u32_mul_1000000(struct i2c_client *client,
|
||||
uint32_t phloat)
|
||||
static u32 float_to_u32_mul_1000000(struct i2c_client *client, u32 phloat)
|
||||
{
|
||||
int32_t exp;
|
||||
uint64_t man;
|
||||
s32 exp;
|
||||
u64 man;
|
||||
|
||||
if (phloat >= 0x80000000) {
|
||||
dev_err(&client->dev, "this is a negative number\n");
|
||||
@ -137,11 +136,11 @@ static int ____ccs_read_addr_8only(struct ccs_sensor *sensor, u16 reg,
|
||||
unsigned int ccs_reg_width(u32 reg)
|
||||
{
|
||||
if (reg & CCS_FL_16BIT)
|
||||
return sizeof(uint16_t);
|
||||
return sizeof(u16);
|
||||
if (reg & CCS_FL_32BIT)
|
||||
return sizeof(uint32_t);
|
||||
return sizeof(u32);
|
||||
|
||||
return sizeof(uint8_t);
|
||||
return sizeof(u8);
|
||||
}
|
||||
|
||||
static u32 ireal32_to_u32_mul_1000000(struct i2c_client *client, u32 val)
|
||||
@ -205,7 +204,7 @@ static int __ccs_read_data(struct ccs_reg *regs, size_t num_regs,
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < num_regs; i++, regs++) {
|
||||
uint8_t *data;
|
||||
u8 *data;
|
||||
|
||||
if (regs->addr + regs->len < CCS_REG_ADDR(reg) + width)
|
||||
continue;
|
||||
@ -216,13 +215,13 @@ static int __ccs_read_data(struct ccs_reg *regs, size_t num_regs,
|
||||
data = ®s->value[CCS_REG_ADDR(reg) - regs->addr];
|
||||
|
||||
switch (width) {
|
||||
case sizeof(uint8_t):
|
||||
case sizeof(u8):
|
||||
*val = *data;
|
||||
break;
|
||||
case sizeof(uint16_t):
|
||||
case sizeof(u16):
|
||||
*val = get_unaligned_be16(data);
|
||||
break;
|
||||
case sizeof(uint32_t):
|
||||
case sizeof(u32):
|
||||
*val = get_unaligned_be32(data);
|
||||
break;
|
||||
default:
|
||||
@ -387,12 +386,20 @@ int ccs_write_data_regs(struct ccs_sensor *sensor, struct ccs_reg *regs,
|
||||
|
||||
for (j = 0; j < regs->len;
|
||||
j += msg.len - 2, regdata += msg.len - 2) {
|
||||
char printbuf[(MAX_WRITE_LEN << 1) +
|
||||
1 /* \0 */] = { 0 };
|
||||
int rval;
|
||||
|
||||
msg.len = min(regs->len - j, MAX_WRITE_LEN);
|
||||
|
||||
bin2hex(printbuf, regdata, msg.len);
|
||||
dev_dbg(&client->dev,
|
||||
"writing msr reg 0x%4.4x value 0x%s\n",
|
||||
regs->addr + j, printbuf);
|
||||
|
||||
put_unaligned_be16(regs->addr + j, buf);
|
||||
memcpy(buf + 2, regdata, msg.len);
|
||||
|
||||
msg.len += 2;
|
||||
|
||||
rval = ccs_write_retry(client, &msg);
|
||||
|
@ -84,11 +84,11 @@ struct ccs_hwconfig {
|
||||
unsigned short i2c_addr_dfl; /* Default i2c addr */
|
||||
unsigned short i2c_addr_alt; /* Alternate i2c addr */
|
||||
|
||||
uint32_t ext_clk; /* sensor external clk */
|
||||
u32 ext_clk; /* sensor external clk */
|
||||
|
||||
unsigned int lanes; /* Number of CSI-2 lanes */
|
||||
uint32_t csi_signalling_mode; /* CCS_CSI_SIGNALLING_MODE_* */
|
||||
uint64_t *op_sys_clock;
|
||||
u32 csi_signalling_mode; /* CCS_CSI_SIGNALLING_MODE_* */
|
||||
u64 *op_sys_clock;
|
||||
|
||||
enum ccs_module_board_orient module_board_orient;
|
||||
|
||||
@ -262,13 +262,13 @@ struct ccs_sensor {
|
||||
unsigned long *valid_link_freqs;
|
||||
|
||||
/* Pixel array controls */
|
||||
struct v4l2_ctrl *analog_gain;
|
||||
struct v4l2_ctrl *exposure;
|
||||
struct v4l2_ctrl *hflip;
|
||||
struct v4l2_ctrl *vflip;
|
||||
struct v4l2_ctrl *vblank;
|
||||
struct v4l2_ctrl *hblank;
|
||||
struct v4l2_ctrl *pixel_rate_parray;
|
||||
struct v4l2_ctrl *luminance_level;
|
||||
/* src controls */
|
||||
struct v4l2_ctrl *link_freq;
|
||||
struct v4l2_ctrl *pixel_rate_csi;
|
||||
|
@ -535,6 +535,8 @@
|
||||
#define SMIAPP_DIGITAL_CROP_CAPABILITY_NONE 0
|
||||
#define SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP 1
|
||||
|
||||
#define SMIAPP_DIGITAL_GAIN_CAPABILITY_PER_CHANNEL 1
|
||||
|
||||
#define SMIAPP_BINNING_CAPABILITY_NO 0
|
||||
#define SMIAPP_BINNING_CAPABILITY_YES 1
|
||||
|
||||
|
@ -390,6 +390,10 @@ static const struct imx219_reg raw10_framefmt_regs[] = {
|
||||
{0x0309, 0x0a},
|
||||
};
|
||||
|
||||
static const s64 imx219_link_freq_menu[] = {
|
||||
IMX219_DEFAULT_LINK_FREQ,
|
||||
};
|
||||
|
||||
static const char * const imx219_test_pattern_menu[] = {
|
||||
"Disabled",
|
||||
"Color Bars",
|
||||
@ -547,6 +551,7 @@ struct imx219 {
|
||||
struct v4l2_ctrl_handler ctrl_handler;
|
||||
/* V4L2 Controls */
|
||||
struct v4l2_ctrl *pixel_rate;
|
||||
struct v4l2_ctrl *link_freq;
|
||||
struct v4l2_ctrl *exposure;
|
||||
struct v4l2_ctrl *vflip;
|
||||
struct v4l2_ctrl *hflip;
|
||||
@ -806,7 +811,9 @@ static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
if (code->index >= (ARRAY_SIZE(codes) / 4))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_lock(&imx219->mutex);
|
||||
code->code = imx219_get_format_code(imx219, codes[code->index * 4]);
|
||||
mutex_unlock(&imx219->mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -816,11 +823,15 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_frame_size_enum *fse)
|
||||
{
|
||||
struct imx219 *imx219 = to_imx219(sd);
|
||||
u32 code;
|
||||
|
||||
if (fse->index >= ARRAY_SIZE(supported_modes))
|
||||
return -EINVAL;
|
||||
|
||||
if (fse->code != imx219_get_format_code(imx219, fse->code))
|
||||
mutex_lock(&imx219->mutex);
|
||||
code = imx219_get_format_code(imx219, fse->code);
|
||||
mutex_unlock(&imx219->mutex);
|
||||
if (fse->code != code)
|
||||
return -EINVAL;
|
||||
|
||||
fse->min_width = supported_modes[fse->index].width;
|
||||
@ -1263,7 +1274,7 @@ static int imx219_init_controls(struct imx219 *imx219)
|
||||
int i, ret;
|
||||
|
||||
ctrl_hdlr = &imx219->ctrl_handler;
|
||||
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 11);
|
||||
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 12);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1277,6 +1288,14 @@ static int imx219_init_controls(struct imx219 *imx219)
|
||||
IMX219_PIXEL_RATE, 1,
|
||||
IMX219_PIXEL_RATE);
|
||||
|
||||
imx219->link_freq =
|
||||
v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops,
|
||||
V4L2_CID_LINK_FREQ,
|
||||
ARRAY_SIZE(imx219_link_freq_menu) - 1, 0,
|
||||
imx219_link_freq_menu);
|
||||
if (imx219->link_freq)
|
||||
imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
|
||||
|
||||
/* Initial vblank/hblank/exposure parameters based on current mode */
|
||||
imx219->vblank = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
|
||||
V4L2_CID_VBLANK, IMX219_VBLANK_MIN,
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Copyright (C) 2018 Intel Corporation
|
||||
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
@ -68,6 +69,9 @@
|
||||
#define REG_CONFIG_MIRROR_FLIP 0x03
|
||||
#define REG_CONFIG_FLIP_TEST_PATTERN 0x02
|
||||
|
||||
/* Input clock frequency in Hz */
|
||||
#define IMX258_INPUT_CLOCK_FREQ 19200000
|
||||
|
||||
struct imx258_reg {
|
||||
u16 address;
|
||||
u8 val;
|
||||
@ -610,6 +614,8 @@ struct imx258 {
|
||||
|
||||
/* Streaming on/off */
|
||||
bool streaming;
|
||||
|
||||
struct clk *clk;
|
||||
};
|
||||
|
||||
static inline struct imx258 *to_imx258(struct v4l2_subdev *_sd)
|
||||
@ -972,6 +978,29 @@ static int imx258_stop_streaming(struct imx258 *imx258)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx258_power_on(struct device *dev)
|
||||
{
|
||||
struct v4l2_subdev *sd = dev_get_drvdata(dev);
|
||||
struct imx258 *imx258 = to_imx258(sd);
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(imx258->clk);
|
||||
if (ret)
|
||||
dev_err(dev, "failed to enable clock\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int imx258_power_off(struct device *dev)
|
||||
{
|
||||
struct v4l2_subdev *sd = dev_get_drvdata(dev);
|
||||
struct imx258 *imx258 = to_imx258(sd);
|
||||
|
||||
clk_disable_unprepare(imx258->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int imx258_set_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct imx258 *imx258 = to_imx258(sd);
|
||||
@ -1018,8 +1047,7 @@ err_unlock:
|
||||
|
||||
static int __maybe_unused imx258_suspend(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
struct v4l2_subdev *sd = dev_get_drvdata(dev);
|
||||
struct imx258 *imx258 = to_imx258(sd);
|
||||
|
||||
if (imx258->streaming)
|
||||
@ -1030,8 +1058,7 @@ static int __maybe_unused imx258_suspend(struct device *dev)
|
||||
|
||||
static int __maybe_unused imx258_resume(struct device *dev)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
struct v4l2_subdev *sd = dev_get_drvdata(dev);
|
||||
struct imx258 *imx258 = to_imx258(sd);
|
||||
int ret;
|
||||
|
||||
@ -1201,9 +1228,26 @@ static int imx258_probe(struct i2c_client *client)
|
||||
int ret;
|
||||
u32 val = 0;
|
||||
|
||||
device_property_read_u32(&client->dev, "clock-frequency", &val);
|
||||
if (val != 19200000)
|
||||
imx258 = devm_kzalloc(&client->dev, sizeof(*imx258), GFP_KERNEL);
|
||||
if (!imx258)
|
||||
return -ENOMEM;
|
||||
|
||||
imx258->clk = devm_clk_get_optional(&client->dev, NULL);
|
||||
if (!imx258->clk) {
|
||||
dev_dbg(&client->dev,
|
||||
"no clock provided, using clock-frequency property\n");
|
||||
|
||||
device_property_read_u32(&client->dev, "clock-frequency", &val);
|
||||
if (val != IMX258_INPUT_CLOCK_FREQ)
|
||||
return -EINVAL;
|
||||
} else if (IS_ERR(imx258->clk)) {
|
||||
return dev_err_probe(&client->dev, PTR_ERR(imx258->clk),
|
||||
"error getting clock\n");
|
||||
}
|
||||
if (clk_get_rate(imx258->clk) != IMX258_INPUT_CLOCK_FREQ) {
|
||||
dev_err(&client->dev, "input clock frequency not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that the device is mounted upside down. The driver only
|
||||
@ -1213,24 +1257,25 @@ static int imx258_probe(struct i2c_client *client)
|
||||
if (ret || val != 180)
|
||||
return -EINVAL;
|
||||
|
||||
imx258 = devm_kzalloc(&client->dev, sizeof(*imx258), GFP_KERNEL);
|
||||
if (!imx258)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Initialize subdev */
|
||||
v4l2_i2c_subdev_init(&imx258->sd, client, &imx258_subdev_ops);
|
||||
|
||||
/* Will be powered off via pm_runtime_idle */
|
||||
ret = imx258_power_on(&client->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Check module identity */
|
||||
ret = imx258_identify_module(imx258);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto error_identify;
|
||||
|
||||
/* Set default mode to max resolution */
|
||||
imx258->cur_mode = &supported_modes[0];
|
||||
|
||||
ret = imx258_init_controls(imx258);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto error_identify;
|
||||
|
||||
/* Initialize subdev */
|
||||
imx258->sd.internal_ops = &imx258_internal_ops;
|
||||
@ -1260,6 +1305,9 @@ error_media_entity:
|
||||
error_handler_free:
|
||||
imx258_free_controls(imx258);
|
||||
|
||||
error_identify:
|
||||
imx258_power_off(&client->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1273,6 +1321,8 @@ static int imx258_remove(struct i2c_client *client)
|
||||
imx258_free_controls(imx258);
|
||||
|
||||
pm_runtime_disable(&client->dev);
|
||||
if (!pm_runtime_status_suspended(&client->dev))
|
||||
imx258_power_off(&client->dev);
|
||||
pm_runtime_set_suspended(&client->dev);
|
||||
|
||||
return 0;
|
||||
@ -1280,6 +1330,7 @@ static int imx258_remove(struct i2c_client *client)
|
||||
|
||||
static const struct dev_pm_ops imx258_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(imx258_suspend, imx258_resume)
|
||||
SET_RUNTIME_PM_OPS(imx258_power_off, imx258_power_on, NULL)
|
||||
};
|
||||
|
||||
#ifdef CONFIG_ACPI
|
||||
@ -1291,11 +1342,18 @@ static const struct acpi_device_id imx258_acpi_ids[] = {
|
||||
MODULE_DEVICE_TABLE(acpi, imx258_acpi_ids);
|
||||
#endif
|
||||
|
||||
static const struct of_device_id imx258_dt_ids[] = {
|
||||
{ .compatible = "sony,imx258" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, imx258_dt_ids);
|
||||
|
||||
static struct i2c_driver imx258_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "imx258",
|
||||
.pm = &imx258_pm_ops,
|
||||
.acpi_match_table = ACPI_PTR(imx258_acpi_ids),
|
||||
.of_match_table = imx258_dt_ids,
|
||||
},
|
||||
.probe_new = imx258_probe,
|
||||
.remove = imx258_remove,
|
||||
|
1132
drivers/media/i2c/imx334.c
Normal file
1132
drivers/media/i2c/imx334.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,7 @@
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "max9271.h"
|
||||
|
||||
@ -339,3 +340,7 @@ int max9271_set_translation(struct max9271_device *dev, u8 source, u8 dest)
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(max9271_set_translation);
|
||||
|
||||
MODULE_DESCRIPTION("Maxim MAX9271 GMSL Serializer");
|
||||
MODULE_AUTHOR("Jacopo Mondi");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
@ -163,6 +163,8 @@ struct max9286_priv {
|
||||
unsigned int mux_channel;
|
||||
bool mux_open;
|
||||
|
||||
u32 reverse_channel_mv;
|
||||
|
||||
struct v4l2_ctrl_handler ctrls;
|
||||
struct v4l2_ctrl *pixelrate;
|
||||
|
||||
@ -336,6 +338,31 @@ static void max9286_configure_i2c(struct max9286_priv *priv, bool localack)
|
||||
usleep_range(3000, 5000);
|
||||
}
|
||||
|
||||
static void max9286_reverse_channel_setup(struct max9286_priv *priv,
|
||||
unsigned int chan_amplitude)
|
||||
{
|
||||
/* Reverse channel transmission time: default to 1. */
|
||||
u8 chan_config = MAX9286_REV_TRF(1);
|
||||
|
||||
/*
|
||||
* Reverse channel setup.
|
||||
*
|
||||
* - Enable custom reverse channel configuration (through register 0x3f)
|
||||
* and set the first pulse length to 35 clock cycles.
|
||||
* - Adjust reverse channel amplitude: values > 130 are programmed
|
||||
* using the additional +100mV REV_AMP_X boost flag
|
||||
*/
|
||||
max9286_write(priv, 0x3f, MAX9286_EN_REV_CFG | MAX9286_REV_FLEN(35));
|
||||
|
||||
if (chan_amplitude > 100) {
|
||||
/* It is not possible to express values (100 < x < 130) */
|
||||
chan_amplitude = max(30U, chan_amplitude - 100);
|
||||
chan_config |= MAX9286_REV_AMP_X;
|
||||
}
|
||||
max9286_write(priv, 0x3b, chan_config | MAX9286_REV_AMP(chan_amplitude));
|
||||
usleep_range(2000, 2500);
|
||||
}
|
||||
|
||||
/*
|
||||
* max9286_check_video_links() - Make sure video links are detected and locked
|
||||
*
|
||||
@ -531,10 +558,14 @@ static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
|
||||
* All enabled sources have probed and enabled their reverse control
|
||||
* channels:
|
||||
*
|
||||
* - Increase the reverse channel amplitude to compensate for the
|
||||
* remote ends high threshold, if not done already
|
||||
* - Verify all configuration links are properly detected
|
||||
* - Disable auto-ack as communication on the control channel are now
|
||||
* stable.
|
||||
*/
|
||||
if (priv->reverse_channel_mv < 170)
|
||||
max9286_reverse_channel_setup(priv, 170);
|
||||
max9286_check_config_link(priv, priv->source_mask);
|
||||
|
||||
/*
|
||||
@ -576,19 +607,19 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
|
||||
|
||||
for_each_source(priv, source) {
|
||||
unsigned int i = to_index(priv, source);
|
||||
struct v4l2_async_subdev *asd;
|
||||
struct max9286_asd *mas;
|
||||
|
||||
asd = v4l2_async_notifier_add_fwnode_subdev(&priv->notifier,
|
||||
mas = v4l2_async_notifier_add_fwnode_subdev(&priv->notifier,
|
||||
source->fwnode,
|
||||
sizeof(*asd));
|
||||
if (IS_ERR(asd)) {
|
||||
struct max9286_asd);
|
||||
if (IS_ERR(mas)) {
|
||||
dev_err(dev, "Failed to add subdev for source %u: %ld",
|
||||
i, PTR_ERR(asd));
|
||||
i, PTR_ERR(mas));
|
||||
v4l2_async_notifier_cleanup(&priv->notifier);
|
||||
return PTR_ERR(asd);
|
||||
return PTR_ERR(mas);
|
||||
}
|
||||
|
||||
to_max9286_asd(asd)->source = source;
|
||||
mas->source = source;
|
||||
}
|
||||
|
||||
priv->notifier.ops = &max9286_notify_ops;
|
||||
@ -941,19 +972,7 @@ static int max9286_setup(struct max9286_priv *priv)
|
||||
* only. This should be disabled after the mux is initialised.
|
||||
*/
|
||||
max9286_configure_i2c(priv, true);
|
||||
|
||||
/*
|
||||
* Reverse channel setup.
|
||||
*
|
||||
* - Enable custom reverse channel configuration (through register 0x3f)
|
||||
* and set the first pulse length to 35 clock cycles.
|
||||
* - Increase the reverse channel amplitude to 170mV to accommodate the
|
||||
* high threshold enabled by the serializer driver.
|
||||
*/
|
||||
max9286_write(priv, 0x3f, MAX9286_EN_REV_CFG | MAX9286_REV_FLEN(35));
|
||||
max9286_write(priv, 0x3b, MAX9286_REV_TRF(1) | MAX9286_REV_AMP(70) |
|
||||
MAX9286_REV_AMP_X);
|
||||
usleep_range(2000, 2500);
|
||||
max9286_reverse_channel_setup(priv, priv->reverse_channel_mv);
|
||||
|
||||
/*
|
||||
* Enable GMSL links, mask unused ones and autodetect link
|
||||
@ -1117,6 +1136,7 @@ static int max9286_parse_dt(struct max9286_priv *priv)
|
||||
struct device_node *i2c_mux;
|
||||
struct device_node *node = NULL;
|
||||
unsigned int i2c_mux_mask = 0;
|
||||
u32 reverse_channel_microvolt;
|
||||
|
||||
/* Balance the of_node_put() performed by of_find_node_by_name(). */
|
||||
of_node_get(dev->of_node);
|
||||
@ -1207,6 +1227,20 @@ static int max9286_parse_dt(struct max9286_priv *priv)
|
||||
}
|
||||
of_node_put(node);
|
||||
|
||||
/*
|
||||
* Parse the initial value of the reverse channel amplitude from
|
||||
* the firmware interface and convert it to millivolts.
|
||||
*
|
||||
* Default it to 170mV for backward compatibility with DTBs that do not
|
||||
* provide the property.
|
||||
*/
|
||||
if (of_property_read_u32(dev->of_node,
|
||||
"maxim,reverse-channel-microvolt",
|
||||
&reverse_channel_microvolt))
|
||||
priv->reverse_channel_mv = 170;
|
||||
else
|
||||
priv->reverse_channel_mv = reverse_channel_microvolt / 1000U;
|
||||
|
||||
priv->route_mask = priv->source_mask;
|
||||
|
||||
return 0;
|
||||
|
@ -4,6 +4,7 @@
|
||||
*
|
||||
* Copyright (C) 2008, Robert Jarzmik <robert.jarzmik@free.fr>
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/videodev2.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/i2c.h>
|
||||
@ -16,7 +17,6 @@
|
||||
#include <linux/property.h>
|
||||
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-clk.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
@ -232,7 +232,7 @@ struct mt9m111 {
|
||||
struct v4l2_ctrl *gain;
|
||||
struct mt9m111_context *ctx;
|
||||
struct v4l2_rect rect; /* cropping rectangle */
|
||||
struct v4l2_clk *clk;
|
||||
struct clk *clk;
|
||||
unsigned int width; /* output */
|
||||
unsigned int height; /* sizes */
|
||||
struct v4l2_fract frame_interval;
|
||||
@ -977,7 +977,7 @@ static int mt9m111_power_on(struct mt9m111 *mt9m111)
|
||||
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
|
||||
int ret;
|
||||
|
||||
ret = v4l2_clk_enable(mt9m111->clk);
|
||||
ret = clk_prepare_enable(mt9m111->clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -995,7 +995,7 @@ out_regulator_disable:
|
||||
regulator_disable(mt9m111->regulator);
|
||||
|
||||
out_clk_disable:
|
||||
v4l2_clk_disable(mt9m111->clk);
|
||||
clk_disable_unprepare(mt9m111->clk);
|
||||
|
||||
dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret);
|
||||
|
||||
@ -1006,7 +1006,7 @@ static void mt9m111_power_off(struct mt9m111 *mt9m111)
|
||||
{
|
||||
mt9m111_suspend(mt9m111);
|
||||
regulator_disable(mt9m111->regulator);
|
||||
v4l2_clk_disable(mt9m111->clk);
|
||||
clk_disable_unprepare(mt9m111->clk);
|
||||
}
|
||||
|
||||
static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
|
||||
@ -1266,7 +1266,7 @@ static int mt9m111_probe(struct i2c_client *client)
|
||||
return ret;
|
||||
}
|
||||
|
||||
mt9m111->clk = v4l2_clk_get(&client->dev, "mclk");
|
||||
mt9m111->clk = devm_clk_get(&client->dev, "mclk");
|
||||
if (IS_ERR(mt9m111->clk))
|
||||
return PTR_ERR(mt9m111->clk);
|
||||
|
||||
@ -1311,7 +1311,7 @@ static int mt9m111_probe(struct i2c_client *client)
|
||||
mt9m111->subdev.ctrl_handler = &mt9m111->hdl;
|
||||
if (mt9m111->hdl.error) {
|
||||
ret = mt9m111->hdl.error;
|
||||
goto out_clkput;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEDIA_CONTROLLER
|
||||
@ -1354,8 +1354,6 @@ out_entityclean:
|
||||
out_hdlfree:
|
||||
#endif
|
||||
v4l2_ctrl_handler_free(&mt9m111->hdl);
|
||||
out_clkput:
|
||||
v4l2_clk_put(mt9m111->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -1366,7 +1364,6 @@ static int mt9m111_remove(struct i2c_client *client)
|
||||
|
||||
v4l2_async_unregister_subdev(&mt9m111->subdev);
|
||||
media_entity_cleanup(&mt9m111->subdev.entity);
|
||||
v4l2_clk_put(mt9m111->clk);
|
||||
v4l2_ctrl_handler_free(&mt9m111->hdl);
|
||||
|
||||
return 0;
|
||||
|
@ -1253,12 +1253,6 @@ static int mt9v111_remove(struct i2c_client *client)
|
||||
mutex_destroy(&mt9v111->pwr_mutex);
|
||||
mutex_destroy(&mt9v111->stream_mutex);
|
||||
|
||||
devm_gpiod_put(mt9v111->dev, mt9v111->oe);
|
||||
devm_gpiod_put(mt9v111->dev, mt9v111->standby);
|
||||
devm_gpiod_put(mt9v111->dev, mt9v111->reset);
|
||||
|
||||
devm_clk_put(mt9v111->dev, mt9v111->clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,7 @@ static int ov02a10_check_sensor_id(struct ov02a10 *ov02a10)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
chip_id = le16_to_cpu(ret);
|
||||
chip_id = le16_to_cpu((__force __le16)ret);
|
||||
|
||||
if ((chip_id & OV02A10_ID_MASK) != OV02A10_ID) {
|
||||
dev_err(&client->dev, "unexpected sensor id(0x%04x)\n", chip_id);
|
||||
|
File diff suppressed because it is too large
Load Diff
2624
drivers/media/i2c/ov5648.c
Normal file
2624
drivers/media/i2c/ov5648.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -2084,7 +2084,8 @@ static int ov5670_init_controls(struct ov5670 *ov5670)
|
||||
|
||||
/* By default, V4L2_CID_PIXEL_RATE is read only */
|
||||
ov5670->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &ov5670_ctrl_ops,
|
||||
V4L2_CID_PIXEL_RATE, 0,
|
||||
V4L2_CID_PIXEL_RATE,
|
||||
link_freq_configs[0].pixel_rate,
|
||||
link_freq_configs[0].pixel_rate,
|
||||
1,
|
||||
link_freq_configs[0].pixel_rate);
|
||||
|
@ -624,7 +624,7 @@ static int ov5675_set_ctrl_hflip(struct ov5675 *ov5675, u32 ctrl_val)
|
||||
|
||||
return ov5675_write_reg(ov5675, OV5675_REG_FORMAT1,
|
||||
OV5675_REG_VALUE_08BIT,
|
||||
ctrl_val ? val & ~BIT(3) : val);
|
||||
ctrl_val ? val & ~BIT(3) : val | BIT(3));
|
||||
}
|
||||
|
||||
static int ov5675_set_ctrl_vflip(struct ov5675 *ov5675, u8 ctrl_val)
|
||||
@ -639,7 +639,7 @@ static int ov5675_set_ctrl_vflip(struct ov5675 *ov5675, u8 ctrl_val)
|
||||
|
||||
ret = ov5675_write_reg(ov5675, OV5675_REG_FORMAT1,
|
||||
OV5675_REG_VALUE_08BIT,
|
||||
ctrl_val ? val | BIT(4) | BIT(5) : val);
|
||||
ctrl_val ? val | BIT(4) | BIT(5) : val & ~BIT(4) & ~BIT(5));
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -652,7 +652,7 @@ static int ov5675_set_ctrl_vflip(struct ov5675 *ov5675, u8 ctrl_val)
|
||||
|
||||
return ov5675_write_reg(ov5675, OV5675_REG_FORMAT2,
|
||||
OV5675_REG_VALUE_08BIT,
|
||||
ctrl_val ? val | BIT(1) : val);
|
||||
ctrl_val ? val | BIT(1) : val & ~BIT(1));
|
||||
}
|
||||
|
||||
static int ov5675_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
|
@ -22,13 +22,13 @@
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/v4l2-mediabus.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
#include <media/v4l2-clk.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
|
||||
@ -194,7 +194,7 @@ struct ov6650 {
|
||||
struct v4l2_ctrl *blue;
|
||||
struct v4l2_ctrl *red;
|
||||
};
|
||||
struct v4l2_clk *clk;
|
||||
struct clk *clk;
|
||||
bool half_scale; /* scale down output by 2 */
|
||||
struct v4l2_rect rect; /* sensor cropping window */
|
||||
struct v4l2_fract tpf; /* as requested with s_frame_interval */
|
||||
@ -459,9 +459,9 @@ static int ov6650_s_power(struct v4l2_subdev *sd, int on)
|
||||
int ret = 0;
|
||||
|
||||
if (on)
|
||||
ret = v4l2_clk_enable(priv->clk);
|
||||
ret = clk_prepare_enable(priv->clk);
|
||||
else
|
||||
v4l2_clk_disable(priv->clk);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -821,14 +821,14 @@ static int ov6650_video_probe(struct v4l2_subdev *sd)
|
||||
u8 pidh, pidl, midh, midl;
|
||||
int i, ret = 0;
|
||||
|
||||
priv->clk = v4l2_clk_get(&client->dev, NULL);
|
||||
priv->clk = devm_clk_get(&client->dev, NULL);
|
||||
if (IS_ERR(priv->clk)) {
|
||||
ret = PTR_ERR(priv->clk);
|
||||
dev_err(&client->dev, "v4l2_clk request err: %d\n", ret);
|
||||
dev_err(&client->dev, "clk request err: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
rate = v4l2_clk_get_rate(priv->clk);
|
||||
rate = clk_get_rate(priv->clk);
|
||||
for (i = 0; rate && i < ARRAY_SIZE(ov6650_xclk); i++) {
|
||||
if (rate != ov6650_xclk[i].rate)
|
||||
continue;
|
||||
@ -839,8 +839,8 @@ static int ov6650_video_probe(struct v4l2_subdev *sd)
|
||||
break;
|
||||
}
|
||||
for (i = 0; !xclk && i < ARRAY_SIZE(ov6650_xclk); i++) {
|
||||
ret = v4l2_clk_set_rate(priv->clk, ov6650_xclk[i].rate);
|
||||
if (ret || v4l2_clk_get_rate(priv->clk) != ov6650_xclk[i].rate)
|
||||
ret = clk_set_rate(priv->clk, ov6650_xclk[i].rate);
|
||||
if (ret || clk_get_rate(priv->clk) != ov6650_xclk[i].rate)
|
||||
continue;
|
||||
|
||||
xclk = &ov6650_xclk[i];
|
||||
@ -852,12 +852,12 @@ static int ov6650_video_probe(struct v4l2_subdev *sd)
|
||||
dev_err(&client->dev, "unable to get supported clock rate\n");
|
||||
if (!ret)
|
||||
ret = -EINVAL;
|
||||
goto eclkput;
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ov6650_s_power(sd, 1);
|
||||
if (ret < 0)
|
||||
goto eclkput;
|
||||
return ret;
|
||||
|
||||
msleep(20);
|
||||
|
||||
@ -899,11 +899,6 @@ static int ov6650_video_probe(struct v4l2_subdev *sd)
|
||||
|
||||
done:
|
||||
ov6650_s_power(sd, 0);
|
||||
if (!ret)
|
||||
return 0;
|
||||
eclkput:
|
||||
v4l2_clk_put(priv->clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -1089,7 +1084,6 @@ static int ov6650_remove(struct i2c_client *client)
|
||||
{
|
||||
struct ov6650 *priv = to_ov6650(client);
|
||||
|
||||
v4l2_clk_put(priv->clk);
|
||||
v4l2_async_unregister_subdev(&priv->subdev);
|
||||
v4l2_ctrl_handler_free(&priv->hdl);
|
||||
return 0;
|
||||
|
@ -428,7 +428,7 @@ static const struct ov8856_reg mode_3264x2448_regs[] = {
|
||||
{0x3810, 0x00},
|
||||
{0x3811, 0x04},
|
||||
{0x3812, 0x00},
|
||||
{0x3813, 0x02},
|
||||
{0x3813, 0x01},
|
||||
{0x3814, 0x01},
|
||||
{0x3815, 0x01},
|
||||
{0x3816, 0x00},
|
||||
@ -821,7 +821,7 @@ static const struct ov8856_reg mode_1632x1224_regs[] = {
|
||||
{0x3810, 0x00},
|
||||
{0x3811, 0x02},
|
||||
{0x3812, 0x00},
|
||||
{0x3813, 0x02},
|
||||
{0x3813, 0x01},
|
||||
{0x3814, 0x03},
|
||||
{0x3815, 0x01},
|
||||
{0x3816, 0x00},
|
||||
|
2972
drivers/media/i2c/ov8865.c
Normal file
2972
drivers/media/i2c/ov8865.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -17,6 +17,7 @@
|
||||
* Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
|
||||
*/
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
@ -26,7 +27,6 @@
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-clk.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
@ -333,13 +333,13 @@ static int ov9640_s_power(struct v4l2_subdev *sd, int on)
|
||||
if (on) {
|
||||
gpiod_set_value(priv->gpio_power, 1);
|
||||
usleep_range(1000, 2000);
|
||||
ret = v4l2_clk_enable(priv->clk);
|
||||
ret = clk_prepare_enable(priv->clk);
|
||||
usleep_range(1000, 2000);
|
||||
gpiod_set_value(priv->gpio_reset, 0);
|
||||
} else {
|
||||
gpiod_set_value(priv->gpio_reset, 1);
|
||||
usleep_range(1000, 2000);
|
||||
v4l2_clk_disable(priv->clk);
|
||||
clk_disable_unprepare(priv->clk);
|
||||
usleep_range(1000, 2000);
|
||||
gpiod_set_value(priv->gpio_power, 0);
|
||||
}
|
||||
@ -719,7 +719,7 @@ static int ov9640_probe(struct i2c_client *client,
|
||||
|
||||
priv->subdev.ctrl_handler = &priv->hdl;
|
||||
|
||||
priv->clk = v4l2_clk_get(&client->dev, "mclk");
|
||||
priv->clk = devm_clk_get(&client->dev, "mclk");
|
||||
if (IS_ERR(priv->clk)) {
|
||||
ret = PTR_ERR(priv->clk);
|
||||
goto ectrlinit;
|
||||
@ -727,17 +727,15 @@ static int ov9640_probe(struct i2c_client *client,
|
||||
|
||||
ret = ov9640_video_probe(client);
|
||||
if (ret)
|
||||
goto eprobe;
|
||||
goto ectrlinit;
|
||||
|
||||
priv->subdev.dev = &client->dev;
|
||||
ret = v4l2_async_register_subdev(&priv->subdev);
|
||||
if (ret)
|
||||
goto eprobe;
|
||||
goto ectrlinit;
|
||||
|
||||
return 0;
|
||||
|
||||
eprobe:
|
||||
v4l2_clk_put(priv->clk);
|
||||
ectrlinit:
|
||||
v4l2_ctrl_handler_free(&priv->hdl);
|
||||
|
||||
@ -749,7 +747,6 @@ static int ov9640_remove(struct i2c_client *client)
|
||||
struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
struct ov9640_priv *priv = to_ov9640_sensor(sd);
|
||||
|
||||
v4l2_clk_put(priv->clk);
|
||||
v4l2_async_unregister_subdev(&priv->subdev);
|
||||
v4l2_ctrl_handler_free(&priv->hdl);
|
||||
|
||||
|
@ -196,7 +196,7 @@ struct ov9640_reg {
|
||||
struct ov9640_priv {
|
||||
struct v4l2_subdev subdev;
|
||||
struct v4l2_ctrl_handler hdl;
|
||||
struct v4l2_clk *clk;
|
||||
struct clk *clk;
|
||||
struct gpio_desc *gpio_power;
|
||||
struct gpio_desc *gpio_reset;
|
||||
|
||||
|
@ -435,7 +435,7 @@ static int rdacm20_get_fmt(struct v4l2_subdev *sd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct v4l2_subdev_video_ops rdacm20_video_ops = {
|
||||
static const struct v4l2_subdev_video_ops rdacm20_video_ops = {
|
||||
.s_stream = rdacm20_s_stream,
|
||||
};
|
||||
|
||||
@ -445,7 +445,7 @@ static const struct v4l2_subdev_pad_ops rdacm20_subdev_pad_ops = {
|
||||
.set_fmt = rdacm20_get_fmt,
|
||||
};
|
||||
|
||||
static struct v4l2_subdev_ops rdacm20_subdev_ops = {
|
||||
static const struct v4l2_subdev_ops rdacm20_subdev_ops = {
|
||||
.video = &rdacm20_video_ops,
|
||||
.pad = &rdacm20_subdev_pad_ops,
|
||||
};
|
||||
|
623
drivers/media/i2c/rdacm21.c
Normal file
623
drivers/media/i2c/rdacm21.c
Normal file
@ -0,0 +1,623 @@
|
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* IMI RDACM21 GMSL Camera Driver
|
||||
*
|
||||
* Copyright (C) 2017-2020 Jacopo Mondi
|
||||
* Copyright (C) 2017-2019 Kieran Bingham
|
||||
* Copyright (C) 2017-2019 Laurent Pinchart
|
||||
* Copyright (C) 2017-2019 Niklas Söderlund
|
||||
* Copyright (C) 2016 Renesas Electronics Corporation
|
||||
* Copyright (C) 2015 Cogent Embedded, Inc.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/fwnode.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include <media/v4l2-async.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include "max9271.h"
|
||||
|
||||
#define MAX9271_RESET_CYCLES 10
|
||||
|
||||
#define OV490_I2C_ADDRESS 0x24
|
||||
|
||||
#define OV490_PAGE_HIGH_REG 0xfffd
|
||||
#define OV490_PAGE_LOW_REG 0xfffe
|
||||
|
||||
/*
|
||||
* The SCCB slave handling is undocumented; the registers naming scheme is
|
||||
* totally arbitrary.
|
||||
*/
|
||||
#define OV490_SCCB_SLAVE_WRITE 0x00
|
||||
#define OV490_SCCB_SLAVE_READ 0x01
|
||||
#define OV490_SCCB_SLAVE0_DIR 0x80195000
|
||||
#define OV490_SCCB_SLAVE0_ADDR_HIGH 0x80195001
|
||||
#define OV490_SCCB_SLAVE0_ADDR_LOW 0x80195002
|
||||
|
||||
#define OV490_DVP_CTRL3 0x80286009
|
||||
|
||||
#define OV490_ODS_CTRL_FRAME_OUTPUT_EN 0x0c
|
||||
#define OV490_ODS_CTRL 0x8029d000
|
||||
|
||||
#define OV490_HOST_CMD 0x808000c0
|
||||
#define OV490_HOST_CMD_TRIGGER 0xc1
|
||||
|
||||
#define OV490_ID_VAL 0x0490
|
||||
#define OV490_ID(_p, _v) ((((_p) & 0xff) << 8) | ((_v) & 0xff))
|
||||
#define OV490_PID 0x8080300a
|
||||
#define OV490_VER 0x8080300b
|
||||
#define OV490_PID_TIMEOUT 20
|
||||
#define OV490_OUTPUT_EN_TIMEOUT 300
|
||||
|
||||
#define OV490_GPIO0 BIT(0)
|
||||
#define OV490_SPWDN0 BIT(0)
|
||||
#define OV490_GPIO_SEL0 0x80800050
|
||||
#define OV490_GPIO_SEL1 0x80800051
|
||||
#define OV490_GPIO_DIRECTION0 0x80800054
|
||||
#define OV490_GPIO_DIRECTION1 0x80800055
|
||||
#define OV490_GPIO_OUTPUT_VALUE0 0x80800058
|
||||
#define OV490_GPIO_OUTPUT_VALUE1 0x80800059
|
||||
|
||||
#define OV490_ISP_HSIZE_LOW 0x80820060
|
||||
#define OV490_ISP_HSIZE_HIGH 0x80820061
|
||||
#define OV490_ISP_VSIZE_LOW 0x80820062
|
||||
#define OV490_ISP_VSIZE_HIGH 0x80820063
|
||||
|
||||
#define OV10640_ID_HIGH 0xa6
|
||||
#define OV10640_CHIP_ID 0x300a
|
||||
#define OV10640_PIXEL_RATE 55000000
|
||||
|
||||
struct rdacm21_device {
|
||||
struct device *dev;
|
||||
struct max9271_device serializer;
|
||||
struct i2c_client *isp;
|
||||
struct v4l2_subdev sd;
|
||||
struct media_pad pad;
|
||||
struct v4l2_mbus_framefmt fmt;
|
||||
struct v4l2_ctrl_handler ctrls;
|
||||
u32 addrs[2];
|
||||
u16 last_page;
|
||||
};
|
||||
|
||||
static inline struct rdacm21_device *sd_to_rdacm21(struct v4l2_subdev *sd)
|
||||
{
|
||||
return container_of(sd, struct rdacm21_device, sd);
|
||||
}
|
||||
|
||||
static const struct ov490_reg {
|
||||
u16 reg;
|
||||
u8 val;
|
||||
} ov490_regs_wizard[] = {
|
||||
{0xfffd, 0x80},
|
||||
{0xfffe, 0x82},
|
||||
{0x0071, 0x11},
|
||||
{0x0075, 0x11},
|
||||
{0xfffe, 0x29},
|
||||
{0x6010, 0x01},
|
||||
/*
|
||||
* OV490 EMB line disable in YUV and RAW data,
|
||||
* NOTE: EMB line is still used in ISP and sensor
|
||||
*/
|
||||
{0xe000, 0x14},
|
||||
{0xfffe, 0x28},
|
||||
{0x6000, 0x04},
|
||||
{0x6004, 0x00},
|
||||
/*
|
||||
* PCLK polarity - useless due to silicon bug.
|
||||
* Use 0x808000bb register instead.
|
||||
*/
|
||||
{0x6008, 0x00},
|
||||
{0xfffe, 0x80},
|
||||
{0x0091, 0x00},
|
||||
/* bit[3]=0 - PCLK polarity workaround. */
|
||||
{0x00bb, 0x1d},
|
||||
/* Ov490 FSIN: app_fsin_from_fsync */
|
||||
{0xfffe, 0x85},
|
||||
{0x0008, 0x00},
|
||||
{0x0009, 0x01},
|
||||
/* FSIN0 source. */
|
||||
{0x000A, 0x05},
|
||||
{0x000B, 0x00},
|
||||
/* FSIN0 delay. */
|
||||
{0x0030, 0x02},
|
||||
{0x0031, 0x00},
|
||||
{0x0032, 0x00},
|
||||
{0x0033, 0x00},
|
||||
/* FSIN1 delay. */
|
||||
{0x0038, 0x02},
|
||||
{0x0039, 0x00},
|
||||
{0x003A, 0x00},
|
||||
{0x003B, 0x00},
|
||||
/* FSIN0 length. */
|
||||
{0x0070, 0x2C},
|
||||
{0x0071, 0x01},
|
||||
{0x0072, 0x00},
|
||||
{0x0073, 0x00},
|
||||
/* FSIN1 length. */
|
||||
{0x0074, 0x64},
|
||||
{0x0075, 0x00},
|
||||
{0x0076, 0x00},
|
||||
{0x0077, 0x00},
|
||||
{0x0000, 0x14},
|
||||
{0x0001, 0x00},
|
||||
{0x0002, 0x00},
|
||||
{0x0003, 0x00},
|
||||
/*
|
||||
* Load fsin0,load fsin1,load other,
|
||||
* It will be cleared automatically.
|
||||
*/
|
||||
{0x0004, 0x32},
|
||||
{0x0005, 0x00},
|
||||
{0x0006, 0x00},
|
||||
{0x0007, 0x00},
|
||||
{0xfffe, 0x80},
|
||||
/* Sensor FSIN. */
|
||||
{0x0081, 0x00},
|
||||
/* ov10640 FSIN enable */
|
||||
{0xfffe, 0x19},
|
||||
{0x5000, 0x00},
|
||||
{0x5001, 0x30},
|
||||
{0x5002, 0x8c},
|
||||
{0x5003, 0xb2},
|
||||
{0xfffe, 0x80},
|
||||
{0x00c0, 0xc1},
|
||||
/* ov10640 HFLIP=1 by default */
|
||||
{0xfffe, 0x19},
|
||||
{0x5000, 0x01},
|
||||
{0x5001, 0x00},
|
||||
{0xfffe, 0x80},
|
||||
{0x00c0, 0xdc},
|
||||
};
|
||||
|
||||
static int ov490_read(struct rdacm21_device *dev, u16 reg, u8 *val)
|
||||
{
|
||||
u8 buf[2] = { reg >> 8, reg };
|
||||
int ret;
|
||||
|
||||
ret = i2c_master_send(dev->isp, buf, 2);
|
||||
if (ret == 2)
|
||||
ret = i2c_master_recv(dev->isp, val, 1);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_dbg(dev->dev, "%s: register 0x%04x read failed (%d)\n",
|
||||
__func__, reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov490_write(struct rdacm21_device *dev, u16 reg, u8 val)
|
||||
{
|
||||
u8 buf[3] = { reg >> 8, reg, val };
|
||||
int ret;
|
||||
|
||||
ret = i2c_master_send(dev->isp, buf, 3);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "%s: register 0x%04x write failed (%d)\n",
|
||||
__func__, reg, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov490_set_page(struct rdacm21_device *dev, u16 page)
|
||||
{
|
||||
u8 page_high = page >> 8;
|
||||
u8 page_low = page;
|
||||
int ret;
|
||||
|
||||
if (page == dev->last_page)
|
||||
return 0;
|
||||
|
||||
if (page_high != (dev->last_page >> 8)) {
|
||||
ret = ov490_write(dev, OV490_PAGE_HIGH_REG, page_high);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (page_low != (u8)dev->last_page) {
|
||||
ret = ov490_write(dev, OV490_PAGE_LOW_REG, page_low);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev->last_page = page;
|
||||
usleep_range(100, 150);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov490_read_reg(struct rdacm21_device *dev, u32 reg, u8 *val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ov490_set_page(dev, reg >> 16);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov490_read(dev, (u16)reg, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_dbg(dev->dev, "%s: 0x%08x = 0x%02x\n", __func__, reg, *val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov490_write_reg(struct rdacm21_device *dev, u32 reg, u8 val)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ov490_set_page(dev, reg >> 16);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = ov490_write(dev, (u16)reg, val);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev_dbg(dev->dev, "%s: 0x%08x = 0x%02x\n", __func__, reg, val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdacm21_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
{
|
||||
struct rdacm21_device *dev = sd_to_rdacm21(sd);
|
||||
|
||||
/*
|
||||
* Enable serial link now that the ISP provides a valid pixel clock
|
||||
* to start serializing video data on the GMSL link.
|
||||
*/
|
||||
return max9271_set_serial_link(&dev->serializer, enable);
|
||||
}
|
||||
|
||||
static int rdacm21_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_mbus_code_enum *code)
|
||||
{
|
||||
if (code->pad || code->index > 0)
|
||||
return -EINVAL;
|
||||
|
||||
code->code = MEDIA_BUS_FMT_YUYV8_1X16;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdacm21_get_fmt(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_format *format)
|
||||
{
|
||||
struct v4l2_mbus_framefmt *mf = &format->format;
|
||||
struct rdacm21_device *dev = sd_to_rdacm21(sd);
|
||||
|
||||
if (format->pad)
|
||||
return -EINVAL;
|
||||
|
||||
mf->width = dev->fmt.width;
|
||||
mf->height = dev->fmt.height;
|
||||
mf->code = MEDIA_BUS_FMT_YUYV8_1X16;
|
||||
mf->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
mf->field = V4L2_FIELD_NONE;
|
||||
mf->ycbcr_enc = V4L2_YCBCR_ENC_601;
|
||||
mf->quantization = V4L2_QUANTIZATION_FULL_RANGE;
|
||||
mf->xfer_func = V4L2_XFER_FUNC_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_video_ops rdacm21_video_ops = {
|
||||
.s_stream = rdacm21_s_stream,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_pad_ops rdacm21_subdev_pad_ops = {
|
||||
.enum_mbus_code = rdacm21_enum_mbus_code,
|
||||
.get_fmt = rdacm21_get_fmt,
|
||||
.set_fmt = rdacm21_get_fmt,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_ops rdacm21_subdev_ops = {
|
||||
.video = &rdacm21_video_ops,
|
||||
.pad = &rdacm21_subdev_pad_ops,
|
||||
};
|
||||
|
||||
static int ov10640_initialize(struct rdacm21_device *dev)
|
||||
{
|
||||
u8 val;
|
||||
|
||||
/* Power-up OV10640 by setting RESETB and PWDNB pins high. */
|
||||
ov490_write_reg(dev, OV490_GPIO_SEL0, OV490_GPIO0);
|
||||
ov490_write_reg(dev, OV490_GPIO_SEL1, OV490_SPWDN0);
|
||||
ov490_write_reg(dev, OV490_GPIO_DIRECTION0, OV490_GPIO0);
|
||||
ov490_write_reg(dev, OV490_GPIO_DIRECTION1, OV490_SPWDN0);
|
||||
ov490_write_reg(dev, OV490_GPIO_OUTPUT_VALUE0, OV490_GPIO0);
|
||||
ov490_write_reg(dev, OV490_GPIO_OUTPUT_VALUE0, OV490_SPWDN0);
|
||||
usleep_range(3000, 5000);
|
||||
|
||||
/* Read OV10640 ID to test communications. */
|
||||
ov490_write_reg(dev, OV490_SCCB_SLAVE0_DIR, OV490_SCCB_SLAVE_READ);
|
||||
ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_HIGH, OV10640_CHIP_ID >> 8);
|
||||
ov490_write_reg(dev, OV490_SCCB_SLAVE0_ADDR_LOW, (u8)OV10640_CHIP_ID);
|
||||
|
||||
/* Trigger SCCB slave transaction and give it some time to complete. */
|
||||
ov490_write_reg(dev, OV490_HOST_CMD, OV490_HOST_CMD_TRIGGER);
|
||||
usleep_range(1000, 1500);
|
||||
|
||||
ov490_read_reg(dev, OV490_SCCB_SLAVE0_DIR, &val);
|
||||
if (val != OV10640_ID_HIGH) {
|
||||
dev_err(dev->dev, "OV10640 ID mismatch: (0x%02x)\n", val);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev_dbg(dev->dev, "OV10640 ID = 0x%2x\n", val);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ov490_initialize(struct rdacm21_device *dev)
|
||||
{
|
||||
u8 pid, ver, val;
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* Read OV490 Id to test communications. Give it up to 40msec to
|
||||
* exit from reset.
|
||||
*/
|
||||
for (i = 0; i < OV490_PID_TIMEOUT; ++i) {
|
||||
ret = ov490_read_reg(dev, OV490_PID, &pid);
|
||||
if (ret == 0)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
if (i == OV490_PID_TIMEOUT) {
|
||||
dev_err(dev->dev, "OV490 PID read failed (%d)\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ov490_read_reg(dev, OV490_VER, &ver);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (OV490_ID(pid, ver) != OV490_ID_VAL) {
|
||||
dev_err(dev->dev, "OV490 ID mismatch (0x%04x)\n",
|
||||
OV490_ID(pid, ver));
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* Wait for firmware boot by reading streamon status. */
|
||||
for (i = 0; i < OV490_OUTPUT_EN_TIMEOUT; ++i) {
|
||||
ov490_read_reg(dev, OV490_ODS_CTRL, &val);
|
||||
if (val == OV490_ODS_CTRL_FRAME_OUTPUT_EN)
|
||||
break;
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
if (i == OV490_OUTPUT_EN_TIMEOUT) {
|
||||
dev_err(dev->dev, "Timeout waiting for firmware boot\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ret = ov10640_initialize(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Program OV490 with register-value table. */
|
||||
for (i = 0; i < ARRAY_SIZE(ov490_regs_wizard); ++i) {
|
||||
ret = ov490_write(dev, ov490_regs_wizard[i].reg,
|
||||
ov490_regs_wizard[i].val);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev,
|
||||
"%s: register %u (0x%04x) write failed (%d)\n",
|
||||
__func__, i, ov490_regs_wizard[i].reg, ret);
|
||||
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
usleep_range(100, 150);
|
||||
}
|
||||
|
||||
/*
|
||||
* The ISP is programmed with the content of a serial flash memory.
|
||||
* Read the firmware configuration to reflect it through the V4L2 APIs.
|
||||
*/
|
||||
ov490_read_reg(dev, OV490_ISP_HSIZE_HIGH, &val);
|
||||
dev->fmt.width = (val & 0xf) << 8;
|
||||
ov490_read_reg(dev, OV490_ISP_HSIZE_LOW, &val);
|
||||
dev->fmt.width |= (val & 0xff);
|
||||
|
||||
ov490_read_reg(dev, OV490_ISP_VSIZE_HIGH, &val);
|
||||
dev->fmt.height = (val & 0xf) << 8;
|
||||
ov490_read_reg(dev, OV490_ISP_VSIZE_LOW, &val);
|
||||
dev->fmt.height |= val & 0xff;
|
||||
|
||||
/* Set bus width to 12 bits with [0:11] ordering. */
|
||||
ov490_write_reg(dev, OV490_DVP_CTRL3, 0x10);
|
||||
|
||||
dev_info(dev->dev, "Identified RDACM21 camera module\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rdacm21_initialize(struct rdacm21_device *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Verify communication with the MAX9271: ping to wakeup. */
|
||||
dev->serializer.client->addr = MAX9271_DEFAULT_ADDR;
|
||||
i2c_smbus_read_byte(dev->serializer.client);
|
||||
usleep_range(3000, 5000);
|
||||
|
||||
/* Enable reverse channel and disable the serial link. */
|
||||
ret = max9271_set_serial_link(&dev->serializer, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Configure I2C bus at 105Kbps speed and configure GMSL. */
|
||||
ret = max9271_configure_i2c(&dev->serializer,
|
||||
MAX9271_I2CSLVSH_469NS_234NS |
|
||||
MAX9271_I2CSLVTO_1024US |
|
||||
MAX9271_I2CMSTBT_105KBPS);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = max9271_verify_id(&dev->serializer);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Enable GPIO1 and hold OV490 in reset during max9271 configuration. */
|
||||
ret = max9271_enable_gpios(&dev->serializer, MAX9271_GPIO1OUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = max9271_clear_gpios(&dev->serializer, MAX9271_GPIO1OUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = max9271_configure_gmsl_link(&dev->serializer);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = max9271_set_address(&dev->serializer, dev->addrs[0]);
|
||||
if (ret)
|
||||
return ret;
|
||||
dev->serializer.client->addr = dev->addrs[0];
|
||||
|
||||
ret = max9271_set_translation(&dev->serializer, dev->addrs[1],
|
||||
OV490_I2C_ADDRESS);
|
||||
if (ret)
|
||||
return ret;
|
||||
dev->isp->addr = dev->addrs[1];
|
||||
|
||||
/* Release OV490 from reset and initialize it. */
|
||||
ret = max9271_set_gpios(&dev->serializer, MAX9271_GPIO1OUT);
|
||||
if (ret)
|
||||
return ret;
|
||||
usleep_range(3000, 5000);
|
||||
|
||||
ret = ov490_initialize(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* Set reverse channel high threshold to increase noise immunity.
|
||||
*
|
||||
* This should be compensated by increasing the reverse channel
|
||||
* amplitude on the remote deserializer side.
|
||||
*/
|
||||
return max9271_set_high_threshold(&dev->serializer, true);
|
||||
}
|
||||
|
||||
static int rdacm21_probe(struct i2c_client *client)
|
||||
{
|
||||
struct rdacm21_device *dev;
|
||||
struct fwnode_handle *ep;
|
||||
int ret;
|
||||
|
||||
dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
dev->dev = &client->dev;
|
||||
dev->serializer.client = client;
|
||||
|
||||
ret = of_property_read_u32_array(client->dev.of_node, "reg",
|
||||
dev->addrs, 2);
|
||||
if (ret < 0) {
|
||||
dev_err(dev->dev, "Invalid DT reg property: %d\n", ret);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Create the dummy I2C client for the sensor. */
|
||||
dev->isp = i2c_new_dummy_device(client->adapter, OV490_I2C_ADDRESS);
|
||||
if (IS_ERR(dev->isp))
|
||||
return PTR_ERR(dev->isp);
|
||||
|
||||
ret = rdacm21_initialize(dev);
|
||||
if (ret < 0)
|
||||
goto error;
|
||||
|
||||
/* Initialize and register the subdevice. */
|
||||
v4l2_i2c_subdev_init(&dev->sd, client, &rdacm21_subdev_ops);
|
||||
dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
|
||||
v4l2_ctrl_handler_init(&dev->ctrls, 1);
|
||||
v4l2_ctrl_new_std(&dev->ctrls, NULL, V4L2_CID_PIXEL_RATE,
|
||||
OV10640_PIXEL_RATE, OV10640_PIXEL_RATE, 1,
|
||||
OV10640_PIXEL_RATE);
|
||||
dev->sd.ctrl_handler = &dev->ctrls;
|
||||
|
||||
ret = dev->ctrls.error;
|
||||
if (ret)
|
||||
goto error_free_ctrls;
|
||||
|
||||
dev->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
dev->sd.entity.flags |= MEDIA_ENT_F_CAM_SENSOR;
|
||||
ret = media_entity_pads_init(&dev->sd.entity, 1, &dev->pad);
|
||||
if (ret < 0)
|
||||
goto error_free_ctrls;
|
||||
|
||||
ep = fwnode_graph_get_next_endpoint(dev_fwnode(&client->dev), NULL);
|
||||
if (!ep) {
|
||||
dev_err(&client->dev,
|
||||
"Unable to get endpoint in node %pOF\n",
|
||||
client->dev.of_node);
|
||||
ret = -ENOENT;
|
||||
goto error_free_ctrls;
|
||||
}
|
||||
dev->sd.fwnode = ep;
|
||||
|
||||
ret = v4l2_async_register_subdev(&dev->sd);
|
||||
if (ret)
|
||||
goto error_put_node;
|
||||
|
||||
return 0;
|
||||
|
||||
error_put_node:
|
||||
fwnode_handle_put(dev->sd.fwnode);
|
||||
error_free_ctrls:
|
||||
v4l2_ctrl_handler_free(&dev->ctrls);
|
||||
error:
|
||||
i2c_unregister_device(dev->isp);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rdacm21_remove(struct i2c_client *client)
|
||||
{
|
||||
struct rdacm21_device *dev = sd_to_rdacm21(i2c_get_clientdata(client));
|
||||
|
||||
v4l2_async_unregister_subdev(&dev->sd);
|
||||
v4l2_ctrl_handler_free(&dev->ctrls);
|
||||
i2c_unregister_device(dev->isp);
|
||||
fwnode_handle_put(dev->sd.fwnode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id rdacm21_of_ids[] = {
|
||||
{ .compatible = "imi,rdacm21" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, rdacm21_of_ids);
|
||||
|
||||
static struct i2c_driver rdacm21_i2c_driver = {
|
||||
.driver = {
|
||||
.name = "rdacm21",
|
||||
.of_match_table = rdacm21_of_ids,
|
||||
},
|
||||
.probe_new = rdacm21_probe,
|
||||
.remove = rdacm21_remove,
|
||||
};
|
||||
|
||||
module_i2c_driver(rdacm21_i2c_driver);
|
||||
|
||||
MODULE_DESCRIPTION("GMSL Camera driver for RDACM21");
|
||||
MODULE_AUTHOR("Jacopo Mondi");
|
||||
MODULE_LICENSE("GPL v2");
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user