media updates for v6.6-rc1

-----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEE+QmuaPwR3wnBdVwACF8+vY7k4RUFAmTxzmEACgkQCF8+vY7k
 4RWP6A/+Ljbwdoq92qOcaKAG2h2HzJa/H+xKMQwqIYjpbXnjNuFD2S9FCRfhNa9b
 Pt4K2g4lH2IJvYiJ3qhBbMxV8GPmovnHFX5LvyTFpRmrtZBAKp+TPXpbPt+a2/WL
 IPfQ0I52/c/JNqhm3fnmKgpXorp0wHYNbfY/LXztslimZj95+t0qjW62BoBmsJ3s
 hR+j/Xlgnd+9gld1OqX6OndH3mpeqDzBl4KZatQzw6yuIo8SK0ASEpu/vzgZoVy+
 WiBtbzMuta2ZghnEHbnCkurwBSU/oLXhBmXsgp+Zdy0gglSk1RBdxM+3O65OVQt3
 CCWSXMS0vGOk6JiogMpcPzO5piaUePcHEIjgAaaepTOzbKaf6PbEd9dj73LT9qcx
 4TYFtGaDDhyDU4nzKTngfNiwmYrL1h+NuG119ZLHfrdH3MT7itIaydwFJRqLC+6D
 7K6/1H2LKq25i+hRp5ZK2pgv0dAJw/nSdwFGFVgWM3Tuyt5dGdL/4SlZO4nIFKF2
 pPWJUTJJP/0t9GUtwWmCh1fdgDr0A6Zg5M2OduyhC/YkqyLuD/02Bb4aR8hzloPj
 pym+94/PFaT5S7zvKywpvyIc8U+87/M2tw+mAPN2r3i4c0RFJa7CkyKqlKTKFw13
 jw7NLLlrRbZ3a3zlhpJVqGLKgF2FlWudLUo4Y4kddWvxTMbwYXs=
 =yuz5
 -----END PGP SIGNATURE-----

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

Pull media updates from Mauro Carvalho Chehab:

 - new i2c drivers: ds90ub913, ds90ub953, ds90ub960, dw9719, ds90ub913

 - new Intel IVSC MEI drivers

 - some Mediatek platform drivers were moved to a common location

 - Intel atomisp2 driver is now working with the main ov2680 driver. Due
   to that, the atomisp2 ov2680 staging one was removed

 - the bttv driver was finally converted to videobuf2 framework. This
   was the last one upstream using videobuf version 1 core. We'll likely
   remove the old videobuf framework on 6.7

 - lots of improvements at atomisp driver: it now works with normal I2C
   sensors. Several compile-mode dependecies to select between ISP2400
   and ISP2401 are now solved in runtime

 - a new ipu-bridge logic was added to work with IVSC MEI drivers

 - venus driver gained better support for new VPU versions

 - the v4l core async framework has gained lots of improvements and
   cleanups

 - lots of other cleanups, improvements and driver fixes

* tag 'media/v6.6-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: (358 commits)
  media: ivsc: Add ACPI dependency
  media: bttv: convert to vb2
  media: bttv: use audio defaults for winfast2000
  media: bttv: refactor bttv_set_dma()
  media: bttv: move vbi_skip/vbi_count out of buffer
  media: bttv: remove crop info from bttv_buffer
  media: bttv: remove tvnorm field from bttv_buffer
  media: bttv: remove format field from bttv_buffer
  media: bttv: move do_crop flag out of bttv_fh
  media: bttv: copy vbi_fmt from bttv_fh
  media: bttv: copy vid fmt/width/height from fh
  media: bttv: radio use v4l2_fh instead of bttv_fh
  media: bttv: replace BUG with WARN_ON
  media: bttv: use video_drvdata to get bttv
  media: i2c: rdacm21: Fix uninitialized value
  media: coda: Remove duplicated include
  media: vivid: fix the racy dev->radio_tx_rds_owner
  media: i2c: ccs: Check rules is non-NULL
  media: i2c: ds90ub960: Fix PLL config for 1200 MHz CSI rate
  media: i2c: ds90ub953: Fix use of uninitialized variables
  ...
This commit is contained in:
Linus Torvalds 2023-09-01 12:21:32 -07:00
commit 307d59039f
372 changed files with 19014 additions and 9622 deletions

View File

@ -18,7 +18,7 @@ The driver implements V4L2, Media controller and V4L2 subdev interfaces.
Camera sensor using V4L2 subdev interface in the kernel is supported.
The driver is implemented using as a reference the Qualcomm Camera Subsystem
driver for Android as found in Code Aurora [#f1]_ [#f2]_.
driver for Android as found in Code Linaro [#f1]_ [#f2]_.
Qualcomm Camera Subsystem hardware
@ -181,5 +181,5 @@ Referenced 2018-06-22.
References
----------
.. [#f1] https://source.codeaurora.org/quic/la/kernel/msm-3.10/
.. [#f2] https://source.codeaurora.org/quic/la/kernel/msm-3.18/
.. [#f1] https://git.codelinaro.org/clo/la/kernel/msm-3.10/
.. [#f2] https://git.codelinaro.org/clo/la/kernel/msm-3.18/

View File

@ -0,0 +1,34 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/i2c-atr.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Common i2c address translator properties
maintainers:
- Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
description:
An I2C Address Translator (ATR) is a device with an I2C slave parent
("upstream") port and N I2C master child ("downstream") ports, and
forwards transactions from upstream to the appropriate downstream port
with a modified slave address. The address used on the parent bus is
called the "alias" and is (potentially) different from the physical
slave address of the child bus. Address translation is done by the
hardware.
properties:
i2c-alias-pool:
$ref: /schemas/types.yaml#/definitions/uint32-array
description:
I2C alias pool is a pool of I2C addresses on the main I2C bus that can be
used to access the remote peripherals on the serializer's I2C bus. The
addresses must be available, not used by any other peripheral. Each
remote peripheral is assigned an alias from the pool, and transactions to
that address will be forwarded to the remote peripheral, with the address
translated to the remote peripheral's real address. This property is not
needed if there are no I2C addressable remote peripherals.
additionalProperties: true
...

View File

@ -47,7 +47,7 @@ patternProperties:
$ref: ../mailbox/fsl,mu.yaml#
"^vpu_core@[0-9a-f]+$":
"^vpu-core@[0-9a-f]+$":
description:
Each core correspond a decoder or encoder, need to configure them
separately. NXP i.MX8QM SoC has one decoder and two encoder, i.MX8QXP SoC
@ -143,7 +143,7 @@ examples:
power-domains = <&pd IMX_SC_R_VPU_MU_2>;
};
vpu_core0: vpu_core@2d080000 {
vpu_core0: vpu-core@2d080000 {
compatible = "nxp,imx8q-vpu-decoder";
reg = <0x2d080000 0x10000>;
power-domains = <&pd IMX_SC_R_VPU_DEC_0>;
@ -154,7 +154,7 @@ examples:
memory-region = <&decoder_boot>, <&decoder_rpc>;
};
vpu_core1: vpu_core@2d090000 {
vpu_core1: vpu-core@2d090000 {
compatible = "nxp,imx8q-vpu-encoder";
reg = <0x2d090000 0x10000>;
power-domains = <&pd IMX_SC_R_VPU_ENC_0>;
@ -165,7 +165,7 @@ examples:
memory-region = <&encoder1_boot>, <&encoder1_rpc>;
};
vpu_core2: vpu_core@2d0a0000 {
vpu_core2: vpu-core@2d0a0000 {
reg = <0x2d0a0000 0x10000>;
compatible = "nxp,imx8q-vpu-encoder";
power-domains = <&pd IMX_SC_R_VPU_ENC_1>;

View File

@ -1,100 +0,0 @@
Cadence MIPI-CSI2 RX controller
===============================
The Cadence MIPI-CSI2 RX controller is a CSI-2 bridge supporting up to 4 CSI
lanes in input, and 4 different pixel streams in output.
Required properties:
- compatible: must be set to "cdns,csi2rx" and an SoC-specific compatible
- reg: base address and size of the memory mapped region
- clocks: phandles to the clocks driving the controller
- clock-names: must contain:
* sys_clk: main clock
* p_clk: register bank clock
* pixel_if[0-3]_clk: pixel stream output clock, one for each stream
implemented in hardware, between 0 and 3
Optional properties:
- phys: phandle to the external D-PHY, phy-names must be provided
- phy-names: must contain "dphy", if the implementation uses an
external D-PHY
Required subnodes:
- ports: A ports node with one port child node per device input and output
port, in accordance with the video interface bindings defined in
Documentation/devicetree/bindings/media/video-interfaces.txt. The
port nodes are numbered as follows:
Port Description
-----------------------------
0 CSI-2 input
1 Stream 0 output
2 Stream 1 output
3 Stream 2 output
4 Stream 3 output
The stream output port nodes are optional if they are not
connected to anything at the hardware level or implemented
in the design.Since there is only one endpoint per port,
the endpoints are not numbered.
Example:
csi2rx: csi-bridge@0d060000 {
compatible = "cdns,csi2rx";
reg = <0x0d060000 0x1000>;
clocks = <&byteclock>, <&byteclock>
<&coreclock>, <&coreclock>,
<&coreclock>, <&coreclock>;
clock-names = "sys_clk", "p_clk",
"pixel_if0_clk", "pixel_if1_clk",
"pixel_if2_clk", "pixel_if3_clk";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
csi2rx_in_sensor: endpoint {
remote-endpoint = <&sensor_out_csi2rx>;
clock-lanes = <0>;
data-lanes = <1 2>;
};
};
port@1 {
reg = <1>;
csi2rx_out_grabber0: endpoint {
remote-endpoint = <&grabber0_in_csi2rx>;
};
};
port@2 {
reg = <2>;
csi2rx_out_grabber1: endpoint {
remote-endpoint = <&grabber1_in_csi2rx>;
};
};
port@3 {
reg = <3>;
csi2rx_out_grabber2: endpoint {
remote-endpoint = <&grabber2_in_csi2rx>;
};
};
port@4 {
reg = <4>;
csi2rx_out_grabber3: endpoint {
remote-endpoint = <&grabber3_in_csi2rx>;
};
};
};
};

View File

@ -0,0 +1,201 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/cdns,csi2rx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Cadence MIPI-CSI2 RX controller
maintainers:
- Maxime Ripard <mripard@kernel.org>
description:
The Cadence MIPI-CSI2 RX controller is a CSI-2 bridge supporting up to 4 CSI
lanes in input, and 4 different pixel streams in output.
properties:
compatible:
items:
- enum:
- starfive,jh7110-csi2rx
- const: cdns,csi2rx
reg:
maxItems: 1
clocks:
items:
- description: CSI2Rx system clock
- description: Gated Register bank clock for APB interface
- description: pixel Clock for Stream interface 0
- description: pixel Clock for Stream interface 1
- description: pixel Clock for Stream interface 2
- description: pixel Clock for Stream interface 3
clock-names:
items:
- const: sys_clk
- const: p_clk
- const: pixel_if0_clk
- const: pixel_if1_clk
- const: pixel_if2_clk
- const: pixel_if3_clk
resets:
items:
- description: CSI2Rx system reset
- description: Gated Register bank reset for APB interface
- description: pixel reset for Stream interface 0
- description: pixel reset for Stream interface 1
- description: pixel reset for Stream interface 2
- description: pixel reset for Stream interface 3
reset-names:
items:
- const: sys
- const: reg_bank
- const: pixel_if0
- const: pixel_if1
- const: pixel_if2
- const: pixel_if3
phys:
maxItems: 1
description: MIPI D-PHY
phy-names:
items:
- const: dphy
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port node, single endpoint describing the CSI-2 transmitter.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
bus-type:
const: 4
clock-lanes:
const: 0
data-lanes:
minItems: 1
maxItems: 4
items:
maximum: 4
required:
- data-lanes
port@1:
$ref: /schemas/graph.yaml#/properties/port
description:
Stream 0 Output port node
port@2:
$ref: /schemas/graph.yaml#/properties/port
description:
Stream 1 Output port node
port@3:
$ref: /schemas/graph.yaml#/properties/port
description:
Stream 2 Output port node
port@4:
$ref: /schemas/graph.yaml#/properties/port
description:
Stream 3 Output port node
required:
- port@0
required:
- compatible
- reg
- clocks
- clock-names
- ports
additionalProperties: false
examples:
- |
csi@d060000 {
compatible = "starfive,jh7110-csi2rx", "cdns,csi2rx";
reg = <0x0d060000 0x1000>;
clocks = <&byteclock 7>, <&byteclock 6>,
<&coreclock 8>, <&coreclock 9>,
<&coreclock 10>, <&coreclock 11>;
clock-names = "sys_clk", "p_clk",
"pixel_if0_clk", "pixel_if1_clk",
"pixel_if2_clk", "pixel_if3_clk";
resets = <&bytereset 9>, <&bytereset 4>,
<&corereset 5>, <&corereset 6>,
<&corereset 7>, <&corereset 8>;
reset-names = "sys", "reg_bank",
"pixel_if0", "pixel_if1",
"pixel_if2", "pixel_if3";
phys = <&csi_phy>;
phy-names = "dphy";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
csi2rx_in_sensor: endpoint {
remote-endpoint = <&sensor_out_csi2rx>;
clock-lanes = <0>;
data-lanes = <1 2>;
};
};
port@1 {
reg = <1>;
csi2rx_out_grabber0: endpoint {
remote-endpoint = <&grabber0_in_csi2rx>;
};
};
port@2 {
reg = <2>;
csi2rx_out_grabber1: endpoint {
remote-endpoint = <&grabber1_in_csi2rx>;
};
};
port@3 {
reg = <3>;
csi2rx_out_grabber2: endpoint {
remote-endpoint = <&grabber2_in_csi2rx>;
};
};
port@4 {
reg = <4>;
csi2rx_out_grabber3: endpoint {
remote-endpoint = <&grabber3_in_csi2rx>;
};
};
};
};
...

View File

@ -53,6 +53,5 @@ examples:
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA124_CLK_CEC>;
clock-names = "cec";
status = "disabled";
hdmi-phandle = <&hdmi>;
};

View File

@ -143,7 +143,6 @@ examples:
mipid02: csi2rx@14 {
compatible = "st,st-mipid02";
reg = <0x14>;
status = "okay";
clocks = <&clk_ext_camera_12>;
clock-names = "xclk";
VDDE-supply = <&vdd>;

View File

@ -0,0 +1,133 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/ti,ds90ub913.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments DS90UB913 FPD-Link III Serializer
maintainers:
- Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
description:
The TI DS90UB913 is an FPD-Link III video serializer for parallel video.
properties:
compatible:
enum:
- ti,ds90ub913a-q1
'#gpio-cells':
const: 2
description:
First cell is the GPO pin number, second cell is the flags. The GPO pin
number must be in range of [0, 3]. Note that GPOs 2 and 3 are not
available in external oscillator mode.
gpio-controller: true
clocks:
maxItems: 1
description:
Reference clock connected to the CLKIN pin.
clock-names:
items:
- const: clkin
'#clock-cells':
const: 0
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: Parallel input port
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
required:
- pclk-sample
port@1:
$ref: /schemas/graph.yaml#/properties/port
unevaluatedProperties: false
description: FPD-Link III output port
required:
- port@0
- port@1
i2c:
$ref: /schemas/i2c/i2c-controller.yaml#
unevaluatedProperties: false
required:
- compatible
- '#gpio-cells'
- gpio-controller
- '#clock-cells'
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
serializer {
compatible = "ti,ds90ub913a-q1";
gpio-controller;
#gpio-cells = <2>;
clocks = <&clk_cam_48M>;
clock-names = "clkin";
#clock-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
ub913_in: endpoint {
remote-endpoint = <&sensor_out>;
pclk-sample = <1>;
};
};
port@1 {
reg = <1>;
endpoint {
remote-endpoint = <&deser_fpd_in>;
};
};
};
i2c {
#address-cells = <1>;
#size-cells = <0>;
sensor@48 {
compatible = "aptina,mt9v111";
reg = <0x48>;
clocks = <&fixed_clock>;
port {
sensor_out: endpoint {
remote-endpoint = <&ub913_in>;
};
};
};
};
};
...

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/ti,ds90ub953.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments DS90UB953 FPD-Link III Serializer
maintainers:
- Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
description:
The TI DS90UB953 is an FPD-Link III video serializer for MIPI CSI-2.
properties:
compatible:
enum:
- ti,ds90ub953-q1
- ti,ds90ub971-q1
'#gpio-cells':
const: 2
description:
First cell is the GPIO pin number, second cell is the flags. The GPIO pin
number must be in range of [0, 3].
gpio-controller: true
clocks:
maxItems: 1
description:
Reference clock connected to the CLKIN pin.
clock-names:
items:
- const: clkin
'#clock-cells':
const: 0
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: CSI-2 input port
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
required:
- data-lanes
port@1:
$ref: /schemas/graph.yaml#/properties/port
unevaluatedProperties: false
description: FPD-Link III output port
required:
- port@0
- port@1
i2c:
$ref: /schemas/i2c/i2c-controller.yaml#
unevaluatedProperties: false
required:
- compatible
- '#gpio-cells'
- gpio-controller
- '#clock-cells'
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
serializer {
compatible = "ti,ds90ub953-q1";
gpio-controller;
#gpio-cells = <2>;
#clock-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
ub953_in: endpoint {
clock-lanes = <0>;
data-lanes = <1 2 3 4>;
remote-endpoint = <&sensor_out>;
};
};
port@1 {
reg = <1>;
endpoint {
remote-endpoint = <&deser_fpd_in>;
};
};
};
i2c {
#address-cells = <1>;
#size-cells = <0>;
sensor@1a {
compatible = "sony,imx274";
reg = <0x1a>;
reset-gpios = <&serializer 0 GPIO_ACTIVE_LOW>;
clocks = <&serializer>;
clock-names = "inck";
port {
sensor_out: endpoint {
remote-endpoint = <&ub953_in>;
};
};
};
};
};
...

View File

@ -0,0 +1,427 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/ti,ds90ub960.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Texas Instruments DS90UB9XX Family FPD-Link Deserializer Hubs
maintainers:
- Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
description:
The TI DS90UB9XX devices are FPD-Link video deserializers with I2C and GPIO
forwarding.
allOf:
- $ref: /schemas/i2c/i2c-atr.yaml#
properties:
compatible:
enum:
- ti,ds90ub960-q1
- ti,ds90ub9702-q1
reg:
maxItems: 1
clocks:
maxItems: 1
description:
Reference clock connected to the REFCLK pin.
clock-names:
items:
- const: refclk
powerdown-gpios:
maxItems: 1
description:
Specifier for the GPIO connected to the PDB pin.
i2c-alias-pool:
minItems: 1
maxItems: 32
links:
type: object
additionalProperties: false
properties:
'#address-cells':
const: 1
'#size-cells':
const: 0
ti,manual-strobe:
type: boolean
description:
Enable manual strobe position and EQ level
patternProperties:
'^link@[0-3]$':
type: object
additionalProperties: false
properties:
reg:
description: The link number
maxItems: 1
i2c-alias:
description:
The I2C address used for the serializer. Transactions to this
address on the I2C bus where the deserializer resides are
forwarded to the serializer.
ti,rx-mode:
$ref: /schemas/types.yaml#/definitions/uint32
enum:
- 0 # RAW10
- 1 # RAW12 HF
- 2 # RAW12 LF
- 3 # CSI2 SYNC
- 4 # CSI2 NON-SYNC
description:
FPD-Link Input Mode. This should reflect the hardware and the
default mode of the connected device.
ti,cdr-mode:
$ref: /schemas/types.yaml#/definitions/uint32
enum:
- 0 # FPD-Link III
- 1 # FPD-Link IV
description:
FPD-Link CDR Mode. This should reflect the hardware and the
default mode of the connected device.
ti,strobe-pos:
$ref: /schemas/types.yaml#/definitions/int32
minimum: -13
maximum: 13
description: Manual strobe position
ti,eq-level:
$ref: /schemas/types.yaml#/definitions/uint32
maximum: 14
description: Manual EQ level
serializer:
type: object
description: FPD-Link Serializer node
required:
- reg
- i2c-alias
- ti,rx-mode
- serializer
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: FPD-Link input 0
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
description:
Endpoint for FPD-Link port. If the RX mode for this port is RAW,
hsync-active and vsync-active must be defined.
port@1:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: FPD-Link input 1
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
description:
Endpoint for FPD-Link port. If the RX mode for this port is RAW,
hsync-active and vsync-active must be defined.
port@2:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: FPD-Link input 2
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
description:
Endpoint for FPD-Link port. If the RX mode for this port is RAW,
hsync-active and vsync-active must be defined.
port@3:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: FPD-Link input 3
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
description:
Endpoint for FPD-Link port. If the RX mode for this port is RAW,
hsync-active and vsync-active must be defined.
port@4:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: CSI-2 Output 0
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
link-frequencies:
maxItems: 1
required:
- data-lanes
- link-frequencies
port@5:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description: CSI-2 Output 1
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
link-frequencies:
maxItems: 1
required:
- data-lanes
- link-frequencies
required:
- port@0
- port@1
- port@2
- port@3
- port@4
- port@5
required:
- compatible
- reg
- clocks
- clock-names
- ports
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
clock-frequency = <400000>;
#address-cells = <1>;
#size-cells = <0>;
deser@3d {
compatible = "ti,ds90ub960-q1";
reg = <0x3d>;
clock-names = "refclk";
clocks = <&fixed_clock>;
powerdown-gpios = <&pca9555 7 GPIO_ACTIVE_LOW>;
i2c-alias-pool = <0x4a 0x4b 0x4c 0x4d 0x4e 0x4f>;
ports {
#address-cells = <1>;
#size-cells = <0>;
/* Port 0, Camera 0 */
port@0 {
reg = <0>;
ub960_fpd3_1_in: endpoint {
remote-endpoint = <&ub953_1_out>;
};
};
/* Port 1, Camera 1 */
port@1 {
reg = <1>;
ub960_fpd3_2_in: endpoint {
remote-endpoint = <&ub913_2_out>;
hsync-active = <0>;
vsync-active = <1>;
};
};
/* Port 2, unconnected */
port@2 {
reg = <2>;
};
/* Port 3, unconnected */
port@3 {
reg = <3>;
};
/* Port 4, CSI-2 TX */
port@4 {
reg = <4>;
ds90ub960_0_csi_out: endpoint {
data-lanes = <1 2 3 4>;
link-frequencies = /bits/ 64 <800000000>;
remote-endpoint = <&csi2_phy0>;
};
};
/* Port 5, unconnected */
port@5 {
reg = <5>;
};
};
links {
#address-cells = <1>;
#size-cells = <0>;
/* Link 0 has DS90UB953 serializer and IMX274 sensor */
link@0 {
reg = <0>;
i2c-alias = <0x44>;
ti,rx-mode = <3>;
serializer1: serializer {
compatible = "ti,ds90ub953-q1";
gpio-controller;
#gpio-cells = <2>;
#clock-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
ub953_1_in: endpoint {
data-lanes = <1 2 3 4>;
remote-endpoint = <&sensor_1_out>;
};
};
port@1 {
reg = <1>;
ub953_1_out: endpoint {
remote-endpoint = <&ub960_fpd3_1_in>;
};
};
};
i2c {
#address-cells = <1>;
#size-cells = <0>;
sensor@1a {
compatible = "sony,imx274";
reg = <0x1a>;
reset-gpios = <&serializer1 0 GPIO_ACTIVE_LOW>;
port {
sensor_1_out: endpoint {
remote-endpoint = <&ub953_1_in>;
};
};
};
};
};
}; /* End of link@0 */
/* Link 1 has DS90UB913 serializer and MT9V111 sensor */
link@1 {
reg = <1>;
i2c-alias = <0x45>;
ti,rx-mode = <0>;
serializer2: serializer {
compatible = "ti,ds90ub913a-q1";
gpio-controller;
#gpio-cells = <2>;
clocks = <&clk_cam_48M>;
clock-names = "clkin";
#clock-cells = <0>;
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
ub913_2_in: endpoint {
remote-endpoint = <&sensor_2_out>;
pclk-sample = <1>;
};
};
port@1 {
reg = <1>;
ub913_2_out: endpoint {
remote-endpoint = <&ub960_fpd3_2_in>;
};
};
};
i2c {
#address-cells = <1>;
#size-cells = <0>;
sensor@48 {
compatible = "aptina,mt9v111";
reg = <0x48>;
clocks = <&serializer2>;
port {
sensor_2_out: endpoint {
remote-endpoint = <&ub913_2_in>;
};
};
};
};
};
}; /* End of link@1 */
};
};
};
...

View File

@ -21,24 +21,33 @@ properties:
- mediatek,mt8183-vcodec-dec
reg:
maxItems: 12
minItems: 11
maxItems: 11
reg-names:
items:
- const: misc
- const: ld
- const: top
- const: cm
- const: ad
- const: av
- const: pp
- const: hwd
- const: hwq
- const: hwb
- const: hwg
interrupts:
maxItems: 1
clocks:
minItems: 1
maxItems: 8
clock-names:
items:
- const: vcodecpll
- const: univpll_d2
- const: clk_cci400_sel
- const: vdec_sel
- const: vdecpll
- const: vencpll
- const: venc_lt_sel
- const: vdec_bus_clk_src
minItems: 1
maxItems: 8
assigned-clocks: true
@ -66,6 +75,10 @@ properties:
description:
Describes point to scp.
mediatek,vdecsys:
$ref: /schemas/types.yaml#/definitions/phandle
description: Phandle to the vdecsys syscon node.
required:
- compatible
- reg
@ -73,8 +86,7 @@ required:
- clocks
- clock-names
- iommus
- assigned-clocks
- assigned-clock-parents
- mediatek,vdecsys
allOf:
- if:
@ -88,6 +100,15 @@ allOf:
required:
- mediatek,scp
properties:
clocks:
minItems: 1
maxItems: 1
clock-names:
items:
- const: vdec
- if:
properties:
compatible:
@ -99,6 +120,22 @@ allOf:
required:
- mediatek,vpu
properties:
clocks:
minItems: 8
maxItems: 8
clock-names:
items:
- const: vcodecpll
- const: univpll_d2
- const: clk_cci400_sel
- const: vdec_sel
- const: vdecpll
- const: vencpll
- const: venc_lt_sel
- const: vdec_bus_clk_src
additionalProperties: false
examples:
@ -109,10 +146,9 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h>
#include <dt-bindings/power/mt8173-power.h>
vcodec_dec: vcodec@16000000 {
vcodec_dec: vcodec@16020000 {
compatible = "mediatek,mt8173-vcodec-dec";
reg = <0x16000000 0x100>, /*VDEC_SYS*/
<0x16020000 0x1000>, /*VDEC_MISC*/
reg = <0x16020000 0x1000>, /*VDEC_MISC*/
<0x16021000 0x800>, /*VDEC_LD*/
<0x16021800 0x800>, /*VDEC_TOP*/
<0x16022000 0x1000>, /*VDEC_CM*/
@ -133,6 +169,7 @@ examples:
<&iommu M4U_PORT_HW_VDEC_VLD_EXT>,
<&iommu M4U_PORT_HW_VDEC_VLD2_EXT>;
mediatek,vpu = <&vpu>;
mediatek,vdecsys = <&vdecsys>;
power-domains = <&scpsys MT8173_POWER_DOMAIN_VDEC>;
clocks = <&apmixedsys CLK_APMIXED_VCODECPLL>,
<&topckgen CLK_TOP_UNIVPLL_D2>,

View File

@ -21,6 +21,7 @@ properties:
enum:
- fsl,imx8mn-isi
- fsl,imx8mp-isi
- fsl,imx93-isi
reg:
maxItems: 1
@ -72,7 +73,9 @@ allOf:
properties:
compatible:
contains:
const: fsl,imx8mn-isi
enum:
- fsl,imx8mn-isi
- fsl,imx93-isi
then:
properties:
interrupts:

View File

@ -109,9 +109,11 @@ your driver:
int (*adap_monitor_all_enable)(struct cec_adapter *adap, bool enable);
int (*adap_monitor_pin_enable)(struct cec_adapter *adap, bool enable);
int (*adap_log_addr)(struct cec_adapter *adap, u8 logical_addr);
void (*adap_configured)(struct cec_adapter *adap, bool configured);
void (*adap_unconfigured)(struct cec_adapter *adap);
int (*adap_transmit)(struct cec_adapter *adap, u8 attempts,
u32 signal_free_time, struct cec_msg *msg);
void (*adap_nb_transmit_canceled)(struct cec_adapter *adap,
const struct cec_msg *msg);
void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
void (*adap_free)(struct cec_adapter *adap);
@ -122,8 +124,8 @@ your driver:
...
};
The seven low-level ops deal with various aspects of controlling the CEC adapter
hardware:
These low-level ops deal with various aspects of controlling the CEC adapter
hardware. They are all called with the mutex adap->lock held.
To enable/disable the hardware::
@ -179,14 +181,12 @@ can receive directed messages to that address.
Note that adap_log_addr must return 0 if logical_addr is CEC_LOG_ADDR_INVALID.
Called when the adapter is fully configured or unconfigured::
Called when the adapter is unconfigured::
void (*adap_configured)(struct cec_adapter *adap, bool configured);
void (*adap_unconfigured)(struct cec_adapter *adap);
If configured == true, then the adapter is fully configured, i.e. all logical
addresses have been successfully claimed. If configured == false, then the
adapter is unconfigured. If the driver has to take specific actions after
(un)configuration, then that can be done through this optional callback.
The adapter is unconfigured. If the driver has to take specific actions after
unconfiguration, then that can be done through this optional callback.
To transmit a new message::
@ -207,6 +207,19 @@ The CEC_FREE_TIME_TO_USEC macro can be used to convert signal_free_time to
microseconds (one data bit period is 2.4 ms).
To pass on the result of a canceled non-blocking transmit::
void (*adap_nb_transmit_canceled)(struct cec_adapter *adap,
const struct cec_msg *msg);
This optional callback can be used to obtain the result of a canceled
non-blocking transmit with sequence number msg->sequence. This is
called if the transmit was aborted, the transmit timed out (i.e. the
hardware never signaled that the transmit finished), or the transmit
was successful, but the wait for the expected reply was either aborted
or it timed out.
To log the current CEC hardware status::
void (*adap_status)(struct cec_adapter *adap, struct seq_file *file);
@ -372,7 +385,8 @@ Implementing the High-Level CEC Adapter
---------------------------------------
The low-level operations drive the hardware, the high-level operations are
CEC protocol driven. The following high-level callbacks are available:
CEC protocol driven. The high-level callbacks are called without the adap->lock
mutex being held. The following high-level callbacks are available:
.. code-block:: none
@ -384,9 +398,19 @@ CEC protocol driven. The following high-level callbacks are available:
...
/* High-level CEC message callback */
void (*configured)(struct cec_adapter *adap);
int (*received)(struct cec_adapter *adap, struct cec_msg *msg);
};
Called when the adapter is configured::
void (*configured)(struct cec_adapter *adap);
The adapter is fully configured, i.e. all logical addresses have been
successfully claimed. If the driver has to take specific actions after
configuration, then that can be done through this optional callback.
The received() callback allows the driver to optionally handle a newly
received CEC message::

View File

@ -0,0 +1,5 @@
.. SPDX-License-Identifier: GPL-2.0
V4L2 CCI kAPI
^^^^^^^^^^^^^
.. kernel-doc:: include/media/v4l2-cci.h

View File

@ -22,6 +22,7 @@ Video4Linux devices
v4l2-mem2mem
v4l2-async
v4l2-fwnode
v4l2-cci
v4l2-rect
v4l2-tuner
v4l2-common

View File

@ -157,6 +157,9 @@ below.
Using one or the other registration method only affects the probing process, the
run-time bridge-subdevice interaction is in both cases the same.
Registering synchronous sub-devices
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the **synchronous** case a device (bridge) driver needs to register the
:c:type:`v4l2_subdev` with the v4l2_device:
@ -175,10 +178,12 @@ You can unregister a sub-device using:
:c:func:`v4l2_device_unregister_subdev <v4l2_device_unregister_subdev>`
(:c:type:`sd <v4l2_subdev>`).
Afterwards the subdev module can be unloaded and
:c:type:`sd <v4l2_subdev>`->dev == ``NULL``.
Registering asynchronous sub-devices
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
In the **asynchronous** case subdevice probing can be invoked independently of
the bridge driver availability. The subdevice driver then has to verify whether
all the requirements for a successful probing are satisfied. This can include a
@ -190,64 +195,89 @@ performed using the :c:func:`v4l2_async_unregister_subdev` call. Subdevices
registered this way are stored in a global list of subdevices, ready to be
picked up by bridge drivers.
Bridge drivers in turn have to register a notifier object. This is
performed using the :c:func:`v4l2_async_nf_register` call. To
unregister the notifier the driver has to call
:c:func:`v4l2_async_nf_unregister`. The former of the two functions
takes two arguments: a pointer to struct :c:type:`v4l2_device` and a
pointer to struct :c:type:`v4l2_async_notifier`.
Asynchronous sub-device notifiers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Bridge drivers in turn have to register a notifier object. This is performed
using the :c:func:`v4l2_async_nf_register` call. To unregister the notifier the
driver has to call :c:func:`v4l2_async_nf_unregister`. Before releasing memory
of an unregister notifier, it must be cleaned up by calling
:c:func:`v4l2_async_nf_cleanup`.
Before registering the notifier, bridge drivers must do two things: first, the
notifier must be initialized using the :c:func:`v4l2_async_nf_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.
notifier must be initialized using the :c:func:`v4l2_async_nf_init`. Second,
bridge drivers can then begin to form a list of async connection descriptors
that the bridge device needs for its
operation. :c:func:`v4l2_async_nf_add_fwnode`,
:c:func:`v4l2_async_nf_add_fwnode_remote` and :c:func:`v4l2_async_nf_add_i2c`
:c:func:`v4l2_async_nf_add_fwnode_remote` and
:c:func:`v4l2_async_nf_add_i2c` are for bridge and ISP drivers for
registering their async sub-devices with the notifier.
Async connection descriptors describe connections to external sub-devices the
drivers for which are not yet probed. Based on an async connection, a media data
or ancillary link may be created when the related sub-device becomes
available. There may be one or more async connections to a given sub-device but
this is not known at the time of adding the connections to the notifier. Async
connections are bound as matching async sub-devices are found, one by one.
:c:func:`v4l2_async_register_subdev_sensor` 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.
Asynchronous sub-device notifier for sub-devices
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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:
A driver that registers an asynchronous sub-device may also register an
asynchronous notifier. This is called an asynchronous sub-device notifier andthe
process is similar to that of a bridge driver apart from that the notifier is
initialised using :c:func:`v4l2_async_subdev_nf_init` instead. A sub-device
notifier may complete only after the V4L2 device becomes available, i.e. there's
a path via async sub-devices and notifiers to a notifier that is not an
asynchronous sub-device notifier.
Asynchronous sub-device registration helper for camera sensor drivers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:c:func:`v4l2_async_register_subdev_sensor` is a helper function for sensor
drivers registering their own async connection, but it also registers a notifier
and further registers async connections for lens and flash devices found in
firmware. The notifier for the sub-device is unregistered and cleaned up with
the async sub-device, using :c:func:`v4l2_async_unregister_subdev`.
Asynchronous sub-device notifier example
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
These functions allocate an async connection descriptor which is of type struct
:c:type:`v4l2_async_connection` embedded in a driver-specific struct. The &struct
:c:type:`v4l2_async_connection` shall be the first member of this struct:
.. code-block:: c
struct my_async_subdev {
struct v4l2_async_subdev asd;
struct my_async_connection {
struct v4l2_async_connection asc;
...
};
struct my_async_subdev *my_asd;
struct my_async_connection *my_asc;
struct fwnode_handle *ep;
...
my_asd = v4l2_async_nf_add_fwnode_remote(&notifier, ep,
struct my_async_subdev);
my_asc = v4l2_async_nf_add_fwnode_remote(&notifier, ep,
struct my_async_connection);
fwnode_handle_put(ep);
if (IS_ERR(asd))
return PTR_ERR(asd);
if (IS_ERR(my_asc))
return PTR_ERR(my_asc);
The V4L2 core will then use these descriptors to match asynchronously
registered subdevices to them. If a match is detected the ``.bound()``
notifier callback is called. After all subdevices have been located the
.complete() callback is called. When a subdevice is removed from the
system the .unbind() method is called. All three callbacks are optional.
Asynchronous sub-device notifier callbacks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The V4L2 core will then use these connection descriptors to match asynchronously
registered subdevices to them. If a match is detected the ``.bound()`` notifier
callback is called. After all connections have been bound the .complete()
callback is called. When a connection is removed from the system the
``.unbind()`` method is called. All three callbacks are optional.
Drivers can store any type of custom data in their driver-specific
:c:type:`v4l2_async_subdev` wrapper. If any of that data requires special
:c:type:`v4l2_async_connection` wrapper. If any of that data requires special
handling when the structure is freed, drivers must implement the ``.destroy()``
notifier callback. The framework will call it right before freeing the
:c:type:`v4l2_async_subdev`.
:c:type:`v4l2_async_connection`.
Calling subdev operations
~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1,96 @@
.. SPDX-License-Identifier: GPL-2.0
=======================
I2C Address Translators
=======================
Author: Luca Ceresoli <luca@lucaceresoli.net>
Author: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Description
-----------
An I2C Address Translator (ATR) is a device with an I2C slave parent
("upstream") port and N I2C master child ("downstream") ports, and
forwards transactions from upstream to the appropriate downstream port
with a modified slave address. The address used on the parent bus is
called the "alias" and is (potentially) different from the physical
slave address of the child bus. Address translation is done by the
hardware.
An ATR looks similar to an i2c-mux except:
- the address on the parent and child busses can be different
- there is normally no need to select the child port; the alias used on the
parent bus implies it
The ATR functionality can be provided by a chip with many other features.
The kernel i2c-atr provides a helper to implement an ATR within a driver.
The ATR creates a new I2C "child" adapter on each child bus. Adding
devices on the child bus ends up in invoking the driver code to select
an available alias. Maintaining an appropriate pool of available aliases
and picking one for each new device is up to the driver implementer. The
ATR maintains a table of currently assigned alias and uses it to modify
all I2C transactions directed to devices on the child buses.
A typical example follows.
Topology::
Slave X @ 0x10
.-----. |
.-----. | |---+---- B
| CPU |--A--| ATR |
`-----' | |---+---- C
`-----' |
Slave Y @ 0x10
Alias table:
A, B and C are three physical I2C busses, electrically independent from
each other. The ATR receives the transactions initiated on bus A and
propagates them on bus B or bus C or none depending on the device address
in the transaction and based on the alias table.
Alias table:
.. table::
=============== =====
Client Alias
=============== =====
X (bus B, 0x10) 0x20
Y (bus C, 0x10) 0x30
=============== =====
Transaction:
- Slave X driver requests a transaction (on adapter B), slave address 0x10
- ATR driver finds slave X is on bus B and has alias 0x20, rewrites
messages with address 0x20, forwards to adapter A
- Physical I2C transaction on bus A, slave address 0x20
- ATR chip detects transaction on address 0x20, finds it in table,
propagates transaction on bus B with address translated to 0x10,
keeps clock streched on bus A waiting for reply
- Slave X chip (on bus B) detects transaction at its own physical
address 0x10 and replies normally
- ATR chip stops clock stretching and forwards reply on bus A,
with address translated back to 0x20
- ATR driver receives the reply, rewrites messages with address 0x10
as they were initially
- Slave X driver gets back the msgs[], with reply and address 0x10
Usage:
1. In the driver (typically in the probe function) add an ATR by
calling i2c_atr_new() passing attach/detach callbacks
2. When the attach callback is called pick an appropriate alias,
configure it in the chip and return the chosen alias in the
alias_id parameter
3. When the detach callback is called, deconfigure the alias from
the chip and put the alias back in the pool for later usage
I2C ATR functions and data structures
-------------------------------------
.. kernel-doc:: include/linux/i2c-atr.h

View File

@ -18,6 +18,7 @@ Introduction
i2c-topology
muxes/i2c-mux-gpio
i2c-sysfs
i2c-address-translators
Writing device drivers
======================

View File

@ -277,7 +277,7 @@ Initialization
other fields
follow standard semantics.
* **Return fields:**
* **Returned fields:**
``sizeimage``
adjusted size of ``OUTPUT`` buffers.
@ -311,7 +311,7 @@ Initialization
``memory``
follows standard semantics.
* **Return fields:**
* **Returned fields:**
``count``
the actual number of buffers allocated.
@ -339,7 +339,7 @@ Initialization
``format``
follows standard semantics.
* **Return fields:**
* **Returned fields:**
``count``
adjusted to the number of allocated buffers.
@ -410,7 +410,7 @@ Capture Setup
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``CAPTURE``.
* **Return fields:**
* **Returned fields:**
``width``, ``height``
frame buffer resolution for the decoded frames.
@ -443,7 +443,7 @@ Capture Setup
``target``
set to ``V4L2_SEL_TGT_COMPOSE``.
* **Return fields:**
* **Returned fields:**
``r.left``, ``r.top``, ``r.width``, ``r.height``
the visible rectangle; it must fit within the frame buffer resolution
@ -552,7 +552,7 @@ Capture Setup
frame is written; defaults to ``V4L2_SEL_TGT_COMPOSE_DEFAULT``;
read-only on hardware without additional compose/scaling capabilities.
* **Return fields:**
* **Returned fields:**
``r.left``, ``r.top``, ``r.width``, ``r.height``
the visible rectangle; it must fit within the frame buffer resolution
@ -629,7 +629,7 @@ Capture Setup
``memory``
follows standard semantics.
* **Return fields:**
* **Returned fields:**
``count``
actual number of buffers allocated.
@ -668,7 +668,7 @@ Capture Setup
a format representing the maximum framebuffer resolution to be
accommodated by newly allocated buffers.
* **Return fields:**
* **Returned fields:**
``count``
adjusted to the number of allocated buffers.

View File

@ -115,8 +115,8 @@ Querying Capabilities
4. The client may use :c:func:`VIDIOC_ENUM_FRAMEINTERVALS` to detect supported
frame intervals for a given format and resolution, passing the desired pixel
format in :c:type:`v4l2_frmsizeenum` ``pixel_format`` and the resolution
in :c:type:`v4l2_frmsizeenum` ``width`` and :c:type:`v4l2_frmsizeenum`
format in :c:type:`v4l2_frmivalenum` ``pixel_format`` and the resolution
in :c:type:`v4l2_frmivalenum` ``width`` and :c:type:`v4l2_frmivalenum`
``height``.
* Values returned by :c:func:`VIDIOC_ENUM_FRAMEINTERVALS` for a coded pixel
@ -163,7 +163,7 @@ Initialization
other fields
follow standard semantics.
* **Return fields:**
* **Returned fields:**
``sizeimage``
adjusted size of ``CAPTURE`` buffers.
@ -189,7 +189,7 @@ Initialization
other fields
follow standard semantics.
* **Return fields:**
* **Returned fields:**
``pixelformat``
raw format supported for the coded format currently selected on
@ -215,7 +215,7 @@ Initialization
other fields
follow standard semantics.
* **Return fields:**
* **Returned fields:**
``width``, ``height``
may be adjusted to match encoder minimums, maximums and alignment
@ -233,7 +233,7 @@ Initialization
:c:func:`VIDIOC_S_PARM`. This also sets the coded frame interval on the
``CAPTURE`` queue to the same value.
* ** Required fields:**
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``OUTPUT``.
@ -245,7 +245,7 @@ Initialization
the desired frame interval; the encoder may adjust it to
match hardware requirements.
* **Return fields:**
* **Returned fields:**
``parm.output.timeperframe``
the adjusted frame interval.
@ -284,7 +284,7 @@ Initialization
the case for off-line encoding. Support for this feature is signalled
by the :ref:`V4L2_FMT_FLAG_ENC_CAP_FRAME_INTERVAL <fmtdesc-flags>` format flag.
* ** Required fields:**
* **Required fields:**
``type``
a ``V4L2_BUF_TYPE_*`` enum appropriate for ``CAPTURE``.
@ -296,7 +296,7 @@ Initialization
the desired coded frame interval; the encoder may adjust it to
match hardware requirements.
* **Return fields:**
* **Returned fields:**
``parm.capture.timeperframe``
the adjusted frame interval.
@ -339,7 +339,7 @@ Initialization
rectangle and may be subject to adjustment to match codec and
hardware constraints.
* **Return fields:**
* **Returned fields:**
``r.left``, ``r.top``, ``r.width``, ``r.height``
visible rectangle adjusted by the encoder.
@ -387,7 +387,7 @@ Initialization
other fields
follow standard semantics.
* **Return fields:**
* **Returned fields:**
``count``
actual number of buffers allocated.
@ -420,7 +420,7 @@ Initialization
other fields
follow standard semantics.
* **Return fields:**
* **Returned fields:**
``count``
adjusted to the number of allocated buffers.

View File

@ -180,7 +180,7 @@ Initialization
``memory``
follows standard semantics.
* **Return fields:**
* **Returned fields:**
``count``
actual number of buffers allocated.
@ -208,7 +208,7 @@ Initialization
follows standard semantics. ``V4L2_MEMORY_USERPTR`` is not supported
for ``CAPTURE`` buffers.
* **Return fields:**
* **Returned fields:**
``count``
adjusted to allocated number of buffers, in case the codec requires

View File

@ -275,6 +275,19 @@ please make a proposal on the linux-media mailing list.
Decoder's implementation can be found here,
`aspeed_codec <https://github.com/AspeedTech-BMC/aspeed_codec/>`__
* .. _V4L2-PIX-FMT-MT2110T:
- ``V4L2_PIX_FMT_MT2110T``
- 'MT2110T'
- This format is two-planar 10-Bit tile mode and having similitude with
``V4L2_PIX_FMT_MM21`` in term of alignment and tiling. Used for VP9, AV1
and HEVC.
* .. _V4L2-PIX-FMT-MT2110R:
- ``V4L2_PIX_FMT_MT2110R``
- 'MT2110R'
- This format is two-planar 10-Bit raster mode and having similitude with
``V4L2_PIX_FMT_MM21`` in term of alignment and tiling. Used for AVC.
.. raw:: latex
\normalsize

View File

@ -58,6 +58,9 @@ the subdevice exposes, drivers return the ENOSPC error code and adjust the
value of the ``num_routes`` field. Application should then reserve enough memory
for all the route entries and call ``VIDIOC_SUBDEV_G_ROUTING`` again.
On a successful ``VIDIOC_SUBDEV_G_ROUTING`` call the driver updates the
``num_routes`` field to reflect the actual number of routes returned.
.. tabularcolumns:: |p{4.4cm}|p{4.4cm}|p{8.7cm}|
.. c:type:: v4l2_subdev_routing
@ -138,9 +141,7 @@ ENOSPC
EINVAL
The sink or source pad identifiers reference a non-existing pad, or reference
pads of different types (ie. the sink_pad identifiers refers to a source pad)
or the sink or source stream identifiers reference a non-existing stream on
the sink or source pad.
pads of different types (ie. the sink_pad identifiers refers to a source pad).
E2BIG
The application provided ``num_routes`` for ``VIDIOC_SUBDEV_S_ROUTING`` is

View File

@ -1086,7 +1086,6 @@ F: include/soc/amlogic/
AMPHION VPU CODEC V4L2 DRIVER
M: Ming Qian <ming.qian@nxp.com>
M: Shijie Qin <shijie.qin@nxp.com>
M: Zhou Peng <eagle.zhou@nxp.com>
L: linux-media@vger.kernel.org
S: Maintained
@ -4469,6 +4468,7 @@ M: Maxime Ripard <mripard@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/cdns,*.txt
F: Documentation/devicetree/bindings/media/cdns,csi2rx.yaml
F: drivers/media/platform/cadence/cdns-csi2*
CADENCE NAND DRIVER
@ -6275,11 +6275,17 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9714.yaml
F: drivers/media/i2c/dw9714.c
DONGWOON DW9768 LENS VOICE COIL DRIVER
M: Dongchun Zhu <dongchun.zhu@mediatek.com>
DONGWOON DW9719 LENS VOICE COIL DRIVER
M: Daniel Scally <djrscally@gmail.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/dw9719.c
DONGWOON DW9768 LENS VOICE COIL DRIVER
L: linux-media@vger.kernel.org
S: Orphan
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9768.yaml
F: drivers/media/i2c/dw9768.c
@ -9668,7 +9674,7 @@ S: Maintained
F: arch/x86/kernel/cpu/hygon.c
HYNIX HI556 SENSOR DRIVER
M: Shawn Tu <shawnx.tu@intel.com>
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
@ -9681,7 +9687,7 @@ S: Maintained
F: drivers/media/i2c/hi846.c
HYNIX HI847 SENSOR DRIVER
M: Shawn Tu <shawnx.tu@intel.com>
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/i2c/hi847.c
@ -9752,6 +9758,14 @@ L: linux-acpi@vger.kernel.org
S: Maintained
F: drivers/i2c/i2c-core-acpi.c
I2C ADDRESS TRANSLATOR (ATR)
M: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
R: Luca Ceresoli <luca.ceresoli@bootlin.com>
L: linux-i2c@vger.kernel.org
S: Maintained
F: drivers/i2c/i2c-atr.c
F: include/linux/i2c-atr.h
I2C CONTROLLER DRIVER FOR NVIDIA GPU
M: Ajay Gupta <ajayg@nvidia.com>
L: linux-i2c@vger.kernel.org
@ -13094,17 +13108,21 @@ F: drivers/staging/media/imx/
F: include/linux/imx-media.h
F: include/media/imx.h
MEDIA DRIVERS FOR FREESCALE IMX7
MEDIA DRIVERS FOR FREESCALE IMX7/8
M: Rui Miguel Silva <rmfrfs@gmail.com>
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
M: Martin Kepplinger <martin.kepplinger@puri.sm>
R: Purism Kernel Team <kernel@puri.sm>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/admin-guide/media/imx7.rst
F: Documentation/devicetree/bindings/media/nxp,imx-mipi-csi2.yaml
F: Documentation/devicetree/bindings/media/nxp,imx7-csi.yaml
F: Documentation/devicetree/bindings/media/nxp,imx8mq-mipi-csi2.yaml
F: drivers/media/platform/nxp/imx-mipi-csis.c
F: drivers/media/platform/nxp/imx7-media-csi.c
F: drivers/media/platform/nxp/imx8mq-mipi-csi2.c
MEDIA DRIVERS FOR HELENE
M: Abylay Ospan <aospan@netup.ru>
@ -15652,7 +15670,7 @@ F: Documentation/filesystems/omfs.rst
F: fs/omfs/
OMNIVISION OG01A1B SENSOR DRIVER
M: Shawn Tu <shawnx.tu@intel.com>
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/i2c/og01a1b.c
@ -15665,9 +15683,8 @@ T: git git://linuxtv.org/media_tree.git
F: drivers/media/i2c/ov01a10.c
OMNIVISION OV02A10 SENSOR DRIVER
M: Dongchun Zhu <dongchun.zhu@mediatek.com>
L: linux-media@vger.kernel.org
S: Maintained
S: Orphan
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov02a10.yaml
F: drivers/media/i2c/ov02a10.c
@ -15702,6 +15719,7 @@ F: drivers/media/i2c/ov13b10.c
OMNIVISION OV2680 SENSOR DRIVER
M: Rui Miguel Silva <rmfrfs@gmail.com>
M: Hans de Goede <hansg@kernel.org>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
@ -15718,7 +15736,7 @@ F: drivers/media/i2c/ov2685.c
OMNIVISION OV2740 SENSOR DRIVER
M: Tianshu Qiu <tian.shu.qiu@intel.com>
R: Shawn Tu <shawnx.tu@intel.com>
R: Sakari Ailus <sakari.ailus@linux.intel.com>
R: Bingbu Cao <bingbu.cao@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
@ -15750,7 +15768,7 @@ F: Documentation/devicetree/bindings/media/i2c/ovti,ov5647.yaml
F: drivers/media/i2c/ov5647.c
OMNIVISION OV5670 SENSOR DRIVER
M: Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
@ -15758,7 +15776,7 @@ F: Documentation/devicetree/bindings/media/i2c/ovti,ov5670.yaml
F: drivers/media/i2c/ov5670.c
OMNIVISION OV5675 SENSOR DRIVER
M: Shawn Tu <shawnx.tu@intel.com>
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
@ -15797,9 +15815,8 @@ F: drivers/media/i2c/ov772x.c
F: include/media/i2c/ov772x.h
OMNIVISION OV7740 SENSOR DRIVER
M: Wenyou Yang <wenyou.yang@microchip.com>
L: linux-media@vger.kernel.org
S: Maintained
S: Orphan
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ov7740.txt
F: drivers/media/i2c/ov7740.c
@ -21503,6 +21520,14 @@ F: drivers/misc/tifm*
F: drivers/mmc/host/tifm_sd.c
F: include/linux/tifm.h
TI FPD-LINK DRIVERS
M: Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/i2c/ti,ds90*
F: drivers/media/i2c/ds90*
F: include/media/i2c/ds90*
TI KEYSTONE MULTICORE NAVIGATOR DRIVERS
M: Nishanth Menon <nm@ti.com>
M: Santosh Shilimkar <ssantosh@kernel.org>
@ -22447,6 +22472,39 @@ L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: drivers/clk/ux500/
V4L2 ASYNC AND FWNODE FRAMEWORKS
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: drivers/media/v4l2-core/v4l2-async.c
F: drivers/media/v4l2-core/v4l2-fwnode.c
F: include/media/v4l2-async.h
F: include/media/v4l2-fwnode.h
V4L2 LENS DRIVERS
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/i2c/ak*
F: drivers/media/i2c/dw*
F: drivers/media/i2c/lm*
V4L2 CAMERA SENSOR DRIVERS
M: Sakari Ailus <sakari.ailus@linux.intel.com>
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/driver-api/media/camera-sensor.rst
F: Documentation/driver-api/media/tx-rx.rst
F: drivers/media/i2c/ar*
F: drivers/media/i2c/hi*
F: drivers/media/i2c/imx*
F: drivers/media/i2c/mt*
F: drivers/media/i2c/og*
F: drivers/media/i2c/ov*
F: drivers/media/i2c/s5*
F: drivers/media/i2c/st-vgxy61.c
VF610 NAND DRIVER
M: Stefan Agner <stefan@agner.ch>
L: linux-mtd@lists.infradead.org

View File

@ -1159,7 +1159,6 @@ CONFIG_XEN_GNTDEV=y
CONFIG_XEN_GRANT_DEV_ALLOC=y
CONFIG_STAGING=y
CONFIG_STAGING_MEDIA=y
CONFIG_VIDEO_IMX_MEDIA=m
CONFIG_VIDEO_MAX96712=m
CONFIG_CHROME_PLATFORMS=y
CONFIG_CROS_EC=y

View File

@ -71,6 +71,15 @@ config I2C_MUX
source "drivers/i2c/muxes/Kconfig"
config I2C_ATR
tristate "I2C Address Translator (ATR) support"
help
Enable support for I2C Address Translator (ATR) chips.
An ATR allows accessing multiple I2C busses from a single
physical bus via address translation instead of bus selection as
i2c-muxes do.
config I2C_HELPER_AUTO
bool "Autoselect pertinent helper modules"
default y

View File

@ -13,6 +13,7 @@ i2c-core-$(CONFIG_OF) += i2c-core-of.o
obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
obj-$(CONFIG_I2C_MUX) += i2c-mux.o
obj-$(CONFIG_I2C_ATR) += i2c-atr.o
obj-y += algos/ busses/ muxes/
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_I2C_SLAVE_EEPROM) += i2c-slave-eeprom.o

710
drivers/i2c/i2c-atr.c Normal file
View File

@ -0,0 +1,710 @@
// SPDX-License-Identifier: GPL-2.0
/*
* I2C Address Translator
*
* Copyright (c) 2019,2022 Luca Ceresoli <luca@lucaceresoli.net>
* Copyright (c) 2022,2023 Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
*
* Originally based on i2c-mux.c
*/
#include <linux/fwnode.h>
#include <linux/i2c-atr.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#define ATR_MAX_ADAPTERS 100 /* Just a sanity limit */
#define ATR_MAX_SYMLINK_LEN 11 /* Longest name is 10 chars: "channel-99" */
/**
* struct i2c_atr_alias_pair - Holds the alias assigned to a client.
* @node: List node
* @client: Pointer to the client on the child bus
* @alias: I2C alias address assigned by the driver.
* This is the address that will be used to issue I2C transactions
* on the parent (physical) bus.
*/
struct i2c_atr_alias_pair {
struct list_head node;
const struct i2c_client *client;
u16 alias;
};
/**
* struct i2c_atr_chan - Data for a channel.
* @adap: The &struct i2c_adapter for the channel
* @atr: The parent I2C ATR
* @chan_id: The ID of this channel
* @alias_list: List of @struct i2c_atr_alias_pair containing the
* assigned aliases
* @orig_addrs_lock: Mutex protecting @orig_addrs
* @orig_addrs: Buffer used to store the original addresses during transmit
* @orig_addrs_size: Size of @orig_addrs
*/
struct i2c_atr_chan {
struct i2c_adapter adap;
struct i2c_atr *atr;
u32 chan_id;
struct list_head alias_list;
/* Lock orig_addrs during xfer */
struct mutex orig_addrs_lock;
u16 *orig_addrs;
unsigned int orig_addrs_size;
};
/**
* struct i2c_atr - The I2C ATR instance
* @parent: The parent &struct i2c_adapter
* @dev: The device that owns the I2C ATR instance
* @ops: &struct i2c_atr_ops
* @priv: Private driver data, set with i2c_atr_set_driver_data()
* @algo: The &struct i2c_algorithm for adapters
* @lock: Lock for the I2C bus segment (see &struct i2c_lock_operations)
* @max_adapters: Maximum number of adapters this I2C ATR can have
* @num_aliases: Number of aliases in the aliases array
* @aliases: The aliases array
* @alias_mask_lock: Lock protecting alias_use_mask
* @alias_use_mask: Bitmask for used aliases in aliases array
* @i2c_nb: Notifier for remote client add & del events
* @adapter: Array of adapters
*/
struct i2c_atr {
struct i2c_adapter *parent;
struct device *dev;
const struct i2c_atr_ops *ops;
void *priv;
struct i2c_algorithm algo;
/* lock for the I2C bus segment (see struct i2c_lock_operations) */
struct mutex lock;
int max_adapters;
size_t num_aliases;
const u16 *aliases;
/* Protects alias_use_mask */
spinlock_t alias_mask_lock;
unsigned long *alias_use_mask;
struct notifier_block i2c_nb;
struct i2c_adapter *adapter[];
};
static struct i2c_atr_alias_pair *
i2c_atr_find_mapping_by_client(const struct list_head *list,
const struct i2c_client *client)
{
struct i2c_atr_alias_pair *c2a;
list_for_each_entry(c2a, list, node) {
if (c2a->client == client)
return c2a;
}
return NULL;
}
static struct i2c_atr_alias_pair *
i2c_atr_find_mapping_by_addr(const struct list_head *list, u16 phys_addr)
{
struct i2c_atr_alias_pair *c2a;
list_for_each_entry(c2a, list, node) {
if (c2a->client->addr == phys_addr)
return c2a;
}
return NULL;
}
/*
* Replace all message addresses with their aliases, saving the original
* addresses.
*
* This function is internal for use in i2c_atr_master_xfer(). It must be
* followed by i2c_atr_unmap_msgs() to restore the original addresses.
*/
static int i2c_atr_map_msgs(struct i2c_atr_chan *chan, struct i2c_msg *msgs,
int num)
{
struct i2c_atr *atr = chan->atr;
static struct i2c_atr_alias_pair *c2a;
int i;
/* Ensure we have enough room to save the original addresses */
if (unlikely(chan->orig_addrs_size < num)) {
u16 *new_buf;
/* We don't care about old data, hence no realloc() */
new_buf = kmalloc_array(num, sizeof(*new_buf), GFP_KERNEL);
if (!new_buf)
return -ENOMEM;
kfree(chan->orig_addrs);
chan->orig_addrs = new_buf;
chan->orig_addrs_size = num;
}
for (i = 0; i < num; i++) {
chan->orig_addrs[i] = msgs[i].addr;
c2a = i2c_atr_find_mapping_by_addr(&chan->alias_list,
msgs[i].addr);
if (!c2a) {
dev_err(atr->dev, "client 0x%02x not mapped!\n",
msgs[i].addr);
while (i--)
msgs[i].addr = chan->orig_addrs[i];
return -ENXIO;
}
msgs[i].addr = c2a->alias;
}
return 0;
}
/*
* Restore all message address aliases with the original addresses. This
* function is internal for use in i2c_atr_master_xfer() and for this reason it
* needs no null and size checks on orig_addr.
*
* @see i2c_atr_map_msgs()
*/
static void i2c_atr_unmap_msgs(struct i2c_atr_chan *chan, struct i2c_msg *msgs,
int num)
{
int i;
for (i = 0; i < num; i++)
msgs[i].addr = chan->orig_addrs[i];
}
static int i2c_atr_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num)
{
struct i2c_atr_chan *chan = adap->algo_data;
struct i2c_atr *atr = chan->atr;
struct i2c_adapter *parent = atr->parent;
int ret;
/* Translate addresses */
mutex_lock(&chan->orig_addrs_lock);
ret = i2c_atr_map_msgs(chan, msgs, num);
if (ret < 0)
goto err_unlock;
/* Perform the transfer */
ret = i2c_transfer(parent, msgs, num);
/* Restore addresses */
i2c_atr_unmap_msgs(chan, msgs, num);
err_unlock:
mutex_unlock(&chan->orig_addrs_lock);
return ret;
}
static int i2c_atr_smbus_xfer(struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write, u8 command,
int size, union i2c_smbus_data *data)
{
struct i2c_atr_chan *chan = adap->algo_data;
struct i2c_atr *atr = chan->atr;
struct i2c_adapter *parent = atr->parent;
struct i2c_atr_alias_pair *c2a;
c2a = i2c_atr_find_mapping_by_addr(&chan->alias_list, addr);
if (!c2a) {
dev_err(atr->dev, "client 0x%02x not mapped!\n", addr);
return -ENXIO;
}
return i2c_smbus_xfer(parent, c2a->alias, flags, read_write, command,
size, data);
}
static u32 i2c_atr_functionality(struct i2c_adapter *adap)
{
struct i2c_atr_chan *chan = adap->algo_data;
struct i2c_adapter *parent = chan->atr->parent;
return parent->algo->functionality(parent);
}
static void i2c_atr_lock_bus(struct i2c_adapter *adapter, unsigned int flags)
{
struct i2c_atr_chan *chan = adapter->algo_data;
struct i2c_atr *atr = chan->atr;
mutex_lock(&atr->lock);
}
static int i2c_atr_trylock_bus(struct i2c_adapter *adapter, unsigned int flags)
{
struct i2c_atr_chan *chan = adapter->algo_data;
struct i2c_atr *atr = chan->atr;
return mutex_trylock(&atr->lock);
}
static void i2c_atr_unlock_bus(struct i2c_adapter *adapter, unsigned int flags)
{
struct i2c_atr_chan *chan = adapter->algo_data;
struct i2c_atr *atr = chan->atr;
mutex_unlock(&atr->lock);
}
static const struct i2c_lock_operations i2c_atr_lock_ops = {
.lock_bus = i2c_atr_lock_bus,
.trylock_bus = i2c_atr_trylock_bus,
.unlock_bus = i2c_atr_unlock_bus,
};
static int i2c_atr_reserve_alias(struct i2c_atr *atr)
{
unsigned long idx;
spin_lock(&atr->alias_mask_lock);
idx = find_first_zero_bit(atr->alias_use_mask, atr->num_aliases);
if (idx >= atr->num_aliases) {
spin_unlock(&atr->alias_mask_lock);
dev_err(atr->dev, "failed to find a free alias\n");
return -EBUSY;
}
set_bit(idx, atr->alias_use_mask);
spin_unlock(&atr->alias_mask_lock);
return atr->aliases[idx];
}
static void i2c_atr_release_alias(struct i2c_atr *atr, u16 alias)
{
unsigned int idx;
spin_lock(&atr->alias_mask_lock);
for (idx = 0; idx < atr->num_aliases; ++idx) {
if (atr->aliases[idx] == alias) {
clear_bit(idx, atr->alias_use_mask);
spin_unlock(&atr->alias_mask_lock);
return;
}
}
spin_unlock(&atr->alias_mask_lock);
/* This should never happen */
dev_warn(atr->dev, "Unable to find mapped alias\n");
}
static int i2c_atr_attach_client(struct i2c_adapter *adapter,
const struct i2c_client *client)
{
struct i2c_atr_chan *chan = adapter->algo_data;
struct i2c_atr *atr = chan->atr;
struct i2c_atr_alias_pair *c2a;
u16 alias;
int ret;
ret = i2c_atr_reserve_alias(atr);
if (ret < 0)
return ret;
alias = ret;
c2a = kzalloc(sizeof(*c2a), GFP_KERNEL);
if (!c2a) {
ret = -ENOMEM;
goto err_release_alias;
}
ret = atr->ops->attach_client(atr, chan->chan_id, client, alias);
if (ret)
goto err_free;
dev_dbg(atr->dev, "chan%u: client 0x%02x mapped at alias 0x%02x (%s)\n",
chan->chan_id, client->addr, alias, client->name);
c2a->client = client;
c2a->alias = alias;
list_add(&c2a->node, &chan->alias_list);
return 0;
err_free:
kfree(c2a);
err_release_alias:
i2c_atr_release_alias(atr, alias);
return ret;
}
static void i2c_atr_detach_client(struct i2c_adapter *adapter,
const struct i2c_client *client)
{
struct i2c_atr_chan *chan = adapter->algo_data;
struct i2c_atr *atr = chan->atr;
struct i2c_atr_alias_pair *c2a;
atr->ops->detach_client(atr, chan->chan_id, client);
c2a = i2c_atr_find_mapping_by_client(&chan->alias_list, client);
if (!c2a) {
/* This should never happen */
dev_warn(atr->dev, "Unable to find address mapping\n");
return;
}
i2c_atr_release_alias(atr, c2a->alias);
dev_dbg(atr->dev,
"chan%u: client 0x%02x unmapped from alias 0x%02x (%s)\n",
chan->chan_id, client->addr, c2a->alias, client->name);
list_del(&c2a->node);
kfree(c2a);
}
static int i2c_atr_bus_notifier_call(struct notifier_block *nb,
unsigned long event, void *device)
{
struct i2c_atr *atr = container_of(nb, struct i2c_atr, i2c_nb);
struct device *dev = device;
struct i2c_client *client;
u32 chan_id;
int ret;
client = i2c_verify_client(dev);
if (!client)
return NOTIFY_DONE;
/* Is the client in one of our adapters? */
for (chan_id = 0; chan_id < atr->max_adapters; ++chan_id) {
if (client->adapter == atr->adapter[chan_id])
break;
}
if (chan_id == atr->max_adapters)
return NOTIFY_DONE;
switch (event) {
case BUS_NOTIFY_ADD_DEVICE:
ret = i2c_atr_attach_client(client->adapter, client);
if (ret)
dev_err(atr->dev,
"Failed to attach remote client '%s': %d\n",
dev_name(dev), ret);
break;
case BUS_NOTIFY_DEL_DEVICE:
i2c_atr_detach_client(client->adapter, client);
break;
default:
break;
}
return NOTIFY_DONE;
}
static int i2c_atr_parse_alias_pool(struct i2c_atr *atr)
{
struct device *dev = atr->dev;
unsigned long *alias_use_mask;
size_t num_aliases;
unsigned int i;
u32 *aliases32;
u16 *aliases16;
int ret;
ret = fwnode_property_count_u32(dev_fwnode(dev), "i2c-alias-pool");
if (ret < 0) {
dev_err(dev, "Failed to count 'i2c-alias-pool' property: %d\n",
ret);
return ret;
}
num_aliases = ret;
if (!num_aliases)
return 0;
aliases32 = kcalloc(num_aliases, sizeof(*aliases32), GFP_KERNEL);
if (!aliases32)
return -ENOMEM;
ret = fwnode_property_read_u32_array(dev_fwnode(dev), "i2c-alias-pool",
aliases32, num_aliases);
if (ret < 0) {
dev_err(dev, "Failed to read 'i2c-alias-pool' property: %d\n",
ret);
goto err_free_aliases32;
}
aliases16 = kcalloc(num_aliases, sizeof(*aliases16), GFP_KERNEL);
if (!aliases16) {
ret = -ENOMEM;
goto err_free_aliases32;
}
for (i = 0; i < num_aliases; i++) {
if (!(aliases32[i] & 0xffff0000)) {
aliases16[i] = aliases32[i];
continue;
}
dev_err(dev, "Failed to parse 'i2c-alias-pool' property: I2C flags are not supported\n");
ret = -EINVAL;
goto err_free_aliases16;
}
alias_use_mask = bitmap_zalloc(num_aliases, GFP_KERNEL);
if (!alias_use_mask) {
ret = -ENOMEM;
goto err_free_aliases16;
}
kfree(aliases32);
atr->num_aliases = num_aliases;
atr->aliases = aliases16;
atr->alias_use_mask = alias_use_mask;
dev_dbg(dev, "i2c-alias-pool has %zu aliases", atr->num_aliases);
return 0;
err_free_aliases16:
kfree(aliases16);
err_free_aliases32:
kfree(aliases32);
return ret;
}
struct i2c_atr *i2c_atr_new(struct i2c_adapter *parent, struct device *dev,
const struct i2c_atr_ops *ops, int max_adapters)
{
struct i2c_atr *atr;
int ret;
if (max_adapters > ATR_MAX_ADAPTERS)
return ERR_PTR(-EINVAL);
if (!ops || !ops->attach_client || !ops->detach_client)
return ERR_PTR(-EINVAL);
atr = kzalloc(struct_size(atr, adapter, max_adapters), GFP_KERNEL);
if (!atr)
return ERR_PTR(-ENOMEM);
mutex_init(&atr->lock);
spin_lock_init(&atr->alias_mask_lock);
atr->parent = parent;
atr->dev = dev;
atr->ops = ops;
atr->max_adapters = max_adapters;
if (parent->algo->master_xfer)
atr->algo.master_xfer = i2c_atr_master_xfer;
if (parent->algo->smbus_xfer)
atr->algo.smbus_xfer = i2c_atr_smbus_xfer;
atr->algo.functionality = i2c_atr_functionality;
ret = i2c_atr_parse_alias_pool(atr);
if (ret)
goto err_destroy_mutex;
atr->i2c_nb.notifier_call = i2c_atr_bus_notifier_call;
ret = bus_register_notifier(&i2c_bus_type, &atr->i2c_nb);
if (ret)
goto err_free_aliases;
return atr;
err_free_aliases:
bitmap_free(atr->alias_use_mask);
kfree(atr->aliases);
err_destroy_mutex:
mutex_destroy(&atr->lock);
kfree(atr);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_NS_GPL(i2c_atr_new, I2C_ATR);
void i2c_atr_delete(struct i2c_atr *atr)
{
unsigned int i;
for (i = 0; i < atr->max_adapters; ++i)
WARN_ON(atr->adapter[i]);
bus_unregister_notifier(&i2c_bus_type, &atr->i2c_nb);
bitmap_free(atr->alias_use_mask);
kfree(atr->aliases);
mutex_destroy(&atr->lock);
kfree(atr);
}
EXPORT_SYMBOL_NS_GPL(i2c_atr_delete, I2C_ATR);
int i2c_atr_add_adapter(struct i2c_atr *atr, u32 chan_id,
struct device *adapter_parent,
struct fwnode_handle *bus_handle)
{
struct i2c_adapter *parent = atr->parent;
struct device *dev = atr->dev;
struct i2c_atr_chan *chan;
char symlink_name[ATR_MAX_SYMLINK_LEN];
int ret;
if (chan_id >= atr->max_adapters) {
dev_err(dev, "No room for more i2c-atr adapters\n");
return -EINVAL;
}
if (atr->adapter[chan_id]) {
dev_err(dev, "Adapter %d already present\n", chan_id);
return -EEXIST;
}
chan = kzalloc(sizeof(*chan), GFP_KERNEL);
if (!chan)
return -ENOMEM;
if (!adapter_parent)
adapter_parent = dev;
chan->atr = atr;
chan->chan_id = chan_id;
INIT_LIST_HEAD(&chan->alias_list);
mutex_init(&chan->orig_addrs_lock);
snprintf(chan->adap.name, sizeof(chan->adap.name), "i2c-%d-atr-%d",
i2c_adapter_id(parent), chan_id);
chan->adap.owner = THIS_MODULE;
chan->adap.algo = &atr->algo;
chan->adap.algo_data = chan;
chan->adap.dev.parent = adapter_parent;
chan->adap.retries = parent->retries;
chan->adap.timeout = parent->timeout;
chan->adap.quirks = parent->quirks;
chan->adap.lock_ops = &i2c_atr_lock_ops;
if (bus_handle) {
device_set_node(&chan->adap.dev, fwnode_handle_get(bus_handle));
} else {
struct fwnode_handle *atr_node;
struct fwnode_handle *child;
u32 reg;
atr_node = device_get_named_child_node(dev, "i2c-atr");
fwnode_for_each_child_node(atr_node, child) {
ret = fwnode_property_read_u32(child, "reg", &reg);
if (ret)
continue;
if (chan_id == reg)
break;
}
device_set_node(&chan->adap.dev, child);
fwnode_handle_put(atr_node);
}
atr->adapter[chan_id] = &chan->adap;
ret = i2c_add_adapter(&chan->adap);
if (ret) {
dev_err(dev, "failed to add atr-adapter %u (error=%d)\n",
chan_id, ret);
goto err_fwnode_put;
}
snprintf(symlink_name, sizeof(symlink_name), "channel-%u",
chan->chan_id);
ret = sysfs_create_link(&chan->adap.dev.kobj, &dev->kobj, "atr_device");
if (ret)
dev_warn(dev, "can't create symlink to atr device\n");
ret = sysfs_create_link(&dev->kobj, &chan->adap.dev.kobj, symlink_name);
if (ret)
dev_warn(dev, "can't create symlink for channel %u\n", chan_id);
dev_dbg(dev, "Added ATR child bus %d\n", i2c_adapter_id(&chan->adap));
return 0;
err_fwnode_put:
fwnode_handle_put(dev_fwnode(&chan->adap.dev));
mutex_destroy(&chan->orig_addrs_lock);
kfree(chan);
return ret;
}
EXPORT_SYMBOL_NS_GPL(i2c_atr_add_adapter, I2C_ATR);
void i2c_atr_del_adapter(struct i2c_atr *atr, u32 chan_id)
{
char symlink_name[ATR_MAX_SYMLINK_LEN];
struct i2c_adapter *adap;
struct i2c_atr_chan *chan;
struct fwnode_handle *fwnode;
struct device *dev = atr->dev;
adap = atr->adapter[chan_id];
if (!adap)
return;
chan = adap->algo_data;
fwnode = dev_fwnode(&adap->dev);
dev_dbg(dev, "Removing ATR child bus %d\n", i2c_adapter_id(adap));
snprintf(symlink_name, sizeof(symlink_name), "channel-%u",
chan->chan_id);
sysfs_remove_link(&dev->kobj, symlink_name);
sysfs_remove_link(&chan->adap.dev.kobj, "atr_device");
i2c_del_adapter(adap);
atr->adapter[chan_id] = NULL;
fwnode_handle_put(fwnode);
mutex_destroy(&chan->orig_addrs_lock);
kfree(chan->orig_addrs);
kfree(chan);
}
EXPORT_SYMBOL_NS_GPL(i2c_atr_del_adapter, I2C_ATR);
void i2c_atr_set_driver_data(struct i2c_atr *atr, void *data)
{
atr->priv = data;
}
EXPORT_SYMBOL_NS_GPL(i2c_atr_set_driver_data, I2C_ATR);
void *i2c_atr_get_driver_data(struct i2c_atr *atr)
{
return atr->priv;
}
EXPORT_SYMBOL_NS_GPL(i2c_atr_get_driver_data, I2C_ATR);
MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>");
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
MODULE_DESCRIPTION("I2C Address Translator");
MODULE_LICENSE("GPL");

View File

@ -385,8 +385,8 @@ static void cec_data_cancel(struct cec_data *data, u8 tx_status, u8 rx_status)
cec_queue_msg_monitor(adap, &data->msg, 1);
if (!data->blocking && data->msg.sequence)
/* Allow drivers to process the message first */
call_op(adap, received, &data->msg);
/* Allow drivers to react to a canceled transmit */
call_void_op(adap, adap_nb_transmit_canceled, &data->msg);
cec_data_completed(data);
}
@ -1348,7 +1348,7 @@ static void cec_adap_unconfigure(struct cec_adapter *adap)
cec_flush(adap);
wake_up_interruptible(&adap->kthread_waitq);
cec_post_state_event(adap);
call_void_op(adap, adap_configured, false);
call_void_op(adap, adap_unconfigured);
}
/*
@ -1539,7 +1539,7 @@ configured:
adap->kthread_config = NULL;
complete(&adap->config_completion);
mutex_unlock(&adap->lock);
call_void_op(adap, adap_configured, true);
call_void_op(adap, configured);
return 0;
unconfigure:

View File

@ -7,6 +7,7 @@
*/
#include <linux/export.h>
#include <linux/platform_device.h>
#include <linux/string.h>
#include <linux/slab.h>
#include <linux/i2c.h>

View File

@ -183,6 +183,7 @@ struct cec_pin {
u16 la_mask;
bool monitor_all;
bool rx_eom;
bool enabled_irq;
bool enable_irq_failed;
enum cec_pin_state state;
struct cec_msg tx_msg;

View File

@ -982,7 +982,7 @@ static enum hrtimer_restart cec_pin_timer(struct hrtimer *timer)
}
if (pin->state != CEC_ST_IDLE || pin->ops->enable_irq == NULL ||
pin->enable_irq_failed || adap->is_configuring ||
adap->is_configured || adap->monitor_all_cnt)
adap->is_configured || adap->monitor_all_cnt || !adap->monitor_pin_cnt)
break;
/* Switch to interrupt mode */
atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_ENABLE);
@ -1033,8 +1033,9 @@ static int cec_pin_thread_func(void *_adap)
{
struct cec_adapter *adap = _adap;
struct cec_pin *pin = adap->pin;
bool irq_enabled = false;
pin->enabled_irq = false;
pin->enable_irq_failed = false;
for (;;) {
wait_event_interruptible(pin->kthread_waitq,
kthread_should_stop() ||
@ -1088,9 +1089,10 @@ static int cec_pin_thread_func(void *_adap)
switch (atomic_xchg(&pin->work_irq_change,
CEC_PIN_IRQ_UNCHANGED)) {
case CEC_PIN_IRQ_DISABLE:
if (irq_enabled) {
call_void_pin_op(pin, disable_irq);
irq_enabled = false;
if (pin->enabled_irq) {
pin->ops->disable_irq(adap);
pin->enabled_irq = false;
pin->enable_irq_failed = false;
}
cec_pin_high(pin);
if (pin->state == CEC_ST_OFF)
@ -1100,21 +1102,29 @@ static int cec_pin_thread_func(void *_adap)
HRTIMER_MODE_REL);
break;
case CEC_PIN_IRQ_ENABLE:
if (irq_enabled)
if (pin->enabled_irq || !pin->ops->enable_irq ||
pin->adap->devnode.unregistered)
break;
pin->enable_irq_failed = !call_pin_op(pin, enable_irq);
pin->enable_irq_failed = !pin->ops->enable_irq(adap);
if (pin->enable_irq_failed) {
cec_pin_to_idle(pin);
hrtimer_start(&pin->timer, ns_to_ktime(0),
HRTIMER_MODE_REL);
} else {
irq_enabled = true;
pin->enabled_irq = true;
}
break;
default:
break;
}
}
if (pin->enabled_irq) {
pin->ops->disable_irq(pin->adap);
pin->enabled_irq = false;
pin->enable_irq_failed = false;
cec_pin_high(pin);
}
return 0;
}
@ -1215,7 +1225,9 @@ static void cec_pin_adap_status(struct cec_adapter *adap,
seq_printf(file, "cec pin: %d\n", call_pin_op(pin, read));
seq_printf(file, "cec pin events dropped: %u\n",
pin->work_pin_events_dropped_cnt);
seq_printf(file, "irq failed: %d\n", pin->enable_irq_failed);
if (pin->ops->enable_irq)
seq_printf(file, "irq %s\n", pin->enabled_irq ? "enabled" :
(pin->enable_irq_failed ? "failed" : "disabled"));
if (pin->timer_100us_overruns) {
seq_printf(file, "timer overruns > 100us: %u of %u\n",
pin->timer_100us_overruns, pin->timer_cnt);
@ -1305,7 +1317,7 @@ void cec_pin_changed(struct cec_adapter *adap, bool value)
cec_pin_update(pin, value, false);
if (!value && (adap->is_configuring || adap->is_configured ||
adap->monitor_all_cnt))
adap->monitor_all_cnt || !adap->monitor_pin_cnt))
atomic_set(&pin->work_irq_change, CEC_PIN_IRQ_DISABLE);
}
EXPORT_SYMBOL_GPL(cec_pin_changed);

View File

@ -589,7 +589,7 @@ MODULE_DEVICE_TABLE(of, ch7322_of_match);
static struct i2c_driver ch7322_i2c_driver = {
.driver = {
.name = "ch7322",
.of_match_table = of_match_ptr(ch7322_of_match),
.of_match_table = ch7322_of_match,
},
.probe = ch7322_probe,
.remove = ch7322_remove,

View File

@ -159,11 +159,6 @@ static int cec_gpio_read_5v(struct cec_adapter *adap)
return gpiod_get_value(cec->v5_gpio);
}
static void cec_gpio_free(struct cec_adapter *adap)
{
cec_gpio_disable_irq(adap);
}
static const struct cec_pin_ops cec_gpio_pin_ops = {
.read = cec_gpio_read,
.low = cec_gpio_low,
@ -171,7 +166,6 @@ static const struct cec_pin_ops cec_gpio_pin_ops = {
.enable_irq = cec_gpio_enable_irq,
.disable_irq = cec_gpio_disable_irq,
.status = cec_gpio_status,
.free = cec_gpio_free,
.read_hpd = cec_gpio_read_hpd,
.read_5v = cec_gpio_read_5v,
};
@ -215,13 +209,11 @@ static int cec_gpio_probe(struct platform_device *pdev)
return PTR_ERR(cec->adap);
ret = devm_request_irq(dev, cec->cec_irq, cec_gpio_irq_handler,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN,
cec->adap->name, cec);
if (ret)
goto del_adap;
cec_gpio_disable_irq(cec->adap);
if (cec->hpd_gpio) {
cec->hpd_irq = gpiod_to_irq(cec->hpd_gpio);
ret = devm_request_threaded_irq(dev, cec->hpd_irq,

View File

@ -717,7 +717,7 @@ static struct platform_driver meson_ao_cec_driver = {
.remove_new = meson_ao_cec_remove,
.driver = {
.name = "meson-ao-cec",
.of_match_table = of_match_ptr(meson_ao_cec_of_match),
.of_match_table = meson_ao_cec_of_match,
},
};

View File

@ -10,7 +10,6 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

View File

@ -348,8 +348,8 @@ static int tegra_cec_probe(struct platform_device *pdev)
cec->tegra_cec_irq = platform_get_irq(pdev, 0);
if (cec->tegra_cec_irq <= 0)
return -EBUSY;
if (cec->tegra_cec_irq < 0)
return cec->tegra_cec_irq;
cec->cec_base = devm_ioremap(&pdev->dev, res->start,
resource_size(res));
@ -462,7 +462,7 @@ static const struct of_device_id tegra_cec_of_match[] = {
static struct platform_driver tegra_cec_driver = {
.driver = {
.name = TEGRA_CEC_NAME,
.of_match_table = of_match_ptr(tegra_cec_of_match),
.of_match_table = tegra_cec_of_match,
},
.probe = tegra_cec_probe,
.remove_new = tegra_cec_remove,

View File

@ -45,89 +45,48 @@ static void smsdvb_print_dvb_stats(struct smsdvb_debugfs *debug_data,
buf = debug_data->stats_data;
n += scnprintf(&buf[n], PAGE_SIZE - n,
"is_rf_locked = %d\n", p->is_rf_locked);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"is_demod_locked = %d\n", p->is_demod_locked);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"is_external_lna_on = %d\n", p->is_external_lna_on);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"SNR = %d\n", p->SNR);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"ber = %d\n", p->ber);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"FIB_CRC = %d\n", p->FIB_CRC);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"ts_per = %d\n", p->ts_per);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"MFER = %d\n", p->MFER);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"RSSI = %d\n", p->RSSI);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"in_band_pwr = %d\n", p->in_band_pwr);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"carrier_offset = %d\n", p->carrier_offset);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"modem_state = %d\n", p->modem_state);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"frequency = %d\n", p->frequency);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"bandwidth = %d\n", p->bandwidth);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"transmission_mode = %d\n", p->transmission_mode);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"modem_state = %d\n", p->modem_state);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"guard_interval = %d\n", p->guard_interval);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"code_rate = %d\n", p->code_rate);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"lp_code_rate = %d\n", p->lp_code_rate);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"hierarchy = %d\n", p->hierarchy);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"constellation = %d\n", p->constellation);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"burst_size = %d\n", p->burst_size);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"burst_duration = %d\n", p->burst_duration);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"burst_cycle_time = %d\n", p->burst_cycle_time);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"calc_burst_cycle_time = %d\n",
p->calc_burst_cycle_time);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"num_of_rows = %d\n", p->num_of_rows);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"num_of_padd_cols = %d\n", p->num_of_padd_cols);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"num_of_punct_cols = %d\n", p->num_of_punct_cols);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"error_ts_packets = %d\n", p->error_ts_packets);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"total_ts_packets = %d\n", p->total_ts_packets);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"num_of_valid_mpe_tlbs = %d\n", p->num_of_valid_mpe_tlbs);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"num_of_invalid_mpe_tlbs = %d\n", p->num_of_invalid_mpe_tlbs);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"num_of_corrected_mpe_tlbs = %d\n", p->num_of_corrected_mpe_tlbs);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"ber_error_count = %d\n", p->ber_error_count);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"ber_bit_count = %d\n", p->ber_bit_count);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"pre_ber = %d\n", p->pre_ber);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"cell_id = %d\n", p->cell_id);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"dvbh_srv_ind_hp = %d\n", p->dvbh_srv_ind_hp);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"dvbh_srv_ind_lp = %d\n", p->dvbh_srv_ind_lp);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"num_mpe_received = %d\n", p->num_mpe_received);
n += sysfs_emit_at(buf, n, "is_rf_locked = %d\n", p->is_rf_locked);
n += sysfs_emit_at(buf, n, "is_demod_locked = %d\n", p->is_demod_locked);
n += sysfs_emit_at(buf, n, "is_external_lna_on = %d\n", p->is_external_lna_on);
n += sysfs_emit_at(buf, n, "SNR = %d\n", p->SNR);
n += sysfs_emit_at(buf, n, "ber = %d\n", p->ber);
n += sysfs_emit_at(buf, n, "FIB_CRC = %d\n", p->FIB_CRC);
n += sysfs_emit_at(buf, n, "ts_per = %d\n", p->ts_per);
n += sysfs_emit_at(buf, n, "MFER = %d\n", p->MFER);
n += sysfs_emit_at(buf, n, "RSSI = %d\n", p->RSSI);
n += sysfs_emit_at(buf, n, "in_band_pwr = %d\n", p->in_band_pwr);
n += sysfs_emit_at(buf, n, "carrier_offset = %d\n", p->carrier_offset);
n += sysfs_emit_at(buf, n, "modem_state = %d\n", p->modem_state);
n += sysfs_emit_at(buf, n, "frequency = %d\n", p->frequency);
n += sysfs_emit_at(buf, n, "bandwidth = %d\n", p->bandwidth);
n += sysfs_emit_at(buf, n, "transmission_mode = %d\n", p->transmission_mode);
n += sysfs_emit_at(buf, n, "modem_state = %d\n", p->modem_state);
n += sysfs_emit_at(buf, n, "guard_interval = %d\n", p->guard_interval);
n += sysfs_emit_at(buf, n, "code_rate = %d\n", p->code_rate);
n += sysfs_emit_at(buf, n, "lp_code_rate = %d\n", p->lp_code_rate);
n += sysfs_emit_at(buf, n, "hierarchy = %d\n", p->hierarchy);
n += sysfs_emit_at(buf, n, "constellation = %d\n", p->constellation);
n += sysfs_emit_at(buf, n, "burst_size = %d\n", p->burst_size);
n += sysfs_emit_at(buf, n, "burst_duration = %d\n", p->burst_duration);
n += sysfs_emit_at(buf, n, "burst_cycle_time = %d\n", p->burst_cycle_time);
n += sysfs_emit_at(buf, n, "calc_burst_cycle_time = %d\n", p->calc_burst_cycle_time);
n += sysfs_emit_at(buf, n, "num_of_rows = %d\n", p->num_of_rows);
n += sysfs_emit_at(buf, n, "num_of_padd_cols = %d\n", p->num_of_padd_cols);
n += sysfs_emit_at(buf, n, "num_of_punct_cols = %d\n", p->num_of_punct_cols);
n += sysfs_emit_at(buf, n, "error_ts_packets = %d\n", p->error_ts_packets);
n += sysfs_emit_at(buf, n, "total_ts_packets = %d\n", p->total_ts_packets);
n += sysfs_emit_at(buf, n, "num_of_valid_mpe_tlbs = %d\n", p->num_of_valid_mpe_tlbs);
n += sysfs_emit_at(buf, n, "num_of_invalid_mpe_tlbs = %d\n", p->num_of_invalid_mpe_tlbs);
n += sysfs_emit_at(buf, n, "num_of_corrected_mpe_tlbs = %d\n",
p->num_of_corrected_mpe_tlbs);
n += sysfs_emit_at(buf, n, "ber_error_count = %d\n", p->ber_error_count);
n += sysfs_emit_at(buf, n, "ber_bit_count = %d\n", p->ber_bit_count);
n += sysfs_emit_at(buf, n, "sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
n += sysfs_emit_at(buf, n, "pre_ber = %d\n", p->pre_ber);
n += sysfs_emit_at(buf, n, "cell_id = %d\n", p->cell_id);
n += sysfs_emit_at(buf, n, "dvbh_srv_ind_hp = %d\n", p->dvbh_srv_ind_hp);
n += sysfs_emit_at(buf, n, "dvbh_srv_ind_lp = %d\n", p->dvbh_srv_ind_lp);
n += sysfs_emit_at(buf, n, "num_mpe_received = %d\n", p->num_mpe_received);
debug_data->stats_count = n;
spin_unlock(&debug_data->lock);
@ -148,78 +107,49 @@ static void smsdvb_print_isdb_stats(struct smsdvb_debugfs *debug_data,
buf = debug_data->stats_data;
n += scnprintf(&buf[n], PAGE_SIZE - n,
"statistics_type = %d\t", p->statistics_type);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"full_size = %d\n", p->full_size);
n += sysfs_emit_at(buf, n, "statistics_type = %d\t", p->statistics_type);
n += sysfs_emit_at(buf, n, "full_size = %d\n", p->full_size);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"is_rf_locked = %d\t\t", p->is_rf_locked);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"is_demod_locked = %d\t", p->is_demod_locked);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"is_external_lna_on = %d\n", p->is_external_lna_on);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"SNR = %d dB\t\t", p->SNR);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"RSSI = %d dBm\t\t", p->RSSI);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"in_band_pwr = %d dBm\n", p->in_band_pwr);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"carrier_offset = %d\t", p->carrier_offset);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"bandwidth = %d\t\t", p->bandwidth);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"frequency = %d Hz\n", p->frequency);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"transmission_mode = %d\t", p->transmission_mode);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"modem_state = %d\t\t", p->modem_state);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"guard_interval = %d\n", p->guard_interval);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"system_type = %d\t\t", p->system_type);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"partial_reception = %d\t", p->partial_reception);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"num_of_layers = %d\n", p->num_of_layers);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
n += sysfs_emit_at(buf, n, "is_rf_locked = %d\t\t", p->is_rf_locked);
n += sysfs_emit_at(buf, n, "is_demod_locked = %d\t", p->is_demod_locked);
n += sysfs_emit_at(buf, n, "is_external_lna_on = %d\n", p->is_external_lna_on);
n += sysfs_emit_at(buf, n, "SNR = %d dB\t\t", p->SNR);
n += sysfs_emit_at(buf, n, "RSSI = %d dBm\t\t", p->RSSI);
n += sysfs_emit_at(buf, n, "in_band_pwr = %d dBm\n", p->in_band_pwr);
n += sysfs_emit_at(buf, n, "carrier_offset = %d\t", p->carrier_offset);
n += sysfs_emit_at(buf, n, "bandwidth = %d\t\t", p->bandwidth);
n += sysfs_emit_at(buf, n, "frequency = %d Hz\n", p->frequency);
n += sysfs_emit_at(buf, n, "transmission_mode = %d\t", p->transmission_mode);
n += sysfs_emit_at(buf, n, "modem_state = %d\t\t", p->modem_state);
n += sysfs_emit_at(buf, n, "guard_interval = %d\n", p->guard_interval);
n += sysfs_emit_at(buf, n, "system_type = %d\t\t", p->system_type);
n += sysfs_emit_at(buf, n, "partial_reception = %d\t", p->partial_reception);
n += sysfs_emit_at(buf, n, "num_of_layers = %d\n", p->num_of_layers);
n += sysfs_emit_at(buf, n, "sms_to_host_tx_errors = %d\n", p->sms_to_host_tx_errors);
for (i = 0; i < 3; i++) {
if (p->layer_info[i].number_of_segments < 1 ||
p->layer_info[i].number_of_segments > 13)
continue;
n += scnprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
n += scnprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
p->layer_info[i].code_rate);
n += scnprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
p->layer_info[i].constellation);
n += scnprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
p->layer_info[i].ber);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"\tber_error_count = %-5d\t",
p->layer_info[i].ber_error_count);
n += scnprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
p->layer_info[i].ber_bit_count);
n += scnprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
p->layer_info[i].pre_ber);
n += scnprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
p->layer_info[i].ts_per);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"\terror_ts_packets = %-5d\t",
p->layer_info[i].error_ts_packets);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"total_ts_packets = %-5d\t",
p->layer_info[i].total_ts_packets);
n += scnprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
p->layer_info[i].ti_ldepth_i);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"\tnumber_of_segments = %d\t",
p->layer_info[i].number_of_segments);
n += scnprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
p->layer_info[i].tmcc_errors);
n += sysfs_emit_at(buf, n, "\nLayer %d\n", i);
n += sysfs_emit_at(buf, n, "\tcode_rate = %d\t", p->layer_info[i].code_rate);
n += sysfs_emit_at(buf, n, "constellation = %d\n", p->layer_info[i].constellation);
n += sysfs_emit_at(buf, n, "\tber = %-5d\t", p->layer_info[i].ber);
n += sysfs_emit_at(buf, n, "\tber_error_count = %-5d\t",
p->layer_info[i].ber_error_count);
n += sysfs_emit_at(buf, n, "ber_bit_count = %-5d\n",
p->layer_info[i].ber_bit_count);
n += sysfs_emit_at(buf, n, "\tpre_ber = %-5d\t", p->layer_info[i].pre_ber);
n += sysfs_emit_at(buf, n, "\tts_per = %-5d\n", p->layer_info[i].ts_per);
n += sysfs_emit_at(buf, n, "\terror_ts_packets = %-5d\t",
p->layer_info[i].error_ts_packets);
n += sysfs_emit_at(buf, n, "total_ts_packets = %-5d\t",
p->layer_info[i].total_ts_packets);
n += sysfs_emit_at(buf, n, "ti_ldepth_i = %d\n", p->layer_info[i].ti_ldepth_i);
n += sysfs_emit_at(buf, n, "\tnumber_of_segments = %d\t",
p->layer_info[i].number_of_segments);
n += sysfs_emit_at(buf, n, "tmcc_errors = %d\n", p->layer_info[i].tmcc_errors);
}
debug_data->stats_count = n;
@ -241,80 +171,50 @@ static void smsdvb_print_isdb_stats_ex(struct smsdvb_debugfs *debug_data,
buf = debug_data->stats_data;
n += scnprintf(&buf[n], PAGE_SIZE - n,
"statistics_type = %d\t", p->statistics_type);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"full_size = %d\n", p->full_size);
n += sysfs_emit_at(buf, n, "statistics_type = %d\t", p->statistics_type);
n += sysfs_emit_at(buf, n, "full_size = %d\n", p->full_size);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"is_rf_locked = %d\t\t", p->is_rf_locked);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"is_demod_locked = %d\t", p->is_demod_locked);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"is_external_lna_on = %d\n", p->is_external_lna_on);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"SNR = %d dB\t\t", p->SNR);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"RSSI = %d dBm\t\t", p->RSSI);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"in_band_pwr = %d dBm\n", p->in_band_pwr);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"carrier_offset = %d\t", p->carrier_offset);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"bandwidth = %d\t\t", p->bandwidth);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"frequency = %d Hz\n", p->frequency);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"transmission_mode = %d\t", p->transmission_mode);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"modem_state = %d\t\t", p->modem_state);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"guard_interval = %d\n", p->guard_interval);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"system_type = %d\t\t", p->system_type);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"partial_reception = %d\t", p->partial_reception);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"num_of_layers = %d\n", p->num_of_layers);
n += scnprintf(&buf[n], PAGE_SIZE - n, "segment_number = %d\t",
p->segment_number);
n += scnprintf(&buf[n], PAGE_SIZE - n, "tune_bw = %d\n",
p->tune_bw);
n += sysfs_emit_at(buf, n, "is_rf_locked = %d\t\t", p->is_rf_locked);
n += sysfs_emit_at(buf, n, "is_demod_locked = %d\t", p->is_demod_locked);
n += sysfs_emit_at(buf, n, "is_external_lna_on = %d\n", p->is_external_lna_on);
n += sysfs_emit_at(buf, n, "SNR = %d dB\t\t", p->SNR);
n += sysfs_emit_at(buf, n, "RSSI = %d dBm\t\t", p->RSSI);
n += sysfs_emit_at(buf, n, "in_band_pwr = %d dBm\n", p->in_band_pwr);
n += sysfs_emit_at(buf, n, "carrier_offset = %d\t", p->carrier_offset);
n += sysfs_emit_at(buf, n, "bandwidth = %d\t\t", p->bandwidth);
n += sysfs_emit_at(buf, n, "frequency = %d Hz\n", p->frequency);
n += sysfs_emit_at(buf, n, "transmission_mode = %d\t", p->transmission_mode);
n += sysfs_emit_at(buf, n, "modem_state = %d\t\t", p->modem_state);
n += sysfs_emit_at(buf, n, "guard_interval = %d\n", p->guard_interval);
n += sysfs_emit_at(buf, n, "system_type = %d\t\t", p->system_type);
n += sysfs_emit_at(buf, n, "partial_reception = %d\t", p->partial_reception);
n += sysfs_emit_at(buf, n, "num_of_layers = %d\n", p->num_of_layers);
n += sysfs_emit_at(buf, n, "segment_number = %d\t", p->segment_number);
n += sysfs_emit_at(buf, n, "tune_bw = %d\n", p->tune_bw);
for (i = 0; i < 3; i++) {
if (p->layer_info[i].number_of_segments < 1 ||
p->layer_info[i].number_of_segments > 13)
continue;
n += scnprintf(&buf[n], PAGE_SIZE - n, "\nLayer %d\n", i);
n += scnprintf(&buf[n], PAGE_SIZE - n, "\tcode_rate = %d\t",
p->layer_info[i].code_rate);
n += scnprintf(&buf[n], PAGE_SIZE - n, "constellation = %d\n",
p->layer_info[i].constellation);
n += scnprintf(&buf[n], PAGE_SIZE - n, "\tber = %-5d\t",
p->layer_info[i].ber);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"\tber_error_count = %-5d\t",
p->layer_info[i].ber_error_count);
n += scnprintf(&buf[n], PAGE_SIZE - n, "ber_bit_count = %-5d\n",
p->layer_info[i].ber_bit_count);
n += scnprintf(&buf[n], PAGE_SIZE - n, "\tpre_ber = %-5d\t",
p->layer_info[i].pre_ber);
n += scnprintf(&buf[n], PAGE_SIZE - n, "\tts_per = %-5d\n",
p->layer_info[i].ts_per);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"\terror_ts_packets = %-5d\t",
p->layer_info[i].error_ts_packets);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"total_ts_packets = %-5d\t",
p->layer_info[i].total_ts_packets);
n += scnprintf(&buf[n], PAGE_SIZE - n, "ti_ldepth_i = %d\n",
p->layer_info[i].ti_ldepth_i);
n += scnprintf(&buf[n], PAGE_SIZE - n,
"\tnumber_of_segments = %d\t",
p->layer_info[i].number_of_segments);
n += scnprintf(&buf[n], PAGE_SIZE - n, "tmcc_errors = %d\n",
p->layer_info[i].tmcc_errors);
n += sysfs_emit_at(buf, n, "\nLayer %d\n", i);
n += sysfs_emit_at(buf, n, "\tcode_rate = %d\t", p->layer_info[i].code_rate);
n += sysfs_emit_at(buf, n, "constellation = %d\n", p->layer_info[i].constellation);
n += sysfs_emit_at(buf, n, "\tber = %-5d\t", p->layer_info[i].ber);
n += sysfs_emit_at(buf, n, "\tber_error_count = %-5d\t",
p->layer_info[i].ber_error_count);
n += sysfs_emit_at(buf, n, "ber_bit_count = %-5d\n",
p->layer_info[i].ber_bit_count);
n += sysfs_emit_at(buf, n, "\tpre_ber = %-5d\t", p->layer_info[i].pre_ber);
n += sysfs_emit_at(buf, n, "\tts_per = %-5d\n", p->layer_info[i].ts_per);
n += sysfs_emit_at(buf, n, "\terror_ts_packets = %-5d\t",
p->layer_info[i].error_ts_packets);
n += sysfs_emit_at(buf, n, "total_ts_packets = %-5d\t",
p->layer_info[i].total_ts_packets);
n += sysfs_emit_at(buf, n, "ti_ldepth_i = %d\n", p->layer_info[i].ti_ldepth_i);
n += sysfs_emit_at(buf, n, "\tnumber_of_segments = %d\t",
p->layer_info[i].number_of_segments);
n += sysfs_emit_at(buf, n, "tmcc_errors = %d\n", p->layer_info[i].tmcc_errors);
}

View File

@ -17,7 +17,7 @@
void smsendian_handle_tx_message(void *buffer)
{
#ifdef __BIG_ENDIAN
struct sms_msg_data *msg = (struct sms_msg_data *)buffer;
struct sms_msg_data *msg = buffer;
int i;
int msg_words;

View File

@ -973,7 +973,9 @@ static void cx24120_set_clock_ratios(struct dvb_frontend *fe)
cmd.arg[8] = (clock_ratios_table[idx].rate >> 8) & 0xff;
cmd.arg[9] = (clock_ratios_table[idx].rate >> 0) & 0xff;
cx24120_message_send(state, &cmd);
ret = cx24120_message_send(state, &cmd);
if (ret != 0)
return;
/* Calculate ber window rates for stat work */
cx24120_calculate_ber_window(state, clock_ratios_table[idx].rate);

View File

@ -497,7 +497,7 @@ static int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth
prediv = reg_1856 & 0x3f;
loopdiv = (reg_1856 >> 6) & 0x3f;
if ((bw != NULL) && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
if (loopdiv && bw && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
dprintk("Updating pll (prediv: old = %d new = %d ; loopdiv : old = %d new = %d)\n", prediv, bw->pll_prediv, loopdiv, bw->pll_ratio);
reg_1856 &= 0xf000;
reg_1857 = dib7000p_read_word(state, 1857);

View File

@ -229,13 +229,8 @@ static int i2c_write(struct drxk_state *state, u8 adr, u8 *data, int len)
struct i2c_msg msg = {
.addr = adr, .flags = 0, .buf = data, .len = len };
dprintk(3, ":");
if (debug > 2) {
int i;
for (i = 0; i < len; i++)
pr_cont(" %02x", data[i]);
pr_cont("\n");
}
dprintk(3, ": %*ph\n", len, data);
status = drxk_i2c_transfer(state, &msg, 1);
if (status >= 0 && status != 1)
status = -EIO;
@ -267,16 +262,7 @@ static int i2c_read(struct drxk_state *state,
pr_err("i2c read error at addr 0x%02x\n", adr);
return status;
}
if (debug > 2) {
int i;
dprintk(2, ": read from");
for (i = 0; i < len; i++)
pr_cont(" %02x", msg[i]);
pr_cont(", value = ");
for (i = 0; i < alen; i++)
pr_cont(" %02x", answ[i]);
pr_cont("\n");
}
dprintk(3, ": read from %*ph, value = %*ph\n", len, msg, alen, answ);
return 0;
}
@ -441,13 +427,8 @@ static int write_block(struct drxk_state *state, u32 address,
}
memcpy(&state->chunk[adr_length], p_block, chunk);
dprintk(2, "(0x%08x, 0x%02x)\n", address, flags);
if (debug > 1) {
int i;
if (p_block)
for (i = 0; i < chunk; i++)
pr_cont(" %02x", p_block[i]);
pr_cont("\n");
}
if (p_block)
dprintk(2, "%*ph\n", chunk, p_block);
status = i2c_write(state, state->demod_address,
&state->chunk[0], chunk + adr_length);
if (status < 0) {

View File

@ -1487,10 +1487,12 @@ static int mb86a16_set_fe(struct mb86a16_state *state)
}
}
mb86a16_read(state, 0x15, &agcval);
mb86a16_read(state, 0x26, &cnmval);
dprintk(verbose, MB86A16_INFO, 1, "AGC = %02x CNM = %02x", agcval, cnmval);
if (mb86a16_read(state, 0x15, &agcval) != 2 || mb86a16_read(state, 0x26, &cnmval) != 2) {
dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
ret = -EREMOTEIO;
} else {
dprintk(verbose, MB86A16_INFO, 1, "AGC = %02x CNM = %02x", agcval, cnmval);
}
return ret;
}

View File

@ -8,7 +8,7 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/regmap.h>
#include <linux/int_log.h>

View File

@ -597,7 +597,8 @@ int avc_tuner_dsd(struct firedtv *fdtv,
case FIREDTV_DVB_C: pos = avc_tuner_dsd_dvb_c(fdtv, p); break;
case FIREDTV_DVB_T: pos = avc_tuner_dsd_dvb_t(fdtv, p); break;
default:
BUG();
ret = -EIO;
goto unlock;
}
pad_operands(c, pos);
@ -612,6 +613,7 @@ int avc_tuner_dsd(struct firedtv *fdtv,
if (status)
*status = r->operand[2];
#endif
unlock:
mutex_unlock(&fdtv->avc_mutex);
if (ret == 0)

View File

@ -25,8 +25,15 @@ config VIDEO_IR_I2C
# V4L2 I2C drivers that are related with Camera support
#
menu "Camera sensor devices"
visible if MEDIA_CAMERA_SUPPORT
menuconfig VIDEO_CAMERA_SENSOR
bool "Camera sensor devices"
depends on MEDIA_CAMERA_SUPPORT && I2C
select MEDIA_CONTROLLER
select V4L2_FWNODE
select VIDEO_V4L2_SUBDEV_API
default y
if VIDEO_CAMERA_SENSOR
config VIDEO_APTINA_PLL
tristate
@ -36,10 +43,6 @@ config VIDEO_CCS_PLL
config VIDEO_AR0521
tristate "ON Semiconductor AR0521 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the ON Semiconductor
AR0521 camera.
@ -49,10 +52,6 @@ config VIDEO_AR0521
config VIDEO_HI556
tristate "Hynix Hi-556 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Hynix
Hi-556 camera.
@ -62,10 +61,6 @@ config VIDEO_HI556
config VIDEO_HI846
tristate "Hynix Hi-846 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Hynix
Hi-846 camera.
@ -75,10 +70,6 @@ config VIDEO_HI846
config VIDEO_HI847
tristate "Hynix Hi-847 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Hynix
Hi-847 camera.
@ -88,10 +79,6 @@ config VIDEO_HI847
config VIDEO_IMX208
tristate "Sony IMX208 sensor support"
depends on I2C && VIDEO_DEV
depends on MEDIA_CAMERA_SUPPORT
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
help
This is a Video4Linux2 sensor driver for the Sony
IMX208 camera.
@ -101,10 +88,7 @@ config VIDEO_IMX208
config VIDEO_IMX214
tristate "Sony IMX214 sensor support"
depends on GPIOLIB && I2C && VIDEO_DEV
select V4L2_FWNODE
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
depends on GPIOLIB
select REGMAP_I2C
help
This is a Video4Linux2 sensor driver for the Sony
@ -115,10 +99,6 @@ config VIDEO_IMX214
config VIDEO_IMX219
tristate "Sony IMX219 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Sony
IMX219 camera.
@ -128,9 +108,6 @@ config VIDEO_IMX219
config VIDEO_IMX258
tristate "Sony IMX258 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
help
This is a Video4Linux2 sensor driver for the Sony
IMX258 camera.
@ -140,9 +117,6 @@ config VIDEO_IMX258
config VIDEO_IMX274
tristate "Sony IMX274 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select REGMAP_I2C
help
This is a V4L2 sensor driver for the Sony IMX274
@ -150,11 +124,8 @@ config VIDEO_IMX274
config VIDEO_IMX290
tristate "Sony IMX290 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select REGMAP_I2C
select V4L2_FWNODE
select V4L2_CCI_I2C
help
This is a Video4Linux2 sensor driver for the Sony
IMX290 camera sensor.
@ -164,10 +135,6 @@ config VIDEO_IMX290
config VIDEO_IMX296
tristate "Sony IMX296 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select V4L2_FWNODE
select VIDEO_V4L2_SUBDEV_API
help
This is a Video4Linux2 sensor driver for the Sony
IMX296 camera.
@ -177,9 +144,6 @@ config VIDEO_IMX296
config VIDEO_IMX319
tristate "Sony IMX319 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
help
This is a Video4Linux2 sensor driver for the Sony
IMX319 camera.
@ -190,10 +154,6 @@ config VIDEO_IMX319
config VIDEO_IMX334
tristate "Sony IMX334 sensor support"
depends on OF_GPIO
depends on I2C && VIDEO_DEV
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Sony
IMX334 camera.
@ -204,10 +164,6 @@ config VIDEO_IMX334
config VIDEO_IMX335
tristate "Sony IMX335 sensor support"
depends on OF_GPIO
depends on I2C && VIDEO_DEV
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Sony
IMX335 camera.
@ -217,9 +173,6 @@ config VIDEO_IMX335
config VIDEO_IMX355
tristate "Sony IMX355 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
help
This is a Video4Linux2 sensor driver for the Sony
IMX355 camera.
@ -230,10 +183,6 @@ config VIDEO_IMX355
config VIDEO_IMX412
tristate "Sony IMX412 sensor support"
depends on OF_GPIO
depends on I2C && VIDEO_DEV
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Sony
IMX412 camera.
@ -244,10 +193,6 @@ config VIDEO_IMX412
config VIDEO_IMX415
tristate "Sony IMX415 sensor support"
depends on OF_GPIO
depends on I2C && VIDEO_DEV
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Sony
IMX415 camera.
@ -260,35 +205,25 @@ config VIDEO_MAX9271_LIB
config VIDEO_MT9M001
tristate "mt9m001 support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
help
This driver supports MT9M001 cameras from Micron, monochrome
and colour models.
config VIDEO_MT9M111
tristate "mt9m111, mt9m112 and mt9m131 support"
depends on I2C && VIDEO_DEV
select V4L2_FWNODE
help
This driver supports MT9M111, MT9M112 and MT9M131 cameras from
Micron/Aptina
config VIDEO_MT9P031
tristate "Aptina MT9P031 support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select VIDEO_APTINA_PLL
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Aptina
(Micron) mt9p031 5 Mpixel camera.
config VIDEO_MT9T112
tristate "Aptina MT9T111/MT9T112 support"
depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor driver for the Aptina
(Micron) MT9T111 and MT9T112 3 Mpixel camera.
@ -298,7 +233,6 @@ config VIDEO_MT9T112
config VIDEO_MT9V011
tristate "Micron mt9v011 sensor support"
depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor driver for the Micron
mt0v011 1.3 Mpixel camera. It currently only works with the
@ -306,18 +240,13 @@ config VIDEO_MT9V011
config VIDEO_MT9V032
tristate "Micron MT9V032 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select REGMAP_I2C
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the Micron
MT9V032 752x480 CMOS sensor.
config VIDEO_MT9V111
tristate "Aptina MT9V111 sensor support"
depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor driver for the Aptina/Micron
MT9V111 sensor.
@ -327,10 +256,6 @@ config VIDEO_MT9V111
config VIDEO_OG01A1B
tristate "OmniVision OG01A1B sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OG01A1B camera.
@ -340,10 +265,6 @@ config VIDEO_OG01A1B
config VIDEO_OV01A10
tristate "OmniVision OV01A10 sensor support"
depends on VIDEO_DEV && I2C
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV01A10 camera.
@ -353,10 +274,6 @@ config VIDEO_OV01A10
config VIDEO_OV02A10
tristate "OmniVision OV02A10 sensor support"
depends on VIDEO_DEV && I2C
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV02A10 camera.
@ -366,10 +283,6 @@ config VIDEO_OV02A10
config VIDEO_OV08D10
tristate "OmniVision OV08D10 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV08D10 camera sensor.
@ -379,10 +292,6 @@ config VIDEO_OV08D10
config VIDEO_OV08X40
tristate "OmniVision OV08X40 sensor support"
depends on VIDEO_DEV && I2C
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV08X40 camera.
@ -392,28 +301,18 @@ config VIDEO_OV08X40
config VIDEO_OV13858
tristate "OmniVision OV13858 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV13858 camera.
config VIDEO_OV13B10
tristate "OmniVision OV13B10 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV13B10 camera.
config VIDEO_OV2640
tristate "OmniVision OV2640 sensor support"
depends on VIDEO_DEV && I2C
select V4L2_ASYNC
help
This is a Video4Linux2 sensor driver for the OmniVision
OV2640 camera.
@ -423,8 +322,7 @@ config VIDEO_OV2640
config VIDEO_OV2659
tristate "OmniVision OV2659 sensor support"
depends on VIDEO_DEV && I2C && GPIOLIB
select V4L2_FWNODE
depends on GPIOLIB
help
This is a Video4Linux2 sensor driver for the OmniVision
OV2659 camera.
@ -434,9 +332,7 @@ config VIDEO_OV2659
config VIDEO_OV2680
tristate "OmniVision OV2680 sensor support"
depends on VIDEO_DEV && I2C
select MEDIA_CONTROLLER
select V4L2_FWNODE
select V4L2_CCI_I2C
help
This is a Video4Linux2 sensor driver for the OmniVision
OV2680 camera.
@ -446,10 +342,6 @@ config VIDEO_OV2680
config VIDEO_OV2685
tristate "OmniVision OV2685 sensor support"
depends on VIDEO_DEV && I2C
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV2685 camera.
@ -459,11 +351,7 @@ config VIDEO_OV2685
config VIDEO_OV2740
tristate "OmniVision OV2740 sensor support"
depends on VIDEO_DEV && I2C
depends on ACPI || COMPILE_TEST
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
select REGMAP_I2C
help
This is a Video4Linux2 sensor driver for the OmniVision
@ -474,10 +362,7 @@ config VIDEO_OV2740
config VIDEO_OV4689
tristate "OmniVision OV4689 sensor support"
depends on GPIOLIB && VIDEO_DEV && I2C
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
depends on GPIOLIB
help
This is a Video4Linux2 sensor-level driver for the OmniVision
OV4689 camera.
@ -488,10 +373,7 @@ config VIDEO_OV4689
config VIDEO_OV5640
tristate "OmniVision OV5640 sensor support"
depends on OF
depends on GPIOLIB && VIDEO_DEV && I2C
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
depends on GPIOLIB
help
This is a Video4Linux2 sensor driver for the Omnivision
OV5640 camera sensor with a MIPI CSI-2 interface.
@ -499,10 +381,6 @@ config VIDEO_OV5640
config VIDEO_OV5645
tristate "OmniVision OV5645 sensor support"
depends on OF
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV5645 camera.
@ -512,10 +390,6 @@ config VIDEO_OV5645
config VIDEO_OV5647
tristate "OmniVision OV5647 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV5647 camera.
@ -525,10 +399,7 @@ config VIDEO_OV5647
config VIDEO_OV5648
tristate "OmniVision OV5648 sensor support"
depends on I2C && PM && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
depends on PM
help
This is a Video4Linux2 sensor driver for the OmniVision
OV5648 camera.
@ -538,10 +409,6 @@ config VIDEO_OV5648
config VIDEO_OV5670
tristate "OmniVision OV5670 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV5670 camera.
@ -551,10 +418,6 @@ config VIDEO_OV5670
config VIDEO_OV5675
tristate "OmniVision OV5675 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV5675 camera.
@ -564,8 +427,7 @@ config VIDEO_OV5675
config VIDEO_OV5693
tristate "OmniVision OV5693 sensor support"
depends on I2C && VIDEO_DEV
select V4L2_FWNODE
select V4L2_CCI_I2C
help
This is a Video4Linux2 sensor driver for the OmniVision
OV5693 camera.
@ -575,8 +437,6 @@ config VIDEO_OV5693
config VIDEO_OV5695
tristate "OmniVision OV5695 sensor support"
depends on I2C && VIDEO_DEV
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV5695 camera.
@ -586,7 +446,6 @@ config VIDEO_OV5695
config VIDEO_OV6650
tristate "OmniVision OV6650 sensor support"
depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor driver for the OmniVision
OV6650 camera.
@ -596,10 +455,6 @@ config VIDEO_OV6650
config VIDEO_OV7251
tristate "OmniVision OV7251 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV7251 camera.
@ -609,7 +464,6 @@ config VIDEO_OV7251
config VIDEO_OV7640
tristate "OmniVision OV7640 sensor support"
depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor driver for the OmniVision
OV7640 camera.
@ -619,8 +473,6 @@ config VIDEO_OV7640
config VIDEO_OV7670
tristate "OmniVision OV7670 sensor support"
depends on I2C && VIDEO_DEV
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV7670 VGA camera. It currently only works with the M88ALP01
@ -628,9 +480,7 @@ config VIDEO_OV7670
config VIDEO_OV772X
tristate "OmniVision OV772x sensor support"
depends on I2C && VIDEO_DEV
select REGMAP_SCCB
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV772x camera.
@ -640,7 +490,6 @@ config VIDEO_OV772X
config VIDEO_OV7740
tristate "OmniVision OV7740 sensor support"
depends on I2C && VIDEO_DEV
select REGMAP_SCCB
help
This is a Video4Linux2 sensor driver for the OmniVision
@ -648,10 +497,6 @@ config VIDEO_OV7740
config VIDEO_OV8856
tristate "OmniVision OV8856 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV8856 camera sensor.
@ -661,10 +506,7 @@ config VIDEO_OV8856
config VIDEO_OV8858
tristate "OmniVision OV8858 sensor support"
depends on I2C && PM && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
depends on PM
help
This is a Video4Linux2 sensor driver for OmniVision
OV8858 camera sensor.
@ -674,10 +516,7 @@ config VIDEO_OV8858
config VIDEO_OV8865
tristate "OmniVision OV8865 sensor support"
depends on I2C && PM && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
depends on PM
help
This is a Video4Linux2 sensor driver for OmniVision
OV8865 camera sensor.
@ -688,10 +527,6 @@ config VIDEO_OV8865
config VIDEO_OV9282
tristate "OmniVision OV9282 sensor support"
depends on OF_GPIO
depends on I2C && VIDEO_DEV
select VIDEO_V4L2_SUBDEV_API
select MEDIA_CONTROLLER
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV9282 camera sensor.
@ -701,16 +536,12 @@ config VIDEO_OV9282
config VIDEO_OV9640
tristate "OmniVision OV9640 sensor support"
depends on I2C && VIDEO_DEV
help
This is a Video4Linux2 sensor driver for the OmniVision
OV9640 camera sensor.
config VIDEO_OV9650
tristate "OmniVision OV9650/OV9652 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select REGMAP_SCCB
help
This is a V4L2 sensor driver for the Omnivision
@ -718,11 +549,7 @@ config VIDEO_OV9650
config VIDEO_OV9734
tristate "OmniVision OV9734 sensor support"
depends on VIDEO_DEV && I2C
depends on ACPI || COMPILE_TEST
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a Video4Linux2 sensor driver for the OmniVision
OV9734 camera.
@ -732,10 +559,6 @@ config VIDEO_OV9734
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
@ -746,10 +569,6 @@ config VIDEO_RDACM20
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
@ -760,7 +579,6 @@ config VIDEO_RDACM21
config VIDEO_RJ54N1
tristate "Sharp RJ54N1CB0C sensor support"
depends on I2C && VIDEO_DEV
help
This is a V4L2 sensor driver for Sharp RJ54N1CB0C CMOS image
sensor.
@ -770,39 +588,26 @@ config VIDEO_RJ54N1
config VIDEO_S5C73M3
tristate "Samsung S5C73M3 sensor support"
depends on I2C && SPI && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
depends on SPI
help
This is a V4L2 sensor driver for Samsung S5C73M3
8 Mpixel camera.
config VIDEO_S5K5BAF
tristate "Samsung S5K5BAF sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a V4L2 sensor driver for Samsung S5K5BAF 2M
camera sensor with an embedded SoC image signal processor.
config VIDEO_S5K6A3
tristate "Samsung S5K6A3 sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
help
This is a V4L2 sensor driver for Samsung S5K6A3 raw
camera sensor.
config VIDEO_ST_VGXY61
tristate "ST VGXY61 sensor support"
depends on OF && GPIOLIB && VIDEO_DEV && I2C
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
depends on OF && GPIOLIB
help
This is a Video4Linux2 sensor driver for the ST VGXY61
camera sensor.
@ -810,7 +615,7 @@ config VIDEO_ST_VGXY61
source "drivers/media/i2c/ccs/Kconfig"
source "drivers/media/i2c/et8ek8/Kconfig"
endmenu
endif
menu "Lens drivers"
visible if MEDIA_CAMERA_SUPPORT
@ -848,6 +653,18 @@ config VIDEO_DW9714
capability. This is designed for linear control of
voice coil motors, controlled via I2C serial interface.
config VIDEO_DW9719
tristate "DW9719 lens voice coil support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_ASYNC
select V4L2_CCI_I2C
help
This is a driver for the DW9719 camera lens voice coil.
This is designed for linear control of voice coil motors,
controlled via I2C serial interface.
config VIDEO_DW9768
tristate "DW9768 lens voice coil support"
depends on I2C && VIDEO_DEV
@ -1625,4 +1442,51 @@ config VIDEO_THS7303
endmenu
#
# Video serializers and deserializers (e.g. FPD-Link)
#
menu "Video serializers and deserializers"
config VIDEO_DS90UB913
tristate "TI DS90UB913 FPD-Link III Serializer"
depends on OF && I2C && VIDEO_DEV && COMMON_CLK
select I2C_ATR
select MEDIA_CONTROLLER
select GPIOLIB
select REGMAP_I2C
select V4L2_FWNODE
select VIDEO_V4L2_SUBDEV_API
help
Device driver for the Texas Instruments DS90UB913
FPD-Link III Serializer.
config VIDEO_DS90UB953
tristate "TI FPD-Link III/IV CSI-2 Serializers"
depends on OF && I2C && VIDEO_DEV && COMMON_CLK
select I2C_ATR
select MEDIA_CONTROLLER
select GPIOLIB
select REGMAP_I2C
select V4L2_FWNODE
select VIDEO_V4L2_SUBDEV_API
help
Device driver for the Texas Instruments DS90UB953
FPD-Link III Serializer and DS90UB971 FPD-Link IV Serializer.
config VIDEO_DS90UB960
tristate "TI FPD-Link III/IV Deserializers"
depends on OF && I2C && VIDEO_DEV && COMMON_CLK
select I2C_ATR
select MEDIA_CONTROLLER
select GPIOLIB
select REGMAP_I2C
select V4L2_FWNODE
select VIDEO_V4L2_SUBDEV_API
help
Device driver for the Texas Instruments DS90UB960
FPD-Link III Deserializer and DS90UB9702 FPD-Link IV Deserializer.
endmenu
endif # VIDEO_DEV

View File

@ -28,7 +28,11 @@ obj-$(CONFIG_VIDEO_CS3308) += cs3308.o
obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
obj-$(CONFIG_VIDEO_CX25840) += cx25840/
obj-$(CONFIG_VIDEO_DS90UB913) += ds90ub913.o
obj-$(CONFIG_VIDEO_DS90UB953) += ds90ub953.o
obj-$(CONFIG_VIDEO_DS90UB960) += ds90ub960.o
obj-$(CONFIG_VIDEO_DW9714) += dw9714.o
obj-$(CONFIG_VIDEO_DW9719) += dw9719.o
obj-$(CONFIG_VIDEO_DW9768) += dw9768.o
obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o
obj-$(CONFIG_VIDEO_ET8EK8) += et8ek8/

View File

@ -349,7 +349,6 @@ static void ad5820_remove(struct i2c_client *client)
static const struct i2c_device_id ad5820_id_table[] = {
{ "ad5820", 0 },
{ "ad5821", 0 },
{ "ad5823", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
@ -357,7 +356,6 @@ MODULE_DEVICE_TABLE(i2c, ad5820_id_table);
static const struct of_device_id ad5820_of_table[] = {
{ .compatible = "adi,ad5820" },
{ .compatible = "adi,ad5821" },
{ .compatible = "adi,ad5823" },
{ }
};
MODULE_DEVICE_TABLE(of, ad5820_of_table);

View File

@ -300,9 +300,6 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
MEDIA_ENT_F_VID_IF_BRIDGE,
is_txa(tx) ? "txa" : "txb");
/* Ensure that matching is based upon the endpoint fwnodes */
tx->sd.fwnode = of_fwnode_handle(state->endpoints[tx->port]);
/* Register internal ops for incremental subdev registration */
tx->sd.internal_ops = &adv748x_csi2_internal_ops;
@ -314,10 +311,15 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
if (ret)
return ret;
ret = adv748x_csi2_init_controls(tx);
ret = v4l2_async_subdev_endpoint_add(&tx->sd,
of_fwnode_handle(state->endpoints[tx->port]));
if (ret)
goto err_free_media;
ret = adv748x_csi2_init_controls(tx);
if (ret)
goto err_cleanup_subdev;
ret = v4l2_async_register_subdev(&tx->sd);
if (ret)
goto err_free_ctrl;
@ -326,6 +328,8 @@ int adv748x_csi2_init(struct adv748x_state *state, struct adv748x_csi2 *tx)
err_free_ctrl:
v4l2_ctrl_handler_free(&tx->ctrl_hdl);
err_cleanup_subdev:
v4l2_subdev_cleanup(&tx->sd);
err_free_media:
media_entity_cleanup(&tx->sd.entity);
@ -340,4 +344,5 @@ void adv748x_csi2_cleanup(struct adv748x_csi2 *tx)
v4l2_async_unregister_subdev(&tx->sd);
media_entity_cleanup(&tx->sd.entity);
v4l2_ctrl_handler_free(&tx->ctrl_hdl);
v4l2_subdev_cleanup(&tx->sd);
}

View File

@ -296,7 +296,7 @@ __ccs_pll_calculate_vt_tree(struct device *dev,
struct ccs_pll_branch_fr *pll_fr = &pll->vt_fr;
struct ccs_pll_branch_bk *pll_bk = &pll->vt_bk;
u32 more_mul;
u16 best_pix_div = SHRT_MAX >> 1, best_div;
u16 best_pix_div = SHRT_MAX >> 1, best_div = lim_bk->max_sys_clk_div;
u16 vt_div, min_sys_div, max_sys_div, sys_div;
pll_fr->pll_ip_clk_freq_hz =

View File

@ -1,11 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
config VIDEO_CCS
tristate "MIPI CCS/SMIA++/SMIA sensor support"
depends on I2C && VIDEO_DEV && HAVE_CLK
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
depends on HAVE_CLK
select VIDEO_CCS_PLL
select V4L2_FWNODE
help
This is a generic driver for MIPI CCS, SMIA++ and SMIA compliant
camera sensors.

View File

@ -464,8 +464,7 @@ static int ccs_data_parse_rules(struct bin_container *bin,
rule_payload = __rule_type + 1;
rule_plen2 = rule_plen - sizeof(*__rule_type);
switch (*__rule_type) {
case CCS_DATA_BLOCK_RULE_ID_IF: {
if (*__rule_type == CCS_DATA_BLOCK_RULE_ID_IF) {
const struct __ccs_data_block_rule_if *__if_rules =
rule_payload;
const size_t __num_if_rules =
@ -514,49 +513,61 @@ static int ccs_data_parse_rules(struct bin_container *bin,
rules->if_rules = if_rule;
rules->num_if_rules = __num_if_rules;
}
break;
}
case CCS_DATA_BLOCK_RULE_ID_READ_ONLY_REGS:
rval = ccs_data_parse_reg_rules(bin, &rules->read_only_regs,
&rules->num_read_only_regs,
rule_payload,
rule_payload + rule_plen2,
dev);
if (rval)
return rval;
break;
case CCS_DATA_BLOCK_RULE_ID_FFD:
rval = ccs_data_parse_ffd(bin, &rules->frame_format,
rule_payload,
rule_payload + rule_plen2,
dev);
if (rval)
return rval;
break;
case CCS_DATA_BLOCK_RULE_ID_MSR:
rval = ccs_data_parse_reg_rules(bin,
&rules->manufacturer_regs,
&rules->num_manufacturer_regs,
rule_payload,
rule_payload + rule_plen2,
dev);
if (rval)
return rval;
break;
case CCS_DATA_BLOCK_RULE_ID_PDAF_READOUT:
rval = ccs_data_parse_pdaf_readout(bin,
&rules->pdaf_readout,
rule_payload,
rule_payload + rule_plen2,
dev);
if (rval)
return rval;
break;
default:
dev_dbg(dev,
"Don't know how to handle rule type %u!\n",
*__rule_type);
return -EINVAL;
} else {
/* Check there was an if rule before any other rules */
if (bin->base && !rules)
return -EINVAL;
switch (*__rule_type) {
case CCS_DATA_BLOCK_RULE_ID_READ_ONLY_REGS:
rval = ccs_data_parse_reg_rules(bin,
rules ?
&rules->read_only_regs : NULL,
rules ?
&rules->num_read_only_regs : NULL,
rule_payload,
rule_payload + rule_plen2,
dev);
if (rval)
return rval;
break;
case CCS_DATA_BLOCK_RULE_ID_FFD:
rval = ccs_data_parse_ffd(bin, rules ?
&rules->frame_format : NULL,
rule_payload,
rule_payload + rule_plen2,
dev);
if (rval)
return rval;
break;
case CCS_DATA_BLOCK_RULE_ID_MSR:
rval = ccs_data_parse_reg_rules(bin,
rules ?
&rules->manufacturer_regs : NULL,
rules ?
&rules->num_manufacturer_regs : NULL,
rule_payload,
rule_payload + rule_plen2,
dev);
if (rval)
return rval;
break;
case CCS_DATA_BLOCK_RULE_ID_PDAF_READOUT:
rval = ccs_data_parse_pdaf_readout(bin,
rules ?
&rules->pdaf_readout : NULL,
rule_payload,
rule_payload + rule_plen2,
dev);
if (rval)
return rval;
break;
default:
dev_dbg(dev,
"Don't know how to handle rule type %u!\n",
*__rule_type);
return -EINVAL;
}
}
__next_rule = __next_rule + rule_hlen + rule_plen;
}

View File

@ -0,0 +1,903 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Driver for the Texas Instruments DS90UB913 video serializer
*
* Based on a driver from Luca Ceresoli <luca@lucaceresoli.net>
*
* Copyright (c) 2019 Luca Ceresoli <luca@lucaceresoli.net>
* Copyright (c) 2023 Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
*/
#include <linux/clk-provider.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/fwnode.h>
#include <linux/gpio/driver.h>
#include <linux/i2c-atr.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/property.h>
#include <linux/regmap.h>
#include <media/i2c/ds90ub9xx.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-mediabus.h>
#include <media/v4l2-subdev.h>
#define UB913_PAD_SINK 0
#define UB913_PAD_SOURCE 1
/*
* UB913 has 4 gpios, but gpios 3 and 4 are reserved for external oscillator
* mode. Thus we only support 2 gpios for now.
*/
#define UB913_NUM_GPIOS 2
#define UB913_REG_RESET_CTL 0x01
#define UB913_REG_RESET_CTL_DIGITAL_RESET_1 BIT(1)
#define UB913_REG_RESET_CTL_DIGITAL_RESET_0 BIT(0)
#define UB913_REG_GENERAL_CFG 0x03
#define UB913_REG_GENERAL_CFG_CRC_ERR_RESET BIT(5)
#define UB913_REG_GENERAL_CFG_PCLK_RISING BIT(0)
#define UB913_REG_MODE_SEL 0x05
#define UB913_REG_MODE_SEL_MODE_OVERRIDE BIT(5)
#define UB913_REG_MODE_SEL_MODE_UP_TO_DATE BIT(4)
#define UB913_REG_MODE_SEL_MODE_MASK GENMASK(3, 0)
#define UB913_REG_CRC_ERRORS_LSB 0x0a
#define UB913_REG_CRC_ERRORS_MSB 0x0b
#define UB913_REG_GENERAL_STATUS 0x0c
#define UB913_REG_GPIO_CFG(n) (0x0d + (n))
#define UB913_REG_GPIO_CFG_ENABLE(n) BIT(0 + (n) * 4)
#define UB913_REG_GPIO_CFG_DIR_INPUT(n) BIT(1 + (n) * 4)
#define UB913_REG_GPIO_CFG_REMOTE_EN(n) BIT(2 + (n) * 4)
#define UB913_REG_GPIO_CFG_OUT_VAL(n) BIT(3 + (n) * 4)
#define UB913_REG_GPIO_CFG_MASK(n) (0xf << ((n) * 4))
#define UB913_REG_SCL_HIGH_TIME 0x11
#define UB913_REG_SCL_LOW_TIME 0x12
#define UB913_REG_PLL_OVR 0x35
struct ub913_data {
struct i2c_client *client;
struct regmap *regmap;
struct clk *clkin;
struct gpio_chip gpio_chip;
struct v4l2_subdev sd;
struct media_pad pads[2];
struct v4l2_async_notifier notifier;
struct v4l2_subdev *source_sd;
u16 source_sd_pad;
u64 enabled_source_streams;
struct clk_hw *clkout_clk_hw;
struct ds90ub9xx_platform_data *plat_data;
bool pclk_polarity_rising;
};
static inline struct ub913_data *sd_to_ub913(struct v4l2_subdev *sd)
{
return container_of(sd, struct ub913_data, sd);
}
struct ub913_format_info {
u32 incode;
u32 outcode;
};
static const struct ub913_format_info ub913_formats[] = {
/* Only RAW10 with 8-bit payload is supported at the moment */
{ .incode = MEDIA_BUS_FMT_YUYV8_2X8, .outcode = MEDIA_BUS_FMT_YUYV8_1X16 },
{ .incode = MEDIA_BUS_FMT_UYVY8_2X8, .outcode = MEDIA_BUS_FMT_UYVY8_1X16 },
{ .incode = MEDIA_BUS_FMT_VYUY8_2X8, .outcode = MEDIA_BUS_FMT_VYUY8_1X16 },
{ .incode = MEDIA_BUS_FMT_YVYU8_2X8, .outcode = MEDIA_BUS_FMT_YVYU8_1X16 },
};
static const struct ub913_format_info *ub913_find_format(u32 incode)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(ub913_formats); i++) {
if (ub913_formats[i].incode == incode)
return &ub913_formats[i];
}
return NULL;
}
static int ub913_read(const struct ub913_data *priv, u8 reg, u8 *val)
{
unsigned int v;
int ret;
ret = regmap_read(priv->regmap, reg, &v);
if (ret < 0) {
dev_err(&priv->client->dev,
"Cannot read register 0x%02x: %d!\n", reg, ret);
return ret;
}
*val = v;
return 0;
}
static int ub913_write(const struct ub913_data *priv, u8 reg, u8 val)
{
int ret;
ret = regmap_write(priv->regmap, reg, val);
if (ret < 0)
dev_err(&priv->client->dev,
"Cannot write register 0x%02x: %d!\n", reg, ret);
return ret;
}
/*
* GPIO chip
*/
static int ub913_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{
return GPIO_LINE_DIRECTION_OUT;
}
static int ub913_gpio_direction_out(struct gpio_chip *gc, unsigned int offset,
int value)
{
struct ub913_data *priv = gpiochip_get_data(gc);
unsigned int reg_idx = offset / 2;
unsigned int field_idx = offset % 2;
return regmap_update_bits(priv->regmap, UB913_REG_GPIO_CFG(reg_idx),
UB913_REG_GPIO_CFG_MASK(field_idx),
UB913_REG_GPIO_CFG_ENABLE(field_idx) |
(value ? UB913_REG_GPIO_CFG_OUT_VAL(field_idx) :
0));
}
static void ub913_gpio_set(struct gpio_chip *gc, unsigned int offset, int value)
{
ub913_gpio_direction_out(gc, offset, value);
}
static int ub913_gpio_of_xlate(struct gpio_chip *gc,
const struct of_phandle_args *gpiospec,
u32 *flags)
{
if (flags)
*flags = gpiospec->args[1];
return gpiospec->args[0];
}
static int ub913_gpiochip_probe(struct ub913_data *priv)
{
struct device *dev = &priv->client->dev;
struct gpio_chip *gc = &priv->gpio_chip;
int ret;
/* Initialize GPIOs 0 and 1 to local control, tri-state */
ub913_write(priv, UB913_REG_GPIO_CFG(0), 0);
gc->label = dev_name(dev);
gc->parent = dev;
gc->owner = THIS_MODULE;
gc->base = -1;
gc->can_sleep = true;
gc->ngpio = UB913_NUM_GPIOS;
gc->get_direction = ub913_gpio_get_direction;
gc->direction_output = ub913_gpio_direction_out;
gc->set = ub913_gpio_set;
gc->of_xlate = ub913_gpio_of_xlate;
gc->of_gpio_n_cells = 2;
ret = gpiochip_add_data(gc, priv);
if (ret) {
dev_err(dev, "Failed to add GPIOs: %d\n", ret);
return ret;
}
return 0;
}
static void ub913_gpiochip_remove(struct ub913_data *priv)
{
gpiochip_remove(&priv->gpio_chip);
}
static const struct regmap_config ub913_regmap_config = {
.name = "ds90ub913",
.reg_bits = 8,
.val_bits = 8,
.reg_format_endian = REGMAP_ENDIAN_DEFAULT,
.val_format_endian = REGMAP_ENDIAN_DEFAULT,
};
/*
* V4L2
*/
static int ub913_enable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{
struct ub913_data *priv = sd_to_ub913(sd);
u64 sink_streams;
int ret;
sink_streams = v4l2_subdev_state_xlate_streams(state, UB913_PAD_SOURCE,
UB913_PAD_SINK,
&streams_mask);
ret = v4l2_subdev_enable_streams(priv->source_sd, priv->source_sd_pad,
sink_streams);
if (ret)
return ret;
priv->enabled_source_streams |= streams_mask;
return 0;
}
static int ub913_disable_streams(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state, u32 pad,
u64 streams_mask)
{
struct ub913_data *priv = sd_to_ub913(sd);
u64 sink_streams;
int ret;
sink_streams = v4l2_subdev_state_xlate_streams(state, UB913_PAD_SOURCE,
UB913_PAD_SINK,
&streams_mask);
ret = v4l2_subdev_disable_streams(priv->source_sd, priv->source_sd_pad,
sink_streams);
if (ret)
return ret;
priv->enabled_source_streams &= ~streams_mask;
return 0;
}
static int _ub913_set_routing(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
struct v4l2_subdev_krouting *routing)
{
static const struct v4l2_mbus_framefmt in_format = {
.width = 640,
.height = 480,
.code = MEDIA_BUS_FMT_UYVY8_2X8,
.field = V4L2_FIELD_NONE,
.colorspace = V4L2_COLORSPACE_SRGB,
.ycbcr_enc = V4L2_YCBCR_ENC_601,
.quantization = V4L2_QUANTIZATION_LIM_RANGE,
.xfer_func = V4L2_XFER_FUNC_SRGB,
};
static const struct v4l2_mbus_framefmt out_format = {
.width = 640,
.height = 480,
.code = MEDIA_BUS_FMT_UYVY8_1X16,
.field = V4L2_FIELD_NONE,
.colorspace = V4L2_COLORSPACE_SRGB,
.ycbcr_enc = V4L2_YCBCR_ENC_601,
.quantization = V4L2_QUANTIZATION_LIM_RANGE,
.xfer_func = V4L2_XFER_FUNC_SRGB,
};
struct v4l2_subdev_stream_configs *stream_configs;
unsigned int i;
int ret;
/*
* Note: we can only support up to V4L2_FRAME_DESC_ENTRY_MAX, until
* frame desc is made dynamically allocated.
*/
if (routing->num_routes > V4L2_FRAME_DESC_ENTRY_MAX)
return -EINVAL;
ret = v4l2_subdev_routing_validate(sd, routing,
V4L2_SUBDEV_ROUTING_ONLY_1_TO_1);
if (ret)
return ret;
ret = v4l2_subdev_set_routing(sd, state, routing);
if (ret)
return ret;
stream_configs = &state->stream_configs;
for (i = 0; i < stream_configs->num_configs; i++) {
if (stream_configs->configs[i].pad == UB913_PAD_SINK)
stream_configs->configs[i].fmt = in_format;
else
stream_configs->configs[i].fmt = out_format;
}
return 0;
}
static int ub913_set_routing(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
enum v4l2_subdev_format_whence which,
struct v4l2_subdev_krouting *routing)
{
struct ub913_data *priv = sd_to_ub913(sd);
if (which == V4L2_SUBDEV_FORMAT_ACTIVE && priv->enabled_source_streams)
return -EBUSY;
return _ub913_set_routing(sd, state, routing);
}
static int ub913_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
struct v4l2_mbus_frame_desc *fd)
{
struct ub913_data *priv = sd_to_ub913(sd);
const struct v4l2_subdev_krouting *routing;
struct v4l2_mbus_frame_desc source_fd;
struct v4l2_subdev_route *route;
struct v4l2_subdev_state *state;
int ret;
if (pad != UB913_PAD_SOURCE)
return -EINVAL;
ret = v4l2_subdev_call(priv->source_sd, pad, get_frame_desc,
priv->source_sd_pad, &source_fd);
if (ret)
return ret;
memset(fd, 0, sizeof(*fd));
fd->type = V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL;
state = v4l2_subdev_lock_and_get_active_state(sd);
routing = &state->routing;
for_each_active_route(routing, route) {
unsigned int i;
if (route->source_pad != pad)
continue;
for (i = 0; i < source_fd.num_entries; i++) {
if (source_fd.entry[i].stream == route->sink_stream)
break;
}
if (i == source_fd.num_entries) {
dev_err(&priv->client->dev,
"Failed to find stream from source frame desc\n");
ret = -EPIPE;
goto out_unlock;
}
fd->entry[fd->num_entries].stream = route->source_stream;
fd->entry[fd->num_entries].flags = source_fd.entry[i].flags;
fd->entry[fd->num_entries].length = source_fd.entry[i].length;
fd->entry[fd->num_entries].pixelcode =
source_fd.entry[i].pixelcode;
fd->num_entries++;
}
out_unlock:
v4l2_subdev_unlock_state(state);
return ret;
}
static int ub913_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
struct v4l2_subdev_format *format)
{
struct ub913_data *priv = sd_to_ub913(sd);
struct v4l2_mbus_framefmt *fmt;
const struct ub913_format_info *finfo;
if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE &&
priv->enabled_source_streams)
return -EBUSY;
/* Source format is fully defined by the sink format, so not settable */
if (format->pad == UB913_PAD_SOURCE)
return v4l2_subdev_get_fmt(sd, state, format);
finfo = ub913_find_format(format->format.code);
if (!finfo) {
finfo = &ub913_formats[0];
format->format.code = finfo->incode;
}
/* Set sink format */
fmt = v4l2_subdev_state_get_stream_format(state, format->pad,
format->stream);
if (!fmt)
return -EINVAL;
*fmt = format->format;
/* Propagate to source format, and adjust the mbus code */
fmt = v4l2_subdev_state_get_opposite_stream_format(state, format->pad,
format->stream);
if (!fmt)
return -EINVAL;
format->format.code = finfo->outcode;
*fmt = format->format;
return 0;
}
static int ub913_init_cfg(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state)
{
struct v4l2_subdev_route routes[] = {
{
.sink_pad = UB913_PAD_SINK,
.sink_stream = 0,
.source_pad = UB913_PAD_SOURCE,
.source_stream = 0,
.flags = V4L2_SUBDEV_ROUTE_FL_ACTIVE,
},
};
struct v4l2_subdev_krouting routing = {
.num_routes = ARRAY_SIZE(routes),
.routes = routes,
};
return _ub913_set_routing(sd, state, &routing);
}
static int ub913_log_status(struct v4l2_subdev *sd)
{
struct ub913_data *priv = sd_to_ub913(sd);
struct device *dev = &priv->client->dev;
u8 v = 0, v1 = 0, v2 = 0;
ub913_read(priv, UB913_REG_MODE_SEL, &v);
dev_info(dev, "MODE_SEL %#02x\n", v);
ub913_read(priv, UB913_REG_CRC_ERRORS_LSB, &v1);
ub913_read(priv, UB913_REG_CRC_ERRORS_MSB, &v2);
dev_info(dev, "CRC errors %u\n", v1 | (v2 << 8));
/* clear CRC errors */
ub913_read(priv, UB913_REG_GENERAL_CFG, &v);
ub913_write(priv, UB913_REG_GENERAL_CFG,
v | UB913_REG_GENERAL_CFG_CRC_ERR_RESET);
ub913_write(priv, UB913_REG_GENERAL_CFG, v);
ub913_read(priv, UB913_REG_GENERAL_STATUS, &v);
dev_info(dev, "GENERAL_STATUS %#02x\n", v);
ub913_read(priv, UB913_REG_PLL_OVR, &v);
dev_info(dev, "PLL_OVR %#02x\n", v);
return 0;
}
static const struct v4l2_subdev_core_ops ub913_subdev_core_ops = {
.log_status = ub913_log_status,
};
static const struct v4l2_subdev_pad_ops ub913_pad_ops = {
.enable_streams = ub913_enable_streams,
.disable_streams = ub913_disable_streams,
.set_routing = ub913_set_routing,
.get_frame_desc = ub913_get_frame_desc,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = ub913_set_fmt,
.init_cfg = ub913_init_cfg,
};
static const struct v4l2_subdev_ops ub913_subdev_ops = {
.core = &ub913_subdev_core_ops,
.pad = &ub913_pad_ops,
};
static const struct media_entity_operations ub913_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
static int ub913_notify_bound(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *source_subdev,
struct v4l2_async_connection *asd)
{
struct ub913_data *priv = sd_to_ub913(notifier->sd);
struct device *dev = &priv->client->dev;
int ret;
ret = media_entity_get_fwnode_pad(&source_subdev->entity,
source_subdev->fwnode,
MEDIA_PAD_FL_SOURCE);
if (ret < 0) {
dev_err(dev, "Failed to find pad for %s\n",
source_subdev->name);
return ret;
}
priv->source_sd = source_subdev;
priv->source_sd_pad = ret;
ret = media_create_pad_link(&source_subdev->entity, priv->source_sd_pad,
&priv->sd.entity, UB913_PAD_SINK,
MEDIA_LNK_FL_ENABLED |
MEDIA_LNK_FL_IMMUTABLE);
if (ret) {
dev_err(dev, "Unable to link %s:%u -> %s:0\n",
source_subdev->name, priv->source_sd_pad,
priv->sd.name);
return ret;
}
return 0;
}
static const struct v4l2_async_notifier_operations ub913_notify_ops = {
.bound = ub913_notify_bound,
};
static int ub913_v4l2_notifier_register(struct ub913_data *priv)
{
struct device *dev = &priv->client->dev;
struct v4l2_async_connection *asd;
struct fwnode_handle *ep_fwnode;
int ret;
ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
UB913_PAD_SINK, 0, 0);
if (!ep_fwnode) {
dev_err(dev, "No graph endpoint\n");
return -ENODEV;
}
v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
asd = v4l2_async_nf_add_fwnode_remote(&priv->notifier, ep_fwnode,
struct v4l2_async_connection);
fwnode_handle_put(ep_fwnode);
if (IS_ERR(asd)) {
dev_err(dev, "Failed to add subdev: %ld", PTR_ERR(asd));
v4l2_async_nf_cleanup(&priv->notifier);
return PTR_ERR(asd);
}
priv->notifier.ops = &ub913_notify_ops;
ret = v4l2_async_nf_register(&priv->notifier);
if (ret) {
dev_err(dev, "Failed to register subdev_notifier");
v4l2_async_nf_cleanup(&priv->notifier);
return ret;
}
return 0;
}
static void ub913_v4l2_nf_unregister(struct ub913_data *priv)
{
v4l2_async_nf_unregister(&priv->notifier);
v4l2_async_nf_cleanup(&priv->notifier);
}
static int ub913_register_clkout(struct ub913_data *priv)
{
struct device *dev = &priv->client->dev;
const char *name;
int ret;
name = kasprintf(GFP_KERNEL, "ds90ub913.%s.clk_out", dev_name(dev));
if (!name)
return -ENOMEM;
priv->clkout_clk_hw = devm_clk_hw_register_fixed_factor(dev, name,
__clk_get_name(priv->clkin), 0, 1, 2);
kfree(name);
if (IS_ERR(priv->clkout_clk_hw))
return dev_err_probe(dev, PTR_ERR(priv->clkout_clk_hw),
"Cannot register clkout hw\n");
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
priv->clkout_clk_hw);
if (ret)
return dev_err_probe(dev, ret,
"Cannot add OF clock provider\n");
return 0;
}
static int ub913_i2c_master_init(struct ub913_data *priv)
{
/* i2c fast mode */
u32 scl_high = 600 + 300; /* high period + rise time, ns */
u32 scl_low = 1300 + 300; /* low period + fall time, ns */
unsigned long ref;
int ret;
ref = clk_get_rate(priv->clkin) / 2;
scl_high = div64_u64((u64)scl_high * ref, 1000000000);
scl_low = div64_u64((u64)scl_low * ref, 1000000000);
ret = ub913_write(priv, UB913_REG_SCL_HIGH_TIME, scl_high);
if (ret)
return ret;
ret = ub913_write(priv, UB913_REG_SCL_LOW_TIME, scl_low);
if (ret)
return ret;
return 0;
}
static int ub913_add_i2c_adapter(struct ub913_data *priv)
{
struct device *dev = &priv->client->dev;
struct fwnode_handle *i2c_handle;
int ret;
i2c_handle = device_get_named_child_node(dev, "i2c");
if (!i2c_handle)
return 0;
ret = i2c_atr_add_adapter(priv->plat_data->atr, priv->plat_data->port,
dev, i2c_handle);
fwnode_handle_put(i2c_handle);
if (ret)
return ret;
return 0;
}
static int ub913_parse_dt(struct ub913_data *priv)
{
struct device *dev = &priv->client->dev;
struct v4l2_fwnode_endpoint vep = {
.bus_type = V4L2_MBUS_PARALLEL,
};
struct fwnode_handle *ep_fwnode;
int ret;
ep_fwnode = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev),
UB913_PAD_SINK, 0, 0);
if (!ep_fwnode)
return dev_err_probe(dev, -ENOENT, "No sink endpoint\n");
ret = v4l2_fwnode_endpoint_parse(ep_fwnode, &vep);
fwnode_handle_put(ep_fwnode);
if (ret)
return dev_err_probe(dev, ret,
"failed to parse sink endpoint data\n");
if (vep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
priv->pclk_polarity_rising = true;
else if (vep.bus.parallel.flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)
priv->pclk_polarity_rising = false;
else
return dev_err_probe(dev, -EINVAL,
"bad value for 'pclk-sample'\n");
return 0;
}
static int ub913_hw_init(struct ub913_data *priv)
{
struct device *dev = &priv->client->dev;
bool mode_override;
u8 mode;
int ret;
u8 v;
ret = ub913_read(priv, UB913_REG_MODE_SEL, &v);
if (ret)
return ret;
if (!(v & UB913_REG_MODE_SEL_MODE_UP_TO_DATE))
return dev_err_probe(dev, -ENODEV,
"Mode value not stabilized\n");
mode_override = v & UB913_REG_MODE_SEL_MODE_OVERRIDE;
mode = v & UB913_REG_MODE_SEL_MODE_MASK;
dev_dbg(dev, "mode from %s: %#x\n",
mode_override ? "reg" : "deserializer", mode);
ret = ub913_i2c_master_init(priv);
if (ret)
return dev_err_probe(dev, ret, "i2c master init failed\n");
ub913_read(priv, UB913_REG_GENERAL_CFG, &v);
v &= ~UB913_REG_GENERAL_CFG_PCLK_RISING;
v |= priv->pclk_polarity_rising ? UB913_REG_GENERAL_CFG_PCLK_RISING : 0;
ub913_write(priv, UB913_REG_GENERAL_CFG, v);
return 0;
}
static int ub913_subdev_init(struct ub913_data *priv)
{
struct device *dev = &priv->client->dev;
int ret;
v4l2_i2c_subdev_init(&priv->sd, priv->client, &ub913_subdev_ops);
priv->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | V4L2_SUBDEV_FL_STREAMS;
priv->sd.entity.function = MEDIA_ENT_F_VID_IF_BRIDGE;
priv->sd.entity.ops = &ub913_entity_ops;
priv->pads[0].flags = MEDIA_PAD_FL_SINK;
priv->pads[1].flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&priv->sd.entity, 2, priv->pads);
if (ret)
return dev_err_probe(dev, ret, "Failed to init pads\n");
ret = v4l2_subdev_init_finalize(&priv->sd);
if (ret)
goto err_entity_cleanup;
ret = ub913_v4l2_notifier_register(priv);
if (ret) {
dev_err_probe(dev, ret,
"v4l2 subdev notifier register failed\n");
goto err_subdev_cleanup;
}
ret = v4l2_async_register_subdev(&priv->sd);
if (ret) {
dev_err_probe(dev, ret, "v4l2_async_register_subdev error\n");
goto err_unreg_notif;
}
return 0;
err_unreg_notif:
ub913_v4l2_nf_unregister(priv);
err_subdev_cleanup:
v4l2_subdev_cleanup(&priv->sd);
err_entity_cleanup:
media_entity_cleanup(&priv->sd.entity);
return ret;
}
static void ub913_subdev_uninit(struct ub913_data *priv)
{
v4l2_async_unregister_subdev(&priv->sd);
ub913_v4l2_nf_unregister(priv);
v4l2_subdev_cleanup(&priv->sd);
fwnode_handle_put(priv->sd.fwnode);
media_entity_cleanup(&priv->sd.entity);
}
static int ub913_probe(struct i2c_client *client)
{
struct device *dev = &client->dev;
struct ub913_data *priv;
int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->client = client;
priv->plat_data = dev_get_platdata(&client->dev);
if (!priv->plat_data)
return dev_err_probe(dev, -ENODEV, "Platform data missing\n");
priv->regmap = devm_regmap_init_i2c(client, &ub913_regmap_config);
if (IS_ERR(priv->regmap))
return dev_err_probe(dev, PTR_ERR(priv->regmap),
"Failed to init regmap\n");
/*
* ub913 can also work without ext clock, but that is not supported by
* the driver yet.
*/
priv->clkin = devm_clk_get(dev, "clkin");
if (IS_ERR(priv->clkin))
return dev_err_probe(dev, PTR_ERR(priv->clkin),
"Cannot get CLKIN\n");
ret = ub913_parse_dt(priv);
if (ret)
return ret;
ret = ub913_hw_init(priv);
if (ret)
return ret;
ret = ub913_gpiochip_probe(priv);
if (ret)
return dev_err_probe(dev, ret, "Failed to init gpiochip\n");
ret = ub913_register_clkout(priv);
if (ret) {
dev_err_probe(dev, ret, "Failed to register clkout\n");
goto err_gpiochip_remove;
}
ret = ub913_subdev_init(priv);
if (ret)
goto err_gpiochip_remove;
ret = ub913_add_i2c_adapter(priv);
if (ret) {
dev_err_probe(dev, ret, "failed to add remote i2c adapter\n");
goto err_subdev_uninit;
}
return 0;
err_subdev_uninit:
ub913_subdev_uninit(priv);
err_gpiochip_remove:
ub913_gpiochip_remove(priv);
return ret;
}
static void ub913_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct ub913_data *priv = sd_to_ub913(sd);
i2c_atr_del_adapter(priv->plat_data->atr, priv->plat_data->port);
ub913_subdev_uninit(priv);
ub913_gpiochip_remove(priv);
}
static const struct i2c_device_id ub913_id[] = { { "ds90ub913a-q1", 0 }, {} };
MODULE_DEVICE_TABLE(i2c, ub913_id);
static const struct of_device_id ub913_dt_ids[] = {
{ .compatible = "ti,ds90ub913a-q1" },
{}
};
MODULE_DEVICE_TABLE(of, ub913_dt_ids);
static struct i2c_driver ds90ub913_driver = {
.probe = ub913_probe,
.remove = ub913_remove,
.id_table = ub913_id,
.driver = {
.name = "ds90ub913a",
.of_match_table = ub913_dt_ids,
},
};
module_i2c_driver(ds90ub913_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Texas Instruments DS90UB913 FPD-Link III Serializer Driver");
MODULE_AUTHOR("Luca Ceresoli <luca@lucaceresoli.net>");
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
MODULE_IMPORT_NS(I2C_ATR);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

350
drivers/media/i2c/dw9719.c Normal file
View File

@ -0,0 +1,350 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2012 Intel Corporation
/*
* Based on linux/modules/camera/drivers/media/i2c/imx/dw9719.c in this repo:
* https://github.com/ZenfoneArea/android_kernel_asus_zenfone5
*/
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/types.h>
#include <media/v4l2-cci.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#define DW9719_MAX_FOCUS_POS 1023
#define DW9719_CTRL_STEPS 16
#define DW9719_CTRL_DELAY_US 1000
#define DW9719_INFO CCI_REG8(0)
#define DW9719_ID 0xF1
#define DW9719_CONTROL CCI_REG8(2)
#define DW9719_ENABLE_RINGING 0x02
#define DW9719_VCM_CURRENT CCI_REG16(3)
#define DW9719_MODE CCI_REG8(6)
#define DW9719_MODE_SAC_SHIFT 4
#define DW9719_MODE_SAC3 4
#define DW9719_VCM_FREQ CCI_REG8(7)
#define DW9719_DEFAULT_VCM_FREQ 0x60
#define to_dw9719_device(x) container_of(x, struct dw9719_device, sd)
struct dw9719_device {
struct v4l2_subdev sd;
struct device *dev;
struct regmap *regmap;
struct regulator *regulator;
u32 sac_mode;
u32 vcm_freq;
struct dw9719_v4l2_ctrls {
struct v4l2_ctrl_handler handler;
struct v4l2_ctrl *focus;
} ctrls;
};
static int dw9719_detect(struct dw9719_device *dw9719)
{
int ret;
u64 val;
ret = cci_read(dw9719->regmap, DW9719_INFO, &val, NULL);
if (ret < 0)
return ret;
if (val != DW9719_ID) {
dev_err(dw9719->dev, "Failed to detect correct id\n");
return -ENXIO;
}
return 0;
}
static int dw9719_power_down(struct dw9719_device *dw9719)
{
return regulator_disable(dw9719->regulator);
}
static int dw9719_power_up(struct dw9719_device *dw9719)
{
int ret;
ret = regulator_enable(dw9719->regulator);
if (ret)
return ret;
/* Jiggle SCL pin to wake up device */
cci_write(dw9719->regmap, DW9719_CONTROL, 1, &ret);
/* Need 100us to transit from SHUTDOWN to STANDBY */
fsleep(100);
cci_write(dw9719->regmap, DW9719_CONTROL, DW9719_ENABLE_RINGING, &ret);
cci_write(dw9719->regmap, DW9719_MODE,
dw9719->sac_mode << DW9719_MODE_SAC_SHIFT, &ret);
cci_write(dw9719->regmap, DW9719_VCM_FREQ, dw9719->vcm_freq, &ret);
if (ret)
dw9719_power_down(dw9719);
return ret;
}
static int dw9719_t_focus_abs(struct dw9719_device *dw9719, s32 value)
{
return cci_write(dw9719->regmap, DW9719_VCM_CURRENT, value, NULL);
}
static int dw9719_set_ctrl(struct v4l2_ctrl *ctrl)
{
struct dw9719_device *dw9719 = container_of(ctrl->handler,
struct dw9719_device,
ctrls.handler);
int ret;
/* Only apply changes to the controls if the device is powered up */
if (!pm_runtime_get_if_in_use(dw9719->dev))
return 0;
switch (ctrl->id) {
case V4L2_CID_FOCUS_ABSOLUTE:
ret = dw9719_t_focus_abs(dw9719, ctrl->val);
break;
default:
ret = -EINVAL;
}
pm_runtime_put(dw9719->dev);
return ret;
}
static const struct v4l2_ctrl_ops dw9719_ctrl_ops = {
.s_ctrl = dw9719_set_ctrl,
};
static int dw9719_suspend(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct dw9719_device *dw9719 = to_dw9719_device(sd);
int ret;
int val;
for (val = dw9719->ctrls.focus->val; val >= 0;
val -= DW9719_CTRL_STEPS) {
ret = dw9719_t_focus_abs(dw9719, val);
if (ret)
return ret;
usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10);
}
return dw9719_power_down(dw9719);
}
static int dw9719_resume(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct dw9719_device *dw9719 = to_dw9719_device(sd);
int current_focus = dw9719->ctrls.focus->val;
int ret;
int val;
ret = dw9719_power_up(dw9719);
if (ret)
return ret;
for (val = current_focus % DW9719_CTRL_STEPS; val < current_focus;
val += DW9719_CTRL_STEPS) {
ret = dw9719_t_focus_abs(dw9719, val);
if (ret)
goto err_power_down;
usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10);
}
return 0;
err_power_down:
dw9719_power_down(dw9719);
return ret;
}
static int dw9719_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
return pm_runtime_resume_and_get(sd->dev);
}
static int dw9719_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
pm_runtime_put(sd->dev);
return 0;
}
static const struct v4l2_subdev_internal_ops dw9719_internal_ops = {
.open = dw9719_open,
.close = dw9719_close,
};
static int dw9719_init_controls(struct dw9719_device *dw9719)
{
const struct v4l2_ctrl_ops *ops = &dw9719_ctrl_ops;
int ret;
v4l2_ctrl_handler_init(&dw9719->ctrls.handler, 1);
dw9719->ctrls.focus = v4l2_ctrl_new_std(&dw9719->ctrls.handler, ops,
V4L2_CID_FOCUS_ABSOLUTE, 0,
DW9719_MAX_FOCUS_POS, 1, 0);
if (dw9719->ctrls.handler.error) {
dev_err(dw9719->dev, "Error initialising v4l2 ctrls\n");
ret = dw9719->ctrls.handler.error;
goto err_free_handler;
}
dw9719->sd.ctrl_handler = &dw9719->ctrls.handler;
return 0;
err_free_handler:
v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
return ret;
}
static const struct v4l2_subdev_ops dw9719_ops = { };
static int dw9719_probe(struct i2c_client *client)
{
struct dw9719_device *dw9719;
int ret;
dw9719 = devm_kzalloc(&client->dev, sizeof(*dw9719), GFP_KERNEL);
if (!dw9719)
return -ENOMEM;
dw9719->regmap = devm_cci_regmap_init_i2c(client, 8);
if (IS_ERR(dw9719->regmap))
return PTR_ERR(dw9719->regmap);
dw9719->dev = &client->dev;
dw9719->sac_mode = DW9719_MODE_SAC3;
dw9719->vcm_freq = DW9719_DEFAULT_VCM_FREQ;
/* Optional indication of SAC mode select */
device_property_read_u32(&client->dev, "dongwoon,sac-mode",
&dw9719->sac_mode);
/* Optional indication of VCM frequency */
device_property_read_u32(&client->dev, "dongwoon,vcm-freq",
&dw9719->vcm_freq);
dw9719->regulator = devm_regulator_get(&client->dev, "vdd");
if (IS_ERR(dw9719->regulator))
return dev_err_probe(&client->dev, PTR_ERR(dw9719->regulator),
"getting regulator\n");
v4l2_i2c_subdev_init(&dw9719->sd, client, &dw9719_ops);
dw9719->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
dw9719->sd.internal_ops = &dw9719_internal_ops;
ret = dw9719_init_controls(dw9719);
if (ret)
return ret;
ret = media_entity_pads_init(&dw9719->sd.entity, 0, NULL);
if (ret < 0)
goto err_free_ctrl_handler;
dw9719->sd.entity.function = MEDIA_ENT_F_LENS;
/*
* We need the driver to work in the event that pm runtime is disable in
* the kernel, so power up and verify the chip now. In the event that
* runtime pm is disabled this will leave the chip on, so that the lens
* will work.
*/
ret = dw9719_power_up(dw9719);
if (ret)
goto err_cleanup_media;
ret = dw9719_detect(dw9719);
if (ret)
goto err_powerdown;
pm_runtime_set_active(&client->dev);
pm_runtime_get_noresume(&client->dev);
pm_runtime_enable(&client->dev);
ret = v4l2_async_register_subdev(&dw9719->sd);
if (ret < 0)
goto err_pm_runtime;
pm_runtime_set_autosuspend_delay(&client->dev, 1000);
pm_runtime_use_autosuspend(&client->dev);
pm_runtime_put_autosuspend(&client->dev);
return ret;
err_pm_runtime:
pm_runtime_disable(&client->dev);
pm_runtime_put_noidle(&client->dev);
err_powerdown:
dw9719_power_down(dw9719);
err_cleanup_media:
media_entity_cleanup(&dw9719->sd.entity);
err_free_ctrl_handler:
v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
return ret;
}
static void dw9719_remove(struct i2c_client *client)
{
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct dw9719_device *dw9719 =
container_of(sd, struct dw9719_device, sd);
v4l2_async_unregister_subdev(sd);
v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
media_entity_cleanup(&dw9719->sd.entity);
pm_runtime_disable(&client->dev);
if (!pm_runtime_status_suspended(&client->dev))
dw9719_power_down(dw9719);
pm_runtime_set_suspended(&client->dev);
}
static const struct i2c_device_id dw9719_id_table[] = {
{ "dw9719" },
{ }
};
MODULE_DEVICE_TABLE(i2c, dw9719_id_table);
static DEFINE_RUNTIME_DEV_PM_OPS(dw9719_pm_ops, dw9719_suspend, dw9719_resume,
NULL);
static struct i2c_driver dw9719_i2c_driver = {
.driver = {
.name = "dw9719",
.pm = pm_sleep_ptr(&dw9719_pm_ops),
},
.probe = dw9719_probe,
.remove = dw9719_remove,
.id_table = dw9719_id_table,
};
module_i2c_driver(dw9719_i2c_driver);
MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
MODULE_DESCRIPTION("DW9719 VCM Driver");
MODULE_LICENSE("GPL");

View File

@ -1,10 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
config VIDEO_ET8EK8
tristate "ET8EK8 camera sensor support"
depends on I2C && VIDEO_DEV
select MEDIA_CONTROLLER
select VIDEO_V4L2_SUBDEV_API
select V4L2_FWNODE
help
This is a driver for the Toshiba ET8EK8 5 MP camera sensor.
It is used for example in Nokia N900 (RX-51).

View File

@ -1357,6 +1357,6 @@ static struct i2c_driver hi556_i2c_driver = {
module_i2c_driver(hi556_i2c_driver);
MODULE_AUTHOR("Shawn Tu <shawnx.tu@intel.com>");
MODULE_AUTHOR("Shawn Tu");
MODULE_DESCRIPTION("Hynix HI556 sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -3005,6 +3005,6 @@ static struct i2c_driver hi847_i2c_driver = {
module_i2c_driver(hi847_i2c_driver);
MODULE_AUTHOR("Shawn Tu <shawnx.tu@intel.com>");
MODULE_AUTHOR("Shawn Tu");
MODULE_DESCRIPTION("Hynix HI847 sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -1109,6 +1109,6 @@ module_i2c_driver(imx208_i2c_driver);
MODULE_AUTHOR("Yeh, Andy <andy.yeh@intel.com>");
MODULE_AUTHOR("Chen, Ping-chung <ping-chung.chen@intel.com>");
MODULE_AUTHOR("Shawn Tu <shawnx.tu@intel.com>");
MODULE_AUTHOR("Shawn Tu");
MODULE_DESCRIPTION("Sony IMX208 sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -345,7 +345,7 @@ static const char * const imx219_supply_name[] = {
* - v flip
* - h&v flips
*/
static const u32 codes[] = {
static const u32 imx219_mbus_formats[] = {
MEDIA_BUS_FMT_SRGGB10_1X10,
MEDIA_BUS_FMT_SGRBG10_1X10,
MEDIA_BUS_FMT_SGBRG10_1X10,
@ -460,8 +460,6 @@ struct imx219 {
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_mbus_framefmt fmt;
struct clk *xclk; /* system clock to IMX219 */
u32 xclk_freq;
@ -481,12 +479,6 @@ struct imx219 {
/* Current mode */
const struct imx219_mode *mode;
/*
* Mutex for serialized access:
* Protect sensor module set pad format and start/stop streaming safely.
*/
struct mutex mutex;
/* Streaming on/off */
bool streaming;
@ -576,64 +568,17 @@ static u32 imx219_get_format_code(struct imx219 *imx219, u32 code)
{
unsigned int i;
lockdep_assert_held(&imx219->mutex);
for (i = 0; i < ARRAY_SIZE(codes); i++)
if (codes[i] == code)
for (i = 0; i < ARRAY_SIZE(imx219_mbus_formats); i++)
if (imx219_mbus_formats[i] == code)
break;
if (i >= ARRAY_SIZE(codes))
if (i >= ARRAY_SIZE(imx219_mbus_formats))
i = 0;
i = (i & ~3) | (imx219->vflip->val ? 2 : 0) |
(imx219->hflip->val ? 1 : 0);
return codes[i];
}
static void imx219_set_default_format(struct imx219 *imx219)
{
struct v4l2_mbus_framefmt *fmt;
fmt = &imx219->fmt;
fmt->code = MEDIA_BUS_FMT_SRGGB10_1X10;
fmt->colorspace = V4L2_COLORSPACE_SRGB;
fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
fmt->colorspace,
fmt->ycbcr_enc);
fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
fmt->width = supported_modes[0].width;
fmt->height = supported_modes[0].height;
fmt->field = V4L2_FIELD_NONE;
}
static int imx219_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct imx219 *imx219 = to_imx219(sd);
struct v4l2_mbus_framefmt *try_fmt =
v4l2_subdev_get_try_format(sd, fh->state, 0);
struct v4l2_rect *try_crop;
mutex_lock(&imx219->mutex);
/* Initialize try_fmt */
try_fmt->width = supported_modes[0].width;
try_fmt->height = supported_modes[0].height;
try_fmt->code = imx219_get_format_code(imx219,
MEDIA_BUS_FMT_SRGGB10_1X10);
try_fmt->field = V4L2_FIELD_NONE;
/* Initialize try_crop rectangle. */
try_crop = v4l2_subdev_get_try_crop(sd, fh->state, 0);
try_crop->top = IMX219_PIXEL_ARRAY_TOP;
try_crop->left = IMX219_PIXEL_ARRAY_LEFT;
try_crop->width = IMX219_PIXEL_ARRAY_WIDTH;
try_crop->height = IMX219_PIXEL_ARRAY_HEIGHT;
mutex_unlock(&imx219->mutex);
return 0;
return imx219_mbus_formats[i];
}
static int imx219_set_ctrl(struct v4l2_ctrl *ctrl)
@ -725,18 +670,52 @@ static const struct v4l2_ctrl_ops imx219_ctrl_ops = {
.s_ctrl = imx219_set_ctrl,
};
static void imx219_update_pad_format(struct imx219 *imx219,
const struct imx219_mode *mode,
struct v4l2_mbus_framefmt *fmt, u32 code)
{
/* Bayer order varies with flips */
fmt->code = imx219_get_format_code(imx219, code);
fmt->width = mode->width;
fmt->height = mode->height;
fmt->field = V4L2_FIELD_NONE;
fmt->colorspace = V4L2_COLORSPACE_RAW;
fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
fmt->xfer_func = V4L2_XFER_FUNC_NONE;
}
static int imx219_init_cfg(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state)
{
struct imx219 *imx219 = to_imx219(sd);
struct v4l2_mbus_framefmt *format;
struct v4l2_rect *crop;
/* Initialize try_fmt */
format = v4l2_subdev_get_pad_format(sd, state, 0);
imx219_update_pad_format(imx219, &supported_modes[0], format,
MEDIA_BUS_FMT_SRGGB10_1X10);
/* Initialize crop rectangle. */
crop = v4l2_subdev_get_pad_crop(sd, state, 0);
crop->top = IMX219_PIXEL_ARRAY_TOP;
crop->left = IMX219_PIXEL_ARRAY_LEFT;
crop->width = IMX219_PIXEL_ARRAY_WIDTH;
crop->height = IMX219_PIXEL_ARRAY_HEIGHT;
return 0;
}
static int imx219_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
struct imx219 *imx219 = to_imx219(sd);
if (code->index >= (ARRAY_SIZE(codes) / 4))
if (code->index >= (ARRAY_SIZE(imx219_mbus_formats) / 4))
return -EINVAL;
mutex_lock(&imx219->mutex);
code->code = imx219_get_format_code(imx219, codes[code->index * 4]);
mutex_unlock(&imx219->mutex);
code->code = imx219_get_format_code(imx219, imx219_mbus_formats[code->index * 4]);
return 0;
}
@ -751,9 +730,7 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd,
if (fse->index >= ARRAY_SIZE(supported_modes))
return -EINVAL;
mutex_lock(&imx219->mutex);
code = imx219_get_format_code(imx219, fse->code);
mutex_unlock(&imx219->mutex);
if (fse->code != code)
return -EINVAL;
@ -765,92 +742,27 @@ static int imx219_enum_frame_size(struct v4l2_subdev *sd,
return 0;
}
static void imx219_reset_colorspace(struct v4l2_mbus_framefmt *fmt)
{
fmt->colorspace = V4L2_COLORSPACE_SRGB;
fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt->colorspace);
fmt->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(true,
fmt->colorspace,
fmt->ycbcr_enc);
fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt->colorspace);
}
static void imx219_update_pad_format(struct imx219 *imx219,
const struct imx219_mode *mode,
struct v4l2_subdev_format *fmt)
{
fmt->format.width = mode->width;
fmt->format.height = mode->height;
fmt->format.field = V4L2_FIELD_NONE;
imx219_reset_colorspace(&fmt->format);
}
static int __imx219_get_pad_format(struct imx219 *imx219,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
struct v4l2_mbus_framefmt *try_fmt =
v4l2_subdev_get_try_format(&imx219->sd, sd_state,
fmt->pad);
/* update the code which could change due to vflip or hflip: */
try_fmt->code = imx219_get_format_code(imx219, try_fmt->code);
fmt->format = *try_fmt;
} else {
imx219_update_pad_format(imx219, imx219->mode, fmt);
fmt->format.code = imx219_get_format_code(imx219,
imx219->fmt.code);
}
return 0;
}
static int imx219_get_pad_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct imx219 *imx219 = to_imx219(sd);
int ret;
mutex_lock(&imx219->mutex);
ret = __imx219_get_pad_format(imx219, sd_state, fmt);
mutex_unlock(&imx219->mutex);
return ret;
}
static int imx219_set_pad_format(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *fmt)
{
struct imx219 *imx219 = to_imx219(sd);
const struct imx219_mode *mode;
struct v4l2_mbus_framefmt *framefmt;
int exposure_max, exposure_def, hblank;
unsigned int i;
mutex_lock(&imx219->mutex);
for (i = 0; i < ARRAY_SIZE(codes); i++)
if (codes[i] == fmt->format.code)
break;
if (i >= ARRAY_SIZE(codes))
i = 0;
/* Bayer order varies with flips */
fmt->format.code = imx219_get_format_code(imx219, codes[i]);
struct v4l2_mbus_framefmt *format;
mode = v4l2_find_nearest_size(supported_modes,
ARRAY_SIZE(supported_modes),
width, height,
fmt->format.width, fmt->format.height);
imx219_update_pad_format(imx219, mode, fmt);
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
framefmt = v4l2_subdev_get_try_format(sd, sd_state, fmt->pad);
*framefmt = fmt->format;
} else if (imx219->mode != mode ||
imx219->fmt.code != fmt->format.code) {
imx219->fmt = fmt->format;
imx219_update_pad_format(imx219, mode, &fmt->format, fmt->format.code);
format = v4l2_subdev_get_pad_format(sd, sd_state, 0);
if (imx219->mode == mode && format->code == fmt->format.code)
return 0;
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
imx219->mode = mode;
/* Update limits and set FPS to default */
__v4l2_ctrl_modify_range(imx219->vblank, IMX219_VBLANK_MIN,
@ -876,14 +788,15 @@ static int imx219_set_pad_format(struct v4l2_subdev *sd,
hblank);
}
mutex_unlock(&imx219->mutex);
*format = fmt->format;
return 0;
}
static int imx219_set_framefmt(struct imx219 *imx219)
static int imx219_set_framefmt(struct imx219 *imx219,
const struct v4l2_mbus_framefmt *format)
{
switch (imx219->fmt.code) {
switch (format->code) {
case MEDIA_BUS_FMT_SRGGB8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
@ -902,7 +815,8 @@ static int imx219_set_framefmt(struct imx219 *imx219)
return -EINVAL;
}
static int imx219_set_binning(struct imx219 *imx219)
static int imx219_set_binning(struct imx219 *imx219,
const struct v4l2_mbus_framefmt *format)
{
if (!imx219->mode->binning) {
return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE,
@ -910,7 +824,7 @@ static int imx219_set_binning(struct imx219 *imx219)
IMX219_BINNING_NONE);
}
switch (imx219->fmt.code) {
switch (format->code) {
case MEDIA_BUS_FMT_SRGGB8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
@ -931,34 +845,13 @@ static int imx219_set_binning(struct imx219 *imx219)
return -EINVAL;
}
static const struct v4l2_rect *
__imx219_get_pad_crop(struct imx219 *imx219,
struct v4l2_subdev_state *sd_state,
unsigned int pad, enum v4l2_subdev_format_whence which)
{
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
return v4l2_subdev_get_try_crop(&imx219->sd, sd_state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return &imx219->mode->crop;
}
return NULL;
}
static int imx219_get_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_selection *sel)
{
switch (sel->target) {
case V4L2_SEL_TGT_CROP: {
struct imx219 *imx219 = to_imx219(sd);
mutex_lock(&imx219->mutex);
sel->r = *__imx219_get_pad_crop(imx219, sd_state, sel->pad,
sel->which);
mutex_unlock(&imx219->mutex);
sel->r = *v4l2_subdev_get_pad_crop(sd, sd_state, 0);
return 0;
}
@ -990,9 +883,11 @@ static int imx219_configure_lanes(struct imx219 *imx219)
IMX219_CSI_2_LANE_MODE : IMX219_CSI_4_LANE_MODE);
};
static int imx219_start_streaming(struct imx219 *imx219)
static int imx219_start_streaming(struct imx219 *imx219,
struct v4l2_subdev_state *state)
{
struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
const struct v4l2_mbus_framefmt *format;
const struct imx219_reg_list *reg_list;
int ret;
@ -1022,14 +917,15 @@ static int imx219_start_streaming(struct imx219 *imx219)
goto err_rpm_put;
}
ret = imx219_set_framefmt(imx219);
format = v4l2_subdev_get_pad_format(&imx219->sd, state, 0);
ret = imx219_set_framefmt(imx219, format);
if (ret) {
dev_err(&client->dev, "%s failed to set frame format: %d\n",
__func__, ret);
goto err_rpm_put;
}
ret = imx219_set_binning(imx219);
ret = imx219_set_binning(imx219, format);
if (ret) {
dev_err(&client->dev, "%s failed to set binning: %d\n",
__func__, ret);
@ -1078,35 +974,30 @@ static void imx219_stop_streaming(struct imx219 *imx219)
static int imx219_set_stream(struct v4l2_subdev *sd, int enable)
{
struct imx219 *imx219 = to_imx219(sd);
struct v4l2_subdev_state *state;
int ret = 0;
mutex_lock(&imx219->mutex);
if (imx219->streaming == enable) {
mutex_unlock(&imx219->mutex);
return 0;
}
state = v4l2_subdev_lock_and_get_active_state(sd);
if (imx219->streaming == enable)
goto unlock;
if (enable) {
/*
* Apply default & customized values
* and then start streaming.
*/
ret = imx219_start_streaming(imx219);
ret = imx219_start_streaming(imx219, state);
if (ret)
goto err_unlock;
goto unlock;
} else {
imx219_stop_streaming(imx219);
}
imx219->streaming = enable;
mutex_unlock(&imx219->mutex);
return ret;
err_unlock:
mutex_unlock(&imx219->mutex);
unlock:
v4l2_subdev_unlock_state(state);
return ret;
}
@ -1171,10 +1062,13 @@ static int __maybe_unused imx219_resume(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct imx219 *imx219 = to_imx219(sd);
struct v4l2_subdev_state *state;
int ret;
if (imx219->streaming) {
ret = imx219_start_streaming(imx219);
state = v4l2_subdev_lock_and_get_active_state(sd);
ret = imx219_start_streaming(imx219, state);
v4l2_subdev_unlock_state(state);
if (ret)
goto error;
}
@ -1235,8 +1129,9 @@ static const struct v4l2_subdev_video_ops imx219_video_ops = {
};
static const struct v4l2_subdev_pad_ops imx219_pad_ops = {
.init_cfg = imx219_init_cfg,
.enum_mbus_code = imx219_enum_mbus_code,
.get_fmt = imx219_get_pad_format,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = imx219_set_pad_format,
.get_selection = imx219_get_selection,
.enum_frame_size = imx219_enum_frame_size,
@ -1248,9 +1143,6 @@ static const struct v4l2_subdev_ops imx219_subdev_ops = {
.pad = &imx219_pad_ops,
};
static const struct v4l2_subdev_internal_ops imx219_internal_ops = {
.open = imx219_open,
};
static unsigned long imx219_get_pixel_rate(struct imx219 *imx219)
{
@ -1272,9 +1164,6 @@ static int imx219_init_controls(struct imx219 *imx219)
if (ret)
return ret;
mutex_init(&imx219->mutex);
ctrl_hdlr->lock = &imx219->mutex;
/* By default, PIXEL_RATE is read only */
imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
V4L2_CID_PIXEL_RATE,
@ -1371,7 +1260,6 @@ static int imx219_init_controls(struct imx219 *imx219)
error:
v4l2_ctrl_handler_free(ctrl_hdlr);
mutex_destroy(&imx219->mutex);
return ret;
}
@ -1379,7 +1267,6 @@ error:
static void imx219_free_controls(struct imx219 *imx219)
{
v4l2_ctrl_handler_free(imx219->sd.ctrl_handler);
mutex_destroy(&imx219->mutex);
}
static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219)
@ -1509,7 +1396,6 @@ static int imx219_probe(struct i2c_client *client)
goto error_power_off;
/* Initialize subdev */
imx219->sd.internal_ops = &imx219_internal_ops;
imx219->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
imx219->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR;
@ -1517,19 +1403,23 @@ static int imx219_probe(struct i2c_client *client)
/* Initialize source pad */
imx219->pad.flags = MEDIA_PAD_FL_SOURCE;
/* Initialize default format */
imx219_set_default_format(imx219);
ret = media_entity_pads_init(&imx219->sd.entity, 1, &imx219->pad);
if (ret) {
dev_err(dev, "failed to init entity pads: %d\n", ret);
goto error_handler_free;
}
imx219->sd.state_lock = imx219->ctrl_handler.lock;
ret = v4l2_subdev_init_finalize(&imx219->sd);
if (ret < 0) {
dev_err(dev, "subdev init error: %d\n", ret);
goto error_media_entity;
}
ret = v4l2_async_register_subdev_sensor(&imx219->sd);
if (ret < 0) {
dev_err(dev, "failed to register sensor sub-device: %d\n", ret);
goto error_media_entity;
goto error_subdev_cleanup;
}
/* Enable runtime PM and turn off the device */
@ -1539,6 +1429,9 @@ static int imx219_probe(struct i2c_client *client)
return 0;
error_subdev_cleanup:
v4l2_subdev_cleanup(&imx219->sd);
error_media_entity:
media_entity_cleanup(&imx219->sd.entity);
@ -1557,6 +1450,7 @@ static void imx219_remove(struct i2c_client *client)
struct imx219 *imx219 = to_imx219(sd);
v4l2_async_unregister_subdev(sd);
v4l2_subdev_cleanup(sd);
media_entity_cleanup(&sd->entity);
imx219_free_controls(imx219);

View File

@ -13,7 +13,7 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@ -21,91 +21,86 @@
#include <asm/unaligned.h>
#include <media/media-entity.h>
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
#define IMX290_REG_SIZE_SHIFT 16
#define IMX290_REG_ADDR_MASK 0xffff
#define IMX290_REG_8BIT(n) ((1U << IMX290_REG_SIZE_SHIFT) | (n))
#define IMX290_REG_16BIT(n) ((2U << IMX290_REG_SIZE_SHIFT) | (n))
#define IMX290_REG_24BIT(n) ((3U << IMX290_REG_SIZE_SHIFT) | (n))
#define IMX290_STANDBY IMX290_REG_8BIT(0x3000)
#define IMX290_REGHOLD IMX290_REG_8BIT(0x3001)
#define IMX290_XMSTA IMX290_REG_8BIT(0x3002)
#define IMX290_ADBIT IMX290_REG_8BIT(0x3005)
#define IMX290_STANDBY CCI_REG8(0x3000)
#define IMX290_REGHOLD CCI_REG8(0x3001)
#define IMX290_XMSTA CCI_REG8(0x3002)
#define IMX290_ADBIT CCI_REG8(0x3005)
#define IMX290_ADBIT_10BIT (0 << 0)
#define IMX290_ADBIT_12BIT (1 << 0)
#define IMX290_CTRL_07 IMX290_REG_8BIT(0x3007)
#define IMX290_CTRL_07 CCI_REG8(0x3007)
#define IMX290_VREVERSE BIT(0)
#define IMX290_HREVERSE BIT(1)
#define IMX290_WINMODE_1080P (0 << 4)
#define IMX290_WINMODE_720P (1 << 4)
#define IMX290_WINMODE_CROP (4 << 4)
#define IMX290_FR_FDG_SEL IMX290_REG_8BIT(0x3009)
#define IMX290_BLKLEVEL IMX290_REG_16BIT(0x300a)
#define IMX290_GAIN IMX290_REG_8BIT(0x3014)
#define IMX290_VMAX IMX290_REG_24BIT(0x3018)
#define IMX290_FR_FDG_SEL CCI_REG8(0x3009)
#define IMX290_BLKLEVEL CCI_REG16(0x300a)
#define IMX290_GAIN CCI_REG8(0x3014)
#define IMX290_VMAX CCI_REG24(0x3018)
#define IMX290_VMAX_MAX 0x3ffff
#define IMX290_HMAX IMX290_REG_16BIT(0x301c)
#define IMX290_HMAX CCI_REG16(0x301c)
#define IMX290_HMAX_MAX 0xffff
#define IMX290_SHS1 IMX290_REG_24BIT(0x3020)
#define IMX290_WINWV_OB IMX290_REG_8BIT(0x303a)
#define IMX290_WINPV IMX290_REG_16BIT(0x303c)
#define IMX290_WINWV IMX290_REG_16BIT(0x303e)
#define IMX290_WINPH IMX290_REG_16BIT(0x3040)
#define IMX290_WINWH IMX290_REG_16BIT(0x3042)
#define IMX290_OUT_CTRL IMX290_REG_8BIT(0x3046)
#define IMX290_SHS1 CCI_REG24(0x3020)
#define IMX290_WINWV_OB CCI_REG8(0x303a)
#define IMX290_WINPV CCI_REG16(0x303c)
#define IMX290_WINWV CCI_REG16(0x303e)
#define IMX290_WINPH CCI_REG16(0x3040)
#define IMX290_WINWH CCI_REG16(0x3042)
#define IMX290_OUT_CTRL CCI_REG8(0x3046)
#define IMX290_ODBIT_10BIT (0 << 0)
#define IMX290_ODBIT_12BIT (1 << 0)
#define IMX290_OPORTSEL_PARALLEL (0x0 << 4)
#define IMX290_OPORTSEL_LVDS_2CH (0xd << 4)
#define IMX290_OPORTSEL_LVDS_4CH (0xe << 4)
#define IMX290_OPORTSEL_LVDS_8CH (0xf << 4)
#define IMX290_XSOUTSEL IMX290_REG_8BIT(0x304b)
#define IMX290_XSOUTSEL CCI_REG8(0x304b)
#define IMX290_XSOUTSEL_XVSOUTSEL_HIGH (0 << 0)
#define IMX290_XSOUTSEL_XVSOUTSEL_VSYNC (2 << 0)
#define IMX290_XSOUTSEL_XHSOUTSEL_HIGH (0 << 2)
#define IMX290_XSOUTSEL_XHSOUTSEL_HSYNC (2 << 2)
#define IMX290_INCKSEL1 IMX290_REG_8BIT(0x305c)
#define IMX290_INCKSEL2 IMX290_REG_8BIT(0x305d)
#define IMX290_INCKSEL3 IMX290_REG_8BIT(0x305e)
#define IMX290_INCKSEL4 IMX290_REG_8BIT(0x305f)
#define IMX290_PGCTRL IMX290_REG_8BIT(0x308c)
#define IMX290_ADBIT1 IMX290_REG_8BIT(0x3129)
#define IMX290_INCKSEL1 CCI_REG8(0x305c)
#define IMX290_INCKSEL2 CCI_REG8(0x305d)
#define IMX290_INCKSEL3 CCI_REG8(0x305e)
#define IMX290_INCKSEL4 CCI_REG8(0x305f)
#define IMX290_PGCTRL CCI_REG8(0x308c)
#define IMX290_ADBIT1 CCI_REG8(0x3129)
#define IMX290_ADBIT1_10BIT 0x1d
#define IMX290_ADBIT1_12BIT 0x00
#define IMX290_INCKSEL5 IMX290_REG_8BIT(0x315e)
#define IMX290_INCKSEL6 IMX290_REG_8BIT(0x3164)
#define IMX290_ADBIT2 IMX290_REG_8BIT(0x317c)
#define IMX290_INCKSEL5 CCI_REG8(0x315e)
#define IMX290_INCKSEL6 CCI_REG8(0x3164)
#define IMX290_ADBIT2 CCI_REG8(0x317c)
#define IMX290_ADBIT2_10BIT 0x12
#define IMX290_ADBIT2_12BIT 0x00
#define IMX290_CHIP_ID IMX290_REG_16BIT(0x319a)
#define IMX290_ADBIT3 IMX290_REG_8BIT(0x31ec)
#define IMX290_CHIP_ID CCI_REG16(0x319a)
#define IMX290_ADBIT3 CCI_REG8(0x31ec)
#define IMX290_ADBIT3_10BIT 0x37
#define IMX290_ADBIT3_12BIT 0x0e
#define IMX290_REPETITION IMX290_REG_8BIT(0x3405)
#define IMX290_PHY_LANE_NUM IMX290_REG_8BIT(0x3407)
#define IMX290_OPB_SIZE_V IMX290_REG_8BIT(0x3414)
#define IMX290_Y_OUT_SIZE IMX290_REG_16BIT(0x3418)
#define IMX290_CSI_DT_FMT IMX290_REG_16BIT(0x3441)
#define IMX290_REPETITION CCI_REG8(0x3405)
#define IMX290_PHY_LANE_NUM CCI_REG8(0x3407)
#define IMX290_OPB_SIZE_V CCI_REG8(0x3414)
#define IMX290_Y_OUT_SIZE CCI_REG16(0x3418)
#define IMX290_CSI_DT_FMT CCI_REG16(0x3441)
#define IMX290_CSI_DT_FMT_RAW10 0x0a0a
#define IMX290_CSI_DT_FMT_RAW12 0x0c0c
#define IMX290_CSI_LANE_MODE IMX290_REG_8BIT(0x3443)
#define IMX290_EXTCK_FREQ IMX290_REG_16BIT(0x3444)
#define IMX290_TCLKPOST IMX290_REG_16BIT(0x3446)
#define IMX290_THSZERO IMX290_REG_16BIT(0x3448)
#define IMX290_THSPREPARE IMX290_REG_16BIT(0x344a)
#define IMX290_TCLKTRAIL IMX290_REG_16BIT(0x344c)
#define IMX290_THSTRAIL IMX290_REG_16BIT(0x344e)
#define IMX290_TCLKZERO IMX290_REG_16BIT(0x3450)
#define IMX290_TCLKPREPARE IMX290_REG_16BIT(0x3452)
#define IMX290_TLPX IMX290_REG_16BIT(0x3454)
#define IMX290_X_OUT_SIZE IMX290_REG_16BIT(0x3472)
#define IMX290_INCKSEL7 IMX290_REG_8BIT(0x3480)
#define IMX290_CSI_LANE_MODE CCI_REG8(0x3443)
#define IMX290_EXTCK_FREQ CCI_REG16(0x3444)
#define IMX290_TCLKPOST CCI_REG16(0x3446)
#define IMX290_THSZERO CCI_REG16(0x3448)
#define IMX290_THSPREPARE CCI_REG16(0x344a)
#define IMX290_TCLKTRAIL CCI_REG16(0x344c)
#define IMX290_THSTRAIL CCI_REG16(0x344e)
#define IMX290_TCLKZERO CCI_REG16(0x3450)
#define IMX290_TCLKPREPARE CCI_REG16(0x3452)
#define IMX290_TLPX CCI_REG16(0x3454)
#define IMX290_X_OUT_SIZE CCI_REG16(0x3472)
#define IMX290_INCKSEL7 CCI_REG8(0x3480)
#define IMX290_PGCTRL_REGEN BIT(0)
#define IMX290_PGCTRL_THRU BIT(1)
@ -181,7 +176,7 @@ enum imx290_model {
struct imx290_model_info {
enum imx290_colour_variant colour_variant;
const struct imx290_regval *init_regs;
const struct cci_reg_sequence *init_regs;
size_t init_regs_num;
const char *name;
};
@ -192,11 +187,6 @@ enum imx290_clk_freq {
IMX290_NUM_CLK
};
struct imx290_regval {
u32 reg;
u32 val;
};
/*
* Clock configuration for registers INCKSEL1 to INCKSEL6.
*/
@ -217,7 +207,7 @@ struct imx290_mode {
u8 link_freq_index;
u8 ctrl_07;
const struct imx290_regval *data;
const struct cci_reg_sequence *data;
u32 data_size;
const struct imx290_clk_cfg *clk_cfg;
@ -271,7 +261,7 @@ static inline struct imx290 *to_imx290(struct v4l2_subdev *_sd)
* Modes and formats
*/
static const struct imx290_regval imx290_global_init_settings[] = {
static const struct cci_reg_sequence imx290_global_init_settings[] = {
{ IMX290_WINWV_OB, 12 },
{ IMX290_WINPH, 0 },
{ IMX290_WINPV, 0 },
@ -279,56 +269,56 @@ static const struct imx290_regval imx290_global_init_settings[] = {
{ IMX290_WINWV, 1097 },
{ IMX290_XSOUTSEL, IMX290_XSOUTSEL_XVSOUTSEL_VSYNC |
IMX290_XSOUTSEL_XHSOUTSEL_HSYNC },
{ IMX290_REG_8BIT(0x3011), 0x02 },
{ IMX290_REG_8BIT(0x3012), 0x64 },
{ IMX290_REG_8BIT(0x3013), 0x00 },
{ CCI_REG8(0x3011), 0x02 },
{ CCI_REG8(0x3012), 0x64 },
{ CCI_REG8(0x3013), 0x00 },
};
static const struct imx290_regval imx290_global_init_settings_290[] = {
{ IMX290_REG_8BIT(0x300f), 0x00 },
{ IMX290_REG_8BIT(0x3010), 0x21 },
{ IMX290_REG_8BIT(0x3016), 0x09 },
{ IMX290_REG_8BIT(0x3070), 0x02 },
{ IMX290_REG_8BIT(0x3071), 0x11 },
{ IMX290_REG_8BIT(0x309b), 0x10 },
{ IMX290_REG_8BIT(0x309c), 0x22 },
{ IMX290_REG_8BIT(0x30a2), 0x02 },
{ IMX290_REG_8BIT(0x30a6), 0x20 },
{ IMX290_REG_8BIT(0x30a8), 0x20 },
{ IMX290_REG_8BIT(0x30aa), 0x20 },
{ IMX290_REG_8BIT(0x30ac), 0x20 },
{ IMX290_REG_8BIT(0x30b0), 0x43 },
{ IMX290_REG_8BIT(0x3119), 0x9e },
{ IMX290_REG_8BIT(0x311c), 0x1e },
{ IMX290_REG_8BIT(0x311e), 0x08 },
{ IMX290_REG_8BIT(0x3128), 0x05 },
{ IMX290_REG_8BIT(0x313d), 0x83 },
{ IMX290_REG_8BIT(0x3150), 0x03 },
{ IMX290_REG_8BIT(0x317e), 0x00 },
{ IMX290_REG_8BIT(0x32b8), 0x50 },
{ IMX290_REG_8BIT(0x32b9), 0x10 },
{ IMX290_REG_8BIT(0x32ba), 0x00 },
{ IMX290_REG_8BIT(0x32bb), 0x04 },
{ IMX290_REG_8BIT(0x32c8), 0x50 },
{ IMX290_REG_8BIT(0x32c9), 0x10 },
{ IMX290_REG_8BIT(0x32ca), 0x00 },
{ IMX290_REG_8BIT(0x32cb), 0x04 },
{ IMX290_REG_8BIT(0x332c), 0xd3 },
{ IMX290_REG_8BIT(0x332d), 0x10 },
{ IMX290_REG_8BIT(0x332e), 0x0d },
{ IMX290_REG_8BIT(0x3358), 0x06 },
{ IMX290_REG_8BIT(0x3359), 0xe1 },
{ IMX290_REG_8BIT(0x335a), 0x11 },
{ IMX290_REG_8BIT(0x3360), 0x1e },
{ IMX290_REG_8BIT(0x3361), 0x61 },
{ IMX290_REG_8BIT(0x3362), 0x10 },
{ IMX290_REG_8BIT(0x33b0), 0x50 },
{ IMX290_REG_8BIT(0x33b2), 0x1a },
{ IMX290_REG_8BIT(0x33b3), 0x04 },
static const struct cci_reg_sequence imx290_global_init_settings_290[] = {
{ CCI_REG8(0x300f), 0x00 },
{ CCI_REG8(0x3010), 0x21 },
{ CCI_REG8(0x3016), 0x09 },
{ CCI_REG8(0x3070), 0x02 },
{ CCI_REG8(0x3071), 0x11 },
{ CCI_REG8(0x309b), 0x10 },
{ CCI_REG8(0x309c), 0x22 },
{ CCI_REG8(0x30a2), 0x02 },
{ CCI_REG8(0x30a6), 0x20 },
{ CCI_REG8(0x30a8), 0x20 },
{ CCI_REG8(0x30aa), 0x20 },
{ CCI_REG8(0x30ac), 0x20 },
{ CCI_REG8(0x30b0), 0x43 },
{ CCI_REG8(0x3119), 0x9e },
{ CCI_REG8(0x311c), 0x1e },
{ CCI_REG8(0x311e), 0x08 },
{ CCI_REG8(0x3128), 0x05 },
{ CCI_REG8(0x313d), 0x83 },
{ CCI_REG8(0x3150), 0x03 },
{ CCI_REG8(0x317e), 0x00 },
{ CCI_REG8(0x32b8), 0x50 },
{ CCI_REG8(0x32b9), 0x10 },
{ CCI_REG8(0x32ba), 0x00 },
{ CCI_REG8(0x32bb), 0x04 },
{ CCI_REG8(0x32c8), 0x50 },
{ CCI_REG8(0x32c9), 0x10 },
{ CCI_REG8(0x32ca), 0x00 },
{ CCI_REG8(0x32cb), 0x04 },
{ CCI_REG8(0x332c), 0xd3 },
{ CCI_REG8(0x332d), 0x10 },
{ CCI_REG8(0x332e), 0x0d },
{ CCI_REG8(0x3358), 0x06 },
{ CCI_REG8(0x3359), 0xe1 },
{ CCI_REG8(0x335a), 0x11 },
{ CCI_REG8(0x3360), 0x1e },
{ CCI_REG8(0x3361), 0x61 },
{ CCI_REG8(0x3362), 0x10 },
{ CCI_REG8(0x33b0), 0x50 },
{ CCI_REG8(0x33b2), 0x1a },
{ CCI_REG8(0x33b3), 0x04 },
};
#define IMX290_NUM_CLK_REGS 2
static const struct imx290_regval xclk_regs[][IMX290_NUM_CLK_REGS] = {
static const struct cci_reg_sequence xclk_regs[][IMX290_NUM_CLK_REGS] = {
[IMX290_CLK_37_125] = {
{ IMX290_EXTCK_FREQ, (37125 * 256) / 1000 },
{ IMX290_INCKSEL7, 0x49 },
@ -339,13 +329,13 @@ static const struct imx290_regval xclk_regs[][IMX290_NUM_CLK_REGS] = {
},
};
static const struct imx290_regval imx290_global_init_settings_327[] = {
{ IMX290_REG_8BIT(0x309e), 0x4A },
{ IMX290_REG_8BIT(0x309f), 0x4A },
{ IMX290_REG_8BIT(0x313b), 0x61 },
static const struct cci_reg_sequence imx290_global_init_settings_327[] = {
{ CCI_REG8(0x309e), 0x4A },
{ CCI_REG8(0x309f), 0x4A },
{ CCI_REG8(0x313b), 0x61 },
};
static const struct imx290_regval imx290_1080p_settings[] = {
static const struct cci_reg_sequence imx290_1080p_settings[] = {
/* mode settings */
{ IMX290_WINWV_OB, 12 },
{ IMX290_OPB_SIZE_V, 10 },
@ -353,7 +343,7 @@ static const struct imx290_regval imx290_1080p_settings[] = {
{ IMX290_Y_OUT_SIZE, 1080 },
};
static const struct imx290_regval imx290_720p_settings[] = {
static const struct cci_reg_sequence imx290_720p_settings[] = {
/* mode settings */
{ IMX290_WINWV_OB, 6 },
{ IMX290_OPB_SIZE_V, 4 },
@ -361,7 +351,7 @@ static const struct imx290_regval imx290_720p_settings[] = {
{ IMX290_Y_OUT_SIZE, 720 },
};
static const struct imx290_regval imx290_10bit_settings[] = {
static const struct cci_reg_sequence imx290_10bit_settings[] = {
{ IMX290_ADBIT, IMX290_ADBIT_10BIT },
{ IMX290_OUT_CTRL, IMX290_ODBIT_10BIT },
{ IMX290_ADBIT1, IMX290_ADBIT1_10BIT },
@ -370,7 +360,7 @@ static const struct imx290_regval imx290_10bit_settings[] = {
{ IMX290_CSI_DT_FMT, IMX290_CSI_DT_FMT_RAW10 },
};
static const struct imx290_regval imx290_12bit_settings[] = {
static const struct cci_reg_sequence imx290_12bit_settings[] = {
{ IMX290_ADBIT, IMX290_ADBIT_12BIT },
{ IMX290_OUT_CTRL, IMX290_ODBIT_12BIT },
{ IMX290_ADBIT1, IMX290_ADBIT1_12BIT },
@ -576,7 +566,7 @@ static inline int imx290_modes_num(const struct imx290 *imx290)
struct imx290_format_info {
u32 code[IMX290_VARIANT_MAX];
u8 bpp;
const struct imx290_regval *regs;
const struct cci_reg_sequence *regs;
unsigned int num_regs;
};
@ -615,63 +605,15 @@ imx290_format_info(const struct imx290 *imx290, u32 code)
return NULL;
}
/* -----------------------------------------------------------------------------
* Register access
*/
static int __always_unused imx290_read(struct imx290 *imx290, u32 addr, u32 *value)
{
u8 data[3] = { 0, 0, 0 };
int ret;
ret = regmap_raw_read(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
if (ret < 0) {
dev_err(imx290->dev, "%u-bit read from 0x%04x failed: %d\n",
((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
addr & IMX290_REG_ADDR_MASK, ret);
return ret;
}
*value = get_unaligned_le24(data);
return 0;
}
static int imx290_write(struct imx290 *imx290, u32 addr, u32 value, int *err)
{
u8 data[3];
int ret;
if (err && *err)
return *err;
put_unaligned_le24(value, data);
ret = regmap_raw_write(imx290->regmap, addr & IMX290_REG_ADDR_MASK,
data, (addr >> IMX290_REG_SIZE_SHIFT) & 3);
if (ret < 0) {
dev_err(imx290->dev, "%u-bit write to 0x%04x failed: %d\n",
((addr >> IMX290_REG_SIZE_SHIFT) & 3) * 8,
addr & IMX290_REG_ADDR_MASK, ret);
if (err)
*err = ret;
}
return ret;
}
static int imx290_set_register_array(struct imx290 *imx290,
const struct imx290_regval *settings,
const struct cci_reg_sequence *settings,
unsigned int num_settings)
{
unsigned int i;
int ret;
for (i = 0; i < num_settings; ++i, ++settings) {
ret = imx290_write(imx290, settings->reg, settings->val, NULL);
if (ret < 0)
return ret;
}
ret = cci_multi_reg_write(imx290->regmap, settings, num_settings, NULL);
if (ret < 0)
return ret;
/* Provide 10ms settle time */
usleep_range(10000, 11000);
@ -689,12 +631,12 @@ static int imx290_set_clock(struct imx290 *imx290)
ret = imx290_set_register_array(imx290, xclk_regs[clk_idx],
IMX290_NUM_CLK_REGS);
imx290_write(imx290, IMX290_INCKSEL1, clk_cfg->incksel1, &ret);
imx290_write(imx290, IMX290_INCKSEL2, clk_cfg->incksel2, &ret);
imx290_write(imx290, IMX290_INCKSEL3, clk_cfg->incksel3, &ret);
imx290_write(imx290, IMX290_INCKSEL4, clk_cfg->incksel4, &ret);
imx290_write(imx290, IMX290_INCKSEL5, clk_cfg->incksel5, &ret);
imx290_write(imx290, IMX290_INCKSEL6, clk_cfg->incksel6, &ret);
cci_write(imx290->regmap, IMX290_INCKSEL1, clk_cfg->incksel1, &ret);
cci_write(imx290->regmap, IMX290_INCKSEL2, clk_cfg->incksel2, &ret);
cci_write(imx290->regmap, IMX290_INCKSEL3, clk_cfg->incksel3, &ret);
cci_write(imx290->regmap, IMX290_INCKSEL4, clk_cfg->incksel4, &ret);
cci_write(imx290->regmap, IMX290_INCKSEL5, clk_cfg->incksel5, &ret);
cci_write(imx290->regmap, IMX290_INCKSEL6, clk_cfg->incksel6, &ret);
return ret;
}
@ -703,9 +645,11 @@ static int imx290_set_data_lanes(struct imx290 *imx290)
{
int ret = 0;
imx290_write(imx290, IMX290_PHY_LANE_NUM, imx290->nlanes - 1, &ret);
imx290_write(imx290, IMX290_CSI_LANE_MODE, imx290->nlanes - 1, &ret);
imx290_write(imx290, IMX290_FR_FDG_SEL, 0x01, &ret);
cci_write(imx290->regmap, IMX290_PHY_LANE_NUM, imx290->nlanes - 1,
&ret);
cci_write(imx290->regmap, IMX290_CSI_LANE_MODE, imx290->nlanes - 1,
&ret);
cci_write(imx290->regmap, IMX290_FR_FDG_SEL, 0x01, &ret);
return ret;
}
@ -716,8 +660,8 @@ static int imx290_set_black_level(struct imx290 *imx290,
{
unsigned int bpp = imx290_format_info(imx290, format->code)->bpp;
return imx290_write(imx290, IMX290_BLKLEVEL,
black_level >> (16 - bpp), err);
return cci_write(imx290->regmap, IMX290_BLKLEVEL,
black_level >> (16 - bpp), err);
}
static int imx290_set_csi_config(struct imx290 *imx290)
@ -743,15 +687,16 @@ static int imx290_set_csi_config(struct imx290 *imx290)
return -EINVAL;
}
imx290_write(imx290, IMX290_REPETITION, csi_cfg->repetition, &ret);
imx290_write(imx290, IMX290_TCLKPOST, csi_cfg->tclkpost, &ret);
imx290_write(imx290, IMX290_THSZERO, csi_cfg->thszero, &ret);
imx290_write(imx290, IMX290_THSPREPARE, csi_cfg->thsprepare, &ret);
imx290_write(imx290, IMX290_TCLKTRAIL, csi_cfg->tclktrail, &ret);
imx290_write(imx290, IMX290_THSTRAIL, csi_cfg->thstrail, &ret);
imx290_write(imx290, IMX290_TCLKZERO, csi_cfg->tclkzero, &ret);
imx290_write(imx290, IMX290_TCLKPREPARE, csi_cfg->tclkprepare, &ret);
imx290_write(imx290, IMX290_TLPX, csi_cfg->tlpx, &ret);
cci_write(imx290->regmap, IMX290_REPETITION, csi_cfg->repetition, &ret);
cci_write(imx290->regmap, IMX290_TCLKPOST, csi_cfg->tclkpost, &ret);
cci_write(imx290->regmap, IMX290_THSZERO, csi_cfg->thszero, &ret);
cci_write(imx290->regmap, IMX290_THSPREPARE, csi_cfg->thsprepare, &ret);
cci_write(imx290->regmap, IMX290_TCLKTRAIL, csi_cfg->tclktrail, &ret);
cci_write(imx290->regmap, IMX290_THSTRAIL, csi_cfg->thstrail, &ret);
cci_write(imx290->regmap, IMX290_TCLKZERO, csi_cfg->tclkzero, &ret);
cci_write(imx290->regmap, IMX290_TCLKPREPARE, csi_cfg->tclkprepare,
&ret);
cci_write(imx290->regmap, IMX290_TLPX, csi_cfg->tlpx, &ret);
return ret;
}
@ -817,13 +762,12 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) {
case V4L2_CID_ANALOGUE_GAIN:
ret = imx290_write(imx290, IMX290_GAIN, ctrl->val, NULL);
ret = cci_write(imx290->regmap, IMX290_GAIN, ctrl->val, NULL);
break;
case V4L2_CID_VBLANK:
ret = imx290_write(imx290, IMX290_VMAX,
ctrl->val + imx290->current_mode->height,
NULL);
ret = cci_write(imx290->regmap, IMX290_VMAX,
ctrl->val + imx290->current_mode->height, NULL);
/*
* Due to the way that exposure is programmed in this sensor in
* relation to VMAX, we have to reprogramme it whenever VMAX is
@ -835,20 +779,20 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
fallthrough;
case V4L2_CID_EXPOSURE:
vmax = imx290->vblank->val + imx290->current_mode->height;
ret = imx290_write(imx290, IMX290_SHS1,
vmax - ctrl->val - 1, NULL);
ret = cci_write(imx290->regmap, IMX290_SHS1,
vmax - ctrl->val - 1, NULL);
break;
case V4L2_CID_TEST_PATTERN:
if (ctrl->val) {
imx290_set_black_level(imx290, format, 0, &ret);
usleep_range(10000, 11000);
imx290_write(imx290, IMX290_PGCTRL,
(u8)(IMX290_PGCTRL_REGEN |
IMX290_PGCTRL_THRU |
IMX290_PGCTRL_MODE(ctrl->val)), &ret);
cci_write(imx290->regmap, IMX290_PGCTRL,
(u8)(IMX290_PGCTRL_REGEN |
IMX290_PGCTRL_THRU |
IMX290_PGCTRL_MODE(ctrl->val)), &ret);
} else {
imx290_write(imx290, IMX290_PGCTRL, 0x00, &ret);
cci_write(imx290->regmap, IMX290_PGCTRL, 0x00, &ret);
usleep_range(10000, 11000);
imx290_set_black_level(imx290, format,
IMX290_BLACK_LEVEL_DEFAULT, &ret);
@ -856,9 +800,8 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
break;
case V4L2_CID_HBLANK:
ret = imx290_write(imx290, IMX290_HMAX,
ctrl->val + imx290->current_mode->width,
NULL);
ret = cci_write(imx290->regmap, IMX290_HMAX,
ctrl->val + imx290->current_mode->width, NULL);
break;
case V4L2_CID_HFLIP:
@ -871,7 +814,7 @@ static int imx290_set_ctrl(struct v4l2_ctrl *ctrl)
reg |= IMX290_HREVERSE;
if (imx290->vflip->val)
reg |= IMX290_VREVERSE;
ret = imx290_write(imx290, IMX290_CTRL_07, reg, NULL);
ret = cci_write(imx290->regmap, IMX290_CTRL_07, reg, NULL);
break;
}
@ -902,7 +845,6 @@ static const char * const imx290_test_pattern_menu[] = {
};
static void imx290_ctrl_update(struct imx290 *imx290,
const struct v4l2_mbus_framefmt *format,
const struct imx290_mode *mode)
{
unsigned int hblank_min = mode->hmax_min - mode->width;
@ -1074,12 +1016,12 @@ static int imx290_start_streaming(struct imx290 *imx290,
return ret;
}
imx290_write(imx290, IMX290_STANDBY, 0x00, &ret);
cci_write(imx290->regmap, IMX290_STANDBY, 0x00, &ret);
msleep(30);
/* Start streaming */
return imx290_write(imx290, IMX290_XMSTA, 0x00, &ret);
return cci_write(imx290->regmap, IMX290_XMSTA, 0x00, &ret);
}
/* Stop streaming */
@ -1087,11 +1029,11 @@ static int imx290_stop_streaming(struct imx290 *imx290)
{
int ret = 0;
imx290_write(imx290, IMX290_STANDBY, 0x01, &ret);
cci_write(imx290->regmap, IMX290_STANDBY, 0x01, &ret);
msleep(30);
return imx290_write(imx290, IMX290_XMSTA, 0x01, &ret);
return cci_write(imx290->regmap, IMX290_XMSTA, 0x01, &ret);
}
static int imx290_set_stream(struct v4l2_subdev *sd, int enable)
@ -1195,7 +1137,7 @@ static int imx290_set_fmt(struct v4l2_subdev *sd,
if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
imx290->current_mode = mode;
imx290_ctrl_update(imx290, &fmt->format, mode);
imx290_ctrl_update(imx290, mode);
imx290_exposure_update(imx290, mode);
}
@ -1300,7 +1242,6 @@ static const struct media_entity_operations imx290_subdev_entity_ops = {
static int imx290_subdev_init(struct imx290 *imx290)
{
struct i2c_client *client = to_i2c_client(imx290->dev);
const struct v4l2_mbus_framefmt *format;
struct v4l2_subdev_state *state;
int ret;
@ -1335,8 +1276,7 @@ static int imx290_subdev_init(struct imx290 *imx290)
}
state = v4l2_subdev_lock_and_get_active_state(&imx290->sd);
format = v4l2_subdev_get_pad_format(&imx290->sd, state, 0);
imx290_ctrl_update(imx290, format, imx290->current_mode);
imx290_ctrl_update(imx290, imx290->current_mode);
v4l2_subdev_unlock_state(state);
return 0;
@ -1417,11 +1357,6 @@ static const struct dev_pm_ops imx290_pm_ops = {
* Probe & remove
*/
static const struct regmap_config imx290_regmap_config = {
.reg_bits = 16,
.val_bits = 8,
};
static const char * const imx290_supply_name[IMX290_NUM_SUPPLIES] = {
"vdda",
"vddd",
@ -1588,7 +1523,7 @@ static int imx290_probe(struct i2c_client *client)
return -ENOMEM;
imx290->dev = dev;
imx290->regmap = devm_regmap_init_i2c(client, &imx290_regmap_config);
imx290->regmap = devm_cci_regmap_init_i2c(client, 16);
if (IS_ERR(imx290->regmap)) {
dev_err(dev, "Unable to initialize I2C\n");
return -ENODEV;

View File

@ -9,7 +9,7 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>

View File

@ -2565,7 +2565,7 @@ static struct i2c_driver imx319_i2c_driver = {
module_i2c_driver(imx319_i2c_driver);
MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");
MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
MODULE_AUTHOR("Rapolu, Chiranjeevi");
MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
MODULE_AUTHOR("Yang, Hyungwoo");
MODULE_DESCRIPTION("Sony imx319 sensor driver");

View File

@ -1851,7 +1851,7 @@ static struct i2c_driver imx355_i2c_driver = {
module_i2c_driver(imx355_i2c_driver);
MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");
MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
MODULE_AUTHOR("Rapolu, Chiranjeevi");
MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
MODULE_AUTHOR("Yang, Hyungwoo");
MODULE_DESCRIPTION("Sony imx355 sensor driver");

View File

@ -9,7 +9,7 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>

View File

@ -1611,7 +1611,7 @@ static const struct dev_pm_ops isl7998x_pm_ops = {
static struct i2c_driver isl7998x_i2c_driver = {
.driver = {
.name = "isl7998x",
.of_match_table = of_match_ptr(isl7998x_of_match),
.of_match_table = isl7998x_of_match,
.pm = &isl7998x_pm_ops,
},
.probe = isl7998x_probe,

View File

@ -161,11 +161,12 @@ struct max9286_source {
};
struct max9286_asd {
struct v4l2_async_subdev base;
struct v4l2_async_connection base;
struct max9286_source *source;
};
static inline struct max9286_asd *to_max9286_asd(struct v4l2_async_subdev *asd)
static inline struct max9286_asd *
to_max9286_asd(struct v4l2_async_connection *asd)
{
return container_of(asd, struct max9286_asd, base);
}
@ -659,7 +660,7 @@ static int max9286_set_pixelrate(struct max9286_priv *priv)
static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *subdev,
struct v4l2_async_subdev *asd)
struct v4l2_async_connection *asd)
{
struct max9286_priv *priv = sd_to_max9286(notifier->sd);
struct max9286_source *source = to_max9286_asd(asd)->source;
@ -721,7 +722,7 @@ static int max9286_notify_bound(struct v4l2_async_notifier *notifier,
static void max9286_notify_unbind(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *subdev,
struct v4l2_async_subdev *asd)
struct v4l2_async_connection *asd)
{
struct max9286_priv *priv = sd_to_max9286(notifier->sd);
struct max9286_source *source = to_max9286_asd(asd)->source;
@ -745,7 +746,7 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
if (!priv->nsources)
return 0;
v4l2_async_nf_init(&priv->notifier);
v4l2_async_subdev_nf_init(&priv->notifier, &priv->sd);
for_each_source(priv, source) {
unsigned int i = to_index(priv, source);
@ -765,7 +766,7 @@ static int max9286_v4l2_notifier_register(struct max9286_priv *priv)
priv->notifier.ops = &max9286_notify_ops;
ret = v4l2_async_subdev_nf_register(&priv->sd, &priv->notifier);
ret = v4l2_async_nf_register(&priv->notifier);
if (ret) {
dev_err(dev, "Failed to register subdev_notifier");
v4l2_async_nf_cleanup(&priv->notifier);
@ -1051,7 +1052,6 @@ static const struct v4l2_ctrl_ops max9286_ctrl_ops = {
static int max9286_v4l2_register(struct max9286_priv *priv)
{
struct device *dev = &priv->client->dev;
struct fwnode_handle *ep;
int ret;
int i;
@ -1093,25 +1093,14 @@ static int max9286_v4l2_register(struct max9286_priv *priv)
if (ret)
goto err_async;
ep = fwnode_graph_get_endpoint_by_id(dev_fwnode(dev), MAX9286_SRC_PAD,
0, 0);
if (!ep) {
dev_err(dev, "Unable to retrieve endpoint on \"port@4\"\n");
ret = -ENOENT;
goto err_async;
}
priv->sd.fwnode = ep;
ret = v4l2_async_register_subdev(&priv->sd);
if (ret < 0) {
dev_err(dev, "Unable to register subdevice\n");
goto err_put_node;
goto err_async;
}
return 0;
err_put_node:
fwnode_handle_put(ep);
err_async:
v4l2_ctrl_handler_free(&priv->ctrls);
max9286_v4l2_notifier_unregister(priv);
@ -1714,7 +1703,7 @@ MODULE_DEVICE_TABLE(of, max9286_dt_ids);
static struct i2c_driver max9286_i2c_driver = {
.driver = {
.name = "max9286",
.of_match_table = of_match_ptr(max9286_dt_ids),
.of_match_table = max9286_dt_ids,
},
.probe = max9286_probe,
.remove = max9286_remove,

View File

@ -1382,7 +1382,7 @@ MODULE_DEVICE_TABLE(i2c, mt9m111_id);
static struct i2c_driver mt9m111_i2c_driver = {
.driver = {
.name = "mt9m111",
.of_match_table = of_match_ptr(mt9m111_of_match),
.of_match_table = mt9m111_of_match,
},
.probe = mt9m111_probe,
.remove = mt9m111_remove,

View File

@ -1121,6 +1121,6 @@ static struct i2c_driver og01a1b_i2c_driver = {
module_i2c_driver(og01a1b_i2c_driver);
MODULE_AUTHOR("Shawn Tu <shawnx.tu@intel.com>");
MODULE_AUTHOR("Shawn Tu");
MODULE_DESCRIPTION("OmniVision OG01A1B sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -992,7 +992,7 @@ static struct i2c_driver ov01a10_i2c_driver = {
.pm = &ov01a10_pm_ops,
.acpi_match_table = ACPI_PTR(ov01a10_acpi_ids),
},
.probe_new = ov01a10_probe,
.probe = ov01a10_probe,
.remove = ov01a10_remove,
};

View File

@ -110,8 +110,6 @@ struct ov08x40_reg_list {
/* Link frequency config */
struct ov08x40_link_freq_config {
u32 pixels_per_line;
/* registers for this link frequency */
struct ov08x40_reg_list reg_list;
};
@ -128,6 +126,9 @@ struct ov08x40_mode {
u32 vts_def;
u32 vts_min;
/* HTS */
u32 hts;
/* Index of Link frequency config to be used */
u32 link_freq_index;
/* Default register values */
@ -2391,6 +2392,7 @@ static const struct ov08x40_mode supported_modes[] = {
.height = 2416,
.vts_def = OV08X40_VTS_30FPS,
.vts_min = OV08X40_VTS_30FPS,
.hts = 640,
.lanes = 4,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_3856x2416_regs),
@ -2403,6 +2405,7 @@ static const struct ov08x40_mode supported_modes[] = {
.height = 1208,
.vts_def = OV08X40_VTS_BIN_30FPS,
.vts_min = OV08X40_VTS_BIN_30FPS,
.hts = 720,
.lanes = 4,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1928x1208_regs),
@ -2846,9 +2849,7 @@ ov08x40_set_pad_format(struct v4l2_subdev *sd,
1,
vblank_def);
__v4l2_ctrl_s_ctrl(ov08x->vblank, vblank_def);
h_blank =
link_freq_configs[mode->link_freq_index].pixels_per_line
- ov08x->cur_mode->width;
h_blank = ov08x->cur_mode->hts;
__v4l2_ctrl_modify_range(ov08x->hblank, h_blank,
h_blank, 1, h_blank);
}
@ -3074,8 +3075,7 @@ static int ov08x40_init_controls(struct ov08x40 *ov08x)
OV08X40_VTS_MAX - mode->height, 1,
vblank_def);
hblank = link_freq_configs[mode->link_freq_index].pixels_per_line -
mode->width;
hblank = ov08x->cur_mode->hts;
ov08x->hblank = v4l2_ctrl_new_std(ctrl_hdlr, &ov08x40_ctrl_ops,
V4L2_CID_HBLANK,
hblank, hblank, 1, hblank);
@ -3320,6 +3320,6 @@ static struct i2c_driver ov08x40_i2c_driver = {
module_i2c_driver(ov08x40_i2c_driver);
MODULE_AUTHOR("Jason Chen <jason.z.chen@intel.com>");
MODULE_AUTHOR("Shawn Tu <shawnx.tu@intel.com>");
MODULE_AUTHOR("Shawn Tu");
MODULE_DESCRIPTION("OmniVision OV08X40 sensor driver");
MODULE_LICENSE("GPL");

View File

@ -1814,7 +1814,7 @@ static struct i2c_driver ov13858_i2c_driver = {
module_i2c_driver(ov13858_i2c_driver);
MODULE_AUTHOR("Kan, Chris <chris.kan@intel.com>");
MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
MODULE_AUTHOR("Rapolu, Chiranjeevi");
MODULE_AUTHOR("Yang, Hyungwoo");
MODULE_DESCRIPTION("Omnivision ov13858 sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -2,6 +2,9 @@
// Copyright (c) 2021 Intel Corporation.
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
@ -573,6 +576,11 @@ struct ov13b10 {
struct media_pad pad;
struct v4l2_ctrl_handler ctrl_handler;
struct clk *img_clk;
struct regulator *avdd;
struct gpio_desc *reset;
/* V4L2 Controls */
struct v4l2_ctrl *link_freq;
struct v4l2_ctrl *pixel_rate;
@ -1051,6 +1059,49 @@ static int ov13b10_identify_module(struct ov13b10 *ov13b)
return 0;
}
static int ov13b10_power_off(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ov13b10 *ov13b10 = to_ov13b10(sd);
gpiod_set_value_cansleep(ov13b10->reset, 1);
if (ov13b10->avdd)
regulator_disable(ov13b10->avdd);
clk_disable_unprepare(ov13b10->img_clk);
return 0;
}
static int ov13b10_power_on(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ov13b10 *ov13b10 = to_ov13b10(sd);
int ret;
ret = clk_prepare_enable(ov13b10->img_clk);
if (ret < 0) {
dev_err(dev, "failed to enable imaging clock: %d", ret);
return ret;
}
if (ov13b10->avdd) {
ret = regulator_enable(ov13b10->avdd);
if (ret < 0) {
dev_err(dev, "failed to enable avdd: %d", ret);
clk_disable_unprepare(ov13b10->img_clk);
return ret;
}
}
gpiod_set_value_cansleep(ov13b10->reset, 0);
/* 5ms to wait ready after XSHUTDN assert */
usleep_range(5000, 5500);
return 0;
}
static int ov13b10_start_streaming(struct ov13b10 *ov13b)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov13b->sd);
@ -1145,7 +1196,7 @@ err_unlock:
return ret;
}
static int __maybe_unused ov13b10_suspend(struct device *dev)
static int ov13b10_suspend(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ov13b10 *ov13b = to_ov13b10(sd);
@ -1153,26 +1204,35 @@ static int __maybe_unused ov13b10_suspend(struct device *dev)
if (ov13b->streaming)
ov13b10_stop_streaming(ov13b);
ov13b10_power_off(dev);
return 0;
}
static int __maybe_unused ov13b10_resume(struct device *dev)
static int ov13b10_resume(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ov13b10 *ov13b = to_ov13b10(sd);
int ret;
ret = ov13b10_power_on(dev);
if (ret)
goto pm_fail;
if (ov13b->streaming) {
ret = ov13b10_start_streaming(ov13b);
if (ret)
goto error;
goto stop_streaming;
}
return 0;
error:
stop_streaming:
ov13b10_stop_streaming(ov13b);
ov13b10_power_off(dev);
pm_fail:
ov13b->streaming = false;
return ret;
}
@ -1317,6 +1377,34 @@ static void ov13b10_free_controls(struct ov13b10 *ov13b)
mutex_destroy(&ov13b->mutex);
}
static int ov13b10_get_pm_resources(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ov13b10 *ov13b = to_ov13b10(sd);
int ret;
ov13b->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(ov13b->reset))
return dev_err_probe(dev, PTR_ERR(ov13b->reset),
"failed to get reset gpio\n");
ov13b->img_clk = devm_clk_get_optional(dev, NULL);
if (IS_ERR(ov13b->img_clk))
return dev_err_probe(dev, PTR_ERR(ov13b->img_clk),
"failed to get imaging clock\n");
ov13b->avdd = devm_regulator_get_optional(dev, "avdd");
if (IS_ERR(ov13b->avdd)) {
ret = PTR_ERR(ov13b->avdd);
ov13b->avdd = NULL;
if (ret != -ENODEV)
return dev_err_probe(dev, ret,
"failed to get avdd regulator\n");
}
return 0;
}
static int ov13b10_check_hwcfg(struct device *dev)
{
struct v4l2_fwnode_endpoint bus_cfg = {
@ -1331,6 +1419,10 @@ static int ov13b10_check_hwcfg(struct device *dev)
if (!fwnode)
return -ENXIO;
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
if (!ep)
return -EPROBE_DEFER;
ret = fwnode_property_read_u32(dev_fwnode(dev), "clock-frequency",
&ext_clk);
if (ret) {
@ -1344,10 +1436,6 @@ static int ov13b10_check_hwcfg(struct device *dev)
return -EINVAL;
}
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
if (!ep)
return -ENXIO;
ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg);
fwnode_handle_put(ep);
if (ret)
@ -1407,13 +1495,23 @@ static int ov13b10_probe(struct i2c_client *client)
/* Initialize subdev */
v4l2_i2c_subdev_init(&ov13b->sd, client, &ov13b10_subdev_ops);
ret = ov13b10_get_pm_resources(&client->dev);
if (ret)
return ret;
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
ov13b10_power_on(&client->dev);
if (ret) {
dev_err(&client->dev, "failed to power on\n");
return ret;
}
/* Check module identity */
ret = ov13b10_identify_module(ov13b);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d\n", ret);
return ret;
goto error_power_off;
}
}
@ -1422,7 +1520,7 @@ static int ov13b10_probe(struct i2c_client *client)
ret = ov13b10_init_controls(ov13b);
if (ret)
return ret;
goto error_power_off;
/* Initialize subdev */
ov13b->sd.internal_ops = &ov13b10_internal_ops;
@ -1462,6 +1560,9 @@ error_handler_free:
ov13b10_free_controls(ov13b);
dev_err(&client->dev, "%s failed:%d\n", __func__, ret);
error_power_off:
ov13b10_power_off(&client->dev);
return ret;
}
@ -1477,13 +1578,13 @@ static void ov13b10_remove(struct i2c_client *client)
pm_runtime_disable(&client->dev);
}
static const struct dev_pm_ops ov13b10_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(ov13b10_suspend, ov13b10_resume)
};
static DEFINE_RUNTIME_DEV_PM_OPS(ov13b10_pm_ops, ov13b10_suspend,
ov13b10_resume, NULL);
#ifdef CONFIG_ACPI
static const struct acpi_device_id ov13b10_acpi_ids[] = {
{"OVTIDB10"},
{"OVTI13B1"},
{ /* sentinel */ }
};
@ -1493,7 +1594,7 @@ MODULE_DEVICE_TABLE(acpi, ov13b10_acpi_ids);
static struct i2c_driver ov13b10_i2c_driver = {
.driver = {
.name = "ov13b10",
.pm = &ov13b10_pm_ops,
.pm = pm_ptr(&ov13b10_pm_ops),
.acpi_match_table = ACPI_PTR(ov13b10_acpi_ids),
},
.probe = ov13b10_probe,

View File

@ -1296,7 +1296,7 @@ MODULE_DEVICE_TABLE(of, ov2640_of_match);
static struct i2c_driver ov2640_i2c_driver = {
.driver = {
.name = "ov2640",
.of_match_table = of_match_ptr(ov2640_of_match),
.of_match_table = ov2640_of_match,
},
.probe = ov2640_probe,
.remove = ov2640_remove,

File diff suppressed because it is too large Load Diff

View File

@ -1223,7 +1223,7 @@ static struct i2c_driver ov2740_i2c_driver = {
module_i2c_driver(ov2740_i2c_driver);
MODULE_AUTHOR("Qiu, Tianshu <tian.shu.qiu@intel.com>");
MODULE_AUTHOR("Shawn Tu <shawnx.tu@intel.com>");
MODULE_AUTHOR("Shawn Tu");
MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
MODULE_DESCRIPTION("OmniVision OV2740 sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -13,8 +13,8 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
@ -568,9 +568,7 @@ static const struct reg_value ov5640_init_setting[] = {
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0}, {0x3000, 0x00, 0, 0},
{0x3002, 0x1c, 0, 0}, {0x3004, 0xff, 0, 0}, {0x3006, 0xc3, 0, 0},
{0x302e, 0x08, 0, 0}, {0x4300, 0x3f, 0, 0},
{0x501f, 0x00, 0, 0}, {0x4407, 0x04, 0, 0},
{0x440e, 0x00, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
{0x4837, 0x0a, 0, 0}, {0x3824, 0x02, 0, 0},
{0x501f, 0x00, 0, 0}, {0x440e, 0x00, 0, 0}, {0x4837, 0x0a, 0, 0},
{0x5000, 0xa7, 0, 0}, {0x5001, 0xa3, 0, 0}, {0x5180, 0xff, 0, 0},
{0x5181, 0xf2, 0, 0}, {0x5182, 0x00, 0, 0}, {0x5183, 0x14, 0, 0},
{0x5184, 0x25, 0, 0}, {0x5185, 0x24, 0, 0}, {0x5186, 0x09, 0, 0},
@ -634,7 +632,8 @@ static const struct reg_value ov5640_setting_low_res[] = {
{0x3a0a, 0x00, 0, 0}, {0x3a0b, 0xf6, 0, 0}, {0x3a0e, 0x03, 0, 0},
{0x3a0d, 0x04, 0, 0}, {0x3a14, 0x03, 0, 0}, {0x3a15, 0xd8, 0, 0},
{0x4001, 0x02, 0, 0}, {0x4004, 0x02, 0, 0},
{0x4407, 0x04, 0, 0}, {0x5001, 0xa3, 0, 0},
{0x4407, 0x04, 0, 0}, {0x460b, 0x35, 0, 0}, {0x460c, 0x22, 0, 0},
{0x3824, 0x02, 0, 0}, {0x5001, 0xa3, 0, 0},
};
static const struct reg_value ov5640_setting_720P_1280_720[] = {
@ -2453,16 +2452,13 @@ static void ov5640_power(struct ov5640_dev *sensor, bool enable)
static void ov5640_powerup_sequence(struct ov5640_dev *sensor)
{
if (sensor->pwdn_gpio) {
gpiod_set_value_cansleep(sensor->reset_gpio, 0);
gpiod_set_value_cansleep(sensor->reset_gpio, 1);
/* camera power cycle */
ov5640_power(sensor, false);
usleep_range(5000, 10000);
usleep_range(5000, 10000); /* t2 */
ov5640_power(sensor, true);
usleep_range(5000, 10000);
gpiod_set_value_cansleep(sensor->reset_gpio, 1);
usleep_range(1000, 2000);
usleep_range(1000, 2000); /* t3 */
gpiod_set_value_cansleep(sensor->reset_gpio, 0);
} else {
@ -2470,7 +2466,7 @@ static void ov5640_powerup_sequence(struct ov5640_dev *sensor)
ov5640_write_reg(sensor, OV5640_REG_SYS_CTRL0,
OV5640_REG_SYS_CTRL0_SW_RST);
}
usleep_range(20000, 25000);
usleep_range(20000, 25000); /* t4 */
/*
* software standby: allows registers programming;
@ -2543,9 +2539,9 @@ static int ov5640_set_power_mipi(struct ov5640_dev *sensor, bool on)
* "ov5640_set_stream_mipi()")
* [4] = 0 : Power up MIPI HS Tx
* [3] = 0 : Power up MIPI LS Rx
* [2] = 0 : MIPI interface disabled
* [2] = 1 : MIPI interface enabled
*/
ret = ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, 0x40);
ret = ov5640_write_reg(sensor, OV5640_REG_IO_MIPI_CTRL00, 0x44);
if (ret)
return ret;

View File

@ -2860,7 +2860,7 @@ static struct i2c_driver ov5670_i2c_driver = {
module_i2c_driver(ov5670_i2c_driver);
MODULE_AUTHOR("Rapolu, Chiranjeevi <chiranjeevi.rapolu@intel.com>");
MODULE_AUTHOR("Rapolu, Chiranjeevi");
MODULE_AUTHOR("Yang, Hyungwoo");
MODULE_DESCRIPTION("Omnivision ov5670 sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -1442,6 +1442,6 @@ static struct i2c_driver ov5675_i2c_driver = {
module_i2c_driver(ov5675_i2c_driver);
MODULE_AUTHOR("Shawn Tu <shawnx.tu@intel.com>");
MODULE_AUTHOR("Shawn Tu");
MODULE_DESCRIPTION("OmniVision OV5675 sensor driver");
MODULE_LICENSE("GPL v2");

View File

@ -12,7 +12,6 @@
* Jake Day
*/
#include <asm/unaligned.h>
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/delay.h>
@ -23,36 +22,32 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <media/v4l2-cci.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#define OV5693_REG_8BIT(n) ((1 << 16) | (n))
#define OV5693_REG_16BIT(n) ((2 << 16) | (n))
#define OV5693_REG_24BIT(n) ((3 << 16) | (n))
#define OV5693_REG_SIZE_SHIFT 16
#define OV5693_REG_ADDR_MASK 0xffff
/* System Control */
#define OV5693_SW_RESET_REG OV5693_REG_8BIT(0x0103)
#define OV5693_SW_STREAM_REG OV5693_REG_8BIT(0x0100)
#define OV5693_SW_RESET_REG CCI_REG8(0x0103)
#define OV5693_SW_STREAM_REG CCI_REG8(0x0100)
#define OV5693_START_STREAMING 0x01
#define OV5693_STOP_STREAMING 0x00
#define OV5693_SW_RESET 0x01
#define OV5693_REG_CHIP_ID OV5693_REG_16BIT(0x300a)
#define OV5693_REG_CHIP_ID CCI_REG16(0x300a)
/* Yes, this is right. The datasheet for the OV5693 gives its ID as 0x5690 */
#define OV5693_CHIP_ID 0x5690
/* Exposure */
#define OV5693_EXPOSURE_CTRL_REG OV5693_REG_24BIT(0x3500)
#define OV5693_EXPOSURE_CTRL_REG CCI_REG24(0x3500)
#define OV5693_EXPOSURE_CTRL_MASK GENMASK(19, 4)
#define OV5693_INTEGRATION_TIME_MARGIN 8
#define OV5693_EXPOSURE_MIN 1
#define OV5693_EXPOSURE_STEP 1
/* Analogue Gain */
#define OV5693_GAIN_CTRL_REG OV5693_REG_16BIT(0x350a)
#define OV5693_GAIN_CTRL_REG CCI_REG16(0x350a)
#define OV5693_GAIN_CTRL_MASK GENMASK(10, 4)
#define OV5693_GAIN_MIN 1
#define OV5693_GAIN_MAX 127
@ -60,9 +55,9 @@
#define OV5693_GAIN_STEP 1
/* Digital Gain */
#define OV5693_MWB_RED_GAIN_REG OV5693_REG_16BIT(0x3400)
#define OV5693_MWB_GREEN_GAIN_REG OV5693_REG_16BIT(0x3402)
#define OV5693_MWB_BLUE_GAIN_REG OV5693_REG_16BIT(0x3404)
#define OV5693_MWB_RED_GAIN_REG CCI_REG16(0x3400)
#define OV5693_MWB_GREEN_GAIN_REG CCI_REG16(0x3402)
#define OV5693_MWB_BLUE_GAIN_REG CCI_REG16(0x3404)
#define OV5693_MWB_GAIN_MASK GENMASK(11, 0)
#define OV5693_MWB_GAIN_MAX 0x0fff
#define OV5693_DIGITAL_GAIN_MIN 1
@ -71,36 +66,36 @@
#define OV5693_DIGITAL_GAIN_STEP 1
/* Timing and Format */
#define OV5693_CROP_START_X_REG OV5693_REG_16BIT(0x3800)
#define OV5693_CROP_START_Y_REG OV5693_REG_16BIT(0x3802)
#define OV5693_CROP_END_X_REG OV5693_REG_16BIT(0x3804)
#define OV5693_CROP_END_Y_REG OV5693_REG_16BIT(0x3806)
#define OV5693_OUTPUT_SIZE_X_REG OV5693_REG_16BIT(0x3808)
#define OV5693_OUTPUT_SIZE_Y_REG OV5693_REG_16BIT(0x380a)
#define OV5693_CROP_START_X_REG CCI_REG16(0x3800)
#define OV5693_CROP_START_Y_REG CCI_REG16(0x3802)
#define OV5693_CROP_END_X_REG CCI_REG16(0x3804)
#define OV5693_CROP_END_Y_REG CCI_REG16(0x3806)
#define OV5693_OUTPUT_SIZE_X_REG CCI_REG16(0x3808)
#define OV5693_OUTPUT_SIZE_Y_REG CCI_REG16(0x380a)
#define OV5693_TIMING_HTS_REG OV5693_REG_16BIT(0x380c)
#define OV5693_TIMING_HTS_REG CCI_REG16(0x380c)
#define OV5693_FIXED_PPL 2688U
#define OV5693_TIMING_VTS_REG OV5693_REG_16BIT(0x380e)
#define OV5693_TIMING_VTS_REG CCI_REG16(0x380e)
#define OV5693_TIMING_MAX_VTS 0xffff
#define OV5693_TIMING_MIN_VTS 0x04
#define OV5693_OFFSET_START_X_REG OV5693_REG_16BIT(0x3810)
#define OV5693_OFFSET_START_Y_REG OV5693_REG_16BIT(0x3812)
#define OV5693_OFFSET_START_X_REG CCI_REG16(0x3810)
#define OV5693_OFFSET_START_Y_REG CCI_REG16(0x3812)
#define OV5693_SUB_INC_X_REG OV5693_REG_8BIT(0x3814)
#define OV5693_SUB_INC_Y_REG OV5693_REG_8BIT(0x3815)
#define OV5693_SUB_INC_X_REG CCI_REG8(0x3814)
#define OV5693_SUB_INC_Y_REG CCI_REG8(0x3815)
#define OV5693_FORMAT1_REG OV5693_REG_8BIT(0x3820)
#define OV5693_FORMAT1_REG CCI_REG8(0x3820)
#define OV5693_FORMAT1_FLIP_VERT_ISP_EN BIT(6)
#define OV5693_FORMAT1_FLIP_VERT_SENSOR_EN BIT(1)
#define OV5693_FORMAT1_VBIN_EN BIT(0)
#define OV5693_FORMAT2_REG OV5693_REG_8BIT(0x3821)
#define OV5693_FORMAT2_REG CCI_REG8(0x3821)
#define OV5693_FORMAT2_HDR_EN BIT(7)
#define OV5693_FORMAT2_FLIP_HORZ_ISP_EN BIT(2)
#define OV5693_FORMAT2_FLIP_HORZ_SENSOR_EN BIT(1)
#define OV5693_FORMAT2_HBIN_EN BIT(0)
#define OV5693_ISP_CTRL2_REG OV5693_REG_8BIT(0x5002)
#define OV5693_ISP_CTRL2_REG CCI_REG8(0x5002)
#define OV5693_ISP_SCALE_ENABLE BIT(7)
/* Pixel Array */
@ -116,7 +111,7 @@
#define OV5693_MIN_CROP_HEIGHT 2
/* Test Pattern */
#define OV5693_TEST_PATTERN_REG OV5693_REG_8BIT(0x5e00)
#define OV5693_TEST_PATTERN_REG CCI_REG8(0x5e00)
#define OV5693_TEST_PATTERN_ENABLE BIT(7)
#define OV5693_TEST_PATTERN_ROLLING BIT(6)
#define OV5693_TEST_PATTERN_RANDOM 0x01
@ -137,19 +132,9 @@ static const char * const ov5693_supply_names[] = {
#define OV5693_NUM_SUPPLIES ARRAY_SIZE(ov5693_supply_names)
struct ov5693_reg {
u32 reg;
u8 val;
};
struct ov5693_reg_list {
u32 num_regs;
const struct ov5693_reg *regs;
};
struct ov5693_device {
struct i2c_client *client;
struct device *dev;
struct regmap *regmap;
/* Protect against concurrent changes to controls */
struct mutex lock;
@ -189,156 +174,151 @@ struct ov5693_device {
} ctrls;
};
static const struct ov5693_reg ov5693_global_regs[] = {
{OV5693_REG_8BIT(0x3016), 0xf0},
{OV5693_REG_8BIT(0x3017), 0xf0},
{OV5693_REG_8BIT(0x3018), 0xf0},
{OV5693_REG_8BIT(0x3022), 0x01},
{OV5693_REG_8BIT(0x3028), 0x44},
{OV5693_REG_8BIT(0x3098), 0x02},
{OV5693_REG_8BIT(0x3099), 0x19},
{OV5693_REG_8BIT(0x309a), 0x02},
{OV5693_REG_8BIT(0x309b), 0x01},
{OV5693_REG_8BIT(0x309c), 0x00},
{OV5693_REG_8BIT(0x30a0), 0xd2},
{OV5693_REG_8BIT(0x30a2), 0x01},
{OV5693_REG_8BIT(0x30b2), 0x00},
{OV5693_REG_8BIT(0x30b3), 0x83},
{OV5693_REG_8BIT(0x30b4), 0x03},
{OV5693_REG_8BIT(0x30b5), 0x04},
{OV5693_REG_8BIT(0x30b6), 0x01},
{OV5693_REG_8BIT(0x3080), 0x01},
{OV5693_REG_8BIT(0x3104), 0x21},
{OV5693_REG_8BIT(0x3106), 0x00},
{OV5693_REG_8BIT(0x3406), 0x01},
{OV5693_REG_8BIT(0x3503), 0x07},
{OV5693_REG_8BIT(0x350b), 0x40},
{OV5693_REG_8BIT(0x3601), 0x0a},
{OV5693_REG_8BIT(0x3602), 0x38},
{OV5693_REG_8BIT(0x3612), 0x80},
{OV5693_REG_8BIT(0x3620), 0x54},
{OV5693_REG_8BIT(0x3621), 0xc7},
{OV5693_REG_8BIT(0x3622), 0x0f},
{OV5693_REG_8BIT(0x3625), 0x10},
{OV5693_REG_8BIT(0x3630), 0x55},
{OV5693_REG_8BIT(0x3631), 0xf4},
{OV5693_REG_8BIT(0x3632), 0x00},
{OV5693_REG_8BIT(0x3633), 0x34},
{OV5693_REG_8BIT(0x3634), 0x02},
{OV5693_REG_8BIT(0x364d), 0x0d},
{OV5693_REG_8BIT(0x364f), 0xdd},
{OV5693_REG_8BIT(0x3660), 0x04},
{OV5693_REG_8BIT(0x3662), 0x10},
{OV5693_REG_8BIT(0x3663), 0xf1},
{OV5693_REG_8BIT(0x3665), 0x00},
{OV5693_REG_8BIT(0x3666), 0x20},
{OV5693_REG_8BIT(0x3667), 0x00},
{OV5693_REG_8BIT(0x366a), 0x80},
{OV5693_REG_8BIT(0x3680), 0xe0},
{OV5693_REG_8BIT(0x3681), 0x00},
{OV5693_REG_8BIT(0x3700), 0x42},
{OV5693_REG_8BIT(0x3701), 0x14},
{OV5693_REG_8BIT(0x3702), 0xa0},
{OV5693_REG_8BIT(0x3703), 0xd8},
{OV5693_REG_8BIT(0x3704), 0x78},
{OV5693_REG_8BIT(0x3705), 0x02},
{OV5693_REG_8BIT(0x370a), 0x00},
{OV5693_REG_8BIT(0x370b), 0x20},
{OV5693_REG_8BIT(0x370c), 0x0c},
{OV5693_REG_8BIT(0x370d), 0x11},
{OV5693_REG_8BIT(0x370e), 0x00},
{OV5693_REG_8BIT(0x370f), 0x40},
{OV5693_REG_8BIT(0x3710), 0x00},
{OV5693_REG_8BIT(0x371a), 0x1c},
{OV5693_REG_8BIT(0x371b), 0x05},
{OV5693_REG_8BIT(0x371c), 0x01},
{OV5693_REG_8BIT(0x371e), 0xa1},
{OV5693_REG_8BIT(0x371f), 0x0c},
{OV5693_REG_8BIT(0x3721), 0x00},
{OV5693_REG_8BIT(0x3724), 0x10},
{OV5693_REG_8BIT(0x3726), 0x00},
{OV5693_REG_8BIT(0x372a), 0x01},
{OV5693_REG_8BIT(0x3730), 0x10},
{OV5693_REG_8BIT(0x3738), 0x22},
{OV5693_REG_8BIT(0x3739), 0xe5},
{OV5693_REG_8BIT(0x373a), 0x50},
{OV5693_REG_8BIT(0x373b), 0x02},
{OV5693_REG_8BIT(0x373c), 0x41},
{OV5693_REG_8BIT(0x373f), 0x02},
{OV5693_REG_8BIT(0x3740), 0x42},
{OV5693_REG_8BIT(0x3741), 0x02},
{OV5693_REG_8BIT(0x3742), 0x18},
{OV5693_REG_8BIT(0x3743), 0x01},
{OV5693_REG_8BIT(0x3744), 0x02},
{OV5693_REG_8BIT(0x3747), 0x10},
{OV5693_REG_8BIT(0x374c), 0x04},
{OV5693_REG_8BIT(0x3751), 0xf0},
{OV5693_REG_8BIT(0x3752), 0x00},
{OV5693_REG_8BIT(0x3753), 0x00},
{OV5693_REG_8BIT(0x3754), 0xc0},
{OV5693_REG_8BIT(0x3755), 0x00},
{OV5693_REG_8BIT(0x3756), 0x1a},
{OV5693_REG_8BIT(0x3758), 0x00},
{OV5693_REG_8BIT(0x3759), 0x0f},
{OV5693_REG_8BIT(0x376b), 0x44},
{OV5693_REG_8BIT(0x375c), 0x04},
{OV5693_REG_8BIT(0x3774), 0x10},
{OV5693_REG_8BIT(0x3776), 0x00},
{OV5693_REG_8BIT(0x377f), 0x08},
{OV5693_REG_8BIT(0x3780), 0x22},
{OV5693_REG_8BIT(0x3781), 0x0c},
{OV5693_REG_8BIT(0x3784), 0x2c},
{OV5693_REG_8BIT(0x3785), 0x1e},
{OV5693_REG_8BIT(0x378f), 0xf5},
{OV5693_REG_8BIT(0x3791), 0xb0},
{OV5693_REG_8BIT(0x3795), 0x00},
{OV5693_REG_8BIT(0x3796), 0x64},
{OV5693_REG_8BIT(0x3797), 0x11},
{OV5693_REG_8BIT(0x3798), 0x30},
{OV5693_REG_8BIT(0x3799), 0x41},
{OV5693_REG_8BIT(0x379a), 0x07},
{OV5693_REG_8BIT(0x379b), 0xb0},
{OV5693_REG_8BIT(0x379c), 0x0c},
{OV5693_REG_8BIT(0x3a04), 0x06},
{OV5693_REG_8BIT(0x3a05), 0x14},
{OV5693_REG_8BIT(0x3e07), 0x20},
{OV5693_REG_8BIT(0x4000), 0x08},
{OV5693_REG_8BIT(0x4001), 0x04},
{OV5693_REG_8BIT(0x4004), 0x08},
{OV5693_REG_8BIT(0x4006), 0x20},
{OV5693_REG_8BIT(0x4008), 0x24},
{OV5693_REG_8BIT(0x4009), 0x10},
{OV5693_REG_8BIT(0x4058), 0x00},
{OV5693_REG_8BIT(0x4101), 0xb2},
{OV5693_REG_8BIT(0x4307), 0x31},
{OV5693_REG_8BIT(0x4511), 0x05},
{OV5693_REG_8BIT(0x4512), 0x01},
{OV5693_REG_8BIT(0x481f), 0x30},
{OV5693_REG_8BIT(0x4826), 0x2c},
{OV5693_REG_8BIT(0x4d02), 0xfd},
{OV5693_REG_8BIT(0x4d03), 0xf5},
{OV5693_REG_8BIT(0x4d04), 0x0c},
{OV5693_REG_8BIT(0x4d05), 0xcc},
{OV5693_REG_8BIT(0x4837), 0x0a},
{OV5693_REG_8BIT(0x5003), 0x20},
{OV5693_REG_8BIT(0x5013), 0x00},
{OV5693_REG_8BIT(0x5842), 0x01},
{OV5693_REG_8BIT(0x5843), 0x2b},
{OV5693_REG_8BIT(0x5844), 0x01},
{OV5693_REG_8BIT(0x5845), 0x92},
{OV5693_REG_8BIT(0x5846), 0x01},
{OV5693_REG_8BIT(0x5847), 0x8f},
{OV5693_REG_8BIT(0x5848), 0x01},
{OV5693_REG_8BIT(0x5849), 0x0c},
{OV5693_REG_8BIT(0x5e10), 0x0c},
{OV5693_REG_8BIT(0x3820), 0x00},
{OV5693_REG_8BIT(0x3821), 0x1e},
{OV5693_REG_8BIT(0x5041), 0x14}
};
static const struct ov5693_reg_list ov5693_global_setting = {
.num_regs = ARRAY_SIZE(ov5693_global_regs),
.regs = ov5693_global_regs,
static const struct cci_reg_sequence ov5693_global_regs[] = {
{CCI_REG8(0x3016), 0xf0},
{CCI_REG8(0x3017), 0xf0},
{CCI_REG8(0x3018), 0xf0},
{CCI_REG8(0x3022), 0x01},
{CCI_REG8(0x3028), 0x44},
{CCI_REG8(0x3098), 0x02},
{CCI_REG8(0x3099), 0x19},
{CCI_REG8(0x309a), 0x02},
{CCI_REG8(0x309b), 0x01},
{CCI_REG8(0x309c), 0x00},
{CCI_REG8(0x30a0), 0xd2},
{CCI_REG8(0x30a2), 0x01},
{CCI_REG8(0x30b2), 0x00},
{CCI_REG8(0x30b3), 0x83},
{CCI_REG8(0x30b4), 0x03},
{CCI_REG8(0x30b5), 0x04},
{CCI_REG8(0x30b6), 0x01},
{CCI_REG8(0x3080), 0x01},
{CCI_REG8(0x3104), 0x21},
{CCI_REG8(0x3106), 0x00},
{CCI_REG8(0x3406), 0x01},
{CCI_REG8(0x3503), 0x07},
{CCI_REG8(0x350b), 0x40},
{CCI_REG8(0x3601), 0x0a},
{CCI_REG8(0x3602), 0x38},
{CCI_REG8(0x3612), 0x80},
{CCI_REG8(0x3620), 0x54},
{CCI_REG8(0x3621), 0xc7},
{CCI_REG8(0x3622), 0x0f},
{CCI_REG8(0x3625), 0x10},
{CCI_REG8(0x3630), 0x55},
{CCI_REG8(0x3631), 0xf4},
{CCI_REG8(0x3632), 0x00},
{CCI_REG8(0x3633), 0x34},
{CCI_REG8(0x3634), 0x02},
{CCI_REG8(0x364d), 0x0d},
{CCI_REG8(0x364f), 0xdd},
{CCI_REG8(0x3660), 0x04},
{CCI_REG8(0x3662), 0x10},
{CCI_REG8(0x3663), 0xf1},
{CCI_REG8(0x3665), 0x00},
{CCI_REG8(0x3666), 0x20},
{CCI_REG8(0x3667), 0x00},
{CCI_REG8(0x366a), 0x80},
{CCI_REG8(0x3680), 0xe0},
{CCI_REG8(0x3681), 0x00},
{CCI_REG8(0x3700), 0x42},
{CCI_REG8(0x3701), 0x14},
{CCI_REG8(0x3702), 0xa0},
{CCI_REG8(0x3703), 0xd8},
{CCI_REG8(0x3704), 0x78},
{CCI_REG8(0x3705), 0x02},
{CCI_REG8(0x370a), 0x00},
{CCI_REG8(0x370b), 0x20},
{CCI_REG8(0x370c), 0x0c},
{CCI_REG8(0x370d), 0x11},
{CCI_REG8(0x370e), 0x00},
{CCI_REG8(0x370f), 0x40},
{CCI_REG8(0x3710), 0x00},
{CCI_REG8(0x371a), 0x1c},
{CCI_REG8(0x371b), 0x05},
{CCI_REG8(0x371c), 0x01},
{CCI_REG8(0x371e), 0xa1},
{CCI_REG8(0x371f), 0x0c},
{CCI_REG8(0x3721), 0x00},
{CCI_REG8(0x3724), 0x10},
{CCI_REG8(0x3726), 0x00},
{CCI_REG8(0x372a), 0x01},
{CCI_REG8(0x3730), 0x10},
{CCI_REG8(0x3738), 0x22},
{CCI_REG8(0x3739), 0xe5},
{CCI_REG8(0x373a), 0x50},
{CCI_REG8(0x373b), 0x02},
{CCI_REG8(0x373c), 0x41},
{CCI_REG8(0x373f), 0x02},
{CCI_REG8(0x3740), 0x42},
{CCI_REG8(0x3741), 0x02},
{CCI_REG8(0x3742), 0x18},
{CCI_REG8(0x3743), 0x01},
{CCI_REG8(0x3744), 0x02},
{CCI_REG8(0x3747), 0x10},
{CCI_REG8(0x374c), 0x04},
{CCI_REG8(0x3751), 0xf0},
{CCI_REG8(0x3752), 0x00},
{CCI_REG8(0x3753), 0x00},
{CCI_REG8(0x3754), 0xc0},
{CCI_REG8(0x3755), 0x00},
{CCI_REG8(0x3756), 0x1a},
{CCI_REG8(0x3758), 0x00},
{CCI_REG8(0x3759), 0x0f},
{CCI_REG8(0x376b), 0x44},
{CCI_REG8(0x375c), 0x04},
{CCI_REG8(0x3774), 0x10},
{CCI_REG8(0x3776), 0x00},
{CCI_REG8(0x377f), 0x08},
{CCI_REG8(0x3780), 0x22},
{CCI_REG8(0x3781), 0x0c},
{CCI_REG8(0x3784), 0x2c},
{CCI_REG8(0x3785), 0x1e},
{CCI_REG8(0x378f), 0xf5},
{CCI_REG8(0x3791), 0xb0},
{CCI_REG8(0x3795), 0x00},
{CCI_REG8(0x3796), 0x64},
{CCI_REG8(0x3797), 0x11},
{CCI_REG8(0x3798), 0x30},
{CCI_REG8(0x3799), 0x41},
{CCI_REG8(0x379a), 0x07},
{CCI_REG8(0x379b), 0xb0},
{CCI_REG8(0x379c), 0x0c},
{CCI_REG8(0x3a04), 0x06},
{CCI_REG8(0x3a05), 0x14},
{CCI_REG8(0x3e07), 0x20},
{CCI_REG8(0x4000), 0x08},
{CCI_REG8(0x4001), 0x04},
{CCI_REG8(0x4004), 0x08},
{CCI_REG8(0x4006), 0x20},
{CCI_REG8(0x4008), 0x24},
{CCI_REG8(0x4009), 0x10},
{CCI_REG8(0x4058), 0x00},
{CCI_REG8(0x4101), 0xb2},
{CCI_REG8(0x4307), 0x31},
{CCI_REG8(0x4511), 0x05},
{CCI_REG8(0x4512), 0x01},
{CCI_REG8(0x481f), 0x30},
{CCI_REG8(0x4826), 0x2c},
{CCI_REG8(0x4d02), 0xfd},
{CCI_REG8(0x4d03), 0xf5},
{CCI_REG8(0x4d04), 0x0c},
{CCI_REG8(0x4d05), 0xcc},
{CCI_REG8(0x4837), 0x0a},
{CCI_REG8(0x5003), 0x20},
{CCI_REG8(0x5013), 0x00},
{CCI_REG8(0x5842), 0x01},
{CCI_REG8(0x5843), 0x2b},
{CCI_REG8(0x5844), 0x01},
{CCI_REG8(0x5845), 0x92},
{CCI_REG8(0x5846), 0x01},
{CCI_REG8(0x5847), 0x8f},
{CCI_REG8(0x5848), 0x01},
{CCI_REG8(0x5849), 0x0c},
{CCI_REG8(0x5e10), 0x0c},
{CCI_REG8(0x3820), 0x00},
{CCI_REG8(0x3821), 0x1e},
{CCI_REG8(0x5041), 0x14}
};
static const struct v4l2_rect ov5693_default_crop = {
@ -373,115 +353,6 @@ static const u8 ov5693_test_pattern_bits[] = {
OV5693_TEST_PATTERN_ROLLING,
};
/* I2C I/O Operations */
static int ov5693_read_reg(struct ov5693_device *ov5693, u32 addr, u32 *value)
{
struct i2c_client *client = ov5693->client;
__be16 reg;
u8 val[4];
struct i2c_msg msg[] = {
{
.addr = client->addr,
.flags = 0,
.len = 2,
.buf = (u8 *)&reg,
},
{
.addr = client->addr,
.flags = I2C_M_RD,
.buf = (u8 *)&val,
},
};
unsigned int len = ((addr >> OV5693_REG_SIZE_SHIFT) & 3);
unsigned int i;
int ret;
reg = cpu_to_be16(addr & OV5693_REG_ADDR_MASK);
msg[1].len = len;
ret = i2c_transfer(client->adapter, msg, 2);
if (ret < 0)
return dev_err_probe(&client->dev, ret,
"Failed to read register 0x%04x\n",
addr & OV5693_REG_ADDR_MASK);
*value = 0;
for (i = 0; i < len; ++i) {
*value <<= 8;
*value |= val[i];
}
return 0;
}
static void ov5693_write_reg(struct ov5693_device *ov5693, u32 addr, u32 value,
int *error)
{
struct i2c_client *client = ov5693->client;
struct {
__be16 reg;
u8 val[4];
} __packed buf;
struct i2c_msg msg = {
.addr = client->addr,
.buf = (u8 *)&buf,
};
unsigned int len = ((addr >> OV5693_REG_SIZE_SHIFT) & 3);
unsigned int i;
int ret;
if (*error < 0)
return;
buf.reg = cpu_to_be16(addr & OV5693_REG_ADDR_MASK);
for (i = 0; i < len; ++i) {
buf.val[len - i - 1] = value & 0xff;
value >>= 8;
}
msg.len = len + 2;
ret = i2c_transfer(client->adapter, &msg, 1);
if (ret < 0) {
dev_err(&client->dev, "Failed to write register 0x%04x: %d\n",
addr & OV5693_REG_ADDR_MASK, ret);
*error = ret;
}
}
static int ov5693_write_reg_array(struct ov5693_device *ov5693,
const struct ov5693_reg_list *reglist)
{
unsigned int i;
int ret = 0;
for (i = 0; i < reglist->num_regs; i++)
ov5693_write_reg(ov5693, reglist->regs[i].reg,
reglist->regs[i].val, &ret);
return ret;
}
static int ov5693_update_bits(struct ov5693_device *ov5693, u32 address,
u32 mask, u32 bits)
{
u32 value = 0;
int ret;
ret = ov5693_read_reg(ov5693, address, &value);
if (ret)
return ret;
value &= ~mask;
value |= bits;
ov5693_write_reg(ov5693, address, value, &ret);
return ret;
}
/* V4L2 Controls Functions */
static int ov5693_flip_vert_configure(struct ov5693_device *ov5693,
@ -491,8 +362,8 @@ static int ov5693_flip_vert_configure(struct ov5693_device *ov5693,
OV5693_FORMAT1_FLIP_VERT_SENSOR_EN;
int ret;
ret = ov5693_update_bits(ov5693, OV5693_FORMAT1_REG, bits,
enable ? bits : 0);
ret = cci_update_bits(ov5693->regmap, OV5693_FORMAT1_REG, bits,
enable ? bits : 0, NULL);
if (ret)
return ret;
@ -506,8 +377,8 @@ static int ov5693_flip_horz_configure(struct ov5693_device *ov5693,
OV5693_FORMAT2_FLIP_HORZ_SENSOR_EN;
int ret;
ret = ov5693_update_bits(ov5693, OV5693_FORMAT2_REG, bits,
enable ? bits : 0);
ret = cci_update_bits(ov5693->regmap, OV5693_FORMAT2_REG, bits,
enable ? bits : 0, NULL);
if (ret)
return ret;
@ -516,10 +387,11 @@ static int ov5693_flip_horz_configure(struct ov5693_device *ov5693,
static int ov5693_get_exposure(struct ov5693_device *ov5693, s32 *value)
{
u32 exposure;
u64 exposure;
int ret;
ret = ov5693_read_reg(ov5693, OV5693_EXPOSURE_CTRL_REG, &exposure);
ret = cci_read(ov5693->regmap, OV5693_EXPOSURE_CTRL_REG, &exposure,
NULL);
if (ret)
return ret;
@ -536,17 +408,17 @@ static int ov5693_exposure_configure(struct ov5693_device *ov5693,
exposure = (exposure << 4) & OV5693_EXPOSURE_CTRL_MASK;
ov5693_write_reg(ov5693, OV5693_EXPOSURE_CTRL_REG, exposure, &ret);
cci_write(ov5693->regmap, OV5693_EXPOSURE_CTRL_REG, exposure, &ret);
return ret;
}
static int ov5693_get_gain(struct ov5693_device *ov5693, u32 *gain)
{
u32 value;
u64 value;
int ret;
ret = ov5693_read_reg(ov5693, OV5693_GAIN_CTRL_REG, &value);
ret = cci_read(ov5693->regmap, OV5693_GAIN_CTRL_REG, &value, NULL);
if (ret)
return ret;
@ -563,9 +435,9 @@ static int ov5693_digital_gain_configure(struct ov5693_device *ov5693,
gain &= OV5693_MWB_GAIN_MASK;
ov5693_write_reg(ov5693, OV5693_MWB_RED_GAIN_REG, gain, &ret);
ov5693_write_reg(ov5693, OV5693_MWB_GREEN_GAIN_REG, gain, &ret);
ov5693_write_reg(ov5693, OV5693_MWB_BLUE_GAIN_REG, gain, &ret);
cci_write(ov5693->regmap, OV5693_MWB_RED_GAIN_REG, gain, &ret);
cci_write(ov5693->regmap, OV5693_MWB_GREEN_GAIN_REG, gain, &ret);
cci_write(ov5693->regmap, OV5693_MWB_BLUE_GAIN_REG, gain, &ret);
return ret;
}
@ -576,7 +448,7 @@ static int ov5693_analog_gain_configure(struct ov5693_device *ov5693, u32 gain)
gain = (gain << 4) & OV5693_GAIN_CTRL_MASK;
ov5693_write_reg(ov5693, OV5693_GAIN_CTRL_REG, gain, &ret);
cci_write(ov5693->regmap, OV5693_GAIN_CTRL_REG, gain, &ret);
return ret;
}
@ -586,7 +458,7 @@ static int ov5693_vts_configure(struct ov5693_device *ov5693, u32 vblank)
u16 vts = ov5693->mode.format.height + vblank;
int ret = 0;
ov5693_write_reg(ov5693, OV5693_TIMING_VTS_REG, vts, &ret);
cci_write(ov5693->regmap, OV5693_TIMING_VTS_REG, vts, &ret);
return ret;
}
@ -595,8 +467,8 @@ static int ov5693_test_pattern_configure(struct ov5693_device *ov5693, u32 idx)
{
int ret = 0;
ov5693_write_reg(ov5693, OV5693_TEST_PATTERN_REG,
ov5693_test_pattern_bits[idx], &ret);
cci_write(ov5693->regmap, OV5693_TEST_PATTERN_REG,
ov5693_test_pattern_bits[idx], &ret);
return ret;
}
@ -685,59 +557,54 @@ static int ov5693_mode_configure(struct ov5693_device *ov5693)
int ret = 0;
/* Crop Start X */
ov5693_write_reg(ov5693, OV5693_CROP_START_X_REG, mode->crop.left,
&ret);
cci_write(ov5693->regmap, OV5693_CROP_START_X_REG, mode->crop.left,
&ret);
/* Offset X */
ov5693_write_reg(ov5693, OV5693_OFFSET_START_X_REG, 0, &ret);
cci_write(ov5693->regmap, OV5693_OFFSET_START_X_REG, 0, &ret);
/* Output Size X */
ov5693_write_reg(ov5693, OV5693_OUTPUT_SIZE_X_REG, mode->format.width,
&ret);
cci_write(ov5693->regmap, OV5693_OUTPUT_SIZE_X_REG, mode->format.width,
&ret);
/* Crop End X */
ov5693_write_reg(ov5693, OV5693_CROP_END_X_REG,
mode->crop.left + mode->crop.width, &ret);
cci_write(ov5693->regmap, OV5693_CROP_END_X_REG,
mode->crop.left + mode->crop.width, &ret);
/* Horizontal Total Size */
ov5693_write_reg(ov5693, OV5693_TIMING_HTS_REG, OV5693_FIXED_PPL,
&ret);
cci_write(ov5693->regmap, OV5693_TIMING_HTS_REG, OV5693_FIXED_PPL,
&ret);
/* Crop Start Y */
ov5693_write_reg(ov5693, OV5693_CROP_START_Y_REG, mode->crop.top,
&ret);
cci_write(ov5693->regmap, OV5693_CROP_START_Y_REG, mode->crop.top,
&ret);
/* Offset Y */
ov5693_write_reg(ov5693, OV5693_OFFSET_START_Y_REG, 0, &ret);
cci_write(ov5693->regmap, OV5693_OFFSET_START_Y_REG, 0, &ret);
/* Output Size Y */
ov5693_write_reg(ov5693, OV5693_OUTPUT_SIZE_Y_REG, mode->format.height,
&ret);
cci_write(ov5693->regmap, OV5693_OUTPUT_SIZE_Y_REG, mode->format.height,
&ret);
/* Crop End Y */
ov5693_write_reg(ov5693, OV5693_CROP_END_Y_REG,
mode->crop.top + mode->crop.height, &ret);
cci_write(ov5693->regmap, OV5693_CROP_END_Y_REG,
mode->crop.top + mode->crop.height, &ret);
/* Subsample X increase */
ov5693_write_reg(ov5693, OV5693_SUB_INC_X_REG,
((mode->inc_x_odd << 4) & 0xf0) | 0x01, &ret);
cci_write(ov5693->regmap, OV5693_SUB_INC_X_REG,
((mode->inc_x_odd << 4) & 0xf0) | 0x01, &ret);
/* Subsample Y increase */
ov5693_write_reg(ov5693, OV5693_SUB_INC_Y_REG,
((mode->inc_y_odd << 4) & 0xf0) | 0x01, &ret);
if (ret)
return ret;
cci_write(ov5693->regmap, OV5693_SUB_INC_Y_REG,
((mode->inc_y_odd << 4) & 0xf0) | 0x01, &ret);
/* Binning */
ret = ov5693_update_bits(ov5693, OV5693_FORMAT1_REG,
OV5693_FORMAT1_VBIN_EN,
mode->binning_y ? OV5693_FORMAT1_VBIN_EN : 0);
if (ret)
return ret;
cci_update_bits(ov5693->regmap, OV5693_FORMAT1_REG,
OV5693_FORMAT1_VBIN_EN,
mode->binning_y ? OV5693_FORMAT1_VBIN_EN : 0, &ret);
ret = ov5693_update_bits(ov5693, OV5693_FORMAT2_REG,
OV5693_FORMAT2_HBIN_EN,
mode->binning_x ? OV5693_FORMAT2_HBIN_EN : 0);
cci_update_bits(ov5693->regmap, OV5693_FORMAT2_REG,
OV5693_FORMAT2_HBIN_EN,
mode->binning_x ? OV5693_FORMAT2_HBIN_EN : 0, &ret);
return ret;
}
@ -746,9 +613,9 @@ static int ov5693_enable_streaming(struct ov5693_device *ov5693, bool enable)
{
int ret = 0;
ov5693_write_reg(ov5693, OV5693_SW_STREAM_REG,
enable ? OV5693_START_STREAMING :
OV5693_STOP_STREAMING, &ret);
cci_write(ov5693->regmap, OV5693_SW_STREAM_REG,
enable ? OV5693_START_STREAMING : OV5693_STOP_STREAMING,
&ret);
return ret;
}
@ -757,7 +624,7 @@ static int ov5693_sw_reset(struct ov5693_device *ov5693)
{
int ret = 0;
ov5693_write_reg(ov5693, OV5693_SW_RESET_REG, OV5693_SW_RESET, &ret);
cci_write(ov5693->regmap, OV5693_SW_RESET_REG, OV5693_SW_RESET, &ret);
return ret;
}
@ -771,7 +638,8 @@ static int ov5693_sensor_init(struct ov5693_device *ov5693)
return dev_err_probe(ov5693->dev, ret,
"software reset error\n");
ret = ov5693_write_reg_array(ov5693, &ov5693_global_setting);
ret = cci_multi_reg_write(ov5693->regmap, ov5693_global_regs,
ARRAY_SIZE(ov5693_global_regs), NULL);
if (ret)
return dev_err_probe(ov5693->dev, ret,
"global settings error\n");
@ -871,15 +739,15 @@ out_unlock:
static int ov5693_detect(struct ov5693_device *ov5693)
{
int ret;
u32 id;
u64 id;
ret = ov5693_read_reg(ov5693, OV5693_REG_CHIP_ID, &id);
ret = cci_read(ov5693->regmap, OV5693_REG_CHIP_ID, &id, NULL);
if (ret)
return ret;
if (id != OV5693_CHIP_ID)
return dev_err_probe(ov5693->dev, -ENODEV,
"sensor ID mismatch. Found 0x%04x\n", id);
"sensor ID mismatch. Got 0x%04llx\n", id);
return 0;
}
@ -1407,9 +1275,12 @@ static int ov5693_probe(struct i2c_client *client)
if (!ov5693)
return -ENOMEM;
ov5693->client = client;
ov5693->dev = &client->dev;
ov5693->regmap = devm_cci_regmap_init_i2c(client, 16);
if (IS_ERR(ov5693->regmap))
return PTR_ERR(ov5693->regmap);
ret = ov5693_check_hwcfg(ov5693);
if (ret)
return ret;

View File

@ -1210,7 +1210,7 @@ static struct i2c_driver ov7740_i2c_driver = {
.driver = {
.name = "ov7740",
.pm = &ov7740_pm_ops,
.of_match_table = of_match_ptr(ov7740_of_match),
.of_match_table = ov7740_of_match,
},
.probe = ov7740_probe,
.remove = ov7740_remove,

View File

@ -567,7 +567,6 @@ again:
static int rdacm20_probe(struct i2c_client *client)
{
struct rdacm20_device *dev;
struct fwnode_handle *ep;
int ret;
dev = devm_kzalloc(&client->dev, sizeof(*dev), GFP_KERNEL);
@ -616,24 +615,12 @@ static int rdacm20_probe(struct i2c_client *client)
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;
goto error_free_ctrls;
return 0;
error_put_node:
fwnode_handle_put(ep);
error_free_ctrls:
v4l2_ctrl_handler_free(&dev->ctrls);
error:
@ -650,7 +637,6 @@ static void rdacm20_remove(struct i2c_client *client)
{
struct rdacm20_device *dev = i2c_to_rdacm20(client);
fwnode_handle_put(dev->sd.fwnode);
v4l2_async_unregister_subdev(&dev->sd);
v4l2_ctrl_handler_free(&dev->ctrls);
media_entity_cleanup(&dev->sd.entity);

View File

@ -351,7 +351,7 @@ static void ov10640_power_up(struct rdacm21_device *dev)
static int ov10640_check_id(struct rdacm21_device *dev)
{
unsigned int i;
u8 val;
u8 val = 0;
/* Read OV10640 ID to test communications. */
for (i = 0; i < OV10640_PID_TIMEOUT; ++i) {
@ -543,7 +543,6 @@ static int rdacm21_initialize(struct rdacm21_device *dev)
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);
@ -588,24 +587,12 @@ static int rdacm21_probe(struct i2c_client *client)
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;
goto error_free_ctrls;
return 0;
error_put_node:
fwnode_handle_put(dev->sd.fwnode);
error_free_ctrls:
v4l2_ctrl_handler_free(&dev->ctrls);
error:

View File

@ -545,7 +545,14 @@ static int mipid02_configure_from_code(struct mipid02_dev *bridge)
static int mipid02_stream_disable(struct mipid02_dev *bridge)
{
struct i2c_client *client = bridge->i2c_client;
int ret;
int ret = -EINVAL;
if (!bridge->s_subdev)
goto error;
ret = v4l2_subdev_call(bridge->s_subdev, video, s_stream, 0);
if (ret)
goto error;
/* Disable all lanes */
ret = mipid02_write_reg(bridge, MIPID02_CLK_LANE_REG1, 0);
@ -633,6 +640,10 @@ static int mipid02_stream_enable(struct mipid02_dev *bridge)
if (ret)
goto error;
ret = v4l2_subdev_call(bridge->s_subdev, video, s_stream, 1);
if (ret)
goto error;
return 0;
error:
@ -829,7 +840,7 @@ static const struct media_entity_operations mipid02_subdev_entity_ops = {
static int mipid02_async_bound(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *s_subdev,
struct v4l2_async_subdev *asd)
struct v4l2_async_connection *asd)
{
struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd);
struct i2c_client *client = bridge->i2c_client;
@ -863,7 +874,7 @@ static int mipid02_async_bound(struct v4l2_async_notifier *notifier,
static void mipid02_async_unbind(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *s_subdev,
struct v4l2_async_subdev *asd)
struct v4l2_async_connection *asd)
{
struct mipid02_dev *bridge = to_mipid02_dev(notifier->sd);
@ -879,7 +890,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
{
struct v4l2_fwnode_endpoint ep = { .bus_type = V4L2_MBUS_CSI2_DPHY };
struct i2c_client *client = bridge->i2c_client;
struct v4l2_async_subdev *asd;
struct v4l2_async_connection *asd;
struct device_node *ep_node;
int ret;
@ -911,10 +922,10 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
bridge->rx = ep;
/* register async notifier so we get noticed when sensor is connected */
v4l2_async_nf_init(&bridge->notifier);
v4l2_async_subdev_nf_init(&bridge->notifier, &bridge->sd);
asd = v4l2_async_nf_add_fwnode_remote(&bridge->notifier,
of_fwnode_handle(ep_node),
struct v4l2_async_subdev);
struct v4l2_async_connection);
of_node_put(ep_node);
if (IS_ERR(asd)) {
@ -924,7 +935,7 @@ static int mipid02_parse_rx_ep(struct mipid02_dev *bridge)
}
bridge->notifier.ops = &mipid02_notifier_ops;
ret = v4l2_async_subdev_nf_register(&bridge->sd, &bridge->notifier);
ret = v4l2_async_nf_register(&bridge->notifier);
if (ret)
v4l2_async_nf_cleanup(&bridge->notifier);

View File

@ -133,8 +133,8 @@ static void i2c_rd(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n)
err = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
if (err != ARRAY_SIZE(msgs)) {
v4l2_err(sd, "%s: reading register 0x%x from 0x%x failed\n",
__func__, reg, client->addr);
v4l2_err(sd, "%s: reading register 0x%x from 0x%x failed: %d\n",
__func__, reg, client->addr, err);
}
}
@ -165,8 +165,8 @@ static void i2c_wr(struct v4l2_subdev *sd, u16 reg, u8 *values, u32 n)
err = i2c_transfer(client->adapter, &msg, 1);
if (err != 1) {
v4l2_err(sd, "%s: writing register 0x%x from 0x%x failed\n",
__func__, reg, client->addr);
v4l2_err(sd, "%s: writing register 0x%x from 0x%x failed: %d\n",
__func__, reg, client->addr, err);
return;
}

View File

@ -1426,7 +1426,7 @@ static int tc358746_init_controls(struct tc358746 *tc358746)
static int tc358746_notify_bound(struct v4l2_async_notifier *notifier,
struct v4l2_subdev *sd,
struct v4l2_async_subdev *asd)
struct v4l2_async_connection *asd)
{
struct tc358746 *tc358746 =
container_of(notifier, struct tc358746, notifier);
@ -1445,7 +1445,7 @@ static int tc358746_async_register(struct tc358746 *tc358746)
struct v4l2_fwnode_endpoint vep = {
.bus_type = V4L2_MBUS_PARALLEL,
};
struct v4l2_async_subdev *asd;
struct v4l2_async_connection *asd;
struct fwnode_handle *ep;
int err;
@ -1460,9 +1460,9 @@ static int tc358746_async_register(struct tc358746 *tc358746)
return err;
}
v4l2_async_nf_init(&tc358746->notifier);
v4l2_async_subdev_nf_init(&tc358746->notifier, &tc358746->sd);
asd = v4l2_async_nf_add_fwnode_remote(&tc358746->notifier, ep,
struct v4l2_async_subdev);
struct v4l2_async_connection);
fwnode_handle_put(ep);
if (IS_ERR(asd)) {
@ -1472,13 +1472,10 @@ static int tc358746_async_register(struct tc358746 *tc358746)
tc358746->notifier.ops = &tc358746_notify_ops;
err = v4l2_async_subdev_nf_register(&tc358746->sd, &tc358746->notifier);
err = v4l2_async_nf_register(&tc358746->notifier);
if (err)
goto err_cleanup;
tc358746->sd.fwnode = fwnode_graph_get_endpoint_by_id(
dev_fwnode(tc358746->sd.dev), TC358746_SOURCE, 0, 0);
err = v4l2_async_register_subdev(&tc358746->sd);
if (err)
goto err_unregister;
@ -1486,7 +1483,6 @@ static int tc358746_async_register(struct tc358746 *tc358746)
return 0;
err_unregister:
fwnode_handle_put(tc358746->sd.fwnode);
v4l2_async_nf_unregister(&tc358746->notifier);
err_cleanup:
v4l2_async_nf_cleanup(&tc358746->notifier);
@ -1605,7 +1601,6 @@ static void tc358746_remove(struct i2c_client *client)
v4l2_fwnode_endpoint_free(&tc358746->csi_vep);
v4l2_async_nf_unregister(&tc358746->notifier);
v4l2_async_nf_cleanup(&tc358746->notifier);
fwnode_handle_put(sd->fwnode);
v4l2_async_unregister_subdev(sd);
media_entity_cleanup(&sd->entity);

View File

@ -2068,6 +2068,10 @@ static int tvp5150_parse_dt(struct tvp5150 *decoder, struct device_node *np)
tvpc->ent.name = devm_kasprintf(dev, GFP_KERNEL, "%s %s",
v4l2c->name, v4l2c->label ?
v4l2c->label : "");
if (!tvpc->ent.name) {
ret = -ENOMEM;
goto err_free;
}
}
ep_np = of_graph_get_endpoint_by_regs(np, TVP5150_PAD_VID_OUT, 0);

View File

@ -16,9 +16,9 @@
#include <linux/kthread.h>
#include <linux/i2c.h>
#include <linux/list.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/nvmem-provider.h>
#include <linux/regmap.h>

View File

@ -73,7 +73,7 @@ config VIDEO_PCI_SKELETON
Enable build of the skeleton PCI driver, used as a reference
when developing new drivers.
source "drivers/media/pci/intel/ipu3/Kconfig"
source "drivers/media/pci/intel/Kconfig"
endif #MEDIA_PCI_SUPPORT
endif #PCI

View File

@ -3,7 +3,7 @@ config VIDEO_BT848
tristate "BT848 Video For Linux"
depends on PCI && I2C && VIDEO_DEV
select I2C_ALGOBIT
select VIDEOBUF_DMA_SG
select VIDEOBUF2_DMA_SG
depends on RC_CORE
depends on MEDIA_RADIO_SUPPORT
select VIDEO_TUNER

View File

@ -231,7 +231,15 @@
#define BT848_INT_ETBF (1<<23)
#define BT848_RISC_VIDEO 1
#define BT848_RISC_TOP 2
#define BT848_RISC_VBI 4
#define BT848_INT_RISCS (0xf<<28)
#define BT848_INT_RISCS_VIDEO (BT848_RISC_VIDEO << 28)
#define BT848_INT_RISCS_TOP (BT848_RISC_TOP << 28)
#define BT848_INT_RISCS_VBI (BT848_RISC_VBI << 28)
#define BT848_INT_RISC_EN (1<<27)
#define BT848_INT_RACK (1<<25)
#define BT848_INT_FIELD (1<<24)

View File

@ -293,16 +293,8 @@ void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
{
unsigned long val;
if (!set) {
/* Not much to do here */
t->audmode = V4L2_TUNER_MODE_LANG1;
t->rxsubchans = V4L2_TUNER_SUB_MONO |
V4L2_TUNER_SUB_STEREO |
V4L2_TUNER_SUB_LANG1 |
V4L2_TUNER_SUB_LANG2;
if (!set)
return;
}
/*btor (0xc32000, BT848_GPIO_OUT_EN);*/
switch (t->audmode) {

File diff suppressed because it is too large Load Diff

View File

@ -67,8 +67,10 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
/* scan lines */
sg = sglist;
for (line = 0; line < store_lines; line++) {
if ((btv->opt_vcr_hack) &&
(line >= (store_lines - VCR_HACK_LINES)))
if ((line >= (store_lines - VCR_HACK_LINES)) &&
(btv->opt_vcr_hack ||
(V4L2_FIELD_HAS_BOTH(btv->field) ||
btv->field == V4L2_FIELD_ALTERNATE)))
continue;
while (offset && offset >= sg_dma_len(sg)) {
offset -= sg_dma_len(sg);
@ -106,7 +108,7 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc,
/* save pointer to jmp instruction address */
risc->jmp = rp;
BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
return 0;
}
@ -227,7 +229,7 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc,
/* save pointer to jmp instruction address */
risc->jmp = rp;
BUG_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
WARN_ON((risc->jmp - risc->cpu + 2) * sizeof(*risc->cpu) > risc->size);
return 0;
}
@ -360,21 +362,75 @@ bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd)
/* ---------------------------------------------------------- */
/* risc group / risc main loop / dma management */
void
bttv_set_dma(struct bttv *btv, int override)
static void bttv_set_risc_status(struct bttv *btv)
{
unsigned long cmd;
int capctl;
unsigned long cmd = BT848_RISC_JUMP;
if (btv->loop_irq) {
cmd |= BT848_RISC_IRQ;
cmd |= (btv->loop_irq & 0x0f) << 16;
cmd |= (~btv->loop_irq & 0x0f) << 20;
}
btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
}
btv->cap_ctl = 0;
if (NULL != btv->curr.top) btv->cap_ctl |= 0x02;
if (NULL != btv->curr.bottom) btv->cap_ctl |= 0x01;
if (NULL != btv->cvbi) btv->cap_ctl |= 0x0c;
static void bttv_set_irq_timer(struct bttv *btv)
{
if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi)
mod_timer(&btv->timeout, jiffies + BTTV_TIMEOUT);
else
del_timer(&btv->timeout);
}
capctl = 0;
capctl |= (btv->cap_ctl & 0x03) ? 0x03 : 0x00; /* capture */
capctl |= (btv->cap_ctl & 0x0c) ? 0x0c : 0x00; /* vbi data */
capctl |= override;
static int bttv_set_capture_control(struct bttv *btv, int start_capture)
{
int capctl = 0;
if (btv->curr.top || btv->curr.bottom)
capctl = BT848_CAP_CTL_CAPTURE_ODD |
BT848_CAP_CTL_CAPTURE_EVEN;
if (btv->cvbi)
capctl |= BT848_CAP_CTL_CAPTURE_VBI_ODD |
BT848_CAP_CTL_CAPTURE_VBI_EVEN;
capctl |= start_capture;
btaor(capctl, ~0x0f, BT848_CAP_CTL);
return capctl;
}
static void bttv_start_dma(struct bttv *btv)
{
if (btv->dma_on)
return;
btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
btor(BT848_GPIO_DMA_CTL_RISC_ENABLE | BT848_GPIO_DMA_CTL_FIFO_ENABLE,
BT848_GPIO_DMA_CTL);
btv->dma_on = 1;
}
static void bttv_stop_dma(struct bttv *btv)
{
if (!btv->dma_on)
return;
btand(~(BT848_GPIO_DMA_CTL_RISC_ENABLE |
BT848_GPIO_DMA_CTL_FIFO_ENABLE), BT848_GPIO_DMA_CTL);
btv->dma_on = 0;
}
void bttv_set_dma(struct bttv *btv, int start_capture)
{
int capctl = 0;
bttv_set_risc_status(btv);
bttv_set_irq_timer(btv);
capctl = bttv_set_capture_control(btv, start_capture);
if (capctl)
bttv_start_dma(btv);
else
bttv_stop_dma(btv);
d2printk("%d: capctl=%x lirq=%d top=%08llx/%08llx even=%08llx/%08llx\n",
btv->c.nr,capctl,btv->loop_irq,
@ -382,34 +438,6 @@ bttv_set_dma(struct bttv *btv, int override)
btv->curr.top ? (unsigned long long)btv->curr.top->top.dma : 0,
btv->cvbi ? (unsigned long long)btv->cvbi->bottom.dma : 0,
btv->curr.bottom ? (unsigned long long)btv->curr.bottom->bottom.dma : 0);
cmd = BT848_RISC_JUMP;
if (btv->loop_irq) {
cmd |= BT848_RISC_IRQ;
cmd |= (btv->loop_irq & 0x0f) << 16;
cmd |= (~btv->loop_irq & 0x0f) << 20;
}
if (btv->curr.frame_irq || btv->loop_irq || btv->cvbi) {
mod_timer(&btv->timeout, jiffies+BTTV_TIMEOUT);
} else {
del_timer(&btv->timeout);
}
btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd);
btaor(capctl, ~0x0f, BT848_CAP_CTL);
if (capctl) {
if (btv->dma_on)
return;
btwrite(btv->main.dma, BT848_RISC_STRT_ADD);
btor(3, BT848_GPIO_DMA_CTL);
btv->dma_on = 1;
} else {
if (!btv->dma_on)
return;
btand(~3, BT848_GPIO_DMA_CTL);
btv->dma_on = 0;
}
return;
}
int
@ -478,17 +506,50 @@ bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
return 0;
}
void
bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf)
int bttv_buffer_risc_vbi(struct bttv *btv, struct bttv_buffer *buf)
{
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
int r = 0;
unsigned int offset;
unsigned int bpl = 2044; /* max. vbipack */
unsigned int padding = VBI_BPL - bpl;
unsigned int skip_lines0 = 0;
unsigned int skip_lines1 = 0;
unsigned int min_vdelay = MIN_VDELAY;
videobuf_waiton(q, &buf->vb, 0, 0);
videobuf_dma_unmap(q->dev, dma);
videobuf_dma_free(dma);
btcx_riscmem_free(btv->c.pci,&buf->bottom);
btcx_riscmem_free(btv->c.pci,&buf->top);
buf->vb.state = VIDEOBUF_NEEDS_INIT;
const struct bttv_tvnorm *tvnorm = btv->vbi_fmt.tvnorm;
struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
struct scatterlist *list = sgt->sgl;
if (btv->vbi_fmt.fmt.count[0] > 0)
skip_lines0 = max(0, (btv->vbi_fmt.fmt.start[0] -
tvnorm->vbistart[0]));
if (btv->vbi_fmt.fmt.count[1] > 0)
skip_lines1 = max(0, (btv->vbi_fmt.fmt.start[1] -
tvnorm->vbistart[1]));
if (btv->vbi_fmt.fmt.count[0] > 0) {
r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, padding,
skip_lines0, btv->vbi_fmt.fmt.count[0]);
if (r)
return r;
}
if (btv->vbi_fmt.fmt.count[1] > 0) {
offset = btv->vbi_fmt.fmt.count[0] * VBI_BPL;
r = bttv_risc_packed(btv, &buf->bottom, list, offset, bpl,
padding, skip_lines1,
btv->vbi_fmt.fmt.count[1]);
if (r)
return r;
}
if (btv->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
min_vdelay += btv->vbi_fmt.end - tvnorm->cropcap.bounds.top;
/* For bttv_buffer_activate_vbi(). */
buf->geo.vdelay = min_vdelay;
return r;
}
int
@ -508,8 +569,7 @@ bttv_buffer_activate_vbi(struct bttv *btv,
if (vbi) {
unsigned int crop, vdelay;
vbi->vb.state = VIDEOBUF_ACTIVE;
list_del(&vbi->vb.queue);
list_del(&vbi->list);
/* VDELAY is start of video, end of VBI capturing. */
crop = btread(BT848_E_CROP);
@ -525,12 +585,12 @@ bttv_buffer_activate_vbi(struct bttv *btv,
btwrite(crop, BT848_O_CROP);
}
if (vbi->vbi_count[0] > 0) {
if (btv->vbi_count[0] > 0) {
top = &vbi->top;
top_irq_flags = 4;
}
if (vbi->vbi_count[1] > 0) {
if (btv->vbi_count[1] > 0) {
top_irq_flags = 0;
bottom = &vbi->bottom;
bottom_irq_flags = 4;
@ -550,16 +610,13 @@ bttv_buffer_activate_video(struct bttv *btv,
/* video capture */
if (NULL != set->top && NULL != set->bottom) {
if (set->top == set->bottom) {
set->top->vb.state = VIDEOBUF_ACTIVE;
if (set->top->vb.queue.next)
list_del(&set->top->vb.queue);
if (set->top->list.next)
list_del(&set->top->list);
} else {
set->top->vb.state = VIDEOBUF_ACTIVE;
set->bottom->vb.state = VIDEOBUF_ACTIVE;
if (set->top->vb.queue.next)
list_del(&set->top->vb.queue);
if (set->bottom->vb.queue.next)
list_del(&set->bottom->vb.queue);
if (set->top->list.next)
list_del(&set->top->list);
if (set->bottom->list.next)
list_del(&set->bottom->list);
}
bttv_apply_geo(btv, &set->top->geo, 1);
bttv_apply_geo(btv, &set->bottom->geo,0);
@ -572,9 +629,8 @@ bttv_buffer_activate_video(struct bttv *btv,
btaor((set->top->btswap & 0x0a) | (set->bottom->btswap & 0x05),
~0x0f, BT848_COLOR_CTL);
} else if (NULL != set->top) {
set->top->vb.state = VIDEOBUF_ACTIVE;
if (set->top->vb.queue.next)
list_del(&set->top->vb.queue);
if (set->top->list.next)
list_del(&set->top->list);
bttv_apply_geo(btv, &set->top->geo,1);
bttv_apply_geo(btv, &set->top->geo,0);
bttv_risc_hook(btv, RISC_SLOT_O_FIELD, &set->top->top,
@ -583,9 +639,8 @@ bttv_buffer_activate_video(struct bttv *btv,
btaor(set->top->btformat & 0xff, ~0xff, BT848_COLOR_FMT);
btaor(set->top->btswap & 0x0f, ~0x0f, BT848_COLOR_CTL);
} else if (NULL != set->bottom) {
set->bottom->vb.state = VIDEOBUF_ACTIVE;
if (set->bottom->vb.queue.next)
list_del(&set->bottom->vb.queue);
if (set->bottom->list.next)
list_del(&set->bottom->list);
bttv_apply_geo(btv, &set->bottom->geo,1);
bttv_apply_geo(btv, &set->bottom->geo,0);
bttv_risc_hook(btv, RISC_SLOT_O_FIELD, NULL, 0);
@ -606,156 +661,146 @@ bttv_buffer_activate_video(struct bttv *btv,
int
bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf)
{
const struct bttv_tvnorm *tvnorm = bttv_tvnorms + buf->tvnorm;
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
dprintk("%d: buffer field: %s format: 0x%08x size: %dx%d\n",
btv->c.nr, v4l2_field_names[buf->vb.field],
buf->fmt->fourcc, buf->vb.width, buf->vb.height);
int r = 0;
const struct bttv_tvnorm *tvnorm = bttv_tvnorms + btv->tvnorm;
struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vbuf.vb2_buf, 0);
struct scatterlist *list = sgt->sgl;
unsigned long size = (btv->fmt->depth * btv->width * btv->height) >> 3;
/* packed pixel modes */
if (buf->fmt->flags & FORMAT_FLAGS_PACKED) {
int bpl = (buf->fmt->depth >> 3) * buf->vb.width;
int bpf = bpl * (buf->vb.height >> 1);
if (btv->fmt->flags & FORMAT_FLAGS_PACKED) {
int bpl = (btv->fmt->depth >> 3) * btv->width;
int bpf = bpl * (btv->height >> 1);
bttv_calc_geo(btv,&buf->geo,buf->vb.width,buf->vb.height,
V4L2_FIELD_HAS_BOTH(buf->vb.field),
tvnorm,&buf->crop);
switch (buf->vb.field) {
bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
V4L2_FIELD_HAS_BOTH(buf->vbuf.field), tvnorm,
&btv->crop[!!btv->do_crop].rect);
switch (buf->vbuf.field) {
case V4L2_FIELD_TOP:
bttv_risc_packed(btv,&buf->top,dma->sglist,
/* offset */ 0,bpl,
/* padding */ 0,/* skip_lines */ 0,
buf->vb.height);
r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
0, btv->height);
break;
case V4L2_FIELD_BOTTOM:
bttv_risc_packed(btv,&buf->bottom,dma->sglist,
0,bpl,0,0,buf->vb.height);
r = bttv_risc_packed(btv, &buf->bottom, list, 0, bpl,
0, 0, btv->height);
break;
case V4L2_FIELD_INTERLACED:
bttv_risc_packed(btv,&buf->top,dma->sglist,
0,bpl,bpl,0,buf->vb.height >> 1);
bttv_risc_packed(btv,&buf->bottom,dma->sglist,
bpl,bpl,bpl,0,buf->vb.height >> 1);
r = bttv_risc_packed(btv, &buf->top, list, 0, bpl,
bpl, 0, btv->height >> 1);
r = bttv_risc_packed(btv, &buf->bottom, list, bpl,
bpl, bpl, 0, btv->height >> 1);
break;
case V4L2_FIELD_SEQ_TB:
bttv_risc_packed(btv,&buf->top,dma->sglist,
0,bpl,0,0,buf->vb.height >> 1);
bttv_risc_packed(btv,&buf->bottom,dma->sglist,
bpf,bpl,0,0,buf->vb.height >> 1);
r = bttv_risc_packed(btv, &buf->top, list, 0, bpl, 0,
0, btv->height >> 1);
r = bttv_risc_packed(btv, &buf->bottom, list, bpf,
bpl, 0, 0, btv->height >> 1);
break;
default:
BUG();
WARN_ON(1);
return -EINVAL;
}
}
/* planar modes */
if (buf->fmt->flags & FORMAT_FLAGS_PLANAR) {
if (btv->fmt->flags & FORMAT_FLAGS_PLANAR) {
int uoffset, voffset;
int ypadding, cpadding, lines;
/* calculate chroma offsets */
uoffset = buf->vb.width * buf->vb.height;
voffset = buf->vb.width * buf->vb.height;
if (buf->fmt->flags & FORMAT_FLAGS_CrCb) {
uoffset = btv->width * btv->height;
voffset = btv->width * btv->height;
if (btv->fmt->flags & FORMAT_FLAGS_CrCb) {
/* Y-Cr-Cb plane order */
uoffset >>= buf->fmt->hshift;
uoffset >>= buf->fmt->vshift;
uoffset >>= btv->fmt->hshift;
uoffset >>= btv->fmt->vshift;
uoffset += voffset;
} else {
/* Y-Cb-Cr plane order */
voffset >>= buf->fmt->hshift;
voffset >>= buf->fmt->vshift;
voffset >>= btv->fmt->hshift;
voffset >>= btv->fmt->vshift;
voffset += uoffset;
}
switch (buf->vb.field) {
switch (buf->vbuf.field) {
case V4L2_FIELD_TOP:
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
buf->vb.height,/* both_fields */ 0,
tvnorm,&buf->crop);
bttv_risc_planar(btv, &buf->top, dma->sglist,
0,buf->vb.width,0,buf->vb.height,
uoffset,voffset,buf->fmt->hshift,
buf->fmt->vshift,0);
bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
0, tvnorm,
&btv->crop[!!btv->do_crop].rect);
r = bttv_risc_planar(btv, &buf->top, list, 0,
btv->width, 0, btv->height,
uoffset, voffset,
btv->fmt->hshift,
btv->fmt->vshift, 0);
break;
case V4L2_FIELD_BOTTOM:
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
buf->vb.height,0,
tvnorm,&buf->crop);
bttv_risc_planar(btv, &buf->bottom, dma->sglist,
0,buf->vb.width,0,buf->vb.height,
uoffset,voffset,buf->fmt->hshift,
buf->fmt->vshift,0);
bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
0, tvnorm,
&btv->crop[!!btv->do_crop].rect);
r = bttv_risc_planar(btv, &buf->bottom, list, 0,
btv->width, 0, btv->height,
uoffset, voffset,
btv->fmt->hshift,
btv->fmt->vshift, 0);
break;
case V4L2_FIELD_INTERLACED:
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
buf->vb.height,1,
tvnorm,&buf->crop);
lines = buf->vb.height >> 1;
ypadding = buf->vb.width;
cpadding = buf->vb.width >> buf->fmt->hshift;
bttv_risc_planar(btv,&buf->top,
dma->sglist,
0,buf->vb.width,ypadding,lines,
uoffset,voffset,
buf->fmt->hshift,
buf->fmt->vshift,
cpadding);
bttv_risc_planar(btv,&buf->bottom,
dma->sglist,
ypadding,buf->vb.width,ypadding,lines,
uoffset+cpadding,
voffset+cpadding,
buf->fmt->hshift,
buf->fmt->vshift,
cpadding);
bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
1, tvnorm,
&btv->crop[!!btv->do_crop].rect);
lines = btv->height >> 1;
ypadding = btv->width;
cpadding = btv->width >> btv->fmt->hshift;
r = bttv_risc_planar(btv, &buf->top, list, 0,
btv->width, ypadding, lines,
uoffset, voffset,
btv->fmt->hshift,
btv->fmt->vshift, cpadding);
r = bttv_risc_planar(btv, &buf->bottom, list,
ypadding, btv->width, ypadding,
lines, uoffset + cpadding,
voffset + cpadding,
btv->fmt->hshift,
btv->fmt->vshift, cpadding);
break;
case V4L2_FIELD_SEQ_TB:
bttv_calc_geo(btv,&buf->geo,buf->vb.width,
buf->vb.height,1,
tvnorm,&buf->crop);
lines = buf->vb.height >> 1;
ypadding = buf->vb.width;
cpadding = buf->vb.width >> buf->fmt->hshift;
bttv_risc_planar(btv,&buf->top,
dma->sglist,
0,buf->vb.width,0,lines,
uoffset >> 1,
voffset >> 1,
buf->fmt->hshift,
buf->fmt->vshift,
0);
bttv_risc_planar(btv,&buf->bottom,
dma->sglist,
lines * ypadding,buf->vb.width,0,lines,
lines * ypadding + (uoffset >> 1),
lines * ypadding + (voffset >> 1),
buf->fmt->hshift,
buf->fmt->vshift,
0);
bttv_calc_geo(btv, &buf->geo, btv->width, btv->height,
1, tvnorm,
&btv->crop[!!btv->do_crop].rect);
lines = btv->height >> 1;
ypadding = btv->width;
cpadding = btv->width >> btv->fmt->hshift;
r = bttv_risc_planar(btv, &buf->top, list, 0,
btv->width, 0, lines,
uoffset >> 1, voffset >> 1,
btv->fmt->hshift,
btv->fmt->vshift, 0);
r = bttv_risc_planar(btv, &buf->bottom, list,
lines * ypadding,
btv->width, 0, lines,
lines * ypadding + (uoffset >> 1),
lines * ypadding + (voffset >> 1),
btv->fmt->hshift,
btv->fmt->vshift, 0);
break;
default:
BUG();
WARN_ON(1);
return -EINVAL;
}
}
/* raw data */
if (buf->fmt->flags & FORMAT_FLAGS_RAW) {
if (btv->fmt->flags & FORMAT_FLAGS_RAW) {
/* build risc code */
buf->vb.field = V4L2_FIELD_SEQ_TB;
bttv_calc_geo(btv,&buf->geo,tvnorm->swidth,tvnorm->sheight,
1,tvnorm,&buf->crop);
bttv_risc_packed(btv, &buf->top, dma->sglist,
/* offset */ 0, RAW_BPL, /* padding */ 0,
/* skip_lines */ 0, RAW_LINES);
bttv_risc_packed(btv, &buf->bottom, dma->sglist,
buf->vb.size/2 , RAW_BPL, 0, 0, RAW_LINES);
buf->vbuf.field = V4L2_FIELD_SEQ_TB;
bttv_calc_geo(btv, &buf->geo, tvnorm->swidth, tvnorm->sheight,
1, tvnorm, &btv->crop[!!btv->do_crop].rect);
r = bttv_risc_packed(btv, &buf->top, list, 0, RAW_BPL, 0, 0,
RAW_LINES);
r = bttv_risc_packed(btv, &buf->bottom, list, size / 2,
RAW_BPL, 0, 0, RAW_LINES);
}
/* copy format info */
buf->btformat = buf->fmt->btformat;
buf->btswap = buf->fmt->btswap;
return 0;
buf->btformat = btv->fmt->btformat;
buf->btswap = btv->fmt->btswap;
return r;
}

View File

@ -34,16 +34,6 @@
to be about 244. */
#define VBI_OFFSET 244
/* 2048 for compatibility with earlier driver versions. The driver
really stores 1024 + tvnorm->vbipack * 4 samples per line in the
buffer. Note tvnorm->vbipack is <= 0xFF (limit of VBIPACK_LO + HI
is 0x1FF DWORDs) and VBI read()s store a frame counter in the last
four bytes of the VBI image. */
#define VBI_BPL 2048
/* Compatibility. */
#define VBI_DEFLINES 16
static unsigned int vbibufs = 4;
static unsigned int vbi_debug;
@ -67,165 +57,123 @@ do { \
/* ----------------------------------------------------------------------- */
/* vbi risc code + mm */
static int vbi_buffer_setup(struct videobuf_queue *q,
unsigned int *count, unsigned int *size)
static int queue_setup_vbi(struct vb2_queue *q, unsigned int *num_buffers,
unsigned int *num_planes, unsigned int sizes[],
struct device *alloc_devs[])
{
struct bttv_fh *fh = q->priv_data;
struct bttv *btv = fh->btv;
struct bttv *btv = vb2_get_drv_priv(q);
unsigned int size = IMAGE_SIZE(&btv->vbi_fmt.fmt);
if (0 == *count)
*count = vbibufs;
*size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
dprintk("setup: samples=%u start=%d,%d count=%u,%u\n",
fh->vbi_fmt.fmt.samples_per_line,
fh->vbi_fmt.fmt.start[0],
fh->vbi_fmt.fmt.start[1],
fh->vbi_fmt.fmt.count[0],
fh->vbi_fmt.fmt.count[1]);
if (*num_planes)
return sizes[0] < size ? -EINVAL : 0;
*num_planes = 1;
sizes[0] = size;
return 0;
}
static int vbi_buffer_prepare(struct videobuf_queue *q,
struct videobuf_buffer *vb,
enum v4l2_field field)
static void buf_queue_vbi(struct vb2_buffer *vb)
{
struct bttv_fh *fh = q->priv_data;
struct bttv *btv = fh->btv;
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
const struct bttv_tvnorm *tvnorm;
unsigned int skip_lines0, skip_lines1, min_vdelay;
int redo_dma_risc;
int rc;
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct vb2_queue *vq = vb->vb2_queue;
struct bttv *btv = vb2_get_drv_priv(vq);
struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
unsigned long flags;
buf->vb.size = IMAGE_SIZE(&fh->vbi_fmt.fmt);
if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
spin_lock_irqsave(&btv->s_lock, flags);
if (list_empty(&btv->vcapture)) {
btv->loop_irq = BT848_RISC_VBI;
if (vb2_is_streaming(&btv->capq))
btv->loop_irq |= BT848_RISC_VIDEO;
bttv_set_dma(btv, BT848_CAP_CTL_CAPTURE_VBI_ODD |
BT848_CAP_CTL_CAPTURE_VBI_EVEN);
}
list_add_tail(&buf->list, &btv->vcapture);
spin_unlock_irqrestore(&btv->s_lock, flags);
}
static int buf_prepare_vbi(struct vb2_buffer *vb)
{
int ret = 0;
struct vb2_queue *vq = vb->vb2_queue;
struct bttv *btv = vb2_get_drv_priv(vq);
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
unsigned int size = IMAGE_SIZE(&btv->vbi_fmt.fmt);
if (vb2_plane_size(vb, 0) < size)
return -EINVAL;
vb2_set_plane_payload(vb, 0, size);
buf->vbuf.field = V4L2_FIELD_NONE;
ret = bttv_buffer_risc_vbi(btv, buf);
tvnorm = fh->vbi_fmt.tvnorm;
/* There's no VBI_VDELAY register, RISC must skip the lines
we don't want. With default parameters we skip zero lines
as earlier driver versions did. The driver permits video
standard changes while capturing, so we use vbi_fmt.tvnorm
instead of btv->tvnorm to skip zero lines after video
standard changes as well. */
skip_lines0 = 0;
skip_lines1 = 0;
if (fh->vbi_fmt.fmt.count[0] > 0)
skip_lines0 = max(0, (fh->vbi_fmt.fmt.start[0]
- tvnorm->vbistart[0]));
if (fh->vbi_fmt.fmt.count[1] > 0)
skip_lines1 = max(0, (fh->vbi_fmt.fmt.start[1]
- tvnorm->vbistart[1]));
redo_dma_risc = 0;
if (buf->vbi_skip[0] != skip_lines0 ||
buf->vbi_skip[1] != skip_lines1 ||
buf->vbi_count[0] != fh->vbi_fmt.fmt.count[0] ||
buf->vbi_count[1] != fh->vbi_fmt.fmt.count[1]) {
buf->vbi_skip[0] = skip_lines0;
buf->vbi_skip[1] = skip_lines1;
buf->vbi_count[0] = fh->vbi_fmt.fmt.count[0];
buf->vbi_count[1] = fh->vbi_fmt.fmt.count[1];
redo_dma_risc = 1;
}
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
redo_dma_risc = 1;
if (0 != (rc = videobuf_iolock(q, &buf->vb, NULL)))
goto fail;
}
if (redo_dma_risc) {
unsigned int bpl, padding, offset;
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
bpl = 2044; /* max. vbipack */
padding = VBI_BPL - bpl;
if (fh->vbi_fmt.fmt.count[0] > 0) {
rc = bttv_risc_packed(btv, &buf->top,
dma->sglist,
/* offset */ 0, bpl,
padding, skip_lines0,
fh->vbi_fmt.fmt.count[0]);
if (0 != rc)
goto fail;
}
if (fh->vbi_fmt.fmt.count[1] > 0) {
offset = fh->vbi_fmt.fmt.count[0] * VBI_BPL;
rc = bttv_risc_packed(btv, &buf->bottom,
dma->sglist,
offset, bpl,
padding, skip_lines1,
fh->vbi_fmt.fmt.count[1]);
if (0 != rc)
goto fail;
}
}
/* VBI capturing ends at VDELAY, start of video capturing,
no matter where the RISC program ends. VDELAY minimum is 2,
bounds.top is the corresponding first field line number
times two. VDELAY counts half field lines. */
min_vdelay = MIN_VDELAY;
if (fh->vbi_fmt.end >= tvnorm->cropcap.bounds.top)
min_vdelay += fh->vbi_fmt.end - tvnorm->cropcap.bounds.top;
/* For bttv_buffer_activate_vbi(). */
buf->geo.vdelay = min_vdelay;
buf->vb.state = VIDEOBUF_PREPARED;
buf->vb.field = field;
dprintk("buf prepare %p: top=%p bottom=%p field=%s\n",
vb, &buf->top, &buf->bottom,
v4l2_field_names[buf->vb.field]);
return 0;
fail:
bttv_dma_free(q,btv,buf);
return rc;
return ret;
}
static void
vbi_buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
static void buf_cleanup_vbi(struct vb2_buffer *vb)
{
struct bttv_fh *fh = q->priv_data;
struct bttv *btv = fh->btv;
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct bttv_buffer *buf = container_of(vbuf, struct bttv_buffer, vbuf);
struct vb2_queue *vq = vb->vb2_queue;
struct bttv *btv = vb2_get_drv_priv(vq);
dprintk("queue %p\n",vb);
buf->vb.state = VIDEOBUF_QUEUED;
list_add_tail(&buf->vb.queue,&btv->vcapture);
if (NULL == btv->cvbi) {
fh->btv->loop_irq |= 4;
bttv_set_dma(btv,0x0c);
}
btcx_riscmem_free(btv->c.pci, &buf->top);
btcx_riscmem_free(btv->c.pci, &buf->bottom);
}
static void vbi_buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
static int start_streaming_vbi(struct vb2_queue *q, unsigned int count)
{
struct bttv_fh *fh = q->priv_data;
struct bttv *btv = fh->btv;
struct bttv_buffer *buf = container_of(vb,struct bttv_buffer,vb);
int ret;
int seqnr = 0;
struct bttv_buffer *buf;
struct bttv *btv = vb2_get_drv_priv(q);
dprintk("free %p\n",vb);
bttv_dma_free(q,fh->btv,buf);
btv->framedrop = 0;
ret = check_alloc_btres_lock(btv, RESOURCE_VBI);
if (ret == 0) {
if (btv->field_count)
seqnr++;
while (!list_empty(&btv->vcapture)) {
buf = list_entry(btv->vcapture.next,
struct bttv_buffer, list);
list_del(&buf->list);
buf->vbuf.sequence = (btv->field_count >> 1) + seqnr++;
vb2_buffer_done(&buf->vbuf.vb2_buf,
VB2_BUF_STATE_QUEUED);
}
return !ret;
}
if (!vb2_is_streaming(&btv->capq)) {
init_irqreg(btv);
btv->field_count = 0;
}
return !ret;
}
const struct videobuf_queue_ops bttv_vbi_qops = {
.buf_setup = vbi_buffer_setup,
.buf_prepare = vbi_buffer_prepare,
.buf_queue = vbi_buffer_queue,
.buf_release = vbi_buffer_release,
static void stop_streaming_vbi(struct vb2_queue *q)
{
struct bttv *btv = vb2_get_drv_priv(q);
unsigned long flags;
vb2_wait_for_all_buffers(q);
spin_lock_irqsave(&btv->s_lock, flags);
free_btres_lock(btv, RESOURCE_VBI);
if (!vb2_is_streaming(&btv->capq)) {
/* stop field counter */
btand(~BT848_INT_VSYNC, BT848_INT_MASK);
}
spin_unlock_irqrestore(&btv->s_lock, flags);
}
const struct vb2_ops bttv_vbi_qops = {
.queue_setup = queue_setup_vbi,
.buf_queue = buf_queue_vbi,
.buf_prepare = buf_prepare_vbi,
.buf_cleanup = buf_cleanup_vbi,
.start_streaming = start_streaming_vbi,
.stop_streaming = stop_streaming_vbi,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
};
/* ----------------------------------------------------------------------- */
@ -250,7 +198,7 @@ static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
if (min_start > max_start)
return -EBUSY;
BUG_ON(max_start >= max_end);
WARN_ON(max_start >= max_end);
f->sampling_rate = tvnorm->Fsc;
f->samples_per_line = VBI_BPL;
@ -299,8 +247,7 @@ static int try_fmt(struct v4l2_vbi_format *f, const struct bttv_tvnorm *tvnorm,
int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
struct bttv *btv = video_drvdata(file);
const struct bttv_tvnorm *tvnorm;
__s32 crop_start;
@ -317,8 +264,7 @@ int bttv_try_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
{
struct bttv_fh *fh = f;
struct bttv *btv = fh->btv;
struct bttv *btv = video_drvdata(file);
const struct bttv_tvnorm *tvnorm;
__s32 start1, end;
int rc;
@ -326,7 +272,7 @@ int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
mutex_lock(&btv->lock);
rc = -EBUSY;
if (fh->resources & RESOURCE_VBI)
if (btv->resources & RESOURCE_VBI)
goto fail;
tvnorm = &bttv_tvnorms[btv->tvnorm];
@ -346,13 +292,9 @@ int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
because vbi_fmt.end counts field lines times two. */
end = max(frt->fmt.vbi.start[0], start1) * 2 + 2;
mutex_lock(&fh->vbi.vb_lock);
fh->vbi_fmt.fmt = frt->fmt.vbi;
fh->vbi_fmt.tvnorm = tvnorm;
fh->vbi_fmt.end = end;
mutex_unlock(&fh->vbi.vb_lock);
btv->vbi_fmt.fmt = frt->fmt.vbi;
btv->vbi_fmt.tvnorm = tvnorm;
btv->vbi_fmt.end = end;
rc = 0;
@ -365,14 +307,14 @@ int bttv_s_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
{
struct bttv_fh *fh = f;
const struct bttv_tvnorm *tvnorm;
struct bttv *btv = video_drvdata(file);
frt->fmt.vbi = fh->vbi_fmt.fmt;
frt->fmt.vbi = btv->vbi_fmt.fmt;
tvnorm = &bttv_tvnorms[fh->btv->tvnorm];
tvnorm = &bttv_tvnorms[btv->tvnorm];
if (tvnorm != fh->vbi_fmt.tvnorm) {
if (tvnorm != btv->vbi_fmt.tvnorm) {
__s32 max_end;
unsigned int i;
@ -388,9 +330,8 @@ int bttv_g_fmt_vbi_cap(struct file *file, void *f, struct v4l2_format *frt)
for (i = 0; i < 2; ++i) {
__s32 new_start;
new_start = frt->fmt.vbi.start[i]
+ tvnorm->vbistart[i]
- fh->vbi_fmt.tvnorm->vbistart[i];
new_start = frt->fmt.vbi.start[i] + tvnorm->vbistart[i]
- btv->vbi_fmt.tvnorm->vbistart[i];
frt->fmt.vbi.start[i] = min(new_start, max_end - 1);
frt->fmt.vbi.count[i] =
@ -430,8 +371,8 @@ void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm)
real_count = ((tvnorm->cropcap.defrect.top >> 1)
- tvnorm->vbistart[0]);
BUG_ON(real_samples_per_line > VBI_BPL);
BUG_ON(real_count > VBI_DEFLINES);
WARN_ON(real_samples_per_line > VBI_BPL);
WARN_ON(real_count > VBI_DEFLINES);
f->tvnorm = tvnorm;

View File

@ -26,7 +26,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-fh.h>
#include <media/videobuf-dma-sg.h>
#include <media/videobuf2-dma-sg.h>
#include <media/tveeprom.h>
#include <media/rc-core.h>
#include <media/i2c/ir-kbd-i2c.h>
@ -142,19 +142,15 @@ struct bttv_geometry {
struct bttv_buffer {
/* common v4l buffer stuff -- must be first */
struct videobuf_buffer vb;
struct vb2_v4l2_buffer vbuf;
struct list_head list;
/* bttv specific */
const struct bttv_format *fmt;
unsigned int tvnorm;
int btformat;
int btswap;
struct bttv_geometry geo;
struct btcx_riscmem top;
struct btcx_riscmem bottom;
struct v4l2_rect crop;
unsigned int vbi_skip[2];
unsigned int vbi_count[2];
};
struct bttv_buffer_set {
@ -176,6 +172,8 @@ struct bttv_vbi_fmt {
};
/* bttv-vbi.c */
extern const struct vb2_ops bttv_vbi_qops;
void bttv_vbi_fmt_reset(struct bttv_vbi_fmt *f, unsigned int norm);
struct bttv_crop {
@ -192,31 +190,6 @@ struct bttv_crop {
__s32 max_scaled_height;
};
struct bttv_fh {
/* This must be the first field in this struct */
struct v4l2_fh fh;
struct bttv *btv;
int resources;
enum v4l2_buf_type type;
/* video capture */
struct videobuf_queue cap;
const struct bttv_format *fmt;
int width;
int height;
/* Application called VIDIOC_S_SELECTION. */
int do_crop;
/* vbi capture */
struct videobuf_queue vbi;
/* Current VBI capture window as seen through this fh (cannot
be global for compatibility with earlier drivers). Protected
by struct bttv.lock and struct bttv_fh.vbi.lock. */
struct bttv_vbi_fmt vbi_fmt;
};
/* ---------------------------------------------------------- */
/* bttv-risc.c */
@ -237,20 +210,27 @@ int bttv_risc_hook(struct bttv *btv, int slot, struct btcx_riscmem *risc,
int bttv_buffer_risc(struct bttv *btv, struct bttv_buffer *buf);
int bttv_buffer_activate_video(struct bttv *btv,
struct bttv_buffer_set *set);
int bttv_buffer_risc_vbi(struct bttv *btv, struct bttv_buffer *buf);
int bttv_buffer_activate_vbi(struct bttv *btv,
struct bttv_buffer *vbi);
void bttv_dma_free(struct videobuf_queue *q, struct bttv *btv,
struct bttv_buffer *buf);
/* ---------------------------------------------------------- */
/* bttv-vbi.c */
/*
* 2048 for compatibility with earlier driver versions. The driver really
* stores 1024 + tvnorm->vbipack * 4 samples per line in the buffer. Note
* tvnorm->vbipack is <= 0xFF (limit of VBIPACK_LO + HI is 0x1FF DWORDs) and
* VBI read()s store a frame counter in the last four bytes of the VBI image.
*/
#define VBI_BPL 2048
#define VBI_DEFLINES 16
int bttv_try_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
int bttv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
int bttv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *f);
extern const struct videobuf_queue_ops bttv_vbi_qops;
/* ---------------------------------------------------------- */
/* bttv-gpio.c */
@ -275,6 +255,8 @@ extern int fini_bttv_i2c(struct bttv *btv);
extern unsigned int bttv_verbose;
extern unsigned int bttv_debug;
extern unsigned int bttv_gpio;
int check_alloc_btres_lock(struct bttv *btv, int bit);
void free_btres_lock(struct bttv *btv, int bits);
extern void bttv_gpio_tracking(struct bttv *btv, char *comment);
#define dprintk(fmt, ...) \
@ -396,7 +378,7 @@ struct bttv {
v4l2_std_id std;
int hue, contrast, bright, saturation;
struct v4l2_framebuffer fbuf;
unsigned int field_count;
__u32 field_count;
/* various options */
int opt_combfilter;
@ -436,7 +418,6 @@ struct bttv {
int loop_irq;
int new_input;
unsigned long cap_ctl;
unsigned long dma_on;
struct timer_list timeout;
struct bttv_suspend_state state;
@ -448,7 +429,25 @@ struct bttv {
unsigned int irq_me;
unsigned int users;
struct bttv_fh init;
struct v4l2_fh fh;
enum v4l2_buf_type type;
enum v4l2_field field;
int field_last;
/* video capture */
struct vb2_queue capq;
const struct bttv_format *fmt;
int width;
int height;
/* vbi capture */
struct vb2_queue vbiq;
struct bttv_vbi_fmt vbi_fmt;
unsigned int vbi_count[2];
/* Application called VIDIOC_S_SELECTION. */
int do_crop;
/* used to make dvb-bt8xx autoloadable */
struct work_struct request_module_wk;
@ -487,6 +486,8 @@ static inline unsigned int bttv_muxsel(const struct bttv *btv,
#endif
void init_irqreg(struct bttv *btv);
#define btwrite(dat,adr) writel((dat), btv->bt848_mmio+(adr))
#define btread(adr) readl(btv->bt848_mmio+(adr))

View File

@ -307,7 +307,7 @@ int cx18_gpio_register(struct cx18 *cx, u32 hw)
void cx18_reset_ir_gpio(void *data)
{
struct cx18 *cx = to_cx18((struct v4l2_device *)data);
struct cx18 *cx = to_cx18(data);
if (cx->card->gpio_i2c_slave_reset.ir_reset_mask == 0)
return;

View File

@ -30,7 +30,7 @@ static void epu_cmd(struct cx18 *cx, u32 sw1)
irqreturn_t cx18_irq_handler(int irq, void *dev_id)
{
struct cx18 *cx = (struct cx18 *)dev_id;
struct cx18 *cx = dev_id;
u32 sw1, sw2, hw2;
sw1 = cx18_read_reg(cx, SW1_INT_STATUS) & cx->sw1_irq_mask;

View File

@ -554,14 +554,14 @@ void cx23885_sram_channel_dump(struct cx23885_dev *dev,
for (i = 0; i < 4; i++) {
risc = cx_read(ch->cmds_start + 4 * (i + 14));
pr_warn("%s: risc%d: ", dev->name, i);
pr_warn("%s: risc%d:", dev->name, i);
cx23885_risc_decode(risc);
}
for (i = 0; i < (64 >> 2); i += n) {
risc = cx_read(ch->ctrl_start + 4 * i);
/* No consideration for bits 63-32 */
pr_warn("%s: (0x%08x) iq %x: ", dev->name,
pr_warn("%s: (0x%08x) iq %x:", dev->name,
ch->ctrl_start + 4 * i, i);
n = cx23885_risc_decode(risc);
for (j = 1; j < n; j++) {
@ -594,7 +594,7 @@ static void cx23885_risc_disasm(struct cx23885_tsport *port,
pr_info("%s: risc disasm: %p [dma=0x%08lx]\n",
dev->name, risc->cpu, (unsigned long)risc->dma);
for (i = 0; i < (risc->size >> 2); i += n) {
pr_info("%s: %04d: ", dev->name, i);
pr_info("%s: %04d:", dev->name, i);
n = cx23885_risc_decode(le32_to_cpu(risc->cpu[i]));
for (j = 1; j < n; j++)
pr_info("%s: %04d: 0x%08x [ arg #%d ]\n",

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