Merge git://git.linuxtv.org/media_stage into media_tree

* git://git.linuxtv.org/media_stage: (216 commits)
  media: v4l2-ctrls-api.c: move ctrl->is_new = 1 to the correct line
  media: Revert "media: saa7146: deprecate hexium_gemini/orion, mxb and ttpci"
  media: Revert "media: av7110: move to staging/media/deprecated/saa7146"
  media: imx-pxp: convert to regmap
  media: imx-pxp: Use non-threaded IRQ
  media: imx-pxp: Introduce pxp_read() and pxp_write() wrappers
  media: imx-pxp: Implement frame size enumeration
  media: imx-pxp: Pass pixel format value to find_format()
  media: imx-pxp: Add media controller support
  media: imx-pxp: Don't set bus_info manually in .querycap()
  media: imx-pxp: Sort headers alphabetically
  media: imx-pxp: add support for i.MX7D
  media: imx-pxp: make data_path_ctrl0 platform dependent
  media: imx-pxp: disable LUT block
  media: imx-pxp: explicitly disable unused blocks
  media: imx-pxp: extract helper function to setup data path
  media: imx-pxp: detect PXP version
  media: dt-bindings: media: fsl-pxp: convert to yaml
  media: imx-mipi-csis: Implement .init_cfg() using .set_fmt()
  media: imx-mipi-csis: Use V4L2 subdev active state
  ...

Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
Mauro Carvalho Chehab 2023-02-15 12:40:21 +01:00
commit 83e0f265aa
244 changed files with 8706 additions and 5335 deletions

View File

@ -340,14 +340,14 @@ and IO24. Monitoring the HPD an 5V lines is not necessary, but it is helpful.
This kernel patch will hook up the cec-gpio driver correctly to
e.g. ``arch/arm/boot/dts/bcm2837-rpi-3-b-plus.dts``::
cec-gpio@7 {
cec@7 {
compatible = "cec-gpio";
cec-gpios = <&gpio 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
hpd-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
v5-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
};
cec-gpio@8 {
cec@8 {
compatible = "cec-gpio";
cec-gpios = <&gpio 8 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
hpd-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>;

View File

@ -1,42 +0,0 @@
* HDMI CEC GPIO driver
The HDMI CEC GPIO module supports CEC implementations where the CEC line
is hooked up to a pull-up GPIO line and - optionally - the HPD line is
hooked up to another GPIO line.
Please note: the maximum voltage for the CEC line is 3.63V, for the HPD and
5V lines it is 5.3V. So you may need some sort of level conversion circuitry
when connecting them to a GPIO line.
Required properties:
- compatible: value must be "cec-gpio".
- cec-gpios: gpio that the CEC line is connected to. The line should be
tagged as open drain.
If the CEC line is associated with an HDMI receiver/transmitter, then the
following property is also required:
- hdmi-phandle - phandle to the HDMI controller, see also cec.txt.
If the CEC line is not associated with an HDMI receiver/transmitter, then
the following property is optional and can be used for debugging HPD changes:
- hpd-gpios: gpio that the HPD line is connected to.
This property is optional and can be used for debugging changes on the 5V line:
- v5-gpios: gpio that the 5V line is connected to.
Example for the Raspberry Pi 3 where the CEC line is connected to
pin 26 aka BCM7 aka CE1 on the GPIO pin header, the HPD line is
connected to pin 11 aka BCM17 and the 5V line is connected to pin
15 aka BCM22 (some level shifter is needed for the HPD and 5V lines!):
#include <dt-bindings/gpio/gpio.h>
cec-gpio {
compatible = "cec-gpio";
cec-gpios = <&gpio 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
hpd-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
v5-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
};

View File

@ -1,8 +0,0 @@
Common bindings for HDMI CEC adapters
- hdmi-phandle: phandle to the HDMI controller.
- needs-hpd: if present the CEC support is only available when the HPD
is high. Some boards only let the CEC pin through if the HPD is high,
for example if there is a level converter that uses the HPD to power
up or down.

View File

@ -2,8 +2,8 @@
# Copyright 2019 BayLibre, SAS
%YAML 1.2
---
$id: "http://devicetree.org/schemas/media/amlogic,meson-gx-ao-cec.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
$id: http://devicetree.org/schemas/media/cec/amlogic,meson-gx-ao-cec.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Amlogic Meson AO-CEC Controller
@ -33,11 +33,8 @@ properties:
interrupts:
maxItems: 1
hdmi-phandle:
description: phandle to the HDMI controller
$ref: /schemas/types.yaml#/definitions/phandle
allOf:
- $ref: cec-common.yaml#
- if:
properties:
compatible:
@ -81,7 +78,7 @@ required:
- clocks
- clock-names
additionalProperties: false
unevaluatedProperties: false
examples:
- |

View File

@ -0,0 +1,28 @@
# SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/cec/cec-common.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: HDMI CEC Adapters Common Properties
maintainers:
- Hans Verkuil <hverkuil@xs4all.nl>
properties:
$nodename:
pattern: "^cec(@[0-9a-f]+|-[0-9]+)?$"
hdmi-phandle:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Phandle to the HDMI controller.
needs-hpd:
type: boolean
description:
The CEC support is only available when the HPD is high. Some boards only
let the CEC pin through if the HPD is high, for example if there is a
level converter that uses the HPD to power up or down.
additionalProperties: true

View File

@ -0,0 +1,74 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/cec/cec-gpio.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: HDMI CEC GPIO
maintainers:
- Hans Verkuil <hverkuil-cisco@xs4all.nl>
description: |
The HDMI CEC GPIO module supports CEC implementations where the CEC line is
hooked up to a pull-up GPIO line and - optionally - the HPD line is hooked up
to another GPIO line.
Please note:: the maximum voltage for the CEC line is 3.63V, for the HPD and
5V lines it is 5.3V. So you may need some sort of level conversion
circuitry when connecting them to a GPIO line.
properties:
compatible:
const: cec-gpio
cec-gpios:
maxItems: 1
description:
GPIO that the CEC line is connected to. The line should be tagged as open
drain.
hpd-gpios:
maxItems: 1
description:
GPIO that the HPD line is connected to. Used for debugging HPD changes
when the CEC line is not associated with an HDMI receiver/transmitter.
v5-gpios:
maxItems: 1
description:
GPIO that the 5V line is connected to. Used for debugging changes on the
5V line.
required:
- compatible
- cec-gpios
allOf:
- $ref: cec-common.yaml#
- if:
required:
- hdmi-phandle
then:
properties:
hpd-gpios: false
- if:
required:
- hpd-gpios
then:
properties:
hdmi-phandle: false
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
cec {
compatible = "cec-gpio";
cec-gpios = <&gpio 7 (GPIO_ACTIVE_HIGH|GPIO_OPEN_DRAIN)>;
hpd-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
v5-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
};

View File

@ -0,0 +1,58 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/cec/nvidia,tegra114-cec.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: NVIDIA Tegra HDMI CEC
maintainers:
- Hans Verkuil <hverkuil-cisco@xs4all.nl>
allOf:
- $ref: cec-common.yaml#
properties:
compatible:
enum:
- nvidia,tegra114-cec
- nvidia,tegra124-cec
- nvidia,tegra210-cec
clocks:
maxItems: 1
clock-names:
items:
- const: cec
interrupts:
maxItems: 1
reg:
maxItems: 1
required:
- compatible
- clocks
- clock-names
- hdmi-phandle
- interrupts
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/tegra124-car.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
cec@70015000 {
compatible = "nvidia,tegra124-cec";
reg = <0x70015000 0x00001000>;
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA124_CLK_CEC>;
clock-names = "cec";
status = "disabled";
hdmi-phandle = <&hdmi>;
};

View File

@ -0,0 +1,66 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/cec/samsung,s5p-cec.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Samsung S5PV210 and Exynos HDMI CEC
maintainers:
- Krzysztof Kozlowski <krzk@kernel.org>
- Marek Szyprowski <m.szyprowski@samsung.com>
allOf:
- $ref: cec-common.yaml#
properties:
compatible:
const: samsung,s5p-cec
clocks:
maxItems: 1
clock-names:
items:
- const: hdmicec
interrupts:
maxItems: 1
samsung,syscon-phandle:
$ref: /schemas/types.yaml#/definitions/phandle
description:
Phandle to PMU system controller interface
reg:
maxItems: 1
required:
- compatible
- clocks
- clock-names
- hdmi-phandle
- interrupts
- samsung,syscon-phandle
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/exynos5420.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
cec@101b0000 {
compatible = "samsung,s5p-cec";
reg = <0x101B0000 0x200>;
clocks = <&clock CLK_HDMI_CEC>;
clock-names = "hdmicec";
interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
hdmi-phandle = <&hdmi>;
needs-hpd;
pinctrl-names = "default";
pinctrl-0 = <&hdmi_cec>;
samsung,syscon-phandle = <&pmu_system_controller>;
};

View File

@ -0,0 +1,66 @@
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/cec/st,stih-cec.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: STMicroelectronics STIH4xx HDMI CEC
maintainers:
- Alain Volmat <alain.volmat@foss.st.com>
allOf:
- $ref: cec-common.yaml#
properties:
compatible:
const: st,stih-cec
clocks:
maxItems: 1
clock-names:
items:
- const: cec-clk
interrupts:
maxItems: 1
interrupt-names:
items:
- const: cec-irq
resets:
maxItems: 1
reg:
maxItems: 1
required:
- compatible
- clocks
- hdmi-phandle
- interrupts
- resets
- reg
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/stih407-resets.h>
cec@94a087c {
compatible = "st,stih-cec";
reg = <0x94a087c 0x64>;
clocks = <&clk_sysin>;
clock-names = "cec-clk";
hdmi-phandle = <&sti_hdmi>;
interrupts = <GIC_SPI 140 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "cec-irq";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_cec0_default>;
resets = <&softreset STIH407_LPM_SOFTRESET>;
};

View File

@ -0,0 +1,53 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/cec/st,stm32-cec.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: STMicroelectronics STM32 CEC
maintainers:
- Yannick Fertre <yannick.fertre@foss.st.com>
properties:
compatible:
const: st,stm32-cec
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
items:
- description: Module Clock
- description: Bus Clock
clock-names:
items:
- const: cec
- const: hdmi-cec
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
additionalProperties: false
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
cec: cec@40006c00 {
compatible = "st,stm32-cec";
reg = <0x40006c00 0x400>;
interrupts = <GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&rcc CEC_K>, <&clk_lse>;
clock-names = "cec", "hdmi-cec";
};
...

View File

@ -0,0 +1,88 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/fsl,imx6ull-pxp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Freescale Pixel Pipeline
maintainers:
- Philipp Zabel <p.zabel@pengutronix.de>
- Michael Tretter <m.tretter@pengutronix.de>
description:
The Pixel Pipeline (PXP) is a memory-to-memory graphics processing engine
that supports scaling, colorspace conversion, alpha blending, rotation, and
pixel conversion via lookup table. Different versions are present on various
i.MX SoCs from i.MX23 to i.MX7.
properties:
compatible:
oneOf:
- enum:
- fsl,imx6ul-pxp
- fsl,imx6ull-pxp
- fsl,imx7d-pxp
- items:
- enum:
- fsl,imx6sll-pxp
- fsl,imx6sx-pxp
- const: fsl,imx6ull-pxp
reg:
maxItems: 1
interrupts:
minItems: 1
maxItems: 2
clocks:
maxItems: 1
clock-names:
const: axi
power-domains:
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
allOf:
- if:
properties:
compatible:
contains:
enum:
- fsl,imx6sx-pxp
- fsl,imx6ul-pxp
then:
properties:
interrupts:
maxItems: 1
else:
properties:
interrupts:
minItems: 2
maxItems: 2
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/imx6ul-clock.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
pxp: pxp@21cc000 {
compatible = "fsl,imx6ull-pxp";
reg = <0x021cc000 0x4000>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "axi";
clocks = <&clks IMX6UL_CLK_PXP>;
};

View File

@ -1,26 +0,0 @@
Freescale Pixel Pipeline
========================
The Pixel Pipeline (PXP) is a memory-to-memory graphics processing engine
that supports scaling, colorspace conversion, alpha blending, rotation, and
pixel conversion via lookup table. Different versions are present on various
i.MX SoCs from i.MX23 to i.MX7.
Required properties:
- compatible: should be "fsl,<soc>-pxp", where SoC can be one of imx23, imx28,
imx6dl, imx6sl, imx6sll, imx6ul, imx6sx, imx6ull, or imx7d.
- reg: the register base and size for the device registers
- interrupts: the PXP interrupt, two interrupts for imx6ull and imx7d.
- clock-names: should be "axi"
- clocks: the PXP AXI clock
Example:
pxp@21cc000 {
compatible = "fsl,imx6ull-pxp";
reg = <0x021cc000 0x4000>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
clock-names = "axi";
clocks = <&clks IMX6UL_CLK_PXP>;
};

View File

@ -1,8 +0,0 @@
Asahi Kasei Microdevices AK7375 voice coil lens driver
AK7375 is a camera voice coil lens.
Mandatory properties:
- compatible: "asahi-kasei,ak7375"
- reg: I2C slave address

View File

@ -0,0 +1,52 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/asahi-kasei,ak7375.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Asahi Kasei Microdevices AK7375 voice coil lens actuator
maintainers:
- Tianshu Qiu <tian.shu.qiu@intel.com>
description:
AK7375 is a voice coil motor (VCM) camera lens actuator that
is controlled over I2C.
properties:
compatible:
const: asahi-kasei,ak7375
reg:
maxItems: 1
vdd-supply:
description: VDD supply
vio-supply:
description: I/O pull-up supply
required:
- compatible
- reg
- vdd-supply
- vio-supply
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
ak7375: camera-lens@c {
compatible = "asahi-kasei,ak7375";
reg = <0x0c>;
vdd-supply = <&vreg_l23a_2p8>;
vio-supply = <&vreg_lvs1a_1p8>;
};
};
...

View File

@ -13,6 +13,9 @@ description:
The Chrontel CH7322 is a discrete HDMI-CEC controller. It is
programmable through I2C and drives a single CEC line.
allOf:
- $ref: /schemas/media/cec/cec-common.yaml#
properties:
compatible:
const: chrontel,ch7322
@ -40,16 +43,12 @@ properties:
if in auto mode.
maxItems: 1
# see ../cec.txt
hdmi-phandle:
description: phandle to the HDMI controller
required:
- compatible
- reg
- interrupts
additionalProperties: false
unevaluatedProperties: false
examples:
- |
@ -58,7 +57,7 @@ examples:
i2c {
#address-cells = <1>;
#size-cells = <0>;
ch7322@75 {
cec@75 {
compatible = "chrontel,ch7322";
reg = <0x75>;
interrupts = <47 IRQ_TYPE_EDGE_RISING>;

View File

@ -0,0 +1,93 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/ovti,ov5670.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Omnivision OV5670 5 Megapixels raw image sensor
maintainers:
- Jacopo Mondi <jacopo.mondi@ideasonboard.com>
description: |-
The OV5670 is a 5 Megapixels raw image sensor which provides images in 10-bits
RAW BGGR Bayer format on a 2 data lanes MIPI CSI-2 serial interface and is
controlled through an I2C compatible control bus.
properties:
compatible:
const: ovti,ov5670
reg:
maxItems: 1
clocks:
description: System clock. From 6 to 27 MHz.
maxItems: 1
powerdown-gpios:
description: Reference to the GPIO connected to the PWDNB pin. Active low.
reset-gpios:
description: Reference to the GPIO connected to the XSHUTDOWN pin. Active low.
maxItems: 1
avdd-supply:
description: Analog circuit power. Typically 2.8V.
dvdd-supply:
description: Digital circuit power. Typically 1.2V.
dovdd-supply:
description: Digital I/O circuit power. Typically 2.8V or 1.8V.
port:
$ref: /schemas/graph.yaml#/$defs/port-base
additionalProperties: false
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
additionalProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 2
items:
enum: [1, 2]
clock-noncontinuous: true
remote-endpoint: true
required:
- compatible
- reg
- clocks
- port
additionalProperties: false
examples:
- |
i2c {
#address-cells = <1>;
#size-cells = <0>;
ov5670: sensor@36 {
compatible = "ovti,ov5670";
reg = <0x36>;
clocks = <&sensor_xclk>;
port {
ov5670_ep: endpoint {
remote-endpoint = <&csi_ep>;
data-lanes = <1 2>;
clock-noncontinuous;
};
};
};
};
...

View File

@ -0,0 +1,122 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
# Copyright (c) 2022 Theobroma Systems Design und Consulting GmbH
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/ovti,ov5675.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Omnivision OV5675 CMOS Sensor
maintainers:
- Quentin Schulz <quentin.schulz@theobroma-systems.com>
allOf:
- $ref: /schemas/media/video-interface-devices.yaml#
description: |
The Omnivision OV5675 is a high performance, 1/5-inch, 5 megapixel, CMOS
image sensor that delivers 2592x1944 at 30fps. It provides full-frame,
sub-sampled, and windowed 10-bit MIPI images in various formats via the
Serial Camera Control Bus (SCCB) interface.
This chip is programmable through I2C and two-wire SCCB. The sensor output
is available via CSI-2 serial data output (up to 2-lane).
properties:
compatible:
const: ovti,ov5675
reg:
maxItems: 1
clocks:
description:
System input clock (aka XVCLK). From 6 to 27 MHz.
maxItems: 1
dovdd-supply:
description:
Digital I/O voltage supply, 1.8 volts.
avdd-supply:
description:
Analog voltage supply, 2.8 volts.
dvdd-supply:
description:
Digital core voltage supply, 1.2 volts.
reset-gpios:
description:
The phandle and specifier for the GPIO that controls sensor reset.
This corresponds to the hardware pin XSHUTDN which is physically
active low.
maxItems: 1
port:
$ref: /schemas/graph.yaml#/$defs/port-base
additionalProperties: false
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 2
# Supports max data transfer of 900 Mbps per lane
link-frequencies: true
required:
- compatible
- reg
- clocks
- dovdd-supply
- avdd-supply
- dvdd-supply
- port
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/clock/px30-cru.h>
#include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/pinctrl/rockchip.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
ov5675: camera@36 {
compatible = "ovti,ov5675";
reg = <0x36>;
reset-gpios = <&gpio2 RK_PB1 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&cif_clkout_m0>;
clocks = <&cru SCLK_CIF_OUT>;
assigned-clocks = <&cru SCLK_CIF_OUT>;
assigned-clock-rates = <19200000>;
avdd-supply = <&vcc_1v8>;
dvdd-supply = <&vcc_1v2>;
dovdd-supply = <&vcc_2v8>;
rotation = <90>;
orientation = <0>;
port {
ucam_out: endpoint {
remote-endpoint = <&mipi_in_ucam>;
data-lanes = <1 2>;
link-frequencies = /bits/ 64 <450000000>;
};
};
};
};
...

View File

@ -0,0 +1,106 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/ovti,ov8858.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: OmniVision OV8858 Image Sensor
maintainers:
- Jacopo Mondi <jacopo.mondi@ideasonboard.com>
- Nicholas Roth <nicholas@rothemail.net>
description: |
The OmniVision OV8858 is a color CMOS 8 Megapixels (3264x2448) image sensor
controlled through an I2C-compatible SCCB bus. The sensor transmits images
on a MIPI CSI-2 output interface with up to 4 data lanes.
properties:
compatible:
const: ovti,ov8858
reg:
maxItems: 1
clocks:
maxItems: 1
description: XVCLK external clock
clock-names:
const: xvclk
dvdd-supply:
description: Digital Domain Power Supply
avdd-supply:
description: Analog Domain Power Supply
dovdd-supply:
description: I/O Domain Power Supply
powerdown-gpios:
description: PWDNB powerdown GPIO (active low)
reset-gpios:
maxItems: 1
description: XSHUTDN reset GPIO (active low)
port:
description: MIPI CSI-2 transmitter port
$ref: /schemas/graph.yaml#/$defs/port-base
additionalProperties: false
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
required:
- data-lanes
required:
- compatible
- reg
- clocks
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/pinctrl/rockchip.h>
#include <dt-bindings/clock/rk3399-cru.h>
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
ov8858: camera@36 {
compatible = "ovti,ov8858";
reg = <0x36>;
clocks = <&cru SCLK_CIF_OUT>;
clock-names = "xvclk";
assigned-clocks = <&cru SCLK_CIF_OUT>;
assigned-clock-rates = <24000000>;
dovdd-supply = <&vcc1v8_dvp>;
reset-gpios = <&gpio1 RK_PA4 GPIO_ACTIVE_LOW>;
powerdown-gpios = <&gpio2 RK_PB4 GPIO_ACTIVE_LOW>;
port {
ucam_out: endpoint {
remote-endpoint = <&mipi_in_ucam>;
data-lanes = <1 2 3 4>;
};
};
};
};
...

View File

@ -0,0 +1,106 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/sony,imx296.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sony IMX296 1/2.8-Inch CMOS Image Sensor
maintainers:
- Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
- Laurent Pinchart <laurent.pinchart@ideasonboard.com>
description: |-
The Sony IMX296 is a 1/2.9-Inch active pixel type CMOS Solid-state image
sensor with square pixel array and 1.58 M effective pixels. This chip
features a global shutter with variable charge-integration time. It is
programmable through I2C and 4-wire interfaces. The sensor output is
available via CSI-2 serial data output (1 Lane).
properties:
compatible:
enum:
- sony,imx296
- sony,imx296ll
- sony,imx296lq
description:
The IMX296 sensor exists in two different models, a colour variant
(IMX296LQ) and a monochrome variant (IMX296LL). The device exposes the
model through registers, allowing for auto-detection with a common
"sony,imx296" compatible string. However, some camera modules disable the
ability to read the sensor model register, which disables this feature.
In those cases, the exact model needs to be specified as "sony,imx296ll"
or "sony,imx296lq".
reg:
maxItems: 1
clocks:
maxItems: 1
clock-names:
description: Input clock (37.125 MHz, 54 MHz or 74.25 MHz)
items:
- const: inck
avdd-supply:
description: Analog power supply (3.3V)
dvdd-supply:
description: Digital power supply (1.2V)
ovdd-supply:
description: Interface power supply (1.8V)
reset-gpios:
description: Sensor reset (XCLR) GPIO
maxItems: 1
port:
$ref: /schemas/graph.yaml#/properties/port
required:
- compatible
- reg
- clocks
- clock-names
- avdd-supply
- dvdd-supply
- ovdd-supply
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
imx296: camera-sensor@1a {
compatible = "sony,imx296";
reg = <0x1a>;
pinctrl-names = "default";
pinctrl-0 = <&camera_rear_default>;
clocks = <&gcc 90>;
clock-names = "inck";
avdd-supply = <&camera_vdda_3v3>;
dvdd-supply = <&camera_vddd_1v2>;
ovdd-supply = <&camera_vddo_1v8>;
reset-gpios = <&msmgpio 35 GPIO_ACTIVE_LOW>;
port {
imx296_ep: endpoint {
remote-endpoint = <&csiphy0_ep>;
};
};
};
};
...

View File

@ -0,0 +1,122 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/i2c/sony,imx415.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Sony IMX415 CMOS Image Sensor
maintainers:
- Michael Riesch <michael.riesch@wolfvision.net>
description: |-
The Sony IMX415 is a diagonal 6.4 mm (Type 1/2.8) CMOS active pixel type
solid-state image sensor with a square pixel array and 8.46 M effective
pixels. This chip operates with analog 2.9 V, digital 1.1 V, and interface
1.8 V triple power supply, and has low power consumption.
The IMX415 is programmable through I2C interface. The sensor output is
available via CSI-2 serial data output (two or four lanes).
allOf:
- $ref: ../video-interface-devices.yaml#
properties:
compatible:
const: sony,imx415
reg:
maxItems: 1
clocks:
description: Input clock (24 MHz, 27 MHz, 37.125 MHz, 72 MHz or 74.25 MHz)
maxItems: 1
avdd-supply:
description: Analog power supply (2.9 V)
dvdd-supply:
description: Digital power supply (1.1 V)
ovdd-supply:
description: Interface power supply (1.8 V)
reset-gpios:
description: Sensor reset (XCLR) GPIO
maxItems: 1
flash-leds: true
lens-focus: true
orientation: true
rotation: true
port:
$ref: /schemas/graph.yaml#/$defs/port-base
properties:
endpoint:
$ref: /schemas/media/video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
oneOf:
- items:
- const: 1
- const: 2
- items:
- const: 1
- const: 2
- const: 3
- const: 4
required:
- data-lanes
- link-frequencies
required:
- endpoint
required:
- compatible
- reg
- clocks
- avdd-supply
- dvdd-supply
- ovdd-supply
- port
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
imx415: camera-sensor@1a {
compatible = "sony,imx415";
reg = <0x1a>;
avdd-supply = <&vcc2v9_cam>;
clocks = <&clock_cam>;
dvdd-supply = <&vcc1v1_cam>;
lens-focus = <&vcm>;
orientation = <2>;
ovdd-supply = <&vcc1v8_cam>;
reset-gpios = <&gpio_expander 14 GPIO_ACTIVE_LOW>;
rotation = <180>;
port {
imx415_ep: endpoint {
data-lanes = <1 2 3 4>;
link-frequencies = /bits/ 64 <445500000>;
remote-endpoint = <&mipi_in>;
};
};
};
};
...

View File

@ -1,36 +0,0 @@
* Samsung HDMI CEC driver
The HDMI CEC module is present is Samsung SoCs and its purpose is to
handle communication between HDMI connected devices over the CEC bus.
Required properties:
- compatible : value should be following
"samsung,s5p-cec"
- reg : Physical base address of the IP registers and length of memory
mapped region.
- interrupts : HDMI CEC interrupt number to the CPU.
- clocks : from common clock binding: handle to HDMI CEC clock.
- clock-names : from common clock binding: must contain "hdmicec",
corresponding to entry in the clocks property.
- samsung,syscon-phandle - phandle to the PMU system controller
- hdmi-phandle - phandle to the HDMI controller, see also cec.txt.
Optional:
- needs-hpd : if present the CEC support is only available when the HPD
is high. See cec.txt for more details.
Example:
hdmicec: cec@100b0000 {
compatible = "samsung,s5p-cec";
reg = <0x100B0000 0x200>;
interrupts = <0 114 0>;
clocks = <&clock CLK_HDMI_CEC>;
clock-names = "hdmicec";
samsung,syscon-phandle = <&pmu_system_controller>;
hdmi-phandle = <&hdmi>;
pinctrl-names = "default";
pinctrl-0 = <&hdmi_cec>;
};

View File

@ -1,27 +0,0 @@
STMicroelectronics STIH4xx HDMI CEC driver
Required properties:
- compatible : value should be "st,stih-cec"
- reg : Physical base address of the IP registers and length of memory
mapped region.
- clocks : from common clock binding: handle to HDMI CEC clock
- interrupts : HDMI CEC interrupt number to the CPU.
- pinctrl-names: Contains only one value - "default"
- pinctrl-0: Specifies the pin control groups used for CEC hardware.
- resets: Reference to a reset controller
- hdmi-phandle: Phandle to the HDMI controller, see also cec.txt.
Example for STIH407:
sti-cec@94a087c {
compatible = "st,stih-cec";
reg = <0x94a087c 0x64>;
clocks = <&clk_sysin>;
clock-names = "cec-clk";
interrupts = <GIC_SPI 140 IRQ_TYPE_NONE>;
interrupt-names = "cec-irq";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_cec0_default>;
resets = <&softreset STIH407_LPM_SOFTRESET>;
hdmi-phandle = <&hdmi>;
};

View File

@ -1,27 +0,0 @@
* Tegra HDMI CEC hardware
The HDMI CEC module is present in Tegra SoCs and its purpose is to
handle communication between HDMI connected devices over the CEC bus.
Required properties:
- compatible : value should be one of the following:
"nvidia,tegra114-cec"
"nvidia,tegra124-cec"
"nvidia,tegra210-cec"
- reg : Physical base address of the IP registers and length of memory
mapped region.
- interrupts : HDMI CEC interrupt number to the CPU.
- clocks : from common clock binding: handle to HDMI CEC clock.
- clock-names : from common clock binding: must contain "cec",
corresponding to the entry in the clocks property.
- hdmi-phandle : phandle to the HDMI controller, see also cec.txt.
Example:
cec@70015000 {
compatible = "nvidia,tegra124-cec";
reg = <0x0 0x70015000 0x0 0x00001000>;
interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA124_CLK_CEC>;
clock-names = "cec";
};

View File

@ -232,12 +232,10 @@ prevent link states from being modified during streaming by calling
The function will mark all the pads which are part of the pipeline as streaming.
The struct media_pipeline instance pointed to by
the pipe argument will be stored in every pad in the pipeline.
Drivers should embed the struct media_pipeline
in higher-level pipeline structures and can then access the
pipeline through the struct media_pad
pipe field.
The struct media_pipeline instance pointed to by the pipe argument will be
stored in every pad in the pipeline. Drivers should embed the struct
media_pipeline in higher-level pipeline structures and can then access the
pipeline through the struct media_pad pipe field.
Calls to :c:func:`media_pipeline_start()` can be nested.
The pipeline pointer must be identical for all nested calls to the function.

View File

@ -23,7 +23,7 @@ proprietary mode.
More details on the ASPEED video hardware operations can be found in
*chapter 6.2.16 KVM Video Driver* of SDK_User_Guide which available on
AspeedTech-BMC/openbmc/releases.
`github <https://github.com/AspeedTech-BMC/openbmc/releases/>`__.
The ASPEED video driver implements the following driver-specific control:

View File

@ -271,7 +271,7 @@ please make a proposal on the linux-media mailing list.
The implementation is based on AST2600 A3 datasheet, revision 0.9, which
is not publicly available. Or you can reference Video stream data format
ASPEED mode compression of SDK_User_Guide which available on
AspeedTech-BMC/openbmc/releases.
`github <https://github.com/AspeedTech-BMC/openbmc/releases/>`__.
Decoder's implementation can be found here,
`aspeed_codec <https://github.com/AspeedTech-BMC/aspeed_codec/>`__

View File

@ -2872,7 +2872,7 @@ M: Marek Szyprowski <m.szyprowski@samsung.com>
L: linux-samsung-soc@vger.kernel.org
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/s5p-cec.txt
F: Documentation/devicetree/bindings/media/cec/samsung,s5p-cec.yaml
F: drivers/media/cec/platform/s5p/
ARM/SAMSUNG S5P SERIES JPEG CODEC SUPPORT
@ -3005,7 +3005,7 @@ M: Hans Verkuil <hverkuil-cisco@xs4all.nl>
L: linux-tegra@vger.kernel.org
L: linux-media@vger.kernel.org
S: Maintained
F: Documentation/devicetree/bindings/media/tegra-cec.txt
F: Documentation/devicetree/bindings/media/cec/nvidia,tegra114-cec.yaml
F: drivers/media/cec/platform/tegra/
ARM/TESLA FSD SoC SUPPORT
@ -3228,7 +3228,7 @@ M: Tianshu Qiu <tian.shu.qiu@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ak7375.txt
F: Documentation/devicetree/bindings/media/i2c/asahi-kasei,ak7375.yaml
F: drivers/media/i2c/ak7375.c
ASAHI KASEI AK8974 DRIVER
@ -4837,7 +4837,7 @@ S: Supported
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
F: Documentation/ABI/testing/debugfs-cec-error-inj
F: Documentation/devicetree/bindings/media/cec.txt
F: Documentation/devicetree/bindings/media/cec/cec-common.yaml
F: Documentation/driver-api/media/cec-core.rst
F: Documentation/userspace-api/media/cec
F: drivers/media/cec/
@ -4853,7 +4853,7 @@ L: linux-media@vger.kernel.org
S: Supported
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/cec-gpio.txt
F: Documentation/devicetree/bindings/media/cec/cec-gpio.yaml
F: drivers/media/cec/platform/cec-gpio/
CELL BROADBAND ENGINE ARCHITECTURE
@ -13572,7 +13572,7 @@ L: linux-amlogic@lists.infradead.org
S: Supported
W: http://linux-meson.com/
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/amlogic,meson-gx-ao-cec.yaml
F: Documentation/devicetree/bindings/media/cec/amlogic,meson-gx-ao-cec.yaml
F: drivers/media/cec/platform/meson/ao-cec-g12a.c
F: drivers/media/cec/platform/meson/ao-cec.c
@ -15467,6 +15467,7 @@ M: Chiranjeevi Rapolu <chiranjeevi.rapolu@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov5670.yaml
F: drivers/media/i2c/ov5670.c
OMNIVISION OV5675 SENSOR DRIVER
@ -15474,6 +15475,7 @@ M: Shawn Tu <shawnx.tu@intel.com>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov5675.yaml
F: drivers/media/i2c/ov5675.c
OMNIVISION OV5693 SENSOR DRIVER
@ -15523,6 +15525,15 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ov8856.yaml
F: drivers/media/i2c/ov8856.c
OMNIVISION OV8858 SENSOR DRIVER
M: Jacopo Mondi <jacopo.mondi@ideasonboard.com>
M: Nicholas Roth <nicholas@rothemail.net>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/ovti,ov8858.yaml
F: drivers/media/i2c/ov8858.c
OMNIVISION OV9282 SENSOR DRIVER
M: Paul J. Murphy <paul.j.murphy@intel.com>
M: Daniele Alessandrelli <daniele.alessandrelli@intel.com>
@ -18403,7 +18414,9 @@ M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: drivers/staging/media/deprecated/saa7146/
F: drivers/media/common/saa7146/
F: drivers/media/pci/saa7146/
F: include/media/drv-intf/saa7146*
SAFESETID SECURITY MODULE
M: Micah Morton <mortonm@chromium.org>
@ -19472,6 +19485,15 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx290.yaml
F: drivers/media/i2c/imx290.c
SONY IMX296 SENSOR DRIVER
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
M: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx296.yaml
F: drivers/media/i2c/imx296.c
SONY IMX319 SENSOR DRIVER
M: Bingbu Cao <bingbu.cao@intel.com>
L: linux-media@vger.kernel.org
@ -19513,6 +19535,14 @@ T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx412.yaml
F: drivers/media/i2c/imx412.c
SONY IMX415 SENSOR DRIVER
M: Michael Riesch <michael.riesch@wolfvision.net>
L: linux-media@vger.kernel.org
S: Maintained
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/i2c/sony,imx415.yaml
F: drivers/media/i2c/imx415.c
SONY MEMORYSTICK SUBSYSTEM
M: Maxim Levitsky <maximlevitsky@gmail.com>
M: Alex Dubov <oakad@yahoo.com>
@ -19951,7 +19981,7 @@ F: sound/soc/sti/
STI CEC DRIVER
M: Alain Volmat <alain.volmat@foss.st.com>
S: Maintained
F: Documentation/devicetree/bindings/media/stih-cec.txt
F: Documentation/devicetree/bindings/media/cec/st,stih-cec.yaml
F: drivers/media/cec/platform/sti/
STK1160 USB VIDEO CAPTURE DRIVER

View File

@ -22,6 +22,7 @@ config VIDEO_TVEEPROM
depends on I2C
source "drivers/media/common/b2c2/Kconfig"
source "drivers/media/common/saa7146/Kconfig"
source "drivers/media/common/siano/Kconfig"
source "drivers/media/common/v4l2-tpg/Kconfig"
source "drivers/media/common/videobuf2/Kconfig"

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-y += b2c2/ siano/ v4l2-tpg/ videobuf2/
obj-y += b2c2/ saa7146/ siano/ v4l2-tpg/ videobuf2/
# Please keep it alphabetically sorted by Kconfig name
# (e. g. LC_ALL=C sort Makefile)

View File

@ -8,8 +8,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <media/drv-intf/saa7146.h>
#include <linux/module.h>
#include "saa7146.h"
static int saa7146_num;

View File

@ -1,8 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-only
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <media/drv-intf/saa7146_vv.h>
#include <linux/module.h>
#include "saa7146_vv.h"
/****************************************************************************/
/* resource management functions, shamelessly stolen from saa7134 driver */

View File

@ -3,7 +3,7 @@
#include <linux/kernel.h>
#include <linux/export.h>
#include "saa7146_vv.h"
#include <media/drv-intf/saa7146_vv.h>
static void calculate_output_format_register(struct saa7146_dev* saa, u32 palette, u32* clip_format)
{

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include "saa7146_vv.h"
#include <media/drv-intf/saa7146_vv.h>
static u32 saa7146_i2c_func(struct i2c_adapter *adapter)
{

View File

@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include "saa7146_vv.h"
#include <media/drv-intf/saa7146_vv.h>
static int vbi_pixel_to_capture = 720 * 2;

View File

@ -1,10 +1,10 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
#include <media/drv-intf/saa7146_vv.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ctrls.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "saa7146_vv.h"
static int max_memory = 32;

View File

@ -502,27 +502,11 @@ static void __vb2_free_mem(struct vb2_queue *q, unsigned int buffers)
* related information, if no buffers are left return the queue to an
* uninitialized state. Might be called even if the queue has already been freed.
*/
static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
{
unsigned int buffer;
/*
* Sanity check: when preparing a buffer the queue lock is released for
* a short while (see __buf_prepare for the details), which would allow
* a race with a reqbufs which can call this function. Removing the
* buffers from underneath __buf_prepare is obviously a bad idea, so we
* check if any of the buffers is in the state PREPARING, and if so we
* just return -EAGAIN.
*/
for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
++buffer) {
if (q->bufs[buffer] == NULL)
continue;
if (q->bufs[buffer]->state == VB2_BUF_STATE_PREPARING) {
dprintk(q, 1, "preparing buffers, cannot free\n");
return -EAGAIN;
}
}
lockdep_assert_held(&q->mmap_lock);
/* Call driver-provided cleanup function for each buffer, if provided */
for (buffer = q->num_buffers - buffers; buffer < q->num_buffers;
@ -616,7 +600,6 @@ static int __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
q->memory = VB2_MEMORY_UNKNOWN;
INIT_LIST_HEAD(&q->queued_list);
}
return 0;
}
bool vb2_buffer_in_use(struct vb2_queue *q, struct vb2_buffer *vb)
@ -798,10 +781,8 @@ int vb2_core_reqbufs(struct vb2_queue *q, enum vb2_memory memory,
* queued without ever calling STREAMON.
*/
__vb2_queue_cancel(q);
ret = __vb2_queue_free(q, q->num_buffers);
__vb2_queue_free(q, q->num_buffers);
mutex_unlock(&q->mmap_lock);
if (ret)
return ret;
/*
* In case of REQBUFS(0) return immediately without calling

View File

@ -2162,11 +2162,11 @@ int cxd2880_tnrdmd_check_internal_cpu_status(struct cxd2880_tnrdmd
else
*task_completed = 0;
return ret;
return 0;
}
if (cpu_status != 0) {
*task_completed = 0;
return ret;
return 0;
}
ret = cxd2880_tnrdmd_mon_internal_cpu_status_sub(tnr_dmd, &cpu_status);

View File

@ -833,12 +833,12 @@ int cxd2880_tnrdmd_dvbt_check_demod_lock(struct cxd2880_tnrdmd
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
return 0;
}
if (sync_stat == 6) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
return ret;
return 0;
}
ret =
@ -854,7 +854,7 @@ int cxd2880_tnrdmd_dvbt_check_demod_lock(struct cxd2880_tnrdmd
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
return 0;
}
int cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd
@ -893,15 +893,15 @@ int cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
return 0;
}
if (ts_lock) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
return ret;
return 0;
} else if (!unlock_detected) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
return 0;
}
ret =
@ -915,5 +915,5 @@ int cxd2880_tnrdmd_dvbt_check_ts_lock(struct cxd2880_tnrdmd
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
return 0;
}

View File

@ -1024,12 +1024,12 @@ int cxd2880_tnrdmd_dvbt2_check_demod_lock(struct cxd2880_tnrdmd
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
return 0;
}
if (sync_stat == 6) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
return ret;
return 0;
}
ret =
@ -1045,7 +1045,7 @@ int cxd2880_tnrdmd_dvbt2_check_demod_lock(struct cxd2880_tnrdmd
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
return 0;
}
int cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd
@ -1084,15 +1084,15 @@ int cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
return 0;
}
if (ts_lock) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_LOCKED;
return ret;
return 0;
} else if (!unlock_detected) {
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
return 0;
}
ret =
@ -1106,7 +1106,7 @@ int cxd2880_tnrdmd_dvbt2_check_ts_lock(struct cxd2880_tnrdmd
else
*lock = CXD2880_TNRDMD_LOCK_RESULT_NOTDETECT;
return ret;
return 0;
}
int cxd2880_tnrdmd_dvbt2_set_plp_cfg(struct cxd2880_tnrdmd

View File

@ -9539,7 +9539,8 @@ ctrl_get_qam_sig_quality(struct drx_demod_instance *demod)
qam_sl_sig_power = DRXJ_QAM_SL_SIG_POWER_QAM256 << 2;
break;
default:
return -EIO;
rc = -EIO;
goto rw_error;
}
/* ------------------------------ */
@ -10916,7 +10917,8 @@ ctrl_set_standard(struct drx_demod_instance *demod, enum drx_standard *standard)
break;
case DRX_STANDARD_AUTO:
default:
return -EINVAL;
rc = -EINVAL;
goto rw_error;
}
/*
@ -11463,7 +11465,8 @@ static int drxj_open(struct drx_demod_instance *demod)
if (DRX_ISPOWERDOWNMODE(demod->my_common_attr->current_power_mode)) {
pr_err("Should powerup before loading the firmware.");
return -EINVAL;
rc = -EINVAL;
goto rw_error;
}
rc = drx_ctrl_u_code(demod, &ucode_info, UCODE_UPLOAD);

View File

@ -1498,6 +1498,7 @@ static int mb86a16_send_diseqc_msg(struct dvb_frontend *fe,
struct dvb_diseqc_master_cmd *cmd)
{
struct mb86a16_state *state = fe->demodulator_priv;
int ret = -EREMOTEIO;
int i;
u8 regs;
@ -1510,8 +1511,10 @@ static int mb86a16_send_diseqc_msg(struct dvb_frontend *fe,
regs = 0x18;
if (cmd->msg_len > 5 || cmd->msg_len < 4)
return -EINVAL;
if (cmd->msg_len > 5 || cmd->msg_len < 4) {
ret = -EINVAL;
goto err;
}
for (i = 0; i < cmd->msg_len; i++) {
if (mb86a16_write(state, regs, cmd->msg[i]) < 0)
@ -1532,7 +1535,7 @@ static int mb86a16_send_diseqc_msg(struct dvb_frontend *fe,
err:
dprintk(verbose, MB86A16_ERROR, 1, "I2C transfer error");
return -EREMOTEIO;
return ret;
}
static int mb86a16_send_diseqc_burst(struct dvb_frontend *fe,

View File

@ -162,6 +162,19 @@ config VIDEO_IMX290
To compile this driver as a module, choose M here: the
module will be called 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.
To compile this driver as a module, choose M here: the
module will be called imx296.
config VIDEO_IMX319
tristate "Sony IMX319 sensor support"
depends on I2C && VIDEO_DEV
@ -228,6 +241,20 @@ config VIDEO_IMX412
To compile this driver as a module, choose M here: the
module will be called 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.
To compile this driver as a module, choose M here: the
module will be called imx415.
config VIDEO_MAX9271_LIB
tristate
@ -645,6 +672,19 @@ config VIDEO_OV8856
To compile this driver as a module, choose M here: the
module will be called 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
help
This is a Video4Linux2 sensor driver for OmniVision
OV8858 camera sensor.
To compile this driver as a module, choose M here: the
module will be called ov8858.
config VIDEO_OV8865
tristate "OmniVision OV8865 sensor support"
depends on I2C && PM && VIDEO_DEV

View File

@ -43,11 +43,13 @@ obj-$(CONFIG_VIDEO_IMX219) += imx219.o
obj-$(CONFIG_VIDEO_IMX258) += imx258.o
obj-$(CONFIG_VIDEO_IMX274) += imx274.o
obj-$(CONFIG_VIDEO_IMX290) += imx290.o
obj-$(CONFIG_VIDEO_IMX296) += imx296.o
obj-$(CONFIG_VIDEO_IMX319) += imx319.o
obj-$(CONFIG_VIDEO_IMX334) += imx334.o
obj-$(CONFIG_VIDEO_IMX335) += imx335.o
obj-$(CONFIG_VIDEO_IMX355) += imx355.o
obj-$(CONFIG_VIDEO_IMX412) += imx412.o
obj-$(CONFIG_VIDEO_IMX415) += imx415.o
obj-$(CONFIG_VIDEO_IR_I2C) += ir-kbd-i2c.o
obj-$(CONFIG_VIDEO_ISL7998X) += isl7998x.o
obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
@ -96,6 +98,7 @@ obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
obj-$(CONFIG_VIDEO_OV772X) += ov772x.o
obj-$(CONFIG_VIDEO_OV7740) += ov7740.o
obj-$(CONFIG_VIDEO_OV8856) += ov8856.o
obj-$(CONFIG_VIDEO_OV8858) += ov8858.o
obj-$(CONFIG_VIDEO_OV8865) += ov8865.o
obj-$(CONFIG_VIDEO_OV9282) += ov9282.o
obj-$(CONFIG_VIDEO_OV9640) += ov9640.o

View File

@ -6,6 +6,7 @@
#include <linux/i2c.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
@ -23,17 +24,29 @@
*/
#define AK7375_CTRL_STEPS 64
#define AK7375_CTRL_DELAY_US 1000
/*
* The vcm may take up 10 ms (tDELAY) to power on and start taking
* I2C messages. Based on AK7371 datasheet.
*/
#define AK7375_POWER_DELAY_US 10000
#define AK7375_REG_POSITION 0x0
#define AK7375_REG_CONT 0x2
#define AK7375_MODE_ACTIVE 0x0
#define AK7375_MODE_STANDBY 0x40
static const char * const ak7375_supply_names[] = {
"vdd",
"vio",
};
/* ak7375 device structure */
struct ak7375_device {
struct v4l2_ctrl_handler ctrls_vcm;
struct v4l2_subdev sd;
struct v4l2_ctrl *focus;
struct regulator_bulk_data supplies[ARRAY_SIZE(ak7375_supply_names)];
/* active or standby mode */
bool active;
};
@ -133,12 +146,24 @@ static int ak7375_probe(struct i2c_client *client)
{
struct ak7375_device *ak7375_dev;
int ret;
unsigned int i;
ak7375_dev = devm_kzalloc(&client->dev, sizeof(*ak7375_dev),
GFP_KERNEL);
if (!ak7375_dev)
return -ENOMEM;
for (i = 0; i < ARRAY_SIZE(ak7375_supply_names); i++)
ak7375_dev->supplies[i].supply = ak7375_supply_names[i];
ret = devm_regulator_bulk_get(&client->dev,
ARRAY_SIZE(ak7375_supply_names),
ak7375_dev->supplies);
if (ret) {
dev_err_probe(&client->dev, ret, "Failed to get regulators\n");
return ret;
}
v4l2_i2c_subdev_init(&ak7375_dev->sd, client, &ak7375_ops);
ak7375_dev->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
ak7375_dev->sd.internal_ops = &ak7375_int_ops;
@ -208,6 +233,11 @@ static int __maybe_unused ak7375_vcm_suspend(struct device *dev)
if (ret)
dev_err(dev, "%s I2C failure: %d\n", __func__, ret);
ret = regulator_bulk_disable(ARRAY_SIZE(ak7375_supply_names),
ak7375_dev->supplies);
if (ret)
return ret;
ak7375_dev->active = false;
return 0;
@ -228,6 +258,14 @@ static int __maybe_unused ak7375_vcm_resume(struct device *dev)
if (ak7375_dev->active)
return 0;
ret = regulator_bulk_enable(ARRAY_SIZE(ak7375_supply_names),
ak7375_dev->supplies);
if (ret)
return ret;
/* Wait for vcm to become ready */
usleep_range(AK7375_POWER_DELAY_US, AK7375_POWER_DELAY_US + 500);
ret = ak7375_i2c_write(ak7375_dev, AK7375_REG_CONT,
AK7375_MODE_ACTIVE, 1);
if (ret) {

View File

@ -42,10 +42,16 @@
/* External clock frequency is 24.0M */
#define IMX219_XCLK_FREQ 24000000
/* Pixel rate is fixed at 182.4M for all the modes */
/* Pixel rate is fixed for all the modes */
#define IMX219_PIXEL_RATE 182400000
#define IMX219_PIXEL_RATE_4LANE 280800000
#define IMX219_DEFAULT_LINK_FREQ 456000000
#define IMX219_DEFAULT_LINK_FREQ_4LANE 363000000
#define IMX219_REG_CSI_LANE_MODE 0x0114
#define IMX219_CSI_2_LANE_MODE 0x01
#define IMX219_CSI_4_LANE_MODE 0x03
/* V_TIMING internal */
#define IMX219_REG_VTS 0x0160
@ -89,6 +95,12 @@
#define IMX219_REG_ORIENTATION 0x0172
/* Binning Mode */
#define IMX219_REG_BINNING_MODE 0x0174
#define IMX219_BINNING_NONE 0x0000
#define IMX219_BINNING_2X2 0x0101
#define IMX219_BINNING_2X2_ANALOG 0x0303
/* Test Pattern Control */
#define IMX219_REG_TEST_PATTERN 0x0600
#define IMX219_TEST_PATTERN_DISABLE 0
@ -143,6 +155,58 @@ struct imx219_mode {
/* Default register values */
struct imx219_reg_list reg_list;
/* 2x2 binning is used */
bool binning;
};
static const struct imx219_reg imx219_common_regs[] = {
{0x0100, 0x00}, /* Mode Select */
/* To Access Addresses 3000-5fff, send the following commands */
{0x30eb, 0x0c},
{0x30eb, 0x05},
{0x300a, 0xff},
{0x300b, 0xff},
{0x30eb, 0x05},
{0x30eb, 0x09},
/* PLL Clock Table */
{0x0301, 0x05}, /* VTPXCK_DIV */
{0x0303, 0x01}, /* VTSYSCK_DIV */
{0x0304, 0x03}, /* PREPLLCK_VT_DIV 0x03 = AUTO set */
{0x0305, 0x03}, /* PREPLLCK_OP_DIV 0x03 = AUTO set */
{0x0306, 0x00}, /* PLL_VT_MPY */
{0x0307, 0x39},
{0x030b, 0x01}, /* OP_SYS_CLK_DIV */
{0x030c, 0x00}, /* PLL_OP_MPY */
{0x030d, 0x72},
/* Undocumented registers */
{0x455e, 0x00},
{0x471e, 0x4b},
{0x4767, 0x0f},
{0x4750, 0x14},
{0x4540, 0x00},
{0x47b4, 0x14},
{0x4713, 0x30},
{0x478b, 0x10},
{0x478f, 0x10},
{0x4793, 0x10},
{0x4797, 0x0e},
{0x479b, 0x0e},
/* Frame Bank Register Group "A" */
{0x0162, 0x0d}, /* Line_Length_A */
{0x0163, 0x78},
{0x0170, 0x01}, /* X_ODD_INC_A */
{0x0171, 0x01}, /* Y_ODD_INC_A */
/* Output setup registers */
{0x0114, 0x01}, /* CSI 2-Lane Mode */
{0x0128, 0x00}, /* DPHY Auto Mode */
{0x012a, 0x18}, /* EXCK_Freq */
{0x012b, 0x00},
};
/*
@ -151,17 +215,6 @@ struct imx219_mode {
* 3280x2464 = mode 2, 1920x1080 = mode 1, 1640x1232 = mode 4, 640x480 = mode 7.
*/
static const struct imx219_reg mode_3280x2464_regs[] = {
{0x0100, 0x00},
{0x30eb, 0x0c},
{0x30eb, 0x05},
{0x300a, 0xff},
{0x300b, 0xff},
{0x30eb, 0x05},
{0x30eb, 0x09},
{0x0114, 0x01},
{0x0128, 0x00},
{0x012a, 0x18},
{0x012b, 0x00},
{0x0164, 0x00},
{0x0165, 0x00},
{0x0166, 0x0c},
@ -174,53 +227,13 @@ static const struct imx219_reg mode_3280x2464_regs[] = {
{0x016d, 0xd0},
{0x016e, 0x09},
{0x016f, 0xa0},
{0x0170, 0x01},
{0x0171, 0x01},
{0x0174, 0x00},
{0x0175, 0x00},
{0x0301, 0x05},
{0x0303, 0x01},
{0x0304, 0x03},
{0x0305, 0x03},
{0x0306, 0x00},
{0x0307, 0x39},
{0x030b, 0x01},
{0x030c, 0x00},
{0x030d, 0x72},
{0x0624, 0x0c},
{0x0625, 0xd0},
{0x0626, 0x09},
{0x0627, 0xa0},
{0x455e, 0x00},
{0x471e, 0x4b},
{0x4767, 0x0f},
{0x4750, 0x14},
{0x4540, 0x00},
{0x47b4, 0x14},
{0x4713, 0x30},
{0x478b, 0x10},
{0x478f, 0x10},
{0x4793, 0x10},
{0x4797, 0x0e},
{0x479b, 0x0e},
{0x0162, 0x0d},
{0x0163, 0x78},
};
static const struct imx219_reg mode_1920_1080_regs[] = {
{0x0100, 0x00},
{0x30eb, 0x05},
{0x30eb, 0x0c},
{0x300a, 0xff},
{0x300b, 0xff},
{0x30eb, 0x05},
{0x30eb, 0x09},
{0x0114, 0x01},
{0x0128, 0x00},
{0x012a, 0x18},
{0x012b, 0x00},
{0x0162, 0x0d},
{0x0163, 0x78},
{0x0164, 0x02},
{0x0165, 0xa8},
{0x0166, 0x0a},
@ -233,49 +246,13 @@ static const struct imx219_reg mode_1920_1080_regs[] = {
{0x016d, 0x80},
{0x016e, 0x04},
{0x016f, 0x38},
{0x0170, 0x01},
{0x0171, 0x01},
{0x0174, 0x00},
{0x0175, 0x00},
{0x0301, 0x05},
{0x0303, 0x01},
{0x0304, 0x03},
{0x0305, 0x03},
{0x0306, 0x00},
{0x0307, 0x39},
{0x030b, 0x01},
{0x030c, 0x00},
{0x030d, 0x72},
{0x0624, 0x07},
{0x0625, 0x80},
{0x0626, 0x04},
{0x0627, 0x38},
{0x455e, 0x00},
{0x471e, 0x4b},
{0x4767, 0x0f},
{0x4750, 0x14},
{0x4540, 0x00},
{0x47b4, 0x14},
{0x4713, 0x30},
{0x478b, 0x10},
{0x478f, 0x10},
{0x4793, 0x10},
{0x4797, 0x0e},
{0x479b, 0x0e},
};
static const struct imx219_reg mode_1640_1232_regs[] = {
{0x0100, 0x00},
{0x30eb, 0x0c},
{0x30eb, 0x05},
{0x300a, 0xff},
{0x300b, 0xff},
{0x30eb, 0x05},
{0x30eb, 0x09},
{0x0114, 0x01},
{0x0128, 0x00},
{0x012a, 0x18},
{0x012b, 0x00},
{0x0164, 0x00},
{0x0165, 0x00},
{0x0166, 0x0c},
@ -288,53 +265,13 @@ static const struct imx219_reg mode_1640_1232_regs[] = {
{0x016d, 0x68},
{0x016e, 0x04},
{0x016f, 0xd0},
{0x0170, 0x01},
{0x0171, 0x01},
{0x0174, 0x01},
{0x0175, 0x01},
{0x0301, 0x05},
{0x0303, 0x01},
{0x0304, 0x03},
{0x0305, 0x03},
{0x0306, 0x00},
{0x0307, 0x39},
{0x030b, 0x01},
{0x030c, 0x00},
{0x030d, 0x72},
{0x0624, 0x06},
{0x0625, 0x68},
{0x0626, 0x04},
{0x0627, 0xd0},
{0x455e, 0x00},
{0x471e, 0x4b},
{0x4767, 0x0f},
{0x4750, 0x14},
{0x4540, 0x00},
{0x47b4, 0x14},
{0x4713, 0x30},
{0x478b, 0x10},
{0x478f, 0x10},
{0x4793, 0x10},
{0x4797, 0x0e},
{0x479b, 0x0e},
{0x0162, 0x0d},
{0x0163, 0x78},
};
static const struct imx219_reg mode_640_480_regs[] = {
{0x0100, 0x00},
{0x30eb, 0x05},
{0x30eb, 0x0c},
{0x300a, 0xff},
{0x300b, 0xff},
{0x30eb, 0x05},
{0x30eb, 0x09},
{0x0114, 0x01},
{0x0128, 0x00},
{0x012a, 0x18},
{0x012b, 0x00},
{0x0162, 0x0d},
{0x0163, 0x78},
{0x0164, 0x03},
{0x0165, 0xe8},
{0x0166, 0x08},
@ -347,35 +284,10 @@ static const struct imx219_reg mode_640_480_regs[] = {
{0x016d, 0x80},
{0x016e, 0x01},
{0x016f, 0xe0},
{0x0170, 0x01},
{0x0171, 0x01},
{0x0174, 0x03},
{0x0175, 0x03},
{0x0301, 0x05},
{0x0303, 0x01},
{0x0304, 0x03},
{0x0305, 0x03},
{0x0306, 0x00},
{0x0307, 0x39},
{0x030b, 0x01},
{0x030c, 0x00},
{0x030d, 0x72},
{0x0624, 0x06},
{0x0625, 0x68},
{0x0626, 0x04},
{0x0627, 0xd0},
{0x455e, 0x00},
{0x471e, 0x4b},
{0x4767, 0x0f},
{0x4750, 0x14},
{0x4540, 0x00},
{0x47b4, 0x14},
{0x4713, 0x30},
{0x478b, 0x10},
{0x478f, 0x10},
{0x4793, 0x10},
{0x4797, 0x0e},
{0x479b, 0x0e},
};
static const struct imx219_reg raw8_framefmt_regs[] = {
@ -394,6 +306,10 @@ static const s64 imx219_link_freq_menu[] = {
IMX219_DEFAULT_LINK_FREQ,
};
static const s64 imx219_link_freq_4lane_menu[] = {
IMX219_DEFAULT_LINK_FREQ_4LANE,
};
static const char * const imx219_test_pattern_menu[] = {
"Disabled",
"Color Bars",
@ -485,6 +401,7 @@ static const struct imx219_mode supported_modes[] = {
.num_of_regs = ARRAY_SIZE(mode_3280x2464_regs),
.regs = mode_3280x2464_regs,
},
.binning = false,
},
{
/* 1080P 30fps cropped */
@ -501,6 +418,7 @@ static const struct imx219_mode supported_modes[] = {
.num_of_regs = ARRAY_SIZE(mode_1920_1080_regs),
.regs = mode_1920_1080_regs,
},
.binning = false,
},
{
/* 2x2 binned 30fps mode */
@ -517,6 +435,7 @@ static const struct imx219_mode supported_modes[] = {
.num_of_regs = ARRAY_SIZE(mode_1640_1232_regs),
.regs = mode_1640_1232_regs,
},
.binning = true,
},
{
/* 640x480 30fps mode */
@ -533,6 +452,7 @@ static const struct imx219_mode supported_modes[] = {
.num_of_regs = ARRAY_SIZE(mode_640_480_regs),
.regs = mode_640_480_regs,
},
.binning = true,
},
};
@ -569,6 +489,9 @@ struct imx219 {
/* Streaming on/off */
bool streaming;
/* Two or Four lanes */
u8 lanes;
};
static inline struct imx219 *to_imx219(struct v4l2_subdev *_sd)
@ -979,6 +902,35 @@ static int imx219_set_framefmt(struct imx219 *imx219)
return -EINVAL;
}
static int imx219_set_binning(struct imx219 *imx219)
{
if (!imx219->mode->binning) {
return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE,
IMX219_REG_VALUE_16BIT,
IMX219_BINNING_NONE);
}
switch (imx219->fmt.code) {
case MEDIA_BUS_FMT_SRGGB8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SBGGR8_1X8:
return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE,
IMX219_REG_VALUE_16BIT,
IMX219_BINNING_2X2_ANALOG);
case MEDIA_BUS_FMT_SRGGB10_1X10:
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SGBRG10_1X10:
case MEDIA_BUS_FMT_SBGGR10_1X10:
return imx219_write_reg(imx219, IMX219_REG_BINNING_MODE,
IMX219_REG_VALUE_16BIT,
IMX219_BINNING_2X2);
}
return -EINVAL;
}
static const struct v4l2_rect *
__imx219_get_pad_crop(struct imx219 *imx219,
struct v4l2_subdev_state *sd_state,
@ -1031,6 +983,13 @@ static int imx219_get_selection(struct v4l2_subdev *sd,
return -EINVAL;
}
static int imx219_configure_lanes(struct imx219 *imx219)
{
return imx219_write_reg(imx219, IMX219_REG_CSI_LANE_MODE,
IMX219_REG_VALUE_08BIT, (imx219->lanes == 2) ?
IMX219_CSI_2_LANE_MODE : IMX219_CSI_4_LANE_MODE);
};
static int imx219_start_streaming(struct imx219 *imx219)
{
struct i2c_client *client = v4l2_get_subdevdata(&imx219->sd);
@ -1041,6 +1000,20 @@ static int imx219_start_streaming(struct imx219 *imx219)
if (ret < 0)
return ret;
/* Send all registers that are common to all modes */
ret = imx219_write_regs(imx219, imx219_common_regs, ARRAY_SIZE(imx219_common_regs));
if (ret) {
dev_err(&client->dev, "%s failed to send mfg header\n", __func__);
goto err_rpm_put;
}
/* Configure two or four Lane mode */
ret = imx219_configure_lanes(imx219);
if (ret) {
dev_err(&client->dev, "%s failed to configure lanes\n", __func__);
goto err_rpm_put;
}
/* Apply default values of current mode */
reg_list = &imx219->mode->reg_list;
ret = imx219_write_regs(imx219, reg_list->regs, reg_list->num_of_regs);
@ -1056,6 +1029,13 @@ static int imx219_start_streaming(struct imx219 *imx219)
goto err_rpm_put;
}
ret = imx219_set_binning(imx219);
if (ret) {
dev_err(&client->dev, "%s failed to set binning: %d\n",
__func__, ret);
goto err_rpm_put;
}
/* Apply customized values from user */
ret = __v4l2_ctrl_handler_setup(imx219->sd.ctrl_handler);
if (ret)
@ -1272,6 +1252,11 @@ static const struct v4l2_subdev_internal_ops imx219_internal_ops = {
.open = imx219_open,
};
static unsigned long imx219_get_pixel_rate(struct imx219 *imx219)
{
return (imx219->lanes == 2) ? IMX219_PIXEL_RATE : IMX219_PIXEL_RATE_4LANE;
}
/* Initialize control handlers */
static int imx219_init_controls(struct imx219 *imx219)
{
@ -1293,15 +1278,16 @@ static int imx219_init_controls(struct imx219 *imx219)
/* By default, PIXEL_RATE is read only */
imx219->pixel_rate = v4l2_ctrl_new_std(ctrl_hdlr, &imx219_ctrl_ops,
V4L2_CID_PIXEL_RATE,
IMX219_PIXEL_RATE,
IMX219_PIXEL_RATE, 1,
IMX219_PIXEL_RATE);
imx219_get_pixel_rate(imx219),
imx219_get_pixel_rate(imx219), 1,
imx219_get_pixel_rate(imx219));
imx219->link_freq =
v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx219_ctrl_ops,
V4L2_CID_LINK_FREQ,
ARRAY_SIZE(imx219_link_freq_menu) - 1, 0,
imx219_link_freq_menu);
(imx219->lanes == 2) ? imx219_link_freq_menu :
imx219_link_freq_4lane_menu);
if (imx219->link_freq)
imx219->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
@ -1396,7 +1382,7 @@ static void imx219_free_controls(struct imx219 *imx219)
mutex_destroy(&imx219->mutex);
}
static int imx219_check_hwcfg(struct device *dev)
static int imx219_check_hwcfg(struct device *dev, struct imx219 *imx219)
{
struct fwnode_handle *endpoint;
struct v4l2_fwnode_endpoint ep_cfg = {
@ -1416,10 +1402,12 @@ static int imx219_check_hwcfg(struct device *dev)
}
/* Check the number of MIPI CSI2 data lanes */
if (ep_cfg.bus.mipi_csi2.num_data_lanes != 2) {
dev_err(dev, "only 2 data lanes are currently supported\n");
if (ep_cfg.bus.mipi_csi2.num_data_lanes != 2 &&
ep_cfg.bus.mipi_csi2.num_data_lanes != 4) {
dev_err(dev, "only 2 or 4 data lanes are currently supported\n");
goto error_out;
}
imx219->lanes = ep_cfg.bus.mipi_csi2.num_data_lanes;
/* Check the link frequency set in device tree */
if (!ep_cfg.nr_of_link_frequencies) {
@ -1428,7 +1416,8 @@ static int imx219_check_hwcfg(struct device *dev)
}
if (ep_cfg.nr_of_link_frequencies != 1 ||
ep_cfg.link_frequencies[0] != IMX219_DEFAULT_LINK_FREQ) {
(ep_cfg.link_frequencies[0] != ((imx219->lanes == 2) ?
IMX219_DEFAULT_LINK_FREQ : IMX219_DEFAULT_LINK_FREQ_4LANE))) {
dev_err(dev, "Link frequency not supported: %lld\n",
ep_cfg.link_frequencies[0]);
goto error_out;
@ -1456,7 +1445,7 @@ static int imx219_probe(struct i2c_client *client)
v4l2_i2c_subdev_init(&imx219->sd, client, &imx219_subdev_ops);
/* Check the hardware configuration in device tree */
if (imx219_check_hwcfg(dev))
if (imx219_check_hwcfg(dev, imx219))
return -EINVAL;
/* Get system clock (xclk) */

File diff suppressed because it is too large Load Diff

1172
drivers/media/i2c/imx296.c Normal file

File diff suppressed because it is too large Load Diff

1300
drivers/media/i2c/imx415.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1113,6 +1113,7 @@ static int max9286_v4l2_register(struct max9286_priv *priv)
err_put_node:
fwnode_handle_put(ep);
err_async:
v4l2_ctrl_handler_free(&priv->ctrls);
max9286_v4l2_notifier_unregister(priv);
return ret;

View File

@ -629,8 +629,10 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
V4L2_CID_TEST_PATTERN,
ARRAY_SIZE(ov2740_test_pattern_menu) - 1,
0, 0, ov2740_test_pattern_menu);
if (ctrl_hdlr->error)
if (ctrl_hdlr->error) {
v4l2_ctrl_handler_free(ctrl_hdlr);
return ctrl_hdlr->error;
}
ov2740->sd.ctrl_handler = ctrl_hdlr;

View File

@ -50,6 +50,7 @@
#define OV5640_REG_SYS_CTRL0 0x3008
#define OV5640_REG_SYS_CTRL0_SW_PWDN 0x42
#define OV5640_REG_SYS_CTRL0_SW_PWUP 0x02
#define OV5640_REG_SYS_CTRL0_SW_RST 0x82
#define OV5640_REG_CHIP_ID 0x300a
#define OV5640_REG_IO_MIPI_CTRL00 0x300e
#define OV5640_REG_PAD_OUTPUT_ENABLE01 0x3017
@ -520,7 +521,18 @@ static u32 ov5640_code_to_bpp(struct ov5640_dev *sensor, u32 code)
*/
/* YUV422 UYVY VGA@30fps */
static const struct v4l2_mbus_framefmt ov5640_default_fmt = {
static const struct v4l2_mbus_framefmt ov5640_csi2_default_fmt = {
.code = MEDIA_BUS_FMT_UYVY8_1X16,
.width = 640,
.height = 480,
.colorspace = V4L2_COLORSPACE_SRGB,
.ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SRGB),
.quantization = V4L2_QUANTIZATION_FULL_RANGE,
.xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SRGB),
.field = V4L2_FIELD_NONE,
};
static const struct v4l2_mbus_framefmt ov5640_dvp_default_fmt = {
.code = MEDIA_BUS_FMT_UYVY8_2X8,
.width = 640,
.height = 480,
@ -532,7 +544,7 @@ static const struct v4l2_mbus_framefmt ov5640_default_fmt = {
};
static const struct reg_value ov5640_init_setting[] = {
{0x3103, 0x11, 0, 0}, {0x3008, 0x82, 0, 5}, {0x3008, 0x42, 0, 0},
{0x3103, 0x11, 0, 0},
{0x3103, 0x03, 0, 0}, {0x3630, 0x36, 0, 0},
{0x3631, 0x0e, 0, 0}, {0x3632, 0xe2, 0, 0}, {0x3633, 0x12, 0, 0},
{0x3621, 0xe0, 0, 0}, {0x3704, 0xa0, 0, 0}, {0x3703, 0x5a, 0, 0},
@ -2424,24 +2436,48 @@ static void ov5640_power(struct ov5640_dev *sensor, bool enable)
gpiod_set_value_cansleep(sensor->pwdn_gpio, enable ? 0 : 1);
}
static void ov5640_reset(struct ov5640_dev *sensor)
/*
* From section 2.7 power up sequence:
* t0 + t1 + t2 >= 5ms Delay from DOVDD stable to PWDN pull down
* t3 >= 1ms Delay from PWDN pull down to RESETB pull up
* t4 >= 20ms Delay from RESETB pull up to SCCB (i2c) stable
*
* Some modules don't expose RESETB/PWDN pins directly, instead providing a
* "PWUP" GPIO which is wired through appropriate delays and inverters to the
* pins.
*
* In such cases, this gpio should be mapped to pwdn_gpio in the driver, and we
* should still toggle the pwdn_gpio below with the appropriate delays, while
* the calls to reset_gpio will be ignored.
*/
static void ov5640_powerup_sequence(struct ov5640_dev *sensor)
{
if (!sensor->reset_gpio)
return;
if (sensor->pwdn_gpio) {
gpiod_set_value_cansleep(sensor->reset_gpio, 0);
gpiod_set_value_cansleep(sensor->reset_gpio, 0);
/* camera power cycle */
ov5640_power(sensor, false);
usleep_range(5000, 10000);
ov5640_power(sensor, true);
usleep_range(5000, 10000);
/* camera power cycle */
ov5640_power(sensor, false);
usleep_range(5000, 10000);
ov5640_power(sensor, true);
usleep_range(5000, 10000);
gpiod_set_value_cansleep(sensor->reset_gpio, 1);
usleep_range(1000, 2000);
gpiod_set_value_cansleep(sensor->reset_gpio, 1);
usleep_range(1000, 2000);
gpiod_set_value_cansleep(sensor->reset_gpio, 0);
gpiod_set_value_cansleep(sensor->reset_gpio, 0);
} else {
/* software reset */
ov5640_write_reg(sensor, OV5640_REG_SYS_CTRL0,
OV5640_REG_SYS_CTRL0_SW_RST);
}
usleep_range(20000, 25000);
/*
* software standby: allows registers programming;
* exit at restore_mode() for CSI, s_stream(1) for DVP
*/
ov5640_write_reg(sensor, OV5640_REG_SYS_CTRL0,
OV5640_REG_SYS_CTRL0_SW_PWDN);
}
static int ov5640_set_power_on(struct ov5640_dev *sensor)
@ -2464,8 +2500,7 @@ static int ov5640_set_power_on(struct ov5640_dev *sensor)
goto xclk_off;
}
ov5640_reset(sensor);
ov5640_power(sensor, true);
ov5640_powerup_sequence(sensor);
ret = ov5640_init_slave_id(sensor);
if (ret)
@ -3316,6 +3351,7 @@ static int ov5640_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
break;
}
pm_runtime_mark_last_busy(&sensor->i2c_client->dev);
pm_runtime_put_autosuspend(&sensor->i2c_client->dev);
return 0;
@ -3391,6 +3427,7 @@ static int ov5640_s_ctrl(struct v4l2_ctrl *ctrl)
break;
}
pm_runtime_mark_last_busy(&sensor->i2c_client->dev);
pm_runtime_put_autosuspend(&sensor->i2c_client->dev);
return ret;
@ -3458,7 +3495,7 @@ static int ov5640_init_controls(struct ov5640_dev *sensor)
/* Auto/manual gain */
ctrls->auto_gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_AUTOGAIN,
0, 1, 1, 1);
ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_GAIN,
ctrls->gain = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_ANALOGUE_GAIN,
0, 1023, 1, 0);
ctrls->saturation = v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION,
@ -3710,8 +3747,10 @@ static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
out:
mutex_unlock(&sensor->lock);
if (!enable || ret)
if (!enable || ret) {
pm_runtime_mark_last_busy(&sensor->i2c_client->dev);
pm_runtime_put_autosuspend(&sensor->i2c_client->dev);
}
return ret;
}
@ -3719,11 +3758,13 @@ out:
static int ov5640_init_cfg(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state)
{
struct ov5640_dev *sensor = to_ov5640_dev(sd);
struct v4l2_mbus_framefmt *fmt =
v4l2_subdev_get_try_format(sd, state, 0);
struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, state, 0);
*fmt = ov5640_default_fmt;
*fmt = ov5640_is_csi2(sensor) ? ov5640_csi2_default_fmt :
ov5640_dvp_default_fmt;
crop->left = OV5640_PIXEL_ARRAY_LEFT;
crop->top = OV5640_PIXEL_ARRAY_TOP;
@ -3812,7 +3853,6 @@ static int ov5640_probe(struct i2c_client *client)
* default init sequence initialize sensor to
* YUV422 UYVY VGA@30fps
*/
sensor->fmt = ov5640_default_fmt;
sensor->frame_interval.numerator = 1;
sensor->frame_interval.denominator = ov5640_framerates[OV5640_30_FPS];
sensor->current_fr = OV5640_30_FPS;
@ -3845,6 +3885,9 @@ static int ov5640_probe(struct i2c_client *client)
return -EINVAL;
}
sensor->fmt = ov5640_is_csi2(sensor) ? ov5640_csi2_default_fmt :
ov5640_dvp_default_fmt;
/* get system clock (xclk) */
sensor->xclk = devm_clk_get(dev, "xclk");
if (IS_ERR(sensor->xclk)) {
@ -3912,6 +3955,7 @@ static int ov5640_probe(struct i2c_client *client)
pm_runtime_set_autosuspend_delay(dev, 1000);
pm_runtime_use_autosuspend(dev);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
return 0;

View File

@ -1,15 +1,24 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2017 Intel Corporation.
#include <asm/unaligned.h>
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-fwnode.h>
#define OV5670_XVCLK_FREQ 19200000
#define OV5670_REG_CHIP_ID 0x300a
#define OV5670_CHIP_ID 0x005670
@ -65,6 +74,10 @@
#define OV5670_REG_VALUE_16BIT 2
#define OV5670_REG_VALUE_24BIT 3
/* Pixel Array */
#define OV5670_NATIVE_WIDTH 2624
#define OV5670_NATIVE_HEIGHT 1980
/* Initial number of frames to skip to avoid possible garbage */
#define OV5670_NUM_OF_SKIP_FRAMES 2
@ -83,6 +96,14 @@ struct ov5670_link_freq_config {
const struct ov5670_reg_list reg_list;
};
static const char * const ov5670_supply_names[] = {
"avdd", /* Analog power */
"dvdd", /* Digital power */
"dovdd", /* Digital output power */
};
#define OV5670_NUM_SUPPLIES ARRAY_SIZE(ov5670_supply_names)
struct ov5670_mode {
/* Frame width in pixels */
u32 width;
@ -99,10 +120,25 @@ struct ov5670_mode {
/* Link frequency needed for this resolution */
u32 link_freq_index;
/* Analog crop rectangle */
const struct v4l2_rect *analog_crop;
/* Sensor register settings for this resolution */
const struct ov5670_reg_list reg_list;
};
/*
* All the modes supported by the driver are obtained by subsampling the
* full pixel array. The below values are reflected in registers from
* 0x3800-0x3807 in the modes register-value tables.
*/
static const struct v4l2_rect ov5670_analog_crop = {
.left = 12,
.top = 4,
.width = 2600,
.height = 1952,
};
static const struct ov5670_reg mipi_data_rate_840mbps[] = {
{0x0300, 0x04},
{0x0301, 0x00},
@ -1750,66 +1786,73 @@ static const struct ov5670_mode supported_modes[] = {
.height = 1944,
.vts_def = OV5670_VTS_30FPS,
.vts_min = OV5670_VTS_30FPS,
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
.analog_crop = &ov5670_analog_crop,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_2592x1944_regs),
.regs = mode_2592x1944_regs,
},
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
},
{
.width = 1296,
.height = 972,
.vts_def = OV5670_VTS_30FPS,
.vts_min = 996,
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
.analog_crop = &ov5670_analog_crop,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1296x972_regs),
.regs = mode_1296x972_regs,
},
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
},
{
.width = 648,
.height = 486,
.vts_def = OV5670_VTS_30FPS,
.vts_min = 516,
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
.analog_crop = &ov5670_analog_crop,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_648x486_regs),
.regs = mode_648x486_regs,
},
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
},
{
.width = 2560,
.height = 1440,
.vts_def = OV5670_VTS_30FPS,
.vts_min = OV5670_VTS_30FPS,
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
.analog_crop = &ov5670_analog_crop,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_2560x1440_regs),
.regs = mode_2560x1440_regs,
},
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
},
{
.width = 1280,
.height = 720,
.vts_def = OV5670_VTS_30FPS,
.vts_min = 1020,
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
.analog_crop = &ov5670_analog_crop,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_1280x720_regs),
.regs = mode_1280x720_regs,
},
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
},
{
.width = 640,
.height = 360,
.vts_def = OV5670_VTS_30FPS,
.vts_min = 510,
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
.analog_crop = &ov5670_analog_crop,
.reg_list = {
.num_of_regs = ARRAY_SIZE(mode_640x360_regs),
.regs = mode_640x360_regs,
},
.link_freq_index = OV5670_LINK_FREQ_422MHZ_INDEX,
}
};
@ -1828,6 +1871,16 @@ struct ov5670 {
/* Current mode */
const struct ov5670_mode *cur_mode;
/* xvclk input clock */
struct clk *xvclk;
/* Regulators */
struct regulator_bulk_data supplies[OV5670_NUM_SUPPLIES];
/* Power-down and reset gpios. */
struct gpio_desc *pwdn_gpio; /* PWDNB pin. */
struct gpio_desc *reset_gpio; /* XSHUTDOWN pin. */
/* To serialize asynchronus callbacks */
struct mutex mutex;
@ -1935,27 +1988,6 @@ static int ov5670_write_reg_list(struct ov5670 *ov5670,
return ov5670_write_regs(ov5670, r_list->regs, r_list->num_of_regs);
}
/* Open sub-device */
static int ov5670_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
{
struct ov5670 *ov5670 = to_ov5670(sd);
struct v4l2_mbus_framefmt *try_fmt =
v4l2_subdev_get_try_format(sd, fh->state, 0);
mutex_lock(&ov5670->mutex);
/* Initialize try_fmt */
try_fmt->width = ov5670->cur_mode->width;
try_fmt->height = ov5670->cur_mode->height;
try_fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
try_fmt->field = V4L2_FIELD_NONE;
/* No crop or compose */
mutex_unlock(&ov5670->mutex);
return 0;
}
static int ov5670_update_digital_gain(struct ov5670 *ov5670, u32 d_gain)
{
int ret;
@ -2006,7 +2038,7 @@ static int ov5670_set_ctrl(struct v4l2_ctrl *ctrl)
struct ov5670, ctrl_handler);
struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd);
s64 max;
int ret = 0;
int ret;
/* Propagate change of current control to all related controls */
switch (ctrl->id) {
@ -2045,7 +2077,13 @@ static int ov5670_set_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_TEST_PATTERN:
ret = ov5670_enable_test_pattern(ov5670, ctrl->val);
break;
case V4L2_CID_HBLANK:
case V4L2_CID_LINK_FREQ:
case V4L2_CID_PIXEL_RATE:
ret = 0;
break;
default:
ret = -EINVAL;
dev_info(&client->dev, "%s Unhandled id:0x%x, val:0x%x\n",
__func__, ctrl->id, ctrl->val);
break;
@ -2155,6 +2193,28 @@ error:
return ret;
}
static int ov5670_init_cfg(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state)
{
struct v4l2_mbus_framefmt *fmt =
v4l2_subdev_get_try_format(sd, state, 0);
const struct ov5670_mode *default_mode = &supported_modes[0];
struct v4l2_rect *crop = v4l2_subdev_get_try_crop(sd, state, 0);
fmt->width = default_mode->width;
fmt->height = default_mode->height;
fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
fmt->field = V4L2_FIELD_NONE;
fmt->colorspace = V4L2_COLORSPACE_SRGB;
fmt->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(V4L2_COLORSPACE_SRGB);
fmt->quantization = V4L2_QUANTIZATION_FULL_RANGE;
fmt->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(V4L2_COLORSPACE_SRGB);
*crop = *default_mode->analog_crop;
return 0;
}
static int ov5670_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
@ -2404,6 +2464,49 @@ unlock_and_return:
return ret;
}
static int __maybe_unused ov5670_runtime_resume(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct ov5670 *ov5670 = to_ov5670(sd);
unsigned long delay_us;
int ret;
ret = clk_prepare_enable(ov5670->xvclk);
if (ret)
return ret;
ret = regulator_bulk_enable(OV5670_NUM_SUPPLIES, ov5670->supplies);
if (ret) {
clk_disable_unprepare(ov5670->xvclk);
return ret;
}
gpiod_set_value_cansleep(ov5670->pwdn_gpio, 0);
gpiod_set_value_cansleep(ov5670->reset_gpio, 0);
/* 8192 * 2 clock pulses before the first SCCB transaction. */
delay_us = DIV_ROUND_UP(8192 * 2 * 1000,
DIV_ROUND_UP(OV5670_XVCLK_FREQ, 1000));
fsleep(delay_us);
return 0;
}
static int __maybe_unused ov5670_runtime_suspend(struct device *dev)
{
struct i2c_client *client = to_i2c_client(dev);
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct ov5670 *ov5670 = to_ov5670(sd);
gpiod_set_value_cansleep(ov5670->reset_gpio, 1);
gpiod_set_value_cansleep(ov5670->pwdn_gpio, 1);
regulator_bulk_disable(OV5670_NUM_SUPPLIES, ov5670->supplies);
clk_disable_unprepare(ov5670->xvclk);
return 0;
}
static int __maybe_unused ov5670_suspend(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
@ -2438,15 +2541,64 @@ static const struct v4l2_subdev_core_ops ov5670_core_ops = {
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
};
static const struct v4l2_rect *
__ov5670_get_pad_crop(struct ov5670 *sensor, struct v4l2_subdev_state *state,
unsigned int pad, enum v4l2_subdev_format_whence which)
{
const struct ov5670_mode *mode = sensor->cur_mode;
switch (which) {
case V4L2_SUBDEV_FORMAT_TRY:
return v4l2_subdev_get_try_crop(&sensor->sd, state, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
return mode->analog_crop;
}
return NULL;
}
static int ov5670_get_selection(struct v4l2_subdev *subdev,
struct v4l2_subdev_state *state,
struct v4l2_subdev_selection *sel)
{
struct ov5670 *sensor = to_ov5670(subdev);
switch (sel->target) {
case V4L2_SEL_TGT_CROP:
mutex_lock(&sensor->mutex);
sel->r = *__ov5670_get_pad_crop(sensor, state, sel->pad,
sel->which);
mutex_unlock(&sensor->mutex);
break;
case V4L2_SEL_TGT_NATIVE_SIZE:
case V4L2_SEL_TGT_CROP_BOUNDS:
sel->r.top = 0;
sel->r.left = 0;
sel->r.width = OV5670_NATIVE_WIDTH;
sel->r.height = OV5670_NATIVE_HEIGHT;
break;
case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r = ov5670_analog_crop;
break;
default:
return -EINVAL;
}
return 0;
}
static const struct v4l2_subdev_video_ops ov5670_video_ops = {
.s_stream = ov5670_set_stream,
};
static const struct v4l2_subdev_pad_ops ov5670_pad_ops = {
.init_cfg = ov5670_init_cfg,
.enum_mbus_code = ov5670_enum_mbus_code,
.get_fmt = ov5670_get_pad_format,
.set_fmt = ov5670_set_pad_format,
.enum_frame_size = ov5670_enum_frame_size,
.get_selection = ov5670_get_selection,
.set_selection = ov5670_get_selection,
};
static const struct v4l2_subdev_sensor_ops ov5670_sensor_ops = {
@ -2464,9 +2616,34 @@ static const struct media_entity_operations ov5670_subdev_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
static const struct v4l2_subdev_internal_ops ov5670_internal_ops = {
.open = ov5670_open,
};
static int ov5670_regulators_probe(struct ov5670 *ov5670)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd);
unsigned int i;
for (i = 0; i < OV5670_NUM_SUPPLIES; i++)
ov5670->supplies[i].supply = ov5670_supply_names[i];
return devm_regulator_bulk_get(&client->dev, OV5670_NUM_SUPPLIES,
ov5670->supplies);
}
static int ov5670_gpio_probe(struct ov5670 *ov5670)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov5670->sd);
ov5670->pwdn_gpio = devm_gpiod_get_optional(&client->dev, "powerdown",
GPIOD_OUT_LOW);
if (IS_ERR(ov5670->pwdn_gpio))
return PTR_ERR(ov5670->pwdn_gpio);
ov5670->reset_gpio = devm_gpiod_get_optional(&client->dev, "reset",
GPIOD_OUT_LOW);
if (IS_ERR(ov5670->reset_gpio))
return PTR_ERR(ov5670->reset_gpio);
return 0;
}
static int ov5670_probe(struct i2c_client *client)
{
@ -2476,10 +2653,6 @@ static int ov5670_probe(struct i2c_client *client)
bool full_power;
int ret;
device_property_read_u32(&client->dev, "clock-frequency", &input_clk);
if (input_clk != 19200000)
return -EINVAL;
ov5670 = devm_kzalloc(&client->dev, sizeof(*ov5670), GFP_KERNEL);
if (!ov5670) {
ret = -ENOMEM;
@ -2487,16 +2660,50 @@ static int ov5670_probe(struct i2c_client *client)
goto error_print;
}
ov5670->xvclk = devm_clk_get(&client->dev, NULL);
if (!IS_ERR_OR_NULL(ov5670->xvclk))
input_clk = clk_get_rate(ov5670->xvclk);
else if (PTR_ERR(ov5670->xvclk) == -ENOENT)
device_property_read_u32(&client->dev, "clock-frequency",
&input_clk);
else
return dev_err_probe(&client->dev, PTR_ERR(ov5670->xvclk),
"error getting clock\n");
if (input_clk != OV5670_XVCLK_FREQ) {
dev_err(&client->dev,
"Unsupported clock frequency %u\n", input_clk);
return -EINVAL;
}
/* Initialize subdev */
v4l2_i2c_subdev_init(&ov5670->sd, client, &ov5670_subdev_ops);
ret = ov5670_regulators_probe(ov5670);
if (ret) {
err_msg = "Regulators probe failed";
goto error_print;
}
ret = ov5670_gpio_probe(ov5670);
if (ret) {
err_msg = "GPIO probe failed";
goto error_print;
}
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
ret = ov5670_runtime_resume(&client->dev);
if (ret) {
err_msg = "Power up failed";
goto error_print;
}
/* Check module identity */
ret = ov5670_identify_module(ov5670);
if (ret) {
err_msg = "ov5670_identify_module() error";
goto error_print;
goto error_power_off;
}
}
@ -2511,7 +2718,6 @@ static int ov5670_probe(struct i2c_client *client)
goto error_mutex_destroy;
}
ov5670->sd.internal_ops = &ov5670_internal_ops;
ov5670->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
V4L2_SUBDEV_FL_HAS_EVENTS;
ov5670->sd.entity.ops = &ov5670_subdev_entity_ops;
@ -2525,24 +2731,27 @@ static int ov5670_probe(struct i2c_client *client)
goto error_handler_free;
}
/* Async register for subdev */
ret = v4l2_async_register_subdev_sensor(&ov5670->sd);
if (ret < 0) {
err_msg = "v4l2_async_register_subdev() error";
goto error_entity_cleanup;
}
ov5670->streaming = false;
/* Set the device's state to active if it's in D0 state. */
if (full_power)
pm_runtime_set_active(&client->dev);
pm_runtime_enable(&client->dev);
/* Async register for subdev */
ret = v4l2_async_register_subdev_sensor(&ov5670->sd);
if (ret < 0) {
err_msg = "v4l2_async_register_subdev() error";
goto error_pm_disable;
}
pm_runtime_idle(&client->dev);
return 0;
error_entity_cleanup:
error_pm_disable:
pm_runtime_disable(&client->dev);
media_entity_cleanup(&ov5670->sd.entity);
error_handler_free:
@ -2551,6 +2760,10 @@ error_handler_free:
error_mutex_destroy:
mutex_destroy(&ov5670->mutex);
error_power_off:
if (full_power)
ov5670_runtime_suspend(&client->dev);
error_print:
dev_err(&client->dev, "%s: %s %d\n", __func__, err_msg, ret);
@ -2568,10 +2781,12 @@ static void ov5670_remove(struct i2c_client *client)
mutex_destroy(&ov5670->mutex);
pm_runtime_disable(&client->dev);
ov5670_runtime_suspend(&client->dev);
}
static const struct dev_pm_ops ov5670_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(ov5670_suspend, ov5670_resume)
SET_RUNTIME_PM_OPS(ov5670_runtime_suspend, ov5670_runtime_resume, NULL)
};
#ifdef CONFIG_ACPI
@ -2583,11 +2798,18 @@ static const struct acpi_device_id ov5670_acpi_ids[] = {
MODULE_DEVICE_TABLE(acpi, ov5670_acpi_ids);
#endif
static const struct of_device_id ov5670_of_ids[] = {
{ .compatible = "ovti,ov5670" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ov5670_of_ids);
static struct i2c_driver ov5670_i2c_driver = {
.driver = {
.name = "ov5670",
.pm = &ov5670_pm_ops,
.acpi_match_table = ACPI_PTR(ov5670_acpi_ids),
.of_match_table = ov5670_of_ids,
},
.probe_new = ov5670_probe,
.remove = ov5670_remove,

View File

@ -3,10 +3,14 @@
#include <asm/unaligned.h>
#include <linux/acpi.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
@ -17,7 +21,7 @@
#define OV5675_LINK_FREQ_450MHZ 450000000ULL
#define OV5675_SCLK 90000000LL
#define OV5675_MCLK 19200000
#define OV5675_XVCLK_19_2 19200000
#define OV5675_DATA_LANES 2
#define OV5675_RGB_DEPTH 10
@ -76,6 +80,14 @@
#define to_ov5675(_sd) container_of(_sd, struct ov5675, sd)
static const char * const ov5675_supply_names[] = {
"avdd", /* Analog power */
"dovdd", /* Digital I/O power */
"dvdd", /* Digital core power */
};
#define OV5675_NUM_SUPPLIES ARRAY_SIZE(ov5675_supply_names)
enum {
OV5675_LINK_FREQ_900MBPS,
};
@ -484,6 +496,9 @@ struct ov5675 {
struct v4l2_subdev sd;
struct media_pad pad;
struct v4l2_ctrl_handler ctrl_handler;
struct clk *xvclk;
struct gpio_desc *reset_gpio;
struct regulator_bulk_data supplies[OV5675_NUM_SUPPLIES];
/* V4L2 Controls */
struct v4l2_ctrl *link_freq;
@ -764,12 +779,14 @@ static const struct v4l2_ctrl_ops ov5675_ctrl_ops = {
static int ov5675_init_controls(struct ov5675 *ov5675)
{
struct i2c_client *client = v4l2_get_subdevdata(&ov5675->sd);
struct v4l2_fwnode_device_properties props;
struct v4l2_ctrl_handler *ctrl_hdlr;
s64 exposure_max, h_blank;
int ret;
ctrl_hdlr = &ov5675->ctrl_handler;
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8);
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
if (ret)
return ret;
@ -820,12 +837,28 @@ static int ov5675_init_controls(struct ov5675 *ov5675)
v4l2_ctrl_new_std(ctrl_hdlr, &ov5675_ctrl_ops,
V4L2_CID_VFLIP, 0, 1, 1, 0);
if (ctrl_hdlr->error)
if (ctrl_hdlr->error) {
v4l2_ctrl_handler_free(ctrl_hdlr);
return ctrl_hdlr->error;
}
ret = v4l2_fwnode_device_parse(&client->dev, &props);
if (ret)
goto error;
ret = v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov5675_ctrl_ops,
&props);
if (ret)
goto error;
ov5675->sd.ctrl_handler = ctrl_hdlr;
return 0;
error:
v4l2_ctrl_handler_free(ctrl_hdlr);
return ret;
}
static void ov5675_update_pad_format(const struct ov5675_mode *mode,
@ -944,6 +977,56 @@ static int ov5675_set_stream(struct v4l2_subdev *sd, int enable)
return ret;
}
static int ov5675_power_off(struct device *dev)
{
/* 512 xvclk cycles after the last SCCB transation or MIPI frame end */
u32 delay_us = DIV_ROUND_UP(512, OV5675_XVCLK_19_2 / 1000 / 1000);
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ov5675 *ov5675 = to_ov5675(sd);
usleep_range(delay_us, delay_us * 2);
clk_disable_unprepare(ov5675->xvclk);
gpiod_set_value_cansleep(ov5675->reset_gpio, 1);
regulator_bulk_disable(OV5675_NUM_SUPPLIES, ov5675->supplies);
return 0;
}
static int ov5675_power_on(struct device *dev)
{
u32 delay_us = DIV_ROUND_UP(8192, OV5675_XVCLK_19_2 / 1000 / 1000);
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct ov5675 *ov5675 = to_ov5675(sd);
int ret;
ret = clk_prepare_enable(ov5675->xvclk);
if (ret < 0) {
dev_err(dev, "failed to enable xvclk: %d\n", ret);
return ret;
}
gpiod_set_value_cansleep(ov5675->reset_gpio, 1);
ret = regulator_bulk_enable(OV5675_NUM_SUPPLIES, ov5675->supplies);
if (ret) {
clk_disable_unprepare(ov5675->xvclk);
return ret;
}
/* Reset pulse should be at least 2ms and reset gpio released only once
* regulators are stable.
*/
usleep_range(2000, 2200);
gpiod_set_value_cansleep(ov5675->reset_gpio, 0);
/* 8192 xvclk cycles prior to the first SCCB transation */
usleep_range(delay_us, delay_us * 2);
return 0;
}
static int __maybe_unused ov5675_suspend(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
@ -1040,6 +1123,31 @@ static int ov5675_get_format(struct v4l2_subdev *sd,
return 0;
}
static int ov5675_get_selection(struct v4l2_subdev *sd,
struct v4l2_subdev_state *state,
struct v4l2_subdev_selection *sel)
{
if (sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
return -EINVAL;
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
sel->r.top = 0;
sel->r.left = 0;
sel->r.width = 2624;
sel->r.height = 2000;
return 0;
case V4L2_SEL_TGT_CROP:
case V4L2_SEL_TGT_CROP_DEFAULT:
sel->r.top = 16;
sel->r.left = 16;
sel->r.width = 2592;
sel->r.height = 1944;
return 0;
}
return -EINVAL;
}
static int ov5675_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
@ -1089,6 +1197,7 @@ static const struct v4l2_subdev_video_ops ov5675_video_ops = {
static const struct v4l2_subdev_pad_ops ov5675_pad_ops = {
.set_fmt = ov5675_set_format,
.get_fmt = ov5675_get_format,
.get_selection = ov5675_get_selection,
.enum_mbus_code = ov5675_enum_mbus_code,
.enum_frame_size = ov5675_enum_frame_size,
};
@ -1106,31 +1215,59 @@ static const struct v4l2_subdev_internal_ops ov5675_internal_ops = {
.open = ov5675_open,
};
static int ov5675_check_hwcfg(struct device *dev)
static int ov5675_get_hwcfg(struct ov5675 *ov5675, struct device *dev)
{
struct fwnode_handle *ep;
struct fwnode_handle *fwnode = dev_fwnode(dev);
struct v4l2_fwnode_endpoint bus_cfg = {
.bus_type = V4L2_MBUS_CSI2_DPHY
};
u32 mclk;
u32 xvclk_rate;
int ret;
unsigned int i, j;
if (!fwnode)
return -ENXIO;
ret = fwnode_property_read_u32(fwnode, "clock-frequency", &mclk);
ov5675->xvclk = devm_clk_get_optional(dev, NULL);
if (IS_ERR(ov5675->xvclk))
return dev_err_probe(dev, PTR_ERR(ov5675->xvclk),
"failed to get xvclk: %ld\n",
PTR_ERR(ov5675->xvclk));
if (ret) {
dev_err(dev, "can't get clock frequency");
if (ov5675->xvclk) {
xvclk_rate = clk_get_rate(ov5675->xvclk);
} else {
ret = fwnode_property_read_u32(fwnode, "clock-frequency",
&xvclk_rate);
if (ret) {
dev_err(dev, "can't get clock frequency");
return ret;
}
}
if (xvclk_rate != OV5675_XVCLK_19_2) {
dev_err(dev, "external clock rate %u is unsupported",
xvclk_rate);
return -EINVAL;
}
ov5675->reset_gpio = devm_gpiod_get_optional(dev, "reset",
GPIOD_OUT_HIGH);
if (IS_ERR(ov5675->reset_gpio)) {
ret = PTR_ERR(ov5675->reset_gpio);
dev_err(dev, "failed to get reset-gpios: %d\n", ret);
return ret;
}
if (mclk != OV5675_MCLK) {
dev_err(dev, "external clock %d is not supported", mclk);
return -EINVAL;
}
for (i = 0; i < OV5675_NUM_SUPPLIES; i++)
ov5675->supplies[i].supply = ov5675_supply_names[i];
ret = devm_regulator_bulk_get(dev, OV5675_NUM_SUPPLIES,
ov5675->supplies);
if (ret)
return ret;
ep = fwnode_graph_get_next_endpoint(fwnode, NULL);
if (!ep)
@ -1185,6 +1322,10 @@ static void ov5675_remove(struct i2c_client *client)
v4l2_ctrl_handler_free(sd->ctrl_handler);
pm_runtime_disable(&client->dev);
mutex_destroy(&ov5675->mutex);
if (!pm_runtime_status_suspended(&client->dev))
ov5675_power_off(&client->dev);
pm_runtime_set_suspended(&client->dev);
}
static int ov5675_probe(struct i2c_client *client)
@ -1193,25 +1334,31 @@ static int ov5675_probe(struct i2c_client *client)
bool full_power;
int ret;
ret = ov5675_check_hwcfg(&client->dev);
if (ret) {
dev_err(&client->dev, "failed to check HW configuration: %d",
ret);
return ret;
}
ov5675 = devm_kzalloc(&client->dev, sizeof(*ov5675), GFP_KERNEL);
if (!ov5675)
return -ENOMEM;
ret = ov5675_get_hwcfg(ov5675, &client->dev);
if (ret) {
dev_err(&client->dev, "failed to get HW configuration: %d",
ret);
return ret;
}
v4l2_i2c_subdev_init(&ov5675->sd, client, &ov5675_subdev_ops);
ret = ov5675_power_on(&client->dev);
if (ret) {
dev_err(&client->dev, "failed to power on: %d\n", ret);
return ret;
}
full_power = acpi_dev_state_d0(&client->dev);
if (full_power) {
ret = ov5675_identify_module(ov5675);
if (ret) {
dev_err(&client->dev, "failed to find sensor: %d", ret);
return ret;
goto probe_power_off;
}
}
@ -1241,11 +1388,6 @@ static int ov5675_probe(struct i2c_client *client)
goto probe_error_media_entity_cleanup;
}
/*
* Device is already turned on by i2c-core with ACPI domain PM.
* Enable runtime PM and turn off the device.
*/
/* Set the device's state to active if it's in D0 state. */
if (full_power)
pm_runtime_set_active(&client->dev);
@ -1260,12 +1402,15 @@ probe_error_media_entity_cleanup:
probe_error_v4l2_ctrl_handler_free:
v4l2_ctrl_handler_free(ov5675->sd.ctrl_handler);
mutex_destroy(&ov5675->mutex);
probe_power_off:
ov5675_power_off(&client->dev);
return ret;
}
static const struct dev_pm_ops ov5675_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(ov5675_suspend, ov5675_resume)
SET_RUNTIME_PM_OPS(ov5675_power_off, ov5675_power_on, NULL)
};
#ifdef CONFIG_ACPI
@ -1277,11 +1422,18 @@ static const struct acpi_device_id ov5675_acpi_ids[] = {
MODULE_DEVICE_TABLE(acpi, ov5675_acpi_ids);
#endif
static const struct of_device_id ov5675_of_match[] = {
{ .compatible = "ovti,ov5675", },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, ov5675_of_match);
static struct i2c_driver ov5675_i2c_driver = {
.driver = {
.name = "ov5675",
.pm = &ov5675_pm_ops,
.acpi_match_table = ACPI_PTR(ov5675_acpi_ids),
.of_match_table = ov5675_of_match,
},
.probe_new = ov5675_probe,
.remove = ov5675_remove,

View File

@ -1840,7 +1840,7 @@ static int ov7670_parse_dt(struct device *dev,
if (bus_cfg.bus_type != V4L2_MBUS_PARALLEL) {
dev_err(dev, "Unsupported media bus type\n");
return ret;
return -EINVAL;
}
info->mbus_config = bus_cfg.bus.parallel.flags;

View File

@ -1462,7 +1462,7 @@ static int ov772x_probe(struct i2c_client *client)
priv->subdev.ctrl_handler = &priv->hdl;
if (priv->hdl.error) {
ret = priv->hdl.error;
goto error_mutex_destroy;
goto error_ctrl_free;
}
priv->clk = clk_get(&client->dev, NULL);
@ -1515,7 +1515,6 @@ error_clk_put:
clk_put(priv->clk);
error_ctrl_free:
v4l2_ctrl_handler_free(&priv->hdl);
error_mutex_destroy:
mutex_destroy(&priv->lock);
return ret;

2008
drivers/media/i2c/ov8858.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -148,7 +148,6 @@ struct ov9282_mode {
/**
* struct ov9282 - ov9282 sensor device structure
* @dev: Pointer to generic device
* @client: Pointer to i2c client
* @sd: V4L2 sub-device
* @pad: Media pad. Only one pad supported
* @reset_gpio: Sensor reset gpio
@ -170,7 +169,6 @@ struct ov9282_mode {
*/
struct ov9282 {
struct device *dev;
struct i2c_client *client;
struct v4l2_subdev sd;
struct media_pad pad;
struct gpio_desc *reset_gpio;
@ -1144,10 +1142,9 @@ static int ov9282_parse_hw_config(struct ov9282 *ov9282)
}
ret = ov9282_configure_regulators(ov9282);
if (ret) {
dev_err(ov9282->dev, "Failed to get power regulators\n");
return ret;
}
if (ret)
return dev_err_probe(ov9282->dev, ret,
"Failed to get power regulators\n");
rate = clk_get_rate(ov9282->inclk);
if (rate != OV9282_INCLK_RATE) {

View File

@ -26,7 +26,6 @@
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-mediabus.h>
#include <media/i2c/s5c73m3.h>
#include <media/v4l2-fwnode.h>
#include "s5c73m3.h"
@ -436,7 +435,7 @@ static int __s5c73m3_s_stream(struct s5c73m3 *state, struct v4l2_subdev *sd,
state->streaming = !!on;
if (!on)
return ret;
return 0;
if (state->apply_fiv) {
ret = s5c73m3_set_frame_rate(state);
@ -1522,25 +1521,16 @@ static const struct v4l2_subdev_ops oif_subdev_ops = {
.video = &s5c73m3_oif_video_ops,
};
static int s5c73m3_get_platform_data(struct s5c73m3 *state)
static int s5c73m3_get_dt_data(struct s5c73m3 *state)
{
struct i2c_client *c = state->i2c_client;
struct device *dev = &c->dev;
const struct s5c73m3_platform_data *pdata = dev->platform_data;
struct device *dev = &state->i2c_client->dev;
struct device_node *node = dev->of_node;
struct device_node *node_ep;
struct v4l2_fwnode_endpoint ep = { .bus_type = 0 };
int ret;
if (!node) {
if (!pdata) {
dev_err(dev, "Platform data not specified\n");
return -EINVAL;
}
state->mclk_frequency = pdata->mclk_frequency;
return 0;
}
if (!node)
return -EINVAL;
state->clock = devm_clk_get(dev, S5C73M3_CLK_NAME);
if (IS_ERR(state->clock))
@ -1603,7 +1593,7 @@ static int s5c73m3_probe(struct i2c_client *client)
return -ENOMEM;
state->i2c_client = client;
ret = s5c73m3_get_platform_data(state);
ret = s5c73m3_get_dt_data(state);
if (ret < 0)
return ret;

View File

@ -23,7 +23,6 @@
#include <media/v4l2-device.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-mediabus.h>
#include <media/i2c/s5c73m3.h>
#include "s5c73m3.h"

View File

@ -16,7 +16,6 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#include <media/i2c/s5c73m3.h>
#define DRIVER_NAME "S5C73M3"

View File

@ -5,7 +5,6 @@
* Copyright (C) 2022 STMicroelectronics SA
*/
#include <asm-generic/unaligned.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
@ -15,6 +14,9 @@
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/units.h>
#include <asm/unaligned.h>
#include <media/mipi-csi2.h>
#include <media/v4l2-async.h>
#include <media/v4l2-ctrls.h>

View File

@ -406,7 +406,7 @@ tc358746_apply_pll_config(struct tc358746 *tc358746)
val = PLL_FRS(ilog2(post)) | RESETB | PLL_EN;
mask = PLL_FRS_MASK | RESETB | PLL_EN;
tc358746_update_bits(tc358746, PLLCTL1_REG, mask, val);
err = tc358746_update_bits(tc358746, PLLCTL1_REG, mask, val);
if (err)
return err;
@ -988,6 +988,8 @@ static int __maybe_unused
tc358746_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
{
struct tc358746 *tc358746 = to_tc358746(sd);
u32 val;
int err;
/* 32-bit registers starting from CLW_DPHYCONTTX */
reg->size = reg->reg < CLW_DPHYCONTTX_REG ? 2 : 4;
@ -995,12 +997,13 @@ tc358746_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
if (!pm_runtime_get_if_in_use(sd->dev))
return 0;
tc358746_read(tc358746, reg->reg, (u32 *)&reg->val);
err = tc358746_read(tc358746, reg->reg, &val);
reg->val = val;
pm_runtime_mark_last_busy(sd->dev);
pm_runtime_put_sync_autosuspend(sd->dev);
return 0;
return err;
}
static int __maybe_unused

View File

@ -716,7 +716,7 @@ done:
__must_check int __media_pipeline_start(struct media_pad *pad,
struct media_pipeline *pipe)
{
struct media_device *mdev = pad->entity->graph_obj.mdev;
struct media_device *mdev = pad->graph_obj.mdev;
struct media_pipeline_pad *err_ppad;
struct media_pipeline_pad *ppad;
int ret;
@ -724,8 +724,8 @@ __must_check int __media_pipeline_start(struct media_pad *pad,
lockdep_assert_held(&mdev->graph_mutex);
/*
* If the entity is already part of a pipeline, that pipeline must
* be the same as the pipe given to media_pipeline_start().
* If the pad is already part of a pipeline, that pipeline must be the
* same as the pipe given to media_pipeline_start().
*/
if (WARN_ON(pad->pipe && pad->pipe != pipe))
return -EINVAL;
@ -864,7 +864,7 @@ EXPORT_SYMBOL_GPL(__media_pipeline_start);
__must_check int media_pipeline_start(struct media_pad *pad,
struct media_pipeline *pipe)
{
struct media_device *mdev = pad->entity->graph_obj.mdev;
struct media_device *mdev = pad->graph_obj.mdev;
int ret;
mutex_lock(&mdev->graph_mutex);
@ -901,7 +901,7 @@ EXPORT_SYMBOL_GPL(__media_pipeline_stop);
void media_pipeline_stop(struct media_pad *pad)
{
struct media_device *mdev = pad->entity->graph_obj.mdev;
struct media_device *mdev = pad->graph_obj.mdev;
mutex_lock(&mdev->graph_mutex);
__media_pipeline_stop(pad);
@ -911,7 +911,7 @@ EXPORT_SYMBOL_GPL(media_pipeline_stop);
__must_check int media_pipeline_alloc_start(struct media_pad *pad)
{
struct media_device *mdev = pad->entity->graph_obj.mdev;
struct media_device *mdev = pad->graph_obj.mdev;
struct media_pipeline *new_pipe = NULL;
struct media_pipeline *pipe;
int ret;
@ -919,7 +919,7 @@ __must_check int media_pipeline_alloc_start(struct media_pad *pad)
mutex_lock(&mdev->graph_mutex);
/*
* Is the entity already part of a pipeline? If not, we need to allocate
* Is the pad already part of a pipeline? If not, we need to allocate
* a pipe.
*/
pipe = media_pad_pipeline(pad);
@ -945,6 +945,61 @@ out:
}
EXPORT_SYMBOL_GPL(media_pipeline_alloc_start);
struct media_pad *
__media_pipeline_pad_iter_next(struct media_pipeline *pipe,
struct media_pipeline_pad_iter *iter,
struct media_pad *pad)
{
if (!pad)
iter->cursor = pipe->pads.next;
if (iter->cursor == &pipe->pads)
return NULL;
pad = list_entry(iter->cursor, struct media_pipeline_pad, list)->pad;
iter->cursor = iter->cursor->next;
return pad;
}
EXPORT_SYMBOL_GPL(__media_pipeline_pad_iter_next);
int media_pipeline_entity_iter_init(struct media_pipeline *pipe,
struct media_pipeline_entity_iter *iter)
{
return media_entity_enum_init(&iter->ent_enum, pipe->mdev);
}
EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_init);
void media_pipeline_entity_iter_cleanup(struct media_pipeline_entity_iter *iter)
{
media_entity_enum_cleanup(&iter->ent_enum);
}
EXPORT_SYMBOL_GPL(media_pipeline_entity_iter_cleanup);
struct media_entity *
__media_pipeline_entity_iter_next(struct media_pipeline *pipe,
struct media_pipeline_entity_iter *iter,
struct media_entity *entity)
{
if (!entity)
iter->cursor = pipe->pads.next;
while (iter->cursor != &pipe->pads) {
struct media_pipeline_pad *ppad;
struct media_entity *entity;
ppad = list_entry(iter->cursor, struct media_pipeline_pad, list);
entity = ppad->pad->entity;
iter->cursor = iter->cursor->next;
if (!media_entity_enum_test_and_set(&iter->ent_enum, entity))
return entity;
}
return NULL;
}
EXPORT_SYMBOL_GPL(__media_pipeline_entity_iter_next);
/* -----------------------------------------------------------------------------
* Links management
*/

View File

@ -27,6 +27,7 @@ if MEDIA_ANALOG_TV_SUPPORT
source "drivers/media/pci/dt3155/Kconfig"
source "drivers/media/pci/ivtv/Kconfig"
source "drivers/media/pci/saa7146/Kconfig"
endif
@ -57,6 +58,7 @@ source "drivers/media/pci/pluto2/Kconfig"
source "drivers/media/pci/pt1/Kconfig"
source "drivers/media/pci/pt3/Kconfig"
source "drivers/media/pci/smipcie/Kconfig"
source "drivers/media/pci/ttpci/Kconfig"
endif

View File

@ -5,7 +5,8 @@
# Please keep it alphabetically sorted by directory
# (e. g. LC_ALL=C sort Makefile)
obj-y += b2c2/ \
obj-y += ttpci/ \
b2c2/ \
pluto2/ \
dm1105/ \
pt1/ \
@ -13,6 +14,7 @@ obj-y += b2c2/ \
mantis/ \
ngene/ \
ddbridge/ \
saa7146/ \
smipcie/ \
netup_unidvb/ \
intel/

View File

@ -1843,6 +1843,9 @@ static void cio2_pci_remove(struct pci_dev *pci_dev)
v4l2_device_unregister(&cio2->v4l2_dev);
media_device_cleanup(&cio2->media_dev);
mutex_destroy(&cio2->lock);
pm_runtime_forbid(&pci_dev->dev);
pm_runtime_get_noresume(&pci_dev->dev);
}
static int __maybe_unused cio2_runtime_suspend(struct device *dev)

View File

@ -978,7 +978,7 @@ static void saa7134_unregister_video(struct saa7134_dev *dev)
}
if (dev->radio_dev) {
if (video_is_registered(dev->radio_dev))
vb2_video_unregister_device(dev->radio_dev);
video_unregister_device(dev->radio_dev);
else
video_device_release(dev->radio_dev);
dev->radio_dev = NULL;

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
config VIDEO_HEXIUM_GEMINI
tristate "Hexium Gemini frame grabber (DEPRECATED)"
tristate "Hexium Gemini frame grabber"
depends on PCI && VIDEO_DEV && I2C
select VIDEO_SAA7146_VV
help
@ -8,28 +8,22 @@ config VIDEO_HEXIUM_GEMINI
grabber card by Hexium. Please note that the Gemini Dual
card is *not* fully supported.
This driver is deprecated and is scheduled for removal by
the beginning of 2023. See the TODO file for more information.
To compile this driver as a module, choose M here: the
module will be called hexium_gemini.
config VIDEO_HEXIUM_ORION
tristate "Hexium HV-PCI6 and Orion frame grabber (DEPRECATED)"
tristate "Hexium HV-PCI6 and Orion frame grabber"
depends on PCI && VIDEO_DEV && I2C
select VIDEO_SAA7146_VV
help
This is a video4linux driver for the Hexium HV-PCI6 and
Orion frame grabber cards by Hexium.
This driver is deprecated and is scheduled for removal by
the beginning of 2023. See the TODO file for more information.
To compile this driver as a module, choose M here: the
module will be called hexium_orion.
config VIDEO_MXB
tristate "Siemens-Nixdorf 'Multimedia eXtension Board' (DEPRECATED)"
tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
depends on PCI && VIDEO_DEV && I2C
select VIDEO_SAA7146_VV
select VIDEO_TUNER
@ -41,8 +35,5 @@ config VIDEO_MXB
This is a video4linux driver for the 'Multimedia eXtension Board'
TV card by Siemens-Nixdorf.
This driver is deprecated and is scheduled for removal by
the beginning of 2023. See the TODO file for more information.
To compile this driver as a module, choose M here: the
module will be called mxb.

View File

@ -13,9 +13,9 @@
#define DEBUG_VARIABLE debug
#include <media/drv-intf/saa7146_vv.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "../common/saa7146_vv.h"
static int debug;
module_param(debug, int, 0);

View File

@ -13,9 +13,9 @@
#define DEBUG_VARIABLE debug
#include <media/drv-intf/saa7146_vv.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "../common/saa7146_vv.h"
static int debug;
module_param(debug, int, 0);

View File

@ -13,13 +13,13 @@
#define DEBUG_VARIABLE debug
#include <media/drv-intf/saa7146_vv.h>
#include <media/tuner.h>
#include <media/v4l2-common.h>
#include <media/i2c/saa7115.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include "../common/saa7146_vv.h"
#include "tea6415c.h"
#include "tea6420.h"

View File

@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
config DVB_BUDGET_CORE
tristate "SAA7146 DVB cards (aka Budget, Nova-PCI) (DEPRECATED)"
tristate "SAA7146 DVB cards (aka Budget, Nova-PCI)"
depends on DVB_CORE && PCI && I2C
select VIDEO_SAA7146
select TTPCI_EEPROM
@ -10,7 +10,7 @@ config DVB_BUDGET_CORE
MPEG2 decoder.
config DVB_BUDGET
tristate "Budget cards (DEPRECATED)"
tristate "Budget cards"
depends on DVB_BUDGET_CORE && I2C
select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
select DVB_VES1X93 if MEDIA_SUBDRV_AUTOSELECT
@ -30,16 +30,13 @@ config DVB_BUDGET
or Nova-PCI cards) without onboard MPEG2 decoder, and without
analog inputs or an onboard Common Interface connector.
This driver is deprecated and is scheduled for removal by
the beginning of 2023. See the TODO file for more information.
Say Y if you own such a card and want to use it.
To compile this driver as a module, choose M here: the
module will be called budget.
config DVB_BUDGET_CI
tristate "Budget cards with onboard CI connector (DEPRECATED)"
tristate "Budget cards with onboard CI connector"
depends on DVB_BUDGET_CORE && I2C
select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT
select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
@ -60,16 +57,13 @@ config DVB_BUDGET_CI
Note: The Common Interface is not yet supported by this driver
due to lack of information from the vendor.
This driver is deprecated and is scheduled for removal by
the beginning of 2023. See the TODO file for more information.
Say Y if you own such a card and want to use it.
To compile this driver as a module, choose M here: the
module will be called budget-ci.
config DVB_BUDGET_AV
tristate "Budget cards with analog video inputs (DEPRECATED)"
tristate "Budget cards with analog video inputs"
depends on DVB_BUDGET_CORE && I2C
select VIDEO_SAA7146_VV
depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV
@ -86,9 +80,6 @@ config DVB_BUDGET_AV
(so called Budget- or Nova-PCI cards) without onboard
MPEG2 decoder, but with one or more analog video inputs.
This driver is deprecated and is scheduled for removal by
the beginning of 2023. See the TODO file for more information.
Say Y if you own such a card and want to use it.
To compile this driver as a module, choose M here: the

View File

@ -29,7 +29,7 @@
#include "tda1004x.h"
#include "tua6100.h"
#include "dvb-pll.h"
#include "../common/saa7146_vv.h"
#include <media/drv-intf/saa7146_vv.h>
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/slab.h>

View File

@ -13,7 +13,7 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include "../common/saa7146.h"
#include <media/drv-intf/saa7146.h>
extern int budget_debug;

View File

@ -250,19 +250,10 @@ static int venc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
}
if (V4L2_TYPE_IS_OUTPUT(f->type)) {
if (!vpu_color_check_primaries(pix_mp->colorspace)) {
venc->params.color.primaries = pix_mp->colorspace;
vpu_color_get_default(venc->params.color.primaries,
&venc->params.color.transfer,
&venc->params.color.matrix,
&venc->params.color.full_range);
}
if (!vpu_color_check_transfers(pix_mp->xfer_func))
venc->params.color.transfer = pix_mp->xfer_func;
if (!vpu_color_check_matrix(pix_mp->ycbcr_enc))
venc->params.color.matrix = pix_mp->ycbcr_enc;
if (!vpu_color_check_full_range(pix_mp->quantization))
venc->params.color.full_range = pix_mp->quantization;
venc->params.color.primaries = pix_mp->colorspace;
venc->params.color.transfer = pix_mp->xfer_func;
venc->params.color.matrix = pix_mp->ycbcr_enc;
venc->params.color.full_range = pix_mp->quantization;
}
pix_mp->colorspace = venc->params.color.primaries;
@ -1281,7 +1272,6 @@ static void venc_init(struct file *file)
f.fmt.pix_mp.width = 1280;
f.fmt.pix_mp.height = 720;
f.fmt.pix_mp.field = V4L2_FIELD_NONE;
f.fmt.pix_mp.colorspace = V4L2_COLORSPACE_REC709;
venc_s_fmt(file, &inst->fh, &f);
memset(&f, 0, sizeof(f));

View File

@ -17,7 +17,7 @@
#include "vpu_helpers.h"
static const u8 colorprimaries[] = {
0,
V4L2_COLORSPACE_LAST,
V4L2_COLORSPACE_REC709, /*Rec. ITU-R BT.709-6*/
0,
0,
@ -31,7 +31,7 @@ static const u8 colorprimaries[] = {
};
static const u8 colortransfers[] = {
0,
V4L2_XFER_FUNC_LAST,
V4L2_XFER_FUNC_709, /*Rec. ITU-R BT.709-6*/
0,
0,
@ -53,7 +53,7 @@ static const u8 colortransfers[] = {
};
static const u8 colormatrixcoefs[] = {
0,
V4L2_YCBCR_ENC_LAST,
V4L2_YCBCR_ENC_709, /*Rec. ITU-R BT.709-6*/
0,
0,

View File

@ -324,11 +324,6 @@ static int vdoa_probe(struct platform_device *pdev)
return 0;
}
static int vdoa_remove(struct platform_device *pdev)
{
return 0;
}
static const struct of_device_id vdoa_dt_ids[] = {
{ .compatible = "fsl,imx6q-vdoa" },
{}
@ -337,7 +332,6 @@ MODULE_DEVICE_TABLE(of, vdoa_dt_ids);
static struct platform_driver vdoa_driver = {
.probe = vdoa_probe,
.remove = vdoa_remove,
.driver = {
.name = VDOA_NAME,
.of_match_table = vdoa_dt_ids,

View File

@ -254,7 +254,7 @@ static int mmpcam_probe(struct platform_device *pdev)
*/
ret = mccic_register(mcam);
if (ret)
return ret;
goto out;
/*
* Add OF clock provider.

View File

@ -3,14 +3,13 @@ config VIDEO_MEDIATEK_MDP3
tristate "MediaTek MDP v3 driver"
depends on MTK_IOMMU || COMPILE_TEST
depends on VIDEO_DEV
depends on ARCH_MEDIATEK || COMPILE_TEST
depends on HAS_DMA
depends on REMOTEPROC
depends on MTK_MMSYS
depends on MTK_CMDQ
depends on MTK_SCP
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
select MTK_MMSYS
select MTK_CMDQ
select MTK_SCP
default n
help
It is a v4l2 driver and present in MediaTek MT8183 SoC.

View File

@ -1002,7 +1002,8 @@ int mdp_comp_config(struct mdp_dev *mdp)
if (!pdev) {
dev_warn(dev, "can't find platform device of node:%s\n",
node->name);
return -ENODEV;
ret = -ENODEV;
goto err_init_comps;
}
comp->comp_dev = &pdev->dev;

View File

@ -207,8 +207,8 @@ static int mdp_probe(struct platform_device *pdev)
}
for (i = 0; i < MDP_PIPE_MAX; i++) {
mdp->mdp_mutex[i] = mtk_mutex_get(&mm_pdev->dev);
if (!mdp->mdp_mutex[i]) {
ret = -ENODEV;
if (IS_ERR(mdp->mdp_mutex[i])) {
ret = PTR_ERR(mdp->mdp_mutex[i]);
goto err_free_mutex;
}
}
@ -289,7 +289,8 @@ err_deinit_comp:
mdp_comp_destroy(mdp);
err_free_mutex:
for (i = 0; i < MDP_PIPE_MAX; i++)
mtk_mutex_put(mdp->mdp_mutex[i]);
if (!IS_ERR_OR_NULL(mdp->mdp_mutex[i]))
mtk_mutex_put(mdp->mdp_mutex[i]);
err_destroy_device:
kfree(mdp);
err_return:

View File

@ -72,9 +72,9 @@ static void mtk_vcodec_dec_pw_off(struct mtk_vcodec_pm *pm)
{
int ret;
ret = pm_runtime_put_sync(pm->dev);
if (ret)
mtk_v4l2_err("pm_runtime_put_sync fail %d", ret);
ret = pm_runtime_put(pm->dev);
if (ret && ret != -EAGAIN)
mtk_v4l2_err("pm_runtime_put fail %d", ret);
}
static void mtk_vcodec_dec_clock_on(struct mtk_vcodec_pm *pm)

View File

@ -565,7 +565,7 @@ static int h264_encode_frame(struct venc_h264_inst *inst,
*bs_size);
++inst->frm_cnt;
++inst->skip_frm_cnt;
return ret;
return 0;
}
irq_status = h264_enc_wait_venc_done(inst);
@ -580,7 +580,7 @@ static int h264_encode_frame(struct venc_h264_inst *inst,
mtk_vcodec_debug(inst, "frm %d bs_size %d key_frm %d <-",
inst->frm_cnt, *bs_size, inst->vpu_inst.is_key_frm);
return ret;
return 0;
}
static void h264_encode_filler(struct venc_h264_inst *inst, void *buf,

View File

@ -32,10 +32,6 @@
#include "microchip-isc-regs.h"
#include "microchip-isc.h"
static unsigned int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)");
#define ISC_IS_FORMAT_RAW(mbus_code) \
(((mbus_code) & 0xf000) == 0x3000)
@ -114,8 +110,8 @@ static int isc_buffer_prepare(struct vb2_buffer *vb)
unsigned long size = isc->fmt.fmt.pix.sizeimage;
if (vb2_plane_size(vb, 0) < size) {
v4l2_err(&isc->v4l2_dev, "buffer too small (%lu < %lu)\n",
vb2_plane_size(vb, 0), size);
dev_err(isc->dev, "buffer too small (%lu < %lu)\n",
vb2_plane_size(vb, 0), size);
return -EINVAL;
}
@ -346,15 +342,14 @@ static int isc_start_streaming(struct vb2_queue *vq, unsigned int count)
/* Enable stream on the sub device */
ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 1);
if (ret && ret != -ENOIOCTLCMD) {
v4l2_err(&isc->v4l2_dev, "stream on failed in subdev %d\n",
ret);
dev_err(isc->dev, "stream on failed in subdev %d\n", ret);
goto err_start_stream;
}
ret = pm_runtime_resume_and_get(isc->dev);
if (ret < 0) {
v4l2_err(&isc->v4l2_dev, "RPM resume failed in subdev %d\n",
ret);
dev_err(isc->dev, "RPM resume failed in subdev %d\n",
ret);
goto err_pm_get;
}
@ -423,8 +418,7 @@ static void isc_stop_streaming(struct vb2_queue *vq)
/* Wait until the end of the current frame */
if (isc->cur_frm && !wait_for_completion_timeout(&isc->comp, 5 * HZ))
v4l2_err(&isc->v4l2_dev,
"Timeout waiting for end of the capture\n");
dev_err(isc->dev, "Timeout waiting for end of the capture\n");
mutex_unlock(&isc->awb_mutex);
@ -436,7 +430,7 @@ static void isc_stop_streaming(struct vb2_queue *vq)
/* Disable stream on the sub device */
ret = v4l2_subdev_call(isc->current_subdev->sd, video, s_stream, 0);
if (ret && ret != -ENOIOCTLCMD)
v4l2_err(&isc->v4l2_dev, "stream off failed in subdev\n");
dev_err(isc->dev, "stream off failed in subdev\n");
/* Release all active buffers */
spin_lock_irqsave(&isc->dma_queue_lock, flags);
@ -620,28 +614,28 @@ static int isc_try_validate_formats(struct isc_device *isc)
break;
default:
/* any other different formats are not supported */
v4l2_err(&isc->v4l2_dev, "Requested unsupported format.\n");
dev_err(isc->dev, "Requested unsupported format.\n");
ret = -EINVAL;
}
v4l2_dbg(1, debug, &isc->v4l2_dev,
"Format validation, requested rgb=%u, yuv=%u, grey=%u, bayer=%u\n",
rgb, yuv, grey, bayer);
dev_dbg(isc->dev,
"Format validation, requested rgb=%u, yuv=%u, grey=%u, bayer=%u\n",
rgb, yuv, grey, bayer);
if (bayer &&
!ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code)) {
v4l2_err(&isc->v4l2_dev, "Cannot output RAW if we do not receive RAW.\n");
dev_err(isc->dev, "Cannot output RAW if we do not receive RAW.\n");
return -EINVAL;
}
if (grey && !ISC_IS_FORMAT_RAW(isc->try_config.sd_format->mbus_code) &&
!ISC_IS_FORMAT_GREY(isc->try_config.sd_format->mbus_code)) {
v4l2_err(&isc->v4l2_dev, "Cannot output GREY if we do not receive RAW/GREY.\n");
dev_err(isc->dev, "Cannot output GREY if we do not receive RAW/GREY.\n");
return -EINVAL;
}
if ((rgb || bayer || yuv) &&
ISC_IS_FORMAT_GREY(isc->try_config.sd_format->mbus_code)) {
v4l2_err(&isc->v4l2_dev, "Cannot convert GREY to another format.\n");
dev_err(isc->dev, "Cannot convert GREY to another format.\n");
return -EINVAL;
}
@ -936,9 +930,9 @@ static int isc_set_fmt(struct isc_device *isc, struct v4l2_format *f)
isc->config = isc->try_config;
isc->fmt = isc->try_fmt;
v4l2_dbg(1, debug, &isc->v4l2_dev, "ISC set_fmt to %.4s @%dx%d\n",
(char *)&f->fmt.pix.pixelformat,
f->fmt.pix.width, f->fmt.pix.height);
dev_dbg(isc->dev, "ISC set_fmt to %.4s @%dx%d\n",
(char *)&f->fmt.pix.pixelformat,
f->fmt.pix.width, f->fmt.pix.height);
return 0;
}
@ -973,9 +967,9 @@ static int isc_validate(struct isc_device *isc)
/* Check if the format is not supported */
if (!sd_fmt) {
v4l2_err(&isc->v4l2_dev,
"Current subdevice is streaming a media bus code that is not supported 0x%x\n",
format.format.code);
dev_err(isc->dev,
"Current subdevice is streaming a media bus code that is not supported 0x%x\n",
format.format.code);
return -EPIPE;
}
@ -993,16 +987,16 @@ static int isc_validate(struct isc_device *isc)
/* Check if the frame size is the same. Otherwise we may overflow */
if (pixfmt->height != format.format.height ||
pixfmt->width != format.format.width) {
v4l2_err(&isc->v4l2_dev,
"ISC not configured with the proper frame size: %dx%d\n",
format.format.width, format.format.height);
dev_err(isc->dev,
"ISC not configured with the proper frame size: %dx%d\n",
format.format.width, format.format.height);
return -EPIPE;
}
v4l2_dbg(1, debug, &isc->v4l2_dev,
"Identified subdev using format %.4s with %dx%d %d bpp\n",
(char *)&sd_fmt->fourcc, pixfmt->width, pixfmt->height,
isc->try_config.bpp);
dev_dbg(isc->dev,
"Identified subdev using format %.4s with %dx%d %d bpp\n",
(char *)&sd_fmt->fourcc, pixfmt->width, pixfmt->height,
isc->try_config.bpp);
/* Reset and restart AWB if the subdevice changed the format */
if (isc->try_config.sd_format && isc->config.sd_format &&
@ -1027,7 +1021,7 @@ static int isc_validate(struct isc_device *isc)
isc->config = isc->try_config;
v4l2_dbg(1, debug, &isc->v4l2_dev, "New ISC configuration in place\n");
dev_dbg(isc->dev, "New ISC configuration in place\n");
return 0;
}
@ -1294,9 +1288,8 @@ static void isc_hist_count(struct isc_device *isc, u32 *min, u32 *max)
if (!*min)
*min = 1;
v4l2_dbg(1, debug, &isc->v4l2_dev,
"isc wb: hist_id %u, hist_count %u",
ctrls->hist_id, *hist_count);
dev_dbg(isc->dev, "isc wb: hist_id %u, hist_count %u",
ctrls->hist_id, *hist_count);
}
static void isc_wb_update(struct isc_ctrls *ctrls)
@ -1318,8 +1311,7 @@ static void isc_wb_update(struct isc_ctrls *ctrls)
(u64)hist_count[ISC_HIS_CFG_MODE_GB];
avg >>= 1;
v4l2_dbg(1, debug, &isc->v4l2_dev,
"isc wb: green components average %llu\n", avg);
dev_dbg(isc->dev, "isc wb: green components average %llu\n", avg);
/* Green histogram is null, nothing to do */
if (!avg)
@ -1373,9 +1365,9 @@ static void isc_wb_update(struct isc_ctrls *ctrls)
else
gw_gain[c] = 1 << 9;
v4l2_dbg(1, debug, &isc->v4l2_dev,
"isc wb: component %d, s_gain %u, gw_gain %u\n",
c, s_gain[c], gw_gain[c]);
dev_dbg(isc->dev,
"isc wb: component %d, s_gain %u, gw_gain %u\n",
c, s_gain[c], gw_gain[c]);
/* multiply both gains and adjust for decimals */
ctrls->gain[c] = s_gain[c] * gw_gain[c];
ctrls->gain[c] >>= 9;
@ -1383,9 +1375,8 @@ static void isc_wb_update(struct isc_ctrls *ctrls)
/* make sure we are not out of range */
ctrls->gain[c] = clamp_val(ctrls->gain[c], 0, GENMASK(12, 0));
v4l2_dbg(1, debug, &isc->v4l2_dev,
"isc wb: component %d, final gain %u\n",
c, ctrls->gain[c]);
dev_dbg(isc->dev, "isc wb: component %d, final gain %u\n",
c, ctrls->gain[c]);
}
}
@ -1406,8 +1397,8 @@ static void isc_awb_work(struct work_struct *w)
isc_hist_count(isc, &min, &max);
v4l2_dbg(1, debug, &isc->v4l2_dev,
"isc wb mode %d: hist min %u , max %u\n", hist_id, min, max);
dev_dbg(isc->dev,
"isc wb mode %d: hist min %u , max %u\n", hist_id, min, max);
ctrls->hist_minmax[hist_id][HIST_MIN_INDEX] = min;
ctrls->hist_minmax[hist_id][HIST_MAX_INDEX] = max;
@ -1446,8 +1437,8 @@ static void isc_awb_work(struct work_struct *w)
* we are basically done.
*/
if (ctrls->awb == ISC_WB_ONETIME) {
v4l2_info(&isc->v4l2_dev,
"Completed one time white-balance adjustment.\n");
dev_info(isc->dev,
"Completed one time white-balance adjustment.\n");
/* update the v4l2 controls values */
isc_update_v4l2_ctrls(isc);
ctrls->awb = ISC_WB_NONE;
@ -1580,8 +1571,7 @@ static int isc_s_awb_ctrl(struct v4l2_ctrl *ctrl)
V4L2_CTRL_FLAG_INACTIVE)) {
ctrls->awb = ISC_WB_ONETIME;
isc_set_histogram(isc, true);
v4l2_dbg(1, debug, &isc->v4l2_dev,
"One time white-balance started.\n");
dev_dbg(isc->dev, "One time white-balance started.\n");
}
return 0;
}
@ -1730,7 +1720,7 @@ static int isc_async_bound(struct v4l2_async_notifier *notifier,
int pad;
if (video_is_registered(&isc->video_dev)) {
v4l2_err(&isc->v4l2_dev, "only supports one sub-device.\n");
dev_err(isc->dev, "only supports one sub-device.\n");
return -EBUSY;
}
@ -1739,8 +1729,7 @@ static int isc_async_bound(struct v4l2_async_notifier *notifier,
pad = media_entity_get_fwnode_pad(&subdev->entity, asd->match.fwnode,
MEDIA_PAD_FL_SOURCE);
if (pad < 0) {
v4l2_err(&isc->v4l2_dev, "failed to find pad for %s\n",
subdev->name);
dev_err(isc->dev, "failed to find pad for %s\n", subdev->name);
return pad;
}
@ -1813,7 +1802,7 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
ret = v4l2_device_register_subdev_nodes(&isc->v4l2_dev);
if (ret < 0) {
v4l2_err(&isc->v4l2_dev, "Failed to register subdev nodes\n");
dev_err(isc->dev, "Failed to register subdev nodes\n");
return ret;
}
@ -1838,8 +1827,7 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
ret = vb2_queue_init(q);
if (ret < 0) {
v4l2_err(&isc->v4l2_dev,
"vb2_queue_init() failed: %d\n", ret);
dev_err(isc->dev, "vb2_queue_init() failed: %d\n", ret);
goto isc_async_complete_err;
}
@ -1850,13 +1838,13 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
ret = isc_set_default_fmt(isc);
if (ret) {
v4l2_err(&isc->v4l2_dev, "Could not set default format\n");
dev_err(isc->dev, "Could not set default format\n");
goto isc_async_complete_err;
}
ret = isc_ctrl_init(isc);
if (ret) {
v4l2_err(&isc->v4l2_dev, "Init isc ctrols failed: %d\n", ret);
dev_err(isc->dev, "Init isc ctrols failed: %d\n", ret);
goto isc_async_complete_err;
}
@ -1876,8 +1864,7 @@ static int isc_async_complete(struct v4l2_async_notifier *notifier)
ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
if (ret < 0) {
v4l2_err(&isc->v4l2_dev,
"video_register_device failed: %d\n", ret);
dev_err(isc->dev, "video_register_device failed: %d\n", ret);
goto isc_async_complete_err;
}

View File

@ -2472,19 +2472,12 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
jpeg->mode = mode;
/* Get clocks */
jpeg->clk_ipg = devm_clk_get(dev, "ipg");
if (IS_ERR(jpeg->clk_ipg)) {
dev_err(dev, "failed to get clock: ipg\n");
ret = PTR_ERR(jpeg->clk_ipg);
goto err_clk;
}
jpeg->clk_per = devm_clk_get(dev, "per");
if (IS_ERR(jpeg->clk_per)) {
dev_err(dev, "failed to get clock: per\n");
ret = PTR_ERR(jpeg->clk_per);
ret = devm_clk_bulk_get_all(&pdev->dev, &jpeg->clks);
if (ret < 0) {
dev_err(dev, "failed to get clock\n");
goto err_clk;
}
jpeg->num_clks = ret;
ret = mxc_jpeg_attach_pm_domains(jpeg);
if (ret < 0) {
@ -2581,32 +2574,20 @@ static int mxc_jpeg_runtime_resume(struct device *dev)
struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);
int ret;
ret = clk_prepare_enable(jpeg->clk_ipg);
ret = clk_bulk_prepare_enable(jpeg->num_clks, jpeg->clks);
if (ret < 0) {
dev_err(dev, "failed to enable clock: ipg\n");
goto err_ipg;
}
ret = clk_prepare_enable(jpeg->clk_per);
if (ret < 0) {
dev_err(dev, "failed to enable clock: per\n");
goto err_per;
dev_err(dev, "failed to enable clock\n");
return ret;
}
return 0;
err_per:
clk_disable_unprepare(jpeg->clk_ipg);
err_ipg:
return ret;
}
static int mxc_jpeg_runtime_suspend(struct device *dev)
{
struct mxc_jpeg_dev *jpeg = dev_get_drvdata(dev);
clk_disable_unprepare(jpeg->clk_ipg);
clk_disable_unprepare(jpeg->clk_per);
clk_bulk_disable_unprepare(jpeg->num_clks, jpeg->clks);
return 0;
}

View File

@ -120,8 +120,8 @@ struct mxc_jpeg_dev {
spinlock_t hw_lock; /* hardware access lock */
unsigned int mode;
struct mutex lock; /* v4l2 ioctls serialization */
struct clk *clk_ipg;
struct clk *clk_per;
struct clk_bulk_data *clks;
int num_clks;
struct platform_device *pdev;
struct device *dev;
void __iomem *base_reg;

View File

@ -327,10 +327,6 @@ struct mipi_csis_device {
u32 hs_settle;
u32 clk_settle;
struct mutex lock; /* Protect csis_fmt and format_mbus */
const struct csis_pix_format *csis_fmt;
struct v4l2_mbus_framefmt format_mbus[CSIS_PADS_NUM];
spinlock_t slock; /* Protect events */
struct mipi_csis_event events[MIPI_CSIS_NUM_EVENTS];
struct dentry *debugfs_root;
@ -559,10 +555,10 @@ static void mipi_csis_system_enable(struct mipi_csis_device *csis, int on)
mipi_csis_write(csis, MIPI_CSIS_DPHY_CMN_CTRL, val);
}
/* Called with the csis.lock mutex held */
static void __mipi_csis_set_format(struct mipi_csis_device *csis)
static void __mipi_csis_set_format(struct mipi_csis_device *csis,
const struct v4l2_mbus_framefmt *format,
const struct csis_pix_format *csis_fmt)
{
struct v4l2_mbus_framefmt *mf = &csis->format_mbus[CSIS_PAD_SINK];
u32 val;
/* Color format */
@ -583,25 +579,26 @@ static void __mipi_csis_set_format(struct mipi_csis_device *csis)
*
* TODO: Verify which other formats require DUAL (or QUAD) modes.
*/
if (csis->csis_fmt->data_type == MIPI_CSI2_DATA_TYPE_YUV422_8)
if (csis_fmt->data_type == MIPI_CSI2_DATA_TYPE_YUV422_8)
val |= MIPI_CSIS_ISPCFG_PIXEL_MODE_DUAL;
val |= MIPI_CSIS_ISPCFG_FMT(csis->csis_fmt->data_type);
val |= MIPI_CSIS_ISPCFG_FMT(csis_fmt->data_type);
mipi_csis_write(csis, MIPI_CSIS_ISP_CONFIG_CH(0), val);
/* Pixel resolution */
val = mf->width | (mf->height << 16);
val = format->width | (format->height << 16);
mipi_csis_write(csis, MIPI_CSIS_ISP_RESOL_CH(0), val);
}
static int mipi_csis_calculate_params(struct mipi_csis_device *csis)
static int mipi_csis_calculate_params(struct mipi_csis_device *csis,
const struct csis_pix_format *csis_fmt)
{
s64 link_freq;
u32 lane_rate;
/* Calculate the line rate from the pixel rate. */
link_freq = v4l2_get_link_freq(csis->src_sd->ctrl_handler,
csis->csis_fmt->width,
csis_fmt->width,
csis->bus.num_data_lanes * 2);
if (link_freq < 0) {
dev_err(csis->dev, "Unable to obtain link frequency: %d\n",
@ -643,7 +640,9 @@ static int mipi_csis_calculate_params(struct mipi_csis_device *csis)
return 0;
}
static void mipi_csis_set_params(struct mipi_csis_device *csis)
static void mipi_csis_set_params(struct mipi_csis_device *csis,
const struct v4l2_mbus_framefmt *format,
const struct csis_pix_format *csis_fmt)
{
int lanes = csis->bus.num_data_lanes;
u32 val;
@ -655,7 +654,7 @@ static void mipi_csis_set_params(struct mipi_csis_device *csis)
val |= MIPI_CSIS_CMN_CTRL_INTER_MODE;
mipi_csis_write(csis, MIPI_CSIS_CMN_CTRL, val);
__mipi_csis_set_format(csis);
__mipi_csis_set_format(csis, format, csis_fmt);
mipi_csis_write(csis, MIPI_CSIS_DPHY_CMN_CTRL,
MIPI_CSIS_DPHY_CMN_CTRL_HSSETTLE(csis->hs_settle) |
@ -728,10 +727,12 @@ static int mipi_csis_clk_get(struct mipi_csis_device *csis)
return ret;
}
static void mipi_csis_start_stream(struct mipi_csis_device *csis)
static void mipi_csis_start_stream(struct mipi_csis_device *csis,
const struct v4l2_mbus_framefmt *format,
const struct csis_pix_format *csis_fmt)
{
mipi_csis_sw_reset(csis);
mipi_csis_set_params(csis);
mipi_csis_set_params(csis, format, csis_fmt);
mipi_csis_system_enable(csis, true);
mipi_csis_enable_interrupts(csis, true);
}
@ -935,120 +936,63 @@ static struct mipi_csis_device *sd_to_mipi_csis_device(struct v4l2_subdev *sdev)
static int mipi_csis_s_stream(struct v4l2_subdev *sd, int enable)
{
struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
const struct v4l2_mbus_framefmt *format;
const struct csis_pix_format *csis_fmt;
struct v4l2_subdev_state *state;
int ret;
if (!enable) {
mutex_lock(&csis->lock);
v4l2_subdev_call(csis->src_sd, video, s_stream, 0);
mipi_csis_stop_stream(csis);
if (csis->debug.enable)
mipi_csis_log_counters(csis, true);
mutex_unlock(&csis->lock);
pm_runtime_put(csis->dev);
return 0;
}
ret = mipi_csis_calculate_params(csis);
state = v4l2_subdev_lock_and_get_active_state(sd);
format = v4l2_subdev_get_pad_format(sd, state, CSIS_PAD_SINK);
csis_fmt = find_csis_format(format->code);
ret = mipi_csis_calculate_params(csis, csis_fmt);
if (ret < 0)
return ret;
goto err_unlock;
mipi_csis_clear_counters(csis);
ret = pm_runtime_resume_and_get(csis->dev);
if (ret < 0)
return ret;
goto err_unlock;
mutex_lock(&csis->lock);
mipi_csis_start_stream(csis, format, csis_fmt);
mipi_csis_start_stream(csis);
ret = v4l2_subdev_call(csis->src_sd, video, s_stream, 1);
if (ret < 0)
goto error;
goto err_stop;
mipi_csis_log_counters(csis, true);
mutex_unlock(&csis->lock);
v4l2_subdev_unlock_state(state);
return 0;
error:
err_stop:
mipi_csis_stop_stream(csis);
mutex_unlock(&csis->lock);
pm_runtime_put(csis->dev);
err_unlock:
v4l2_subdev_unlock_state(state);
return ret;
}
static struct v4l2_mbus_framefmt *
mipi_csis_get_format(struct mipi_csis_device *csis,
struct v4l2_subdev_state *sd_state,
enum v4l2_subdev_format_whence which,
unsigned int pad)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
return v4l2_subdev_get_try_format(&csis->sd, sd_state, pad);
return &csis->format_mbus[pad];
}
static int mipi_csis_init_cfg(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state)
{
struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
struct v4l2_mbus_framefmt *fmt_sink;
struct v4l2_mbus_framefmt *fmt_source;
enum v4l2_subdev_format_whence which;
which = sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
fmt_sink = mipi_csis_get_format(csis, sd_state, which, CSIS_PAD_SINK);
fmt_sink->code = MEDIA_BUS_FMT_UYVY8_1X16;
fmt_sink->width = MIPI_CSIS_DEF_PIX_WIDTH;
fmt_sink->height = MIPI_CSIS_DEF_PIX_HEIGHT;
fmt_sink->field = V4L2_FIELD_NONE;
fmt_sink->colorspace = V4L2_COLORSPACE_SMPTE170M;
fmt_sink->xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt_sink->colorspace);
fmt_sink->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt_sink->colorspace);
fmt_sink->quantization =
V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt_sink->colorspace,
fmt_sink->ycbcr_enc);
fmt_source = mipi_csis_get_format(csis, sd_state, which,
CSIS_PAD_SOURCE);
*fmt_source = *fmt_sink;
return 0;
}
static int mipi_csis_get_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
struct v4l2_mbus_framefmt *fmt;
fmt = mipi_csis_get_format(csis, sd_state, sdformat->which,
sdformat->pad);
mutex_lock(&csis->lock);
sdformat->format = *fmt;
mutex_unlock(&csis->lock);
return 0;
}
static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
/*
* The CSIS can't transcode in any way, the source format is identical
* to the sink format.
@ -1059,8 +1003,7 @@ static int mipi_csis_enum_mbus_code(struct v4l2_subdev *sd,
if (code->index > 0)
return -EINVAL;
fmt = mipi_csis_get_format(csis, sd_state, code->which,
code->pad);
fmt = v4l2_subdev_get_pad_format(sd, sd_state, code->pad);
code->code = fmt->code;
return 0;
}
@ -1080,7 +1023,6 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
struct csis_pix_format const *csis_fmt;
struct v4l2_mbus_framefmt *fmt;
unsigned int align;
@ -1090,7 +1032,7 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
* modified.
*/
if (sdformat->pad == CSIS_PAD_SOURCE)
return mipi_csis_get_fmt(sd, sd_state, sdformat);
return v4l2_subdev_get_fmt(sd, sd_state, sdformat);
if (sdformat->pad != CSIS_PAD_SINK)
return -EINVAL;
@ -1128,14 +1070,12 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
&sdformat->format.height, 1,
CSIS_MAX_PIX_HEIGHT, 0, 0);
fmt = mipi_csis_get_format(csis, sd_state, sdformat->which,
sdformat->pad);
mutex_lock(&csis->lock);
fmt = v4l2_subdev_get_pad_format(sd, sd_state, sdformat->pad);
fmt->code = csis_fmt->code;
fmt->width = sdformat->format.width;
fmt->height = sdformat->format.height;
fmt->field = V4L2_FIELD_NONE;
fmt->colorspace = sdformat->format.colorspace;
fmt->quantization = sdformat->format.quantization;
fmt->xfer_func = sdformat->format.xfer_func;
@ -1144,48 +1084,65 @@ static int mipi_csis_set_fmt(struct v4l2_subdev *sd,
sdformat->format = *fmt;
/* Propagate the format from sink to source. */
fmt = mipi_csis_get_format(csis, sd_state, sdformat->which,
CSIS_PAD_SOURCE);
fmt = v4l2_subdev_get_pad_format(sd, sd_state, CSIS_PAD_SOURCE);
*fmt = sdformat->format;
/* The format on the source pad might change due to unpacking. */
fmt->code = csis_fmt->output;
/* Store the CSIS format descriptor for active formats. */
if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
csis->csis_fmt = csis_fmt;
mutex_unlock(&csis->lock);
return 0;
}
static int mipi_csis_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
struct v4l2_mbus_frame_desc *fd)
{
struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
struct v4l2_mbus_frame_desc_entry *entry = &fd->entry[0];
const struct csis_pix_format *csis_fmt;
const struct v4l2_mbus_framefmt *fmt;
struct v4l2_subdev_state *state;
if (pad != CSIS_PAD_SOURCE)
return -EINVAL;
state = v4l2_subdev_lock_and_get_active_state(sd);
fmt = v4l2_subdev_get_pad_format(sd, state, CSIS_PAD_SOURCE);
csis_fmt = find_csis_format(fmt->code);
v4l2_subdev_unlock_state(state);
fd->type = V4L2_MBUS_FRAME_DESC_TYPE_PARALLEL;
fd->num_entries = 1;
memset(entry, 0, sizeof(*entry));
mutex_lock(&csis->lock);
entry->flags = 0;
entry->pixelcode = csis->csis_fmt->code;
entry->pixelcode = csis_fmt->code;
entry->bus.csi2.vc = 0;
entry->bus.csi2.dt = csis->csis_fmt->data_type;
mutex_unlock(&csis->lock);
entry->bus.csi2.dt = csis_fmt->data_type;
return 0;
}
static int mipi_csis_init_cfg(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state)
{
struct v4l2_subdev_format fmt = {
.pad = CSIS_PAD_SINK,
};
fmt.format.code = mipi_csis_formats[0].code;
fmt.format.width = MIPI_CSIS_DEF_PIX_WIDTH;
fmt.format.height = MIPI_CSIS_DEF_PIX_HEIGHT;
fmt.format.colorspace = V4L2_COLORSPACE_SMPTE170M;
fmt.format.xfer_func = V4L2_MAP_XFER_FUNC_DEFAULT(fmt.format.colorspace);
fmt.format.ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(fmt.format.colorspace);
fmt.format.quantization =
V4L2_MAP_QUANTIZATION_DEFAULT(false, fmt.format.colorspace,
fmt.format.ycbcr_enc);
return mipi_csis_set_fmt(sd, sd_state, &fmt);
}
static int mipi_csis_log_status(struct v4l2_subdev *sd)
{
struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
@ -1208,7 +1165,7 @@ static const struct v4l2_subdev_video_ops mipi_csis_video_ops = {
static const struct v4l2_subdev_pad_ops mipi_csis_pad_ops = {
.init_cfg = mipi_csis_init_cfg,
.enum_mbus_code = mipi_csis_enum_mbus_code,
.get_fmt = mipi_csis_get_fmt,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = mipi_csis_set_fmt,
.get_frame_desc = mipi_csis_get_frame_desc,
};
@ -1348,40 +1305,34 @@ static int __maybe_unused mipi_csis_runtime_suspend(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
int ret = 0;
mutex_lock(&csis->lock);
int ret;
ret = mipi_csis_phy_disable(csis);
if (ret)
goto unlock;
return -EAGAIN;
mipi_csis_clk_disable(csis);
unlock:
mutex_unlock(&csis->lock);
return ret ? -EAGAIN : 0;
return 0;
}
static int __maybe_unused mipi_csis_runtime_resume(struct device *dev)
{
struct v4l2_subdev *sd = dev_get_drvdata(dev);
struct mipi_csis_device *csis = sd_to_mipi_csis_device(sd);
int ret = 0;
mutex_lock(&csis->lock);
int ret;
ret = mipi_csis_phy_enable(csis);
if (ret)
goto unlock;
return -EAGAIN;
mipi_csis_clk_enable(csis);
ret = mipi_csis_clk_enable(csis);
if (ret) {
mipi_csis_phy_disable(csis);
return ret;
}
unlock:
mutex_unlock(&csis->lock);
return ret ? -EAGAIN : 0;
return 0;
}
static const struct dev_pm_ops mipi_csis_pm_ops = {
@ -1396,6 +1347,7 @@ static const struct dev_pm_ops mipi_csis_pm_ops = {
static int mipi_csis_subdev_init(struct mipi_csis_device *csis)
{
struct v4l2_subdev *sd = &csis->sd;
int ret;
v4l2_subdev_init(sd, &mipi_csis_subdev_ops);
sd->owner = THIS_MODULE;
@ -1417,15 +1369,21 @@ static int mipi_csis_subdev_init(struct mipi_csis_device *csis)
return -ENOENT;
}
csis->csis_fmt = &mipi_csis_formats[0];
mipi_csis_init_cfg(sd, NULL);
csis->pads[CSIS_PAD_SINK].flags = MEDIA_PAD_FL_SINK
| MEDIA_PAD_FL_MUST_CONNECT;
csis->pads[CSIS_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE
| MEDIA_PAD_FL_MUST_CONNECT;
return media_entity_pads_init(&sd->entity, CSIS_PADS_NUM,
csis->pads);
ret = media_entity_pads_init(&sd->entity, CSIS_PADS_NUM, csis->pads);
if (ret)
return ret;
ret = v4l2_subdev_init_finalize(sd);
if (ret) {
media_entity_cleanup(&sd->entity);
return ret;
}
return 0;
}
static int mipi_csis_parse_dt(struct mipi_csis_device *csis)
@ -1450,7 +1408,6 @@ static int mipi_csis_probe(struct platform_device *pdev)
if (!csis)
return -ENOMEM;
mutex_init(&csis->lock);
spin_lock_init(&csis->slock);
csis->dev = dev;
@ -1496,20 +1453,20 @@ static int mipi_csis_probe(struct platform_device *pdev)
dev_name(dev), csis);
if (ret) {
dev_err(dev, "Interrupt request failed\n");
goto disable_clock;
goto err_disable_clock;
}
/* Initialize and register the subdev. */
ret = mipi_csis_subdev_init(csis);
if (ret < 0)
goto disable_clock;
goto err_disable_clock;
platform_set_drvdata(pdev, &csis->sd);
ret = mipi_csis_async_register(csis);
if (ret < 0) {
dev_err(dev, "async register failed: %d\n", ret);
goto cleanup;
goto err_cleanup;
}
/* Initialize debugfs. */
@ -1520,7 +1477,7 @@ static int mipi_csis_probe(struct platform_device *pdev)
if (!pm_runtime_enabled(dev)) {
ret = mipi_csis_runtime_resume(dev);
if (ret < 0)
goto unregister_all;
goto err_unregister_all;
}
dev_info(dev, "lanes: %d, freq: %u\n",
@ -1528,17 +1485,17 @@ static int mipi_csis_probe(struct platform_device *pdev)
return 0;
unregister_all:
err_unregister_all:
mipi_csis_debugfs_exit(csis);
cleanup:
err_cleanup:
v4l2_subdev_cleanup(&csis->sd);
media_entity_cleanup(&csis->sd.entity);
v4l2_async_nf_unregister(&csis->notifier);
v4l2_async_nf_cleanup(&csis->notifier);
v4l2_async_unregister_subdev(&csis->sd);
disable_clock:
err_disable_clock:
mipi_csis_clk_disable(csis);
fwnode_handle_put(csis->sd.fwnode);
mutex_destroy(&csis->lock);
return ret;
}
@ -1556,9 +1513,9 @@ static int mipi_csis_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
mipi_csis_runtime_suspend(&pdev->dev);
mipi_csis_clk_disable(csis);
v4l2_subdev_cleanup(&csis->sd);
media_entity_cleanup(&csis->sd.entity);
fwnode_handle_put(csis->sd.fwnode);
mutex_destroy(&csis->lock);
pm_runtime_set_suspended(&pdev->dev);
return 0;

View File

@ -10,6 +10,7 @@
* Pawel Osciak, <pawel@osciak.com>
* Marek Szyprowski, <m.szyprowski@samsung.com>
*/
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
@ -18,15 +19,18 @@
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <media/v4l2-mem2mem.h>
#include <media/v4l2-device.h>
#include <media/v4l2-ioctl.h>
#include <media/media-device.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/v4l2-event.h>
#include <media/v4l2-ioctl.h>
#include <media/v4l2-mem2mem.h>
#include <media/videobuf2-dma-contig.h>
#include "imx-pxp.h"
@ -52,6 +56,11 @@ MODULE_PARM_DESC(debug, "activates debug info");
#define MEM2MEM_HFLIP (1 << 0)
#define MEM2MEM_VFLIP (1 << 1)
#define PXP_VERSION_MAJOR(version) \
FIELD_GET(BM_PXP_VERSION_MAJOR, version)
#define PXP_VERSION_MINOR(version) \
FIELD_GET(BM_PXP_VERSION_MINOR, version)
#define dprintk(dev, fmt, arg...) \
v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
@ -168,14 +177,21 @@ enum {
V4L2_M2M_DST = 1,
};
static struct pxp_fmt *find_format(struct v4l2_format *f)
static const struct regmap_config pxp_regmap_config = {
.reg_bits = 32,
.reg_stride = 4,
.val_bits = 32,
.max_register = HW_PXP_VERSION,
};
static struct pxp_fmt *find_format(unsigned int pixelformat)
{
struct pxp_fmt *fmt;
unsigned int k;
for (k = 0; k < NUM_FORMATS; k++) {
fmt = &formats[k];
if (fmt->fourcc == f->fmt.pix.pixelformat)
if (fmt->fourcc == pixelformat)
break;
}
@ -185,12 +201,23 @@ static struct pxp_fmt *find_format(struct v4l2_format *f)
return &formats[k];
}
struct pxp_ctx;
struct pxp_pdata {
u32 (*data_path_ctrl0)(struct pxp_ctx *ctx);
};
struct pxp_dev {
struct v4l2_device v4l2_dev;
struct video_device vfd;
#ifdef CONFIG_MEDIA_CONTROLLER
struct media_device mdev;
#endif
struct clk *clk;
void __iomem *mmio;
struct regmap *regmap;
const struct pxp_pdata *pdata;
atomic_t num_inst;
struct mutex dev_mutex;
@ -234,6 +261,20 @@ static struct pxp_q_data *get_q_data(struct pxp_ctx *ctx,
return &ctx->q_data[V4L2_M2M_DST];
}
static inline u32 pxp_read(struct pxp_dev *dev, u32 reg)
{
u32 value;
regmap_read(dev->regmap, reg, &value);
return value;
}
static inline void pxp_write(struct pxp_dev *dev, u32 reg, u32 value)
{
regmap_write(dev->regmap, reg, value);
}
static u32 pxp_v4l2_pix_fmt_to_ps_format(u32 v4l2_pix_fmt)
{
switch (v4l2_pix_fmt) {
@ -486,11 +527,11 @@ static void pxp_setup_csc(struct pxp_ctx *ctx)
csc1_coef = csc1_coef_smpte240m_lim;
}
writel(csc1_coef[0], dev->mmio + HW_PXP_CSC1_COEF0);
writel(csc1_coef[1], dev->mmio + HW_PXP_CSC1_COEF1);
writel(csc1_coef[2], dev->mmio + HW_PXP_CSC1_COEF2);
pxp_write(dev, HW_PXP_CSC1_COEF0, csc1_coef[0]);
pxp_write(dev, HW_PXP_CSC1_COEF1, csc1_coef[1]);
pxp_write(dev, HW_PXP_CSC1_COEF2, csc1_coef[2]);
} else {
writel(BM_PXP_CSC1_COEF0_BYPASS, dev->mmio + HW_PXP_CSC1_COEF0);
pxp_write(dev, HW_PXP_CSC1_COEF0, BM_PXP_CSC1_COEF0_BYPASS);
}
if (!pxp_v4l2_pix_fmt_is_yuv(ctx->q_data[V4L2_M2M_SRC].fmt->fourcc) &&
@ -706,18 +747,95 @@ static void pxp_setup_csc(struct pxp_ctx *ctx)
BP_PXP_CSC2_CTRL_CSC_MODE;
}
writel(csc2_ctrl, dev->mmio + HW_PXP_CSC2_CTRL);
writel(csc2_coef[0], dev->mmio + HW_PXP_CSC2_COEF0);
writel(csc2_coef[1], dev->mmio + HW_PXP_CSC2_COEF1);
writel(csc2_coef[2], dev->mmio + HW_PXP_CSC2_COEF2);
writel(csc2_coef[3], dev->mmio + HW_PXP_CSC2_COEF3);
writel(csc2_coef[4], dev->mmio + HW_PXP_CSC2_COEF4);
writel(csc2_coef[5], dev->mmio + HW_PXP_CSC2_COEF5);
pxp_write(dev, HW_PXP_CSC2_CTRL, csc2_ctrl);
pxp_write(dev, HW_PXP_CSC2_COEF0, csc2_coef[0]);
pxp_write(dev, HW_PXP_CSC2_COEF1, csc2_coef[1]);
pxp_write(dev, HW_PXP_CSC2_COEF2, csc2_coef[2]);
pxp_write(dev, HW_PXP_CSC2_COEF3, csc2_coef[3]);
pxp_write(dev, HW_PXP_CSC2_COEF4, csc2_coef[4]);
pxp_write(dev, HW_PXP_CSC2_COEF5, csc2_coef[5]);
} else {
writel(BM_PXP_CSC2_CTRL_BYPASS, dev->mmio + HW_PXP_CSC2_CTRL);
pxp_write(dev, HW_PXP_CSC2_CTRL, BM_PXP_CSC2_CTRL_BYPASS);
}
}
static u32 pxp_imx6ull_data_path_ctrl0(struct pxp_ctx *ctx)
{
u32 ctrl0;
ctrl0 = 0;
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(3);
/* Bypass Dithering x3CH */
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(1);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(3);
/* Select Rotation */
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(0);
/* Bypass LUT */
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(1);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(3);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(3);
/* Select CSC 2 */
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(0);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(3);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(3);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(3);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(3);
/* Bypass Rotation 2 */
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(0);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(3);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(3);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(3);
return ctrl0;
}
static u32 pxp_imx7d_data_path_ctrl0(struct pxp_ctx *ctx)
{
u32 ctrl0;
ctrl0 = 0;
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(3);
/* Select Rotation 0 */
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(0);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(3);
/* Select MUX11 for Rotation 0 */
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(1);
/* Bypass LUT */
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(1);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(3);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(3);
/* Select CSC 2 */
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(0);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(3);
/* Select Composite Alpha Blending/Color Key 0 for CSC 2 */
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(1);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(3);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(3);
/* Bypass Rotation 1 */
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(0);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(3);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(3);
ctrl0 |= BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(3);
return ctrl0;
}
static void pxp_set_data_path(struct pxp_ctx *ctx)
{
struct pxp_dev *dev = ctx->dev;
u32 ctrl0;
u32 ctrl1;
ctrl0 = dev->pdata->data_path_ctrl0(ctx);
ctrl1 = 0;
ctrl1 |= BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(3);
ctrl1 |= BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(3);
pxp_write(dev, HW_PXP_DATA_PATH_CTRL0, ctrl0);
pxp_write(dev, HW_PXP_DATA_PATH_CTRL1, ctrl1);
}
static int pxp_start(struct pxp_ctx *ctx, struct vb2_v4l2_buffer *in_vb,
struct vb2_v4l2_buffer *out_vb)
{
@ -871,67 +989,48 @@ static int pxp_start(struct pxp_ctx *ctx, struct vb2_v4l2_buffer *in_vb,
BF_PXP_PS_SCALE_XSCALE(xscale);
ps_offset = BF_PXP_PS_OFFSET_YOFFSET(0) | BF_PXP_PS_OFFSET_XOFFSET(0);
writel(ctrl, dev->mmio + HW_PXP_CTRL);
pxp_write(dev, HW_PXP_CTRL, ctrl);
/* skip STAT */
writel(out_ctrl, dev->mmio + HW_PXP_OUT_CTRL);
writel(out_buf, dev->mmio + HW_PXP_OUT_BUF);
writel(out_buf2, dev->mmio + HW_PXP_OUT_BUF2);
writel(out_pitch, dev->mmio + HW_PXP_OUT_PITCH);
writel(out_lrc, dev->mmio + HW_PXP_OUT_LRC);
writel(out_ps_ulc, dev->mmio + HW_PXP_OUT_PS_ULC);
writel(out_ps_lrc, dev->mmio + HW_PXP_OUT_PS_LRC);
writel(as_ulc, dev->mmio + HW_PXP_OUT_AS_ULC);
writel(as_lrc, dev->mmio + HW_PXP_OUT_AS_LRC);
writel(ps_ctrl, dev->mmio + HW_PXP_PS_CTRL);
writel(ps_buf, dev->mmio + HW_PXP_PS_BUF);
writel(ps_ubuf, dev->mmio + HW_PXP_PS_UBUF);
writel(ps_vbuf, dev->mmio + HW_PXP_PS_VBUF);
writel(ps_pitch, dev->mmio + HW_PXP_PS_PITCH);
writel(0x00ffffff, dev->mmio + HW_PXP_PS_BACKGROUND_0);
writel(ps_scale, dev->mmio + HW_PXP_PS_SCALE);
writel(ps_offset, dev->mmio + HW_PXP_PS_OFFSET);
pxp_write(dev, HW_PXP_OUT_CTRL, out_ctrl);
pxp_write(dev, HW_PXP_OUT_BUF, out_buf);
pxp_write(dev, HW_PXP_OUT_BUF2, out_buf2);
pxp_write(dev, HW_PXP_OUT_PITCH, out_pitch);
pxp_write(dev, HW_PXP_OUT_LRC, out_lrc);
pxp_write(dev, HW_PXP_OUT_PS_ULC, out_ps_ulc);
pxp_write(dev, HW_PXP_OUT_PS_LRC, out_ps_lrc);
pxp_write(dev, HW_PXP_OUT_AS_ULC, as_ulc);
pxp_write(dev, HW_PXP_OUT_AS_LRC, as_lrc);
pxp_write(dev, HW_PXP_PS_CTRL, ps_ctrl);
pxp_write(dev, HW_PXP_PS_BUF, ps_buf);
pxp_write(dev, HW_PXP_PS_UBUF, ps_ubuf);
pxp_write(dev, HW_PXP_PS_VBUF, ps_vbuf);
pxp_write(dev, HW_PXP_PS_PITCH, ps_pitch);
pxp_write(dev, HW_PXP_PS_BACKGROUND_0, 0x00ffffff);
pxp_write(dev, HW_PXP_PS_SCALE, ps_scale);
pxp_write(dev, HW_PXP_PS_OFFSET, ps_offset);
/* disable processed surface color keying */
writel(0x00ffffff, dev->mmio + HW_PXP_PS_CLRKEYLOW_0);
writel(0x00000000, dev->mmio + HW_PXP_PS_CLRKEYHIGH_0);
pxp_write(dev, HW_PXP_PS_CLRKEYLOW_0, 0x00ffffff);
pxp_write(dev, HW_PXP_PS_CLRKEYHIGH_0, 0x00000000);
/* disable alpha surface color keying */
writel(0x00ffffff, dev->mmio + HW_PXP_AS_CLRKEYLOW_0);
writel(0x00000000, dev->mmio + HW_PXP_AS_CLRKEYHIGH_0);
pxp_write(dev, HW_PXP_AS_CLRKEYLOW_0, 0x00ffffff);
pxp_write(dev, HW_PXP_AS_CLRKEYHIGH_0, 0x00000000);
/* setup CSC */
pxp_setup_csc(ctx);
/* bypass LUT */
writel(BM_PXP_LUT_CTRL_BYPASS, dev->mmio + HW_PXP_LUT_CTRL);
pxp_write(dev, HW_PXP_LUT_CTRL, BM_PXP_LUT_CTRL_BYPASS);
writel(BF_PXP_DATA_PATH_CTRL0_MUX15_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX14_SEL(1)|
BF_PXP_DATA_PATH_CTRL0_MUX13_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX12_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX11_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX10_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX9_SEL(1)|
BF_PXP_DATA_PATH_CTRL0_MUX8_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX7_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX6_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX5_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX4_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX3_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX2_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX1_SEL(0)|
BF_PXP_DATA_PATH_CTRL0_MUX0_SEL(0),
dev->mmio + HW_PXP_DATA_PATH_CTRL0);
writel(BF_PXP_DATA_PATH_CTRL1_MUX17_SEL(1) |
BF_PXP_DATA_PATH_CTRL1_MUX16_SEL(1),
dev->mmio + HW_PXP_DATA_PATH_CTRL1);
pxp_set_data_path(ctx);
writel(0xffff, dev->mmio + HW_PXP_IRQ_MASK);
pxp_write(dev, HW_PXP_IRQ_MASK, 0xffff);
/* ungate, enable PS/AS/OUT and PXP operation */
writel(BM_PXP_CTRL_IRQ_ENABLE, dev->mmio + HW_PXP_CTRL_SET);
writel(BM_PXP_CTRL_ENABLE | BM_PXP_CTRL_ENABLE_CSC2 |
BM_PXP_CTRL_ENABLE_LUT | BM_PXP_CTRL_ENABLE_ROTATE0 |
BM_PXP_CTRL_ENABLE_PS_AS_OUT, dev->mmio + HW_PXP_CTRL_SET);
pxp_write(dev, HW_PXP_CTRL_SET, BM_PXP_CTRL_IRQ_ENABLE);
pxp_write(dev, HW_PXP_CTRL_SET,
BM_PXP_CTRL_ENABLE | BM_PXP_CTRL_ENABLE_CSC2 |
BM_PXP_CTRL_ENABLE_ROTATE0 | BM_PXP_CTRL_ENABLE_PS_AS_OUT);
return 0;
}
@ -1004,23 +1103,23 @@ static irqreturn_t pxp_irq_handler(int irq, void *dev_id)
struct pxp_dev *dev = dev_id;
u32 stat;
stat = readl(dev->mmio + HW_PXP_STAT);
stat = pxp_read(dev, HW_PXP_STAT);
if (stat & BM_PXP_STAT_IRQ0) {
/* we expect x = 0, y = height, irq0 = 1 */
if (stat & ~(BM_PXP_STAT_BLOCKX | BM_PXP_STAT_BLOCKY |
BM_PXP_STAT_IRQ0))
dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat);
writel(BM_PXP_STAT_IRQ0, dev->mmio + HW_PXP_STAT_CLR);
pxp_write(dev, HW_PXP_STAT_CLR, BM_PXP_STAT_IRQ0);
pxp_job_finish(dev);
} else {
u32 irq = readl(dev->mmio + HW_PXP_IRQ);
u32 irq = pxp_read(dev, HW_PXP_IRQ);
dprintk(dev, "%s: stat = 0x%08x\n", __func__, stat);
dprintk(dev, "%s: irq = 0x%08x\n", __func__, irq);
writel(irq, dev->mmio + HW_PXP_IRQ_CLR);
pxp_write(dev, HW_PXP_IRQ_CLR, irq);
}
return IRQ_HANDLED;
@ -1034,8 +1133,6 @@ static int pxp_querycap(struct file *file, void *priv,
{
strscpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
strscpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
snprintf(cap->bus_info, sizeof(cap->bus_info),
"platform:%s", MEM2MEM_NAME);
return 0;
}
@ -1181,10 +1278,10 @@ static int pxp_try_fmt_vid_cap(struct file *file, void *priv,
struct pxp_fmt *fmt;
struct pxp_ctx *ctx = file2ctx(file);
fmt = find_format(f);
fmt = find_format(f->fmt.pix.pixelformat);
if (!fmt) {
f->fmt.pix.pixelformat = formats[0].fourcc;
fmt = find_format(f);
fmt = find_format(f->fmt.pix.pixelformat);
}
if (!(fmt->types & MEM2MEM_CAPTURE)) {
v4l2_err(&ctx->dev->v4l2_dev,
@ -1209,10 +1306,10 @@ static int pxp_try_fmt_vid_out(struct file *file, void *priv,
struct pxp_fmt *fmt;
struct pxp_ctx *ctx = file2ctx(file);
fmt = find_format(f);
fmt = find_format(f->fmt.pix.pixelformat);
if (!fmt) {
f->fmt.pix.pixelformat = formats[0].fourcc;
fmt = find_format(f);
fmt = find_format(f->fmt.pix.pixelformat);
}
if (!(fmt->types & MEM2MEM_OUTPUT)) {
v4l2_err(&ctx->dev->v4l2_dev,
@ -1245,7 +1342,7 @@ static int pxp_s_fmt(struct pxp_ctx *ctx, struct v4l2_format *f)
return -EBUSY;
}
q_data->fmt = find_format(f);
q_data->fmt = find_format(f->fmt.pix.pixelformat);
q_data->width = f->fmt.pix.width;
q_data->height = f->fmt.pix.height;
q_data->bytesperline = f->fmt.pix.bytesperline;
@ -1304,6 +1401,26 @@ static int pxp_s_fmt_vid_out(struct file *file, void *priv,
return 0;
}
static int pxp_enum_framesizes(struct file *file, void *fh,
struct v4l2_frmsizeenum *fsize)
{
if (fsize->index > 0)
return -EINVAL;
if (!find_format(fsize->pixel_format))
return -EINVAL;
fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
fsize->stepwise.min_width = MIN_W;
fsize->stepwise.max_width = MAX_W;
fsize->stepwise.step_width = 1 << ALIGN_W;
fsize->stepwise.min_height = MIN_H;
fsize->stepwise.max_height = MAX_H;
fsize->stepwise.step_height = 1 << ALIGN_H;
return 0;
}
static u8 pxp_degrees_to_rot_mode(u32 degrees)
{
switch (degrees) {
@ -1372,6 +1489,8 @@ static const struct v4l2_ioctl_ops pxp_ioctl_ops = {
.vidioc_try_fmt_vid_out = pxp_try_fmt_vid_out,
.vidioc_s_fmt_vid_out = pxp_s_fmt_vid_out,
.vidioc_enum_framesizes = pxp_enum_framesizes,
.vidioc_reqbufs = v4l2_m2m_ioctl_reqbufs,
.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
@ -1644,18 +1763,18 @@ static int pxp_soft_reset(struct pxp_dev *dev)
int ret;
u32 val;
writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_CLR);
writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_CLR);
pxp_write(dev, HW_PXP_CTRL_CLR, BM_PXP_CTRL_SFTRST);
pxp_write(dev, HW_PXP_CTRL_CLR, BM_PXP_CTRL_CLKGATE);
writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_SET);
pxp_write(dev, HW_PXP_CTRL_SET, BM_PXP_CTRL_SFTRST);
ret = readl_poll_timeout(dev->mmio + HW_PXP_CTRL, val,
val & BM_PXP_CTRL_CLKGATE, 0, 100);
ret = regmap_read_poll_timeout(dev->regmap, HW_PXP_CTRL, val,
val & BM_PXP_CTRL_CLKGATE, 0, 100);
if (ret < 0)
return ret;
writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_CLR);
writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_CLR);
pxp_write(dev, HW_PXP_CTRL_CLR, BM_PXP_CTRL_SFTRST);
pxp_write(dev, HW_PXP_CTRL_CLR, BM_PXP_CTRL_CLKGATE);
return 0;
}
@ -1664,13 +1783,17 @@ static int pxp_probe(struct platform_device *pdev)
{
struct pxp_dev *dev;
struct video_device *vfd;
u32 hw_version;
int irq;
int ret;
void __iomem *mmio;
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
if (!dev)
return -ENOMEM;
dev->pdata = of_device_get_match_data(&pdev->dev);
dev->clk = devm_clk_get(&pdev->dev, "axi");
if (IS_ERR(dev->clk)) {
ret = PTR_ERR(dev->clk);
@ -1678,9 +1801,11 @@ static int pxp_probe(struct platform_device *pdev)
return ret;
}
dev->mmio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(dev->mmio))
return PTR_ERR(dev->mmio);
mmio = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(mmio))
return PTR_ERR(mmio);
dev->regmap = devm_regmap_init_mmio(&pdev->dev, mmio,
&pxp_regmap_config);
irq = platform_get_irq(pdev, 0);
if (irq < 0)
@ -1688,8 +1813,8 @@ static int pxp_probe(struct platform_device *pdev)
spin_lock_init(&dev->irqlock);
ret = devm_request_threaded_irq(&pdev->dev, irq, NULL, pxp_irq_handler,
IRQF_ONESHOT, dev_name(&pdev->dev), dev);
ret = devm_request_irq(&pdev->dev, irq, pxp_irq_handler, 0,
dev_name(&pdev->dev), dev);
if (ret < 0) {
dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
return ret;
@ -1705,6 +1830,10 @@ static int pxp_probe(struct platform_device *pdev)
goto err_clk;
}
hw_version = pxp_read(dev, HW_PXP_VERSION);
dev_dbg(&pdev->dev, "PXP Version %u.%u\n",
PXP_VERSION_MAJOR(hw_version), PXP_VERSION_MINOR(hw_version));
ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
if (ret)
goto err_clk;
@ -1737,8 +1866,34 @@ static int pxp_probe(struct platform_device *pdev)
goto err_m2m;
}
#ifdef CONFIG_MEDIA_CONTROLLER
dev->mdev.dev = &pdev->dev;
strscpy(dev->mdev.model, MEM2MEM_NAME, sizeof(dev->mdev.model));
media_device_init(&dev->mdev);
dev->v4l2_dev.mdev = &dev->mdev;
ret = v4l2_m2m_register_media_controller(dev->m2m_dev, vfd,
MEDIA_ENT_F_PROC_VIDEO_PIXEL_FORMATTER);
if (ret) {
dev_err(&pdev->dev, "Failed to initialize media device\n");
goto err_vfd;
}
ret = media_device_register(&dev->mdev);
if (ret) {
dev_err(&pdev->dev, "Failed to register media device\n");
goto err_m2m_mc;
}
#endif
return 0;
#ifdef CONFIG_MEDIA_CONTROLLER
err_m2m_mc:
v4l2_m2m_unregister_media_controller(dev->m2m_dev);
err_vfd:
video_unregister_device(vfd);
#endif
err_m2m:
v4l2_m2m_release(dev->m2m_dev);
err_v4l2:
@ -1753,12 +1908,17 @@ static int pxp_remove(struct platform_device *pdev)
{
struct pxp_dev *dev = platform_get_drvdata(pdev);
writel(BM_PXP_CTRL_CLKGATE, dev->mmio + HW_PXP_CTRL_SET);
writel(BM_PXP_CTRL_SFTRST, dev->mmio + HW_PXP_CTRL_SET);
pxp_write(dev, HW_PXP_CTRL_SET, BM_PXP_CTRL_CLKGATE);
pxp_write(dev, HW_PXP_CTRL_SET, BM_PXP_CTRL_SFTRST);
clk_disable_unprepare(dev->clk);
v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
#ifdef CONFIG_MEDIA_CONTROLLER
media_device_unregister(&dev->mdev);
v4l2_m2m_unregister_media_controller(dev->m2m_dev);
#endif
video_unregister_device(&dev->vfd);
v4l2_m2m_release(dev->m2m_dev);
v4l2_device_unregister(&dev->v4l2_dev);
@ -1766,8 +1926,17 @@ static int pxp_remove(struct platform_device *pdev)
return 0;
}
static const struct pxp_pdata pxp_imx6ull_pdata = {
.data_path_ctrl0 = pxp_imx6ull_data_path_ctrl0,
};
static const struct pxp_pdata pxp_imx7d_pdata = {
.data_path_ctrl0 = pxp_imx7d_data_path_ctrl0,
};
static const struct of_device_id pxp_dt_ids[] = {
{ .compatible = "fsl,imx6ull-pxp", .data = NULL },
{ .compatible = "fsl,imx6ull-pxp", .data = &pxp_imx6ull_pdata },
{ .compatible = "fsl,imx7d-pxp", .data = &pxp_imx7d_pdata },
{ },
};
MODULE_DEVICE_TABLE(of, pxp_dt_ids);

View File

@ -211,7 +211,6 @@ struct imx7_csi {
int irq;
struct clk *mclk;
struct mutex lock; /* Protects is_streaming, format_mbus, cc */
spinlock_t irqlock; /* Protects last_eof */
/* Media and V4L2 device */
@ -227,9 +226,6 @@ struct imx7_csi {
struct v4l2_subdev sd;
struct media_pad pad[IMX7_CSI_PADS_NUM];
struct v4l2_mbus_framefmt format_mbus[IMX7_CSI_PADS_NUM];
const struct imx7_csi_pixfmt *cc[IMX7_CSI_PADS_NUM];
/* Video device */
struct video_device *vdev; /* Video device */
struct media_pad vdev_pad; /* Video device pad */
@ -510,7 +506,8 @@ static void imx7_csi_dma_stop(struct imx7_csi *csi)
imx7_csi_hw_disable_irq(csi);
}
static void imx7_csi_configure(struct imx7_csi *csi)
static void imx7_csi_configure(struct imx7_csi *csi,
struct v4l2_subdev_state *sd_state)
{
struct v4l2_pix_format *out_pix = &csi->vdev_fmt;
int width = out_pix->width;
@ -541,12 +538,17 @@ static void imx7_csi_configure(struct imx7_csi *csi)
out_pix->pixelformat == V4L2_PIX_FMT_YUYV)
width *= 2;
} else {
const struct v4l2_mbus_framefmt *sink_fmt;
sink_fmt = v4l2_subdev_get_pad_format(&csi->sd, sd_state,
IMX7_CSI_PAD_SINK);
cr1 = BIT_SOF_POL | BIT_REDGE | BIT_HSYNC_POL | BIT_FCC
| BIT_MCLKDIV(1) | BIT_MCLKEN;
cr18 |= BIT_DATA_FROM_MIPI;
switch (csi->format_mbus[IMX7_CSI_PAD_SINK].code) {
switch (sink_fmt->code) {
case MEDIA_BUS_FMT_Y8_1X8:
case MEDIA_BUS_FMT_SBGGR8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
@ -627,7 +629,8 @@ static void imx7_csi_configure(struct imx7_csi *csi)
imx7_csi_reg_write(csi, stride, CSI_CSIFBUF_PARA);
}
static int imx7_csi_init(struct imx7_csi *csi)
static int imx7_csi_init(struct imx7_csi *csi,
struct v4l2_subdev_state *sd_state)
{
int ret;
@ -635,7 +638,7 @@ static int imx7_csi_init(struct imx7_csi *csi)
if (ret < 0)
return ret;
imx7_csi_configure(csi);
imx7_csi_configure(csi, sd_state);
ret = imx7_csi_dma_setup(csi);
if (ret < 0) {
@ -1413,14 +1416,15 @@ static void imx7_csi_video_buf_queue(struct vb2_buffer *vb)
static int imx7_csi_video_validate_fmt(struct imx7_csi *csi)
{
struct v4l2_subdev_format fmt_src;
struct v4l2_subdev_format fmt_src = {
.pad = IMX7_CSI_PAD_SRC,
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
};
const struct imx7_csi_pixfmt *cc;
int ret;
/* Retrieve the media bus format on the source subdev. */
fmt_src.pad = IMX7_CSI_PAD_SRC;
fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
ret = v4l2_subdev_call(&csi->sd, pad, get_fmt, NULL, &fmt_src);
ret = v4l2_subdev_call_state_active(&csi->sd, pad, get_fmt, &fmt_src);
if (ret)
return ret;
@ -1601,17 +1605,15 @@ static struct imx7_csi_vb2_buffer *imx7_csi_video_next_buf(struct imx7_csi *csi)
static int imx7_csi_video_init_format(struct imx7_csi *csi)
{
struct v4l2_subdev_format fmt_src = {
.pad = IMX7_CSI_PAD_SRC,
.which = V4L2_SUBDEV_FORMAT_ACTIVE,
};
fmt_src.format.code = IMX7_CSI_DEF_MBUS_CODE;
fmt_src.format.width = IMX7_CSI_DEF_PIX_WIDTH;
fmt_src.format.height = IMX7_CSI_DEF_PIX_HEIGHT;
struct v4l2_mbus_framefmt format = { };
imx7_csi_mbus_fmt_to_pix_fmt(&csi->vdev_fmt, &fmt_src.format, NULL);
csi->vdev_compose.width = fmt_src.format.width;
csi->vdev_compose.height = fmt_src.format.height;
format.code = IMX7_CSI_DEF_MBUS_CODE;
format.width = IMX7_CSI_DEF_PIX_WIDTH;
format.height = IMX7_CSI_DEF_PIX_HEIGHT;
imx7_csi_mbus_fmt_to_pix_fmt(&csi->vdev_fmt, &format, NULL);
csi->vdev_compose.width = format.width;
csi->vdev_compose.height = format.height;
csi->vdev_cc = imx7_csi_find_pixel_format(csi->vdev_fmt.pixelformat);
@ -1730,20 +1732,13 @@ static int imx7_csi_video_init(struct imx7_csi *csi)
static int imx7_csi_s_stream(struct v4l2_subdev *sd, int enable)
{
struct imx7_csi *csi = v4l2_get_subdevdata(sd);
struct v4l2_subdev_state *sd_state;
int ret = 0;
mutex_lock(&csi->lock);
if (!csi->src_sd) {
ret = -EPIPE;
goto out_unlock;
}
if (csi->is_streaming == !!enable)
goto out_unlock;
sd_state = v4l2_subdev_lock_and_get_active_state(sd);
if (enable) {
ret = imx7_csi_init(csi);
ret = imx7_csi_init(csi, sd_state);
if (ret < 0)
goto out_unlock;
@ -1765,29 +1760,14 @@ static int imx7_csi_s_stream(struct v4l2_subdev *sd, int enable)
csi->is_streaming = !!enable;
out_unlock:
mutex_unlock(&csi->lock);
v4l2_subdev_unlock_state(sd_state);
return ret;
}
static struct v4l2_mbus_framefmt *
imx7_csi_get_format(struct imx7_csi *csi,
struct v4l2_subdev_state *sd_state,
unsigned int pad,
enum v4l2_subdev_format_whence which)
{
if (which == V4L2_SUBDEV_FORMAT_TRY)
return v4l2_subdev_get_try_format(&csi->sd, sd_state, pad);
return &csi->format_mbus[pad];
}
static int imx7_csi_init_cfg(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state)
{
const enum v4l2_subdev_format_whence which =
sd_state ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
struct imx7_csi *csi = v4l2_get_subdevdata(sd);
const struct imx7_csi_pixfmt *cc;
int i;
@ -1795,7 +1775,7 @@ static int imx7_csi_init_cfg(struct v4l2_subdev *sd,
for (i = 0; i < IMX7_CSI_PADS_NUM; i++) {
struct v4l2_mbus_framefmt *mf =
imx7_csi_get_format(csi, sd_state, i, which);
v4l2_subdev_get_pad_format(sd, sd_state, i);
mf->code = IMX7_CSI_DEF_MBUS_CODE;
mf->width = IMX7_CSI_DEF_PIX_WIDTH;
@ -1807,8 +1787,6 @@ static int imx7_csi_init_cfg(struct v4l2_subdev *sd,
mf->ycbcr_enc = V4L2_MAP_YCBCR_ENC_DEFAULT(mf->colorspace);
mf->quantization = V4L2_MAP_QUANTIZATION_DEFAULT(!cc->yuv,
mf->colorspace, mf->ycbcr_enc);
csi->cc[i] = cc;
}
return 0;
@ -1818,59 +1796,30 @@ static int imx7_csi_enum_mbus_code(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_mbus_code_enum *code)
{
struct imx7_csi *csi = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *in_fmt;
int ret = 0;
mutex_lock(&csi->lock);
in_fmt = imx7_csi_get_format(csi, sd_state, IMX7_CSI_PAD_SINK,
code->which);
in_fmt = v4l2_subdev_get_pad_format(sd, sd_state, IMX7_CSI_PAD_SINK);
switch (code->pad) {
case IMX7_CSI_PAD_SINK:
ret = imx7_csi_enum_mbus_formats(&code->code, code->index);
break;
case IMX7_CSI_PAD_SRC:
if (code->index != 0) {
ret = -EINVAL;
goto out_unlock;
break;
}
code->code = in_fmt->code;
break;
default:
ret = -EINVAL;
break;
}
out_unlock:
mutex_unlock(&csi->lock);
return ret;
}
static int imx7_csi_get_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat)
{
struct imx7_csi *csi = v4l2_get_subdevdata(sd);
struct v4l2_mbus_framefmt *fmt;
int ret = 0;
mutex_lock(&csi->lock);
fmt = imx7_csi_get_format(csi, sd_state, sdformat->pad,
sdformat->which);
if (!fmt) {
ret = -EINVAL;
goto out_unlock;
}
sdformat->format = *fmt;
out_unlock:
mutex_unlock(&csi->lock);
return ret;
}
@ -1920,19 +1869,16 @@ static void imx7_csi_try_colorimetry(struct v4l2_mbus_framefmt *tryfmt)
tryfmt->ycbcr_enc);
}
static int imx7_csi_try_fmt(struct imx7_csi *csi,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat,
const struct imx7_csi_pixfmt **cc)
static void imx7_csi_try_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_state *sd_state,
struct v4l2_subdev_format *sdformat,
const struct imx7_csi_pixfmt **cc)
{
const struct imx7_csi_pixfmt *in_cc;
struct v4l2_mbus_framefmt *in_fmt;
u32 code;
in_fmt = imx7_csi_get_format(csi, sd_state, IMX7_CSI_PAD_SINK,
sdformat->which);
if (!in_fmt)
return -EINVAL;
in_fmt = v4l2_subdev_get_pad_format(sd, sd_state, IMX7_CSI_PAD_SINK);
switch (sdformat->pad) {
case IMX7_CSI_PAD_SRC:
@ -1949,6 +1895,7 @@ static int imx7_csi_try_fmt(struct imx7_csi *csi,
sdformat->format.quantization = in_fmt->quantization;
sdformat->format.ycbcr_enc = in_fmt->ycbcr_enc;
break;
case IMX7_CSI_PAD_SINK:
*cc = imx7_csi_find_mbus_format(sdformat->format.code);
if (!*cc) {
@ -1960,13 +1907,9 @@ static int imx7_csi_try_fmt(struct imx7_csi *csi,
if (sdformat->format.field != V4L2_FIELD_INTERLACED)
sdformat->format.field = V4L2_FIELD_NONE;
break;
default:
return -EINVAL;
}
imx7_csi_try_colorimetry(&sdformat->format);
return 0;
}
static int imx7_csi_set_fmt(struct v4l2_subdev *sd,
@ -1979,28 +1922,13 @@ static int imx7_csi_set_fmt(struct v4l2_subdev *sd,
const struct imx7_csi_pixfmt *cc;
struct v4l2_mbus_framefmt *fmt;
struct v4l2_subdev_format format;
int ret = 0;
if (sdformat->pad >= IMX7_CSI_PADS_NUM)
return -EINVAL;
if (csi->is_streaming)
return -EBUSY;
mutex_lock(&csi->lock);
imx7_csi_try_fmt(sd, sd_state, sdformat, &cc);
if (csi->is_streaming) {
ret = -EBUSY;
goto out_unlock;
}
ret = imx7_csi_try_fmt(csi, sd_state, sdformat, &cc);
if (ret < 0)
goto out_unlock;
fmt = imx7_csi_get_format(csi, sd_state, sdformat->pad,
sdformat->which);
if (!fmt) {
ret = -EINVAL;
goto out_unlock;
}
fmt = v4l2_subdev_get_pad_format(sd, sd_state, sdformat->pad);
*fmt = sdformat->format;
@ -2009,25 +1937,14 @@ static int imx7_csi_set_fmt(struct v4l2_subdev *sd,
format.pad = IMX7_CSI_PAD_SRC;
format.which = sdformat->which;
format.format = sdformat->format;
if (imx7_csi_try_fmt(csi, sd_state, &format, &outcc)) {
ret = -EINVAL;
goto out_unlock;
}
outfmt = imx7_csi_get_format(csi, sd_state, IMX7_CSI_PAD_SRC,
sdformat->which);
*outfmt = format.format;
imx7_csi_try_fmt(sd, sd_state, &format, &outcc);
if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
csi->cc[IMX7_CSI_PAD_SRC] = outcc;
outfmt = v4l2_subdev_get_pad_format(sd, sd_state,
IMX7_CSI_PAD_SRC);
*outfmt = format.format;
}
if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
csi->cc[sdformat->pad] = cc;
out_unlock:
mutex_unlock(&csi->lock);
return ret;
return 0;
}
static int imx7_csi_pad_link_validate(struct v4l2_subdev *sd,
@ -2040,9 +1957,6 @@ static int imx7_csi_pad_link_validate(struct v4l2_subdev *sd,
unsigned int i;
int ret;
if (!csi->src_sd)
return -EPIPE;
/*
* Validate the source link, and record whether the source uses the
* parallel input or the CSI-2 receiver.
@ -2130,7 +2044,7 @@ static const struct v4l2_subdev_video_ops imx7_csi_video_ops = {
static const struct v4l2_subdev_pad_ops imx7_csi_pad_ops = {
.init_cfg = imx7_csi_init_cfg,
.enum_mbus_code = imx7_csi_enum_mbus_code,
.get_fmt = imx7_csi_get_fmt,
.get_fmt = v4l2_subdev_get_fmt,
.set_fmt = imx7_csi_set_fmt,
.link_validate = imx7_csi_pad_link_validate,
};
@ -2203,7 +2117,7 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
ret = PTR_ERR(asd);
/* OK if asd already exists */
if (ret != -EEXIST)
return ret;
goto error;
}
}
@ -2211,15 +2125,20 @@ static int imx7_csi_async_register(struct imx7_csi *csi)
ret = v4l2_async_nf_register(&csi->v4l2_dev, &csi->notifier);
if (ret)
return ret;
goto error;
return 0;
error:
v4l2_async_nf_cleanup(&csi->notifier);
return ret;
}
static void imx7_csi_media_cleanup(struct imx7_csi *csi)
{
v4l2_device_unregister(&csi->v4l2_dev);
media_device_unregister(&csi->mdev);
v4l2_subdev_cleanup(&csi->sd);
media_device_cleanup(&csi->mdev);
}
@ -2287,6 +2206,10 @@ static int imx7_csi_media_init(struct imx7_csi *csi)
if (ret)
goto error;
ret = v4l2_subdev_init_finalize(&csi->sd);
if (ret)
goto error;
ret = v4l2_device_register_subdev(&csi->v4l2_dev, &csi->sd);
if (ret)
goto error;
@ -2312,27 +2235,22 @@ static int imx7_csi_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, csi);
spin_lock_init(&csi->irqlock);
mutex_init(&csi->lock);
/* Acquire resources and install interrupt handler. */
csi->mclk = devm_clk_get(&pdev->dev, "mclk");
if (IS_ERR(csi->mclk)) {
ret = PTR_ERR(csi->mclk);
dev_err(dev, "Failed to get mclk: %d", ret);
goto destroy_mutex;
return ret;
}
csi->irq = platform_get_irq(pdev, 0);
if (csi->irq < 0) {
ret = csi->irq;
goto destroy_mutex;
}
if (csi->irq < 0)
return csi->irq;
csi->regbase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(csi->regbase)) {
ret = PTR_ERR(csi->regbase);
goto destroy_mutex;
}
if (IS_ERR(csi->regbase))
return PTR_ERR(csi->regbase);
csi->model = (enum imx_csi_model)(uintptr_t)of_device_get_match_data(&pdev->dev);
@ -2340,34 +2258,23 @@ static int imx7_csi_probe(struct platform_device *pdev)
(void *)csi);
if (ret < 0) {
dev_err(dev, "Request CSI IRQ failed.\n");
goto destroy_mutex;
return ret;
}
/* Initialize all the media device infrastructure. */
ret = imx7_csi_media_init(csi);
if (ret)
goto destroy_mutex;
/* Set the default mbus formats. */
ret = imx7_csi_init_cfg(&csi->sd, NULL);
if (ret)
goto media_cleanup;
return ret;
ret = imx7_csi_async_register(csi);
if (ret)
goto subdev_notifier_cleanup;
goto err_media_cleanup;
return 0;
subdev_notifier_cleanup:
v4l2_async_nf_unregister(&csi->notifier);
v4l2_async_nf_cleanup(&csi->notifier);
media_cleanup:
err_media_cleanup:
imx7_csi_media_cleanup(csi);
destroy_mutex:
mutex_destroy(&csi->lock);
return ret;
}
@ -2381,8 +2288,6 @@ static int imx7_csi_remove(struct platform_device *pdev)
v4l2_async_nf_cleanup(&csi->notifier);
v4l2_async_unregister_subdev(&csi->sd);
mutex_destroy(&csi->lock);
return 0;
}

View File

@ -429,7 +429,8 @@ static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy,
array_size = ARRAY_SIZE(lane_regs_sm8250[0]);
break;
default:
unreachable();
WARN(1, "unknown cspi version\n");
return;
}
for (l = 0; l < 5; l++) {

View File

@ -406,7 +406,7 @@ static void rzg2l_csi2_mipi_link_disable(struct rzg2l_csi2 *csi2)
if (!(rzg2l_csi2_read(csi2, CSI2nRTST) & CSI2nRTST_VSRSTS))
break;
usleep_range(100, 200);
};
}
if (!timeout)
dev_err(csi2->dev, "Clearing CSI2nRTST.VSRSTS timed out\n");

View File

@ -404,7 +404,7 @@ void rzg2l_cru_stop_image_processing(struct rzg2l_cru_dev *cru)
break;
usleep_range(10, 20);
};
}
/* Notify that AXI bus can not stop here */
if (!retries)

View File

@ -1131,10 +1131,12 @@ static void rkisp1_try_fmt(const struct rkisp1_capture *cap,
const struct rkisp1_capture_config *config = cap->config;
const struct rkisp1_capture_fmt_cfg *fmt;
const struct v4l2_format_info *info;
const unsigned int max_widths[] = { RKISP1_RSZ_MP_SRC_MAX_WIDTH,
RKISP1_RSZ_SP_SRC_MAX_WIDTH };
const unsigned int max_heights[] = { RKISP1_RSZ_MP_SRC_MAX_HEIGHT,
RKISP1_RSZ_SP_SRC_MAX_HEIGHT};
static const unsigned int max_widths[] = {
RKISP1_RSZ_MP_SRC_MAX_WIDTH, RKISP1_RSZ_SP_SRC_MAX_WIDTH
};
static const unsigned int max_heights[] = {
RKISP1_RSZ_MP_SRC_MAX_HEIGHT, RKISP1_RSZ_SP_SRC_MAX_HEIGHT
};
fmt = rkisp1_find_fmt_cfg(cap, pixm->pixelformat);
if (!fmt) {
@ -1336,8 +1338,9 @@ void rkisp1_capture_devs_unregister(struct rkisp1_device *rkisp1)
static int rkisp1_register_capture(struct rkisp1_capture *cap)
{
const char * const dev_names[] = {RKISP1_MP_DEV_NAME,
RKISP1_SP_DEV_NAME};
static const char * const dev_names[] = {
RKISP1_MP_DEV_NAME, RKISP1_SP_DEV_NAME
};
struct v4l2_device *v4l2_dev = &cap->rkisp1->v4l2_dev;
struct video_device *vdev = &cap->vnode.vdev;
struct rkisp1_vdev_node *node;

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