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:
commit
83e0f265aa
|
@ -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>;
|
||||
|
|
|
@ -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>;
|
||||
};
|
|
@ -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.
|
|
@ -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:
|
||||
- |
|
|
@ -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
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
|
@ -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";
|
||||
};
|
||||
|
||||
...
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
|
@ -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
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -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>;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
...
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
...
|
|
@ -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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
|
@ -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";
|
||||
};
|
|
@ -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.
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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/>`__
|
||||
|
|
46
MAINTAINERS
46
MAINTAINERS
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
@ -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 */
|
|
@ -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)
|
||||
{
|
|
@ -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)
|
||||
{
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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 *)®->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
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
|
@ -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);
|
|
@ -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);
|
|
@ -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"
|
||||
|
|
@ -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
|
|
@ -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>
|
|
@ -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;
|
||||
|
|
@ -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));
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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++) {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue