1
0
Fork 0

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
  ...
master
Linus Torvalds 2021-02-21 14:10:36 -08:00
commit de16175788
292 changed files with 22233 additions and 5319 deletions

View File

@ -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)

View 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";
};
};
...

View File

@ -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"
};

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View 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>;
};
};
};
};

View File

@ -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>;

View File

@ -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

View File

@ -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:
};
};
...

View File

@ -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

View File

@ -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

View File

@ -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

View 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>;
};
};
};
};

View File

@ -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:

View 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 = <&reg_ov8865_avdd>;
dovdd-supply = <&reg_ov8865_dovdd>;
dvdd-supply = <&reg_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>;
};
};
};
};
...

View File

@ -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:

View File

@ -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

View 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>;
};
};
};
};
...

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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:

View File

@ -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
...

View File

@ -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 = <&regulator1>;
vddcore-supply = <&regulator2>;
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 = <&regulator1>;
vddcore-supply = <&regulator2>;
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.

View 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 = <&regulator1>;
vddcore-supply = <&regulator2>;
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 = <&regulator1>;
vddcore-supply = <&regulator2>;
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>;
};
};
};
...

View File

@ -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

View File

@ -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
----------

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -15,7 +15,6 @@ Video4Linux devices
v4l2-controls
v4l2-videobuf
v4l2-videobuf2
v4l2-clocks
v4l2-dv-timings
v4l2-flash-led-class
v4l2-mc

View File

@ -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(&notifier, 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()``

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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) {

View File

@ -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)

View File

@ -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.
*/

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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:

View File

@ -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:

File diff suppressed because it is too large Load Diff

View 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_ */

View 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;
};

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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;

View File

@ -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.
*

View File

@ -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;

View File

@ -10,6 +10,8 @@
#include <linux/types.h>
struct device;
/**
* struct ccs_data_block_version - CCS static data version
* @version_major: Major version number

View File

@ -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 = &regs->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);

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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,

File diff suppressed because it is too large Load Diff

View File

@ -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");

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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},

File diff suppressed because it is too large Load Diff

View File

@ -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);

View File

@ -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;

View File

@ -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,
};

View 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