Merge branch 'next' of git://linuxtv.org/media-ci/media-pending.git

This commit is contained in:
Stephen Rothwell 2025-01-14 11:13:15 +11:00
commit 4576dc76bc
164 changed files with 4603 additions and 6314 deletions

View File

@ -98,7 +98,7 @@ frames in packed raw Bayer format to IPU3 CSI2 receiver.
# and that ov5670 sensor is connected to i2c bus 10 with address 0x36 # and that ov5670 sensor is connected to i2c bus 10 with address 0x36
export SDEV=$(media-ctl -d $MDEV -e "ov5670 10-0036") export SDEV=$(media-ctl -d $MDEV -e "ov5670 10-0036")
# Establish the link for the media devices using media-ctl [#f3]_ # Establish the link for the media devices using media-ctl
media-ctl -d $MDEV -l "ov5670:0 -> ipu3-csi2 0:0[1]" media-ctl -d $MDEV -l "ov5670:0 -> ipu3-csi2 0:0[1]"
# Set the format for the media devices # Set the format for the media devices
@ -589,12 +589,8 @@ preserved.
References References
========== ==========
.. [#f5] drivers/staging/media/ipu3/include/uapi/intel-ipu3.h
.. [#f1] https://github.com/intel/nvt .. [#f1] https://github.com/intel/nvt
.. [#f2] http://git.ideasonboard.org/yavta.git .. [#f2] http://git.ideasonboard.org/yavta.git
.. [#f3] http://git.ideasonboard.org/?p=media-ctl.git;a=summary
.. [#f4] ImgU limitation requires an additional 16x16 for all input resolutions .. [#f4] ImgU limitation requires an additional 16x16 for all input resolutions

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/allwinner,sun50i-h6-vpu-g2.yaml# $id: http://devicetree.org/schemas/media/allwinner,sun50i-h6-vpu-g2.yaml#

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/amlogic,meson-ir-tx.yaml# $id: http://devicetree.org/schemas/media/amlogic,meson-ir-tx.yaml#

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/amphion,vpu.yaml# $id: http://devicetree.org/schemas/media/amphion,vpu.yaml#

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/fsl,imx6ull-pxp.yaml# $id: http://devicetree.org/schemas/media/fsl,imx6ull-pxp.yaml#

View File

@ -33,6 +33,8 @@ properties:
- sony,imx290lqr # Colour - sony,imx290lqr # Colour
- sony,imx290llr # Monochrome - sony,imx290llr # Monochrome
- sony,imx327lqr # Colour - sony,imx327lqr # Colour
- sony,imx462lqr # Colour
- sony,imx462llr # Monochrome
- const: sony,imx290 - const: sony,imx290
deprecated: true deprecated: true

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/mediatek,vcodec-decoder.yaml# $id: http://devicetree.org/schemas/media/mediatek,vcodec-decoder.yaml#

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/mediatek,vcodec-encoder.yaml# $id: http://devicetree.org/schemas/media/mediatek,vcodec-encoder.yaml#

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/mediatek,vcodec-subdev-decoder.yaml# $id: http://devicetree.org/schemas/media/mediatek,vcodec-subdev-decoder.yaml#

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/microchip,sama5d4-vdec.yaml# $id: http://devicetree.org/schemas/media/microchip,sama5d4-vdec.yaml#
@ -36,12 +35,12 @@ additionalProperties: false
examples: examples:
- | - |
#include <dt-bindings/clock/at91.h> #include <dt-bindings/clock/at91.h>
#include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/irq.h>
vdec0: vdec@300000 { vdec@300000 {
compatible = "microchip,sama5d4-vdec"; compatible = "microchip,sama5d4-vdec";
reg = <0x00300000 0x100000>; reg = <0x00300000 0x100000>;
interrupts = <19 IRQ_TYPE_LEVEL_HIGH 4>; interrupts = <19 IRQ_TYPE_LEVEL_HIGH 4>;
clocks = <&pmc PMC_TYPE_PERIPHERAL 19>; clocks = <&pmc PMC_TYPE_PERIPHERAL 19>;
}; };

View File

@ -21,6 +21,7 @@ properties:
enum: enum:
- fsl,imx8mn-isi - fsl,imx8mn-isi
- fsl,imx8mp-isi - fsl,imx8mp-isi
- fsl,imx8ulp-isi
- fsl,imx93-isi - fsl,imx93-isi
reg: reg:
@ -75,6 +76,7 @@ allOf:
contains: contains:
enum: enum:
- fsl,imx8mn-isi - fsl,imx8mn-isi
- fsl,imx8ulp-isi
- fsl,imx93-isi - fsl,imx93-isi
then: then:
properties: properties:

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/nxp,imx8mq-vpu.yaml# $id: http://devicetree.org/schemas/media/nxp,imx8mq-vpu.yaml#
@ -44,26 +43,26 @@ additionalProperties: false
examples: examples:
- | - |
#include <dt-bindings/clock/imx8mq-clock.h> #include <dt-bindings/clock/imx8mq-clock.h>
#include <dt-bindings/power/imx8mq-power.h> #include <dt-bindings/power/imx8mq-power.h>
#include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
vpu_g1: video-codec@38300000 { video-codec@38300000 {
compatible = "nxp,imx8mq-vpu-g1"; compatible = "nxp,imx8mq-vpu-g1";
reg = <0x38300000 0x10000>; reg = <0x38300000 0x10000>;
interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MQ_CLK_VPU_G1_ROOT>; clocks = <&clk IMX8MQ_CLK_VPU_G1_ROOT>;
power-domains = <&vpu_blk_ctrl IMX8MQ_VPUBLK_PD_G1>; power-domains = <&vpu_blk_ctrl IMX8MQ_VPUBLK_PD_G1>;
}; };
- | - |
#include <dt-bindings/clock/imx8mq-clock.h> #include <dt-bindings/clock/imx8mq-clock.h>
#include <dt-bindings/power/imx8mq-power.h> #include <dt-bindings/power/imx8mq-power.h>
#include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
vpu_g2: video-codec@38300000 { video-codec@38300000 {
compatible = "nxp,imx8mq-vpu-g2"; compatible = "nxp,imx8mq-vpu-g2";
reg = <0x38310000 0x10000>; reg = <0x38310000 0x10000>;
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clk IMX8MQ_CLK_VPU_G2_ROOT>; clocks = <&clk IMX8MQ_CLK_VPU_G2_ROOT>;
power-domains = <&vpu_blk_ctrl IMX8MQ_VPUBLK_PD_G2>; power-domains = <&vpu_blk_ctrl IMX8MQ_VPUBLK_PD_G2>;
}; };

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/qcom,msm8916-camss.yaml# $id: http://devicetree.org/schemas/media/qcom,msm8916-camss.yaml#

View File

@ -45,6 +45,7 @@ properties:
required: required:
- compatible - compatible
deprecated: true
additionalProperties: false additionalProperties: false
video-encoder: video-encoder:
@ -57,13 +58,12 @@ properties:
required: required:
- compatible - compatible
deprecated: true
additionalProperties: false additionalProperties: false
required: required:
- compatible - compatible
- iommus - iommus
- video-decoder
- video-encoder
unevaluatedProperties: false unevaluatedProperties: false
@ -83,12 +83,4 @@ examples:
power-domains = <&gcc VENUS_GDSC>; power-domains = <&gcc VENUS_GDSC>;
iommus = <&apps_iommu 5>; iommus = <&apps_iommu 5>;
memory-region = <&venus_mem>; memory-region = <&venus_mem>;
video-decoder {
compatible = "venus-decoder";
};
video-encoder {
compatible = "venus-encoder";
};
}; };

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/qcom,msm8996-camss.yaml# $id: http://devicetree.org/schemas/media/qcom,msm8996-camss.yaml#

View File

@ -70,6 +70,7 @@ properties:
required: required:
- compatible - compatible
deprecated: true
additionalProperties: false additionalProperties: false
video-encoder: video-encoder:
@ -82,14 +83,13 @@ properties:
required: required:
- compatible - compatible
deprecated: true
additionalProperties: false additionalProperties: false
required: required:
- compatible - compatible
- power-domain-names - power-domain-names
- iommus - iommus
- video-decoder
- video-encoder
unevaluatedProperties: false unevaluatedProperties: false
@ -114,12 +114,4 @@ examples:
"vcodec0_core", "vcodec0_bus"; "vcodec0_core", "vcodec0_bus";
iommus = <&apps_smmu 0x0c00 0x60>; iommus = <&apps_smmu 0x0c00 0x60>;
memory-region = <&venus_mem>; memory-region = <&venus_mem>;
video-decoder {
compatible = "venus-decoder";
};
video-encoder {
compatible = "venus-encoder";
};
}; };

View File

@ -0,0 +1,425 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/qcom,sc7280-camss.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Qualcomm SC7280 CAMSS ISP
maintainers:
- Azam Sadiq Pasha Kapatrala Syed <akapatra@quicinc.com>
- Hariram Purushothaman <hariramp@quicinc.com>
description:
The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms.
properties:
compatible:
const: qcom,sc7280-camss
reg:
maxItems: 15
reg-names:
items:
- const: csid0
- const: csid1
- const: csid2
- const: csid_lite0
- const: csid_lite1
- const: csiphy0
- const: csiphy1
- const: csiphy2
- const: csiphy3
- const: csiphy4
- const: vfe0
- const: vfe1
- const: vfe2
- const: vfe_lite0
- const: vfe_lite1
clocks:
maxItems: 33
clock-names:
items:
- const: camnoc_axi
- const: cpas_ahb
- const: csiphy0
- const: csiphy0_timer
- const: csiphy1
- const: csiphy1_timer
- const: csiphy2
- const: csiphy2_timer
- const: csiphy3
- const: csiphy3_timer
- const: csiphy4
- const: csiphy4_timer
- const: gcc_camera_ahb
- const: gcc_cam_hf_axi
- const: icp_ahb
- const: vfe0
- const: vfe0_axi
- const: vfe0_cphy_rx
- const: vfe0_csid
- const: vfe1
- const: vfe1_axi
- const: vfe1_cphy_rx
- const: vfe1_csid
- const: vfe2
- const: vfe2_axi
- const: vfe2_cphy_rx
- const: vfe2_csid
- const: vfe_lite0
- const: vfe_lite0_cphy_rx
- const: vfe_lite0_csid
- const: vfe_lite1
- const: vfe_lite1_cphy_rx
- const: vfe_lite1_csid
interrupts:
maxItems: 15
interrupt-names:
items:
- const: csid0
- const: csid1
- const: csid2
- const: csid_lite0
- const: csid_lite1
- const: csiphy0
- const: csiphy1
- const: csiphy2
- const: csiphy3
- const: csiphy4
- const: vfe0
- const: vfe1
- const: vfe2
- const: vfe_lite0
- const: vfe_lite1
interconnects:
maxItems: 2
interconnect-names:
items:
- const: ahb
- const: hf_0
iommus:
maxItems: 1
power-domains:
items:
- description: IFE0 GDSC - Image Front End, Global Distributed Switch Controller.
- description: IFE1 GDSC - Image Front End, Global Distributed Switch Controller.
- description: IFE2 GDSC - Image Front End, Global Distributed Switch Controller.
- description: Titan GDSC - Titan ISP Block, Global Distributed Switch Controller.
power-domain-names:
items:
- const: ife0
- const: ife1
- const: ife2
- const: top
vdda-phy-supply:
description:
Phandle to a regulator supply to PHY core block.
vdda-pll-supply:
description:
Phandle to 1.8V regulator supply to PHY refclk pll block.
ports:
$ref: /schemas/graph.yaml#/properties/ports
description:
CSI input ports.
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port for receiving CSI data on CSIPHY 0.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
required:
- data-lanes
port@1:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port for receiving CSI data on CSIPHY 1.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
required:
- data-lanes
port@2:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port for receiving CSI data on CSIPHY 2.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
required:
- data-lanes
port@3:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port for receiving CSI data on CSIPHY 3.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
required:
- data-lanes
port@4:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port for receiving CSI data on CSIPHY 4.
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
maxItems: 4
required:
- data-lanes
required:
- compatible
- reg
- reg-names
- clocks
- clock-names
- interrupts
- interrupt-names
- interconnects
- interconnect-names
- iommus
- power-domains
- power-domain-names
- vdda-phy-supply
- vdda-pll-supply
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/qcom,camcc-sc7280.h>
#include <dt-bindings/clock/qcom,gcc-sc7280.h>
#include <dt-bindings/interconnect/qcom,sc7280.h>
#include <dt-bindings/interconnect/qcom,icc.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/qcom-rpmpd.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
isp@acb3000 {
compatible = "qcom,sc7280-camss";
reg = <0x0 0x0acb3000 0x0 0x1000>,
<0x0 0x0acba000 0x0 0x1000>,
<0x0 0x0acc1000 0x0 0x1000>,
<0x0 0x0acc8000 0x0 0x1000>,
<0x0 0x0accf000 0x0 0x1000>,
<0x0 0x0ace0000 0x0 0x2000>,
<0x0 0x0ace2000 0x0 0x2000>,
<0x0 0x0ace4000 0x0 0x2000>,
<0x0 0x0ace6000 0x0 0x2000>,
<0x0 0x0ace8000 0x0 0x2000>,
<0x0 0x0acaf000 0x0 0x4000>,
<0x0 0x0acb6000 0x0 0x4000>,
<0x0 0x0acbd000 0x0 0x4000>,
<0x0 0x0acc4000 0x0 0x4000>,
<0x0 0x0accb000 0x0 0x4000>;
reg-names = "csid0",
"csid1",
"csid2",
"csid_lite0",
"csid_lite1",
"csiphy0",
"csiphy1",
"csiphy2",
"csiphy3",
"csiphy4",
"vfe0",
"vfe1",
"vfe2",
"vfe_lite0",
"vfe_lite1";
clocks = <&camcc CAM_CC_CAMNOC_AXI_CLK>,
<&camcc CAM_CC_CPAS_AHB_CLK>,
<&camcc CAM_CC_CSIPHY0_CLK>,
<&camcc CAM_CC_CSI0PHYTIMER_CLK>,
<&camcc CAM_CC_CSIPHY1_CLK>,
<&camcc CAM_CC_CSI1PHYTIMER_CLK>,
<&camcc CAM_CC_CSIPHY2_CLK>,
<&camcc CAM_CC_CSI2PHYTIMER_CLK>,
<&camcc CAM_CC_CSIPHY3_CLK>,
<&camcc CAM_CC_CSI3PHYTIMER_CLK>,
<&camcc CAM_CC_CSIPHY4_CLK>,
<&camcc CAM_CC_CSI4PHYTIMER_CLK>,
<&gcc GCC_CAMERA_AHB_CLK>,
<&gcc GCC_CAMERA_HF_AXI_CLK>,
<&camcc CAM_CC_ICP_AHB_CLK>,
<&camcc CAM_CC_IFE_0_CLK>,
<&camcc CAM_CC_IFE_0_AXI_CLK>,
<&camcc CAM_CC_IFE_0_CPHY_RX_CLK>,
<&camcc CAM_CC_IFE_0_CSID_CLK>,
<&camcc CAM_CC_IFE_1_CLK>,
<&camcc CAM_CC_IFE_1_AXI_CLK>,
<&camcc CAM_CC_IFE_1_CPHY_RX_CLK>,
<&camcc CAM_CC_IFE_1_CSID_CLK>,
<&camcc CAM_CC_IFE_2_CLK>,
<&camcc CAM_CC_IFE_2_AXI_CLK>,
<&camcc CAM_CC_IFE_2_CPHY_RX_CLK>,
<&camcc CAM_CC_IFE_2_CSID_CLK>,
<&camcc CAM_CC_IFE_LITE_0_CLK>,
<&camcc CAM_CC_IFE_LITE_0_CPHY_RX_CLK>,
<&camcc CAM_CC_IFE_LITE_0_CSID_CLK>,
<&camcc CAM_CC_IFE_LITE_1_CLK>,
<&camcc CAM_CC_IFE_LITE_1_CPHY_RX_CLK>,
<&camcc CAM_CC_IFE_LITE_1_CSID_CLK>;
clock-names = "camnoc_axi",
"cpas_ahb",
"csiphy0",
"csiphy0_timer",
"csiphy1",
"csiphy1_timer",
"csiphy2",
"csiphy2_timer",
"csiphy3",
"csiphy3_timer",
"csiphy4",
"csiphy4_timer",
"gcc_camera_ahb",
"gcc_cam_hf_axi",
"icp_ahb",
"vfe0",
"vfe0_axi",
"vfe0_cphy_rx",
"vfe0_csid",
"vfe1",
"vfe1_axi",
"vfe1_cphy_rx",
"vfe1_csid",
"vfe2",
"vfe2_axi",
"vfe2_cphy_rx",
"vfe2_csid",
"vfe_lite0",
"vfe_lite0_cphy_rx",
"vfe_lite0_csid",
"vfe_lite1",
"vfe_lite1_cphy_rx",
"vfe_lite1_csid";
interrupts = <GIC_SPI 464 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 466 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 640 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 468 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 359 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 477 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 478 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 479 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 448 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 122 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 465 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 467 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 641 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 469 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 360 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "csid0",
"csid1",
"csid2",
"csid_lite0",
"csid_lite1",
"csiphy0",
"csiphy1",
"csiphy2",
"csiphy3",
"csiphy4",
"vfe0",
"vfe1",
"vfe2",
"vfe_lite0",
"vfe_lite1";
interconnects = <&gem_noc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY
&cnoc2 SLAVE_CAMERA_CFG QCOM_ICC_TAG_ACTIVE_ONLY>,
<&mmss_noc MASTER_CAMNOC_HF QCOM_ICC_TAG_ALWAYS
&mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>;
interconnect-names = "ahb",
"hf_0";
iommus = <&apps_smmu 0x800 0x4e0>;
power-domains = <&camcc CAM_CC_IFE_0_GDSC>,
<&camcc CAM_CC_IFE_1_GDSC>,
<&camcc CAM_CC_IFE_2_GDSC>,
<&camcc CAM_CC_TITAN_TOP_GDSC>;
power-domain-names = "ife0",
"ife1",
"ife2",
"top";
vdda-phy-supply = <&vreg_l10c_0p88>;
vdda-pll-supply = <&vreg_l6b_1p2>;
ports {
#address-cells = <1>;
#size-cells = <0>;
};
};
};

View File

@ -68,6 +68,7 @@ properties:
required: required:
- compatible - compatible
deprecated: true
additionalProperties: false additionalProperties: false
video-encoder: video-encoder:
@ -80,14 +81,13 @@ properties:
required: required:
- compatible - compatible
deprecated: true
additionalProperties: false additionalProperties: false
required: required:
- compatible - compatible
- power-domain-names - power-domain-names
- iommus - iommus
- video-decoder
- video-encoder
unevaluatedProperties: false unevaluatedProperties: false
@ -125,14 +125,6 @@ examples:
memory-region = <&video_mem>; memory-region = <&video_mem>;
video-decoder {
compatible = "venus-decoder";
};
video-encoder {
compatible = "venus-encoder";
};
video-firmware { video-firmware {
iommus = <&apps_smmu 0x21a2 0x0>; iommus = <&apps_smmu 0x21a2 0x0>;
}; };

View File

@ -328,26 +328,26 @@ examples:
vdda-phy-supply = <&vreg_l6d>; vdda-phy-supply = <&vreg_l6d>;
vdda-pll-supply = <&vreg_l4d>; vdda-pll-supply = <&vreg_l4d>;
interrupts = <GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>, interrupts = <GIC_SPI 359 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 360 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 448 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 464 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 464 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 465 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 466 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 467 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 468 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 469 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 477 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 478 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 478 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 479 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 479 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 640 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 640 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 641 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 641 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 758 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 758 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 759 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 759 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 760 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 760 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 761 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 761 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 762 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 762 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 764 IRQ_TYPE_LEVEL_HIGH>; <GIC_SPI 764 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "csid1_lite", interrupt-names = "csid1_lite",
"vfe_lite1", "vfe_lite1",

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/qcom,sdm660-camss.yaml# $id: http://devicetree.org/schemas/media/qcom,sdm660-camss.yaml#

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/qcom,sdm845-camss.yaml# $id: http://devicetree.org/schemas/media/qcom,sdm845-camss.yaml#
@ -296,16 +295,16 @@ examples:
"vfe_lite_cphy_rx", "vfe_lite_cphy_rx",
"vfe_lite_src"; "vfe_lite_src";
interrupts = <GIC_SPI 464 IRQ_TYPE_LEVEL_HIGH>, interrupts = <GIC_SPI 464 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 466 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 468 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 477 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 478 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 478 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 479 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 479 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 448 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 465 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 467 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>; <GIC_SPI 469 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "csid0", interrupt-names = "csid0",
"csid1", "csid1",

View File

@ -70,6 +70,7 @@ properties:
required: required:
- compatible - compatible
deprecated: true
additionalProperties: false additionalProperties: false
video-core1: video-core1:
@ -82,14 +83,13 @@ properties:
required: required:
- compatible - compatible
deprecated: true
additionalProperties: false additionalProperties: false
required: required:
- compatible - compatible
- power-domain-names - power-domain-names
- iommus - iommus
- video-core0
- video-core1
unevaluatedProperties: false unevaluatedProperties: false
@ -119,12 +119,4 @@ examples:
iommus = <&apps_smmu 0x10a0 0x8>, iommus = <&apps_smmu 0x10a0 0x8>,
<&apps_smmu 0x10b0 0x0>; <&apps_smmu 0x10b0 0x0>;
memory-region = <&venus_mem>; memory-region = <&venus_mem>;
video-core0 {
compatible = "venus-decoder";
};
video-core1 {
compatible = "venus-encoder";
};
}; };

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/qcom,sm8250-camss.yaml# $id: http://devicetree.org/schemas/media/qcom,sm8250-camss.yaml#
@ -329,20 +328,20 @@ examples:
vdda-phy-supply = <&vreg_l5a_0p88>; vdda-phy-supply = <&vreg_l5a_0p88>;
vdda-pll-supply = <&vreg_l9a_1p2>; vdda-pll-supply = <&vreg_l9a_1p2>;
interrupts = <GIC_SPI 477 IRQ_TYPE_LEVEL_HIGH>, interrupts = <GIC_SPI 477 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 478 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 478 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 479 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 479 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 448 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 448 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 86 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 89 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 464 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 464 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 466 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 466 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 468 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 468 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 359 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 359 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 465 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 465 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 467 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 467 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>, <GIC_SPI 469 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 360 IRQ_TYPE_LEVEL_HIGH>; <GIC_SPI 360 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "csiphy0", interrupt-names = "csiphy0",
"csiphy1", "csiphy1",
"csiphy2", "csiphy2",

View File

@ -73,6 +73,7 @@ properties:
required: required:
- compatible - compatible
deprecated: true
additionalProperties: false additionalProperties: false
video-encoder: video-encoder:
@ -85,6 +86,7 @@ properties:
required: required:
- compatible - compatible
deprecated: true
additionalProperties: false additionalProperties: false
required: required:
@ -95,8 +97,6 @@ required:
- iommus - iommus
- resets - resets
- reset-names - reset-names
- video-decoder
- video-encoder
unevaluatedProperties: false unevaluatedProperties: false
@ -132,12 +132,4 @@ examples:
resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>, resets = <&gcc GCC_VIDEO_AXI0_CLK_ARES>,
<&videocc VIDEO_CC_MVS0C_CLK_ARES>; <&videocc VIDEO_CC_MVS0C_CLK_ARES>;
reset-names = "bus", "core"; reset-names = "bus", "core";
video-decoder {
compatible = "venus-decoder";
};
video-encoder {
compatible = "venus-encoder";
};
}; };

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/rockchip,rk3568-vepu.yaml# $id: http://devicetree.org/schemas/media/rockchip,rk3568-vepu.yaml#

View File

@ -1,5 +1,4 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) # SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
%YAML 1.2 %YAML 1.2
--- ---
$id: http://devicetree.org/schemas/media/rockchip-vpu.yaml# $id: http://devicetree.org/schemas/media/rockchip-vpu.yaml#
@ -92,18 +91,18 @@ additionalProperties: false
examples: examples:
- | - |
#include <dt-bindings/clock/rk3288-cru.h> #include <dt-bindings/clock/rk3288-cru.h>
#include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/power/rk3288-power.h> #include <dt-bindings/power/rk3288-power.h>
vpu: video-codec@ff9a0000 { video-codec@ff9a0000 {
compatible = "rockchip,rk3288-vpu"; compatible = "rockchip,rk3288-vpu";
reg = <0xff9a0000 0x800>; reg = <0xff9a0000 0x800>;
interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>, interrupts = <GIC_SPI 9 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>; <GIC_SPI 10 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "vepu", "vdpu"; interrupt-names = "vepu", "vdpu";
clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>; clocks = <&cru ACLK_VCODEC>, <&cru HCLK_VCODEC>;
clock-names = "aclk", "hclk"; clock-names = "aclk", "hclk";
power-domains = <&power RK3288_PD_VIDEO>; power-domains = <&power RK3288_PD_VIDEO>;
iommus = <&vpu_mmu>; iommus = <&vpu_mmu>;
}; };

View File

@ -12,7 +12,9 @@ maintainers:
properties: properties:
compatible: compatible:
const: st,stm32mp13-dcmipp enum:
- st,stm32mp13-dcmipp
- st,stm32mp25-dcmipp
reg: reg:
maxItems: 1 maxItems: 1
@ -21,11 +23,24 @@ properties:
maxItems: 1 maxItems: 1
clocks: clocks:
maxItems: 1 items:
- description: bus clock
- description: csi clock
minItems: 1
clock-names:
items:
- const: kclk
- const: mclk
minItems: 1
resets: resets:
maxItems: 1 maxItems: 1
access-controllers:
minItems: 1
maxItems: 2
port: port:
$ref: /schemas/graph.yaml#/$defs/port-base $ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false unevaluatedProperties: false
@ -39,7 +54,7 @@ properties:
properties: properties:
bus-type: bus-type:
enum: [5, 6] enum: [4, 5, 6]
default: 5 default: 5
bus-width: bus-width:
@ -50,9 +65,6 @@ properties:
hsync-active: true hsync-active: true
vsync-active: true vsync-active: true
required:
- pclk-sample
required: required:
- compatible - compatible
- reg - reg
@ -61,6 +73,35 @@ required:
- resets - resets
- port - port
allOf:
- if:
properties:
compatible:
contains:
enum:
- st,stm32mp13-dcmipp
then:
properties:
clocks:
maxItems: 1
clock-names:
maxItems: 1
port:
properties:
endpoint:
properties:
bus-type:
enum: [5, 6]
else:
properties:
clocks:
minItems: 2
clock-names:
minItems: 2
additionalProperties: false additionalProperties: false
examples: examples:

View File

@ -0,0 +1,125 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/media/st,stm32mp25-csi.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: STMicroelectronics STM32 CSI controller
description:
The STM32 CSI controller allows connecting a CSI based
camera to the DCMIPP camera pipeline.
maintainers:
- Alain Volmat <alain.volmat@foss.st.com>
properties:
compatible:
enum:
- st,stm32mp25-csi
reg:
maxItems: 1
interrupts:
maxItems: 1
clocks:
maxItems: 3
clock-names:
items:
- const: pclk
- const: txesc
- const: csi2phy
resets:
maxItems: 1
vdd-supply:
description: Digital core power supply (0.91V)
vdda18-supply:
description: System analog power supply (1.8V)
access-controllers:
minItems: 1
maxItems: 2
ports:
$ref: /schemas/graph.yaml#/properties/ports
properties:
port@0:
$ref: /schemas/graph.yaml#/$defs/port-base
unevaluatedProperties: false
description:
Input port node
properties:
endpoint:
$ref: video-interfaces.yaml#
unevaluatedProperties: false
properties:
data-lanes:
minItems: 1
items:
- const: 1
- const: 2
required:
- data-lanes
port@1:
$ref: /schemas/graph.yaml#/properties/port
description:
Output port node
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
- resets
- ports
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/st,stm32mp25-rcc.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/media/video-interfaces.h>
#include <dt-bindings/reset/st,stm32mp25-rcc.h>
csi@48020000 {
compatible = "st,stm32mp25-csi";
reg = <0x48020000 0x2000>;
interrupts = <GIC_SPI 142 IRQ_TYPE_LEVEL_HIGH>;
resets = <&rcc CSI_R>;
clocks = <&rcc CK_KER_CSI>, <&rcc CK_KER_CSITXESC>, <&rcc CK_KER_CSIPHY>;
clock-names = "pclk", "txesc", "csi2phy";
ports {
#address-cells = <1>;
#size-cells = <0>;
port@0 {
reg = <0>;
endpoint {
remote-endpoint = <&imx335_ep>;
data-lanes = <1 2>;
bus-type = <MEDIA_BUS_TYPE_CSI2_DPHY>;
};
};
port@1 {
reg = <1>;
endpoint {
remote-endpoint = <&dcmipp_0>;
};
};
};
};
...

View File

@ -210,6 +210,27 @@ properties:
lane-polarities property is omitted, the value must be interpreted as 0 lane-polarities property is omitted, the value must be interpreted as 0
(normal). This property is valid for serial busses only. (normal). This property is valid for serial busses only.
line-orders:
$ref: /schemas/types.yaml#/definitions/uint32-array
minItems: 1
maxItems: 8
items:
enum:
- 0 # ABC
- 1 # ACB
- 2 # BAC
- 3 # BCA
- 4 # CAB
- 5 # CBA
description:
An array of line orders of the CSI-2 C-PHY data lanes. The order of the
lanes are the same as in data-lanes property. Valid values are 0-5 as
defined in the MIPI Discovery and Configuration (DisCo) Specification for
Imaging. The length of the array must be the same length as the
data-lanes property. If the line-orders property is omitted, the value
shall be interpreted as 0 (ABC). This property is valid for CSI-2 C-PHY
busses only.
strobe: strobe:
$ref: /schemas/types.yaml#/definitions/uint32 $ref: /schemas/types.yaml#/definitions/uint32
enum: [ 0, 1 ] enum: [ 0, 1 ]

View File

@ -50,7 +50,7 @@ The :ref:`V4L2_CID_LINK_FREQ <v4l2-cid-link-freq>` control is used to tell the
receiver the frequency of the bus (i.e. it is not the same as the symbol rate). receiver the frequency of the bus (i.e. it is not the same as the symbol rate).
``.enable_streams()`` and ``.disable_streams()`` callbacks ``.enable_streams()`` and ``.disable_streams()`` callbacks
^^^^^^^^^^^^^^^^^^^^^^^^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The struct v4l2_subdev_pad_ops->enable_streams() and struct The struct v4l2_subdev_pad_ops->enable_streams() and struct
v4l2_subdev_pad_ops->disable_streams() callbacks are used by the receiver driver v4l2_subdev_pad_ops->disable_streams() callbacks are used by the receiver driver
@ -79,14 +79,15 @@ where
* - link_freq * - link_freq
- The value of the ``V4L2_CID_LINK_FREQ`` integer64 menu item. - The value of the ``V4L2_CID_LINK_FREQ`` integer64 menu item.
* - nr_of_lanes * - nr_of_lanes
- Number of data lanes used on the CSI-2 link. This can - Number of data lanes used on the CSI-2 link.
be obtained from the OF endpoint configuration.
* - 2 * - 2
- Data is transferred on both rising and falling edge of the signal. - Data is transferred on both rising and falling edge of the signal.
* - bits_per_sample * - bits_per_sample
- Number of bits per sample. - Number of bits per sample.
* - k * - k
- 16 for D-PHY and 7 for C-PHY - 16 for D-PHY and 7 for C-PHY.
Information on whether D-PHY or C-PHY is used, and the value of ``nr_of_lanes``, can be obtained from the OF endpoint configuration.
.. note:: .. note::

View File

@ -816,7 +816,7 @@ F: drivers/media/platform/sunxi/sun4i-csi/
ALLWINNER A31 CSI DRIVER ALLWINNER A31 CSI DRIVER
M: Yong Deng <yong.deng@magewell.com> M: Yong Deng <yong.deng@magewell.com>
M: Paul Kocialkowski <paul.kocialkowski@bootlin.com> M: Paul Kocialkowski <paulk@sys-base.io>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
T: git git://linuxtv.org/media.git T: git git://linuxtv.org/media.git
@ -824,7 +824,7 @@ F: Documentation/devicetree/bindings/media/allwinner,sun6i-a31-csi.yaml
F: drivers/media/platform/sunxi/sun6i-csi/ F: drivers/media/platform/sunxi/sun6i-csi/
ALLWINNER A31 ISP DRIVER ALLWINNER A31 ISP DRIVER
M: Paul Kocialkowski <paul.kocialkowski@bootlin.com> M: Paul Kocialkowski <paulk@sys-base.io>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
T: git git://linuxtv.org/media.git T: git git://linuxtv.org/media.git
@ -833,7 +833,7 @@ F: drivers/staging/media/sunxi/sun6i-isp/
F: drivers/staging/media/sunxi/sun6i-isp/uapi/sun6i-isp-config.h F: drivers/staging/media/sunxi/sun6i-isp/uapi/sun6i-isp-config.h
ALLWINNER A31 MIPI CSI-2 BRIDGE DRIVER ALLWINNER A31 MIPI CSI-2 BRIDGE DRIVER
M: Paul Kocialkowski <paul.kocialkowski@bootlin.com> M: Paul Kocialkowski <paulk@sys-base.io>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
T: git git://linuxtv.org/media.git T: git git://linuxtv.org/media.git
@ -876,7 +876,7 @@ F: drivers/thermal/sun8i_thermal.c
ALLWINNER VPU DRIVER ALLWINNER VPU DRIVER
M: Maxime Ripard <mripard@kernel.org> M: Maxime Ripard <mripard@kernel.org>
M: Paul Kocialkowski <paul.kocialkowski@bootlin.com> M: Paul Kocialkowski <paulk@sys-base.io>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
S: Maintained S: Maintained
F: drivers/staging/media/sunxi/cedrus/ F: drivers/staging/media/sunxi/cedrus/
@ -7246,7 +7246,7 @@ F: Documentation/devicetree/bindings/display/panel/lg,sw43408.yaml
F: drivers/gpu/drm/panel/panel-lg-sw43408.c F: drivers/gpu/drm/panel/panel-lg-sw43408.c
DRM DRIVER FOR LOGICVC DISPLAY CONTROLLER DRM DRIVER FOR LOGICVC DISPLAY CONTROLLER
M: Paul Kocialkowski <paul.kocialkowski@bootlin.com> M: Paul Kocialkowski <paulk@sys-base.io>
S: Supported S: Supported
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: drivers/gpu/drm/logicvc/ F: drivers/gpu/drm/logicvc/
@ -10052,7 +10052,8 @@ F: include/trace/events/handshake.h
F: net/handshake/ F: net/handshake/
HANTRO VPU CODEC DRIVER HANTRO VPU CODEC DRIVER
M: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> M: Nicolas Dufresne <nicolas.dufresne@collabora.com>
M: Benjamin Gaignard <benjamin.gaignard@collabora.com>
M: Philipp Zabel <p.zabel@pengutronix.de> M: Philipp Zabel <p.zabel@pengutronix.de>
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
L: linux-rockchip@lists.infradead.org L: linux-rockchip@lists.infradead.org
@ -14530,6 +14531,14 @@ W: https://linuxtv.org
T: git git://linuxtv.org/media.git T: git git://linuxtv.org/media.git
F: drivers/media/dvb-frontends/stv6111* F: drivers/media/dvb-frontends/stv6111*
MEDIA DRIVERS FOR STM32 - CSI
M: Alain Volmat <alain.volmat@foss.st.com>
L: linux-media@vger.kernel.org
S: Supported
T: git git://linuxtv.org/media_tree.git
F: Documentation/devicetree/bindings/media/st,stm32mp25-csi.yaml
F: drivers/media/platform/st/stm32/stm32-csi.c
MEDIA DRIVERS FOR STM32 - DCMI / DCMIPP MEDIA DRIVERS FOR STM32 - DCMI / DCMIPP
M: Hugues Fruchet <hugues.fruchet@foss.st.com> M: Hugues Fruchet <hugues.fruchet@foss.st.com>
M: Alain Volmat <alain.volmat@foss.st.com> M: Alain Volmat <alain.volmat@foss.st.com>
@ -24488,7 +24497,11 @@ L: linux-media@vger.kernel.org
S: Maintained S: Maintained
W: http://www.ideasonboard.org/uvc/ W: http://www.ideasonboard.org/uvc/
T: git git://linuxtv.org/media.git T: git git://linuxtv.org/media.git
F: Documentation/userspace-api/media/drivers/uvcvideo.rst
F: Documentation/userspace-api/media/v4l/metafmt-uvc.rst
F: drivers/media/common/uvc.c
F: drivers/media/usb/uvc/ F: drivers/media/usb/uvc/
F: include/linux/usb/uvc.h
F: include/uapi/linux/uvcvideo.h F: include/uapi/linux/uvcvideo.h
USB WEBCAM GADGET USB WEBCAM GADGET

View File

@ -7,12 +7,13 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/ktime.h> #include <linux/ktime.h>
#include <linux/slab.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>

View File

@ -5,13 +5,14 @@
* Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved. * Copyright 2016 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/ */
#include <linux/debugfs.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/kmod.h> #include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/types.h> #include <linux/types.h>

View File

@ -4,8 +4,9 @@
*/ */
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h>
#include <linux/sched/types.h> #include <linux/sched/types.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <media/cec-pin.h> #include <media/cec-pin.h>
#include "cec-pin-priv.h" #include "cec-pin-priv.h"

View File

@ -4,8 +4,9 @@
*/ */
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h>
#include <linux/sched/types.h> #include <linux/sched/types.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <media/cec-pin.h> #include <media/cec-pin.h>
#include "cec-pin-priv.h" #include "cec-pin-priv.h"

View File

@ -3,11 +3,12 @@
* Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/ */
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/gpio/consumer.h> #include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/seq_file.h>
#include <media/cec-notifier.h> #include <media/cec-notifier.h>
#include <media/cec-pin.h> #include <media/cec-pin.h>

View File

@ -125,8 +125,6 @@ void flexcop_dma_free(struct flexcop_dma *dma);
int flexcop_dma_control_timer_irq(struct flexcop_device *fc, int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
flexcop_dma_index_t no, int onoff); flexcop_dma_index_t no, int onoff);
int flexcop_dma_control_size_irq(struct flexcop_device *fc,
flexcop_dma_index_t no, int onoff);
int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma, int flexcop_dma_config(struct flexcop_device *fc, struct flexcop_dma *dma,
flexcop_dma_index_t dma_idx); flexcop_dma_index_t dma_idx);
int flexcop_dma_xfer_control(struct flexcop_device *fc, int flexcop_dma_xfer_control(struct flexcop_device *fc,
@ -170,8 +168,6 @@ int flexcop_sram_init(struct flexcop_device *fc);
void flexcop_determine_revision(struct flexcop_device *fc); void flexcop_determine_revision(struct flexcop_device *fc);
void flexcop_device_name(struct flexcop_device *fc, void flexcop_device_name(struct flexcop_device *fc,
const char *prefix, const char *suffix); const char *prefix, const char *suffix);
void flexcop_dump_reg(struct flexcop_device *fc,
flexcop_ibi_register reg, int num);
/* from flexcop-hw-filter.c */ /* from flexcop-hw-filter.c */
int flexcop_pid_feed_control(struct flexcop_device *fc, int flexcop_pid_feed_control(struct flexcop_device *fc,

View File

@ -70,16 +70,3 @@ void flexcop_device_name(struct flexcop_device *fc,
flexcop_bus_names[fc->bus_type], flexcop_bus_names[fc->bus_type],
flexcop_revision_names[fc->rev], suffix); flexcop_revision_names[fc->rev], suffix);
} }
void flexcop_dump_reg(struct flexcop_device *fc,
flexcop_ibi_register reg, int num)
{
flexcop_ibi_value v;
int i;
for (i = 0; i < num; i++) {
v = fc->read_ibi_reg(fc, reg+4*i);
deb_rdump("0x%03x: %08x, ", reg+4*i, v.raw);
}
deb_rdump("\n");
}
EXPORT_SYMBOL(flexcop_dump_reg);

View File

@ -731,7 +731,7 @@ static int dvb_dmxdev_filter_start(struct dmxdev_filter *filter)
ret = (*secfeed)->allocate_filter(*secfeed, secfilter); ret = (*secfeed)->allocate_filter(*secfeed, secfilter);
if (ret < 0) { if (ret < 0) {
dvb_dmxdev_feed_restart(filter); dvb_dmxdev_feed_restart(filter);
filter->feed.sec->start_filtering(*secfeed); *secfeed = NULL;
dprintk("could not get filter\n"); dprintk("could not get filter\n");
return ret; return ret;
} }

View File

@ -311,12 +311,8 @@ static int cxd2841er_set_reg_bits(struct cxd2841er_priv *priv,
static u32 cxd2841er_calc_iffreq_xtal(enum cxd2841er_xtal xtal, u32 ifhz) static u32 cxd2841er_calc_iffreq_xtal(enum cxd2841er_xtal xtal, u32 ifhz)
{ {
u64 tmp; return div_u64(ifhz * 16777216ull,
(xtal == SONY_XTAL_24000) ? 48000000 : 41000000);
tmp = (u64) ifhz * 16777216;
do_div(tmp, ((xtal == SONY_XTAL_24000) ? 48000000 : 41000000));
return (u32) tmp;
} }
static u32 cxd2841er_calc_iffreq(u32 ifhz) static u32 cxd2841er_calc_iffreq(u32 ifhz)

View File

@ -3335,9 +3335,11 @@ static int ccs_probe(struct i2c_client *client)
rval = request_firmware(&fw, filename, &client->dev); rval = request_firmware(&fw, filename, &client->dev);
if (!rval) { if (!rval) {
ccs_data_parse(&sensor->sdata, fw->data, fw->size, &client->dev, rval = ccs_data_parse(&sensor->sdata, fw->data, fw->size,
true); &client->dev, true);
release_firmware(fw); release_firmware(fw);
if (rval)
goto out_power_off;
} }
if (!(ccsdev->flags & CCS_DEVICE_FLAG_IS_SMIA) || if (!(ccsdev->flags & CCS_DEVICE_FLAG_IS_SMIA) ||
@ -3351,9 +3353,11 @@ static int ccs_probe(struct i2c_client *client)
rval = request_firmware(&fw, filename, &client->dev); rval = request_firmware(&fw, filename, &client->dev);
if (!rval) { if (!rval) {
ccs_data_parse(&sensor->mdata, fw->data, fw->size, rval = ccs_data_parse(&sensor->mdata, fw->data,
&client->dev, true); fw->size, &client->dev, true);
release_firmware(fw); release_firmware(fw);
if (rval)
goto out_release_sdata;
} }
} }
@ -3566,15 +3570,15 @@ out_disable_runtime_pm:
out_cleanup: out_cleanup:
ccs_cleanup(sensor); ccs_cleanup(sensor);
out_free_ccs_limits:
kfree(sensor->ccs_limits);
out_release_mdata: out_release_mdata:
kvfree(sensor->mdata.backing); kvfree(sensor->mdata.backing);
out_release_sdata: out_release_sdata:
kvfree(sensor->sdata.backing); kvfree(sensor->sdata.backing);
out_free_ccs_limits:
kfree(sensor->ccs_limits);
out_power_off: out_power_off:
ccs_power_off(&client->dev); ccs_power_off(&client->dev);
mutex_destroy(&sensor->mutex); mutex_destroy(&sensor->mutex);

View File

@ -10,6 +10,7 @@
#include <linux/limits.h> #include <linux/limits.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/string.h>
#include "ccs-data-defs.h" #include "ccs-data-defs.h"
@ -97,7 +98,7 @@ ccs_data_parse_length_specifier(const struct __ccs_data_length_specifier *__len,
plen = ((size_t) plen = ((size_t)
(__len3->length[0] & (__len3->length[0] &
((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1)) ((1 << CCS_DATA_LENGTH_SPECIFIER_SIZE_SHIFT) - 1))
<< 16) + (__len3->length[0] << 8) + __len3->length[1]; << 16) + (__len3->length[1] << 8) + __len3->length[2];
break; break;
} }
default: default:
@ -948,15 +949,15 @@ int ccs_data_parse(struct ccs_data_container *ccsdata, const void *data,
rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, verbose); rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, verbose);
if (rval) if (rval)
return rval; goto out_cleanup;
rval = bin_backing_alloc(&bin); rval = bin_backing_alloc(&bin);
if (rval) if (rval)
return rval; goto out_cleanup;
rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, false); rval = __ccs_data_parse(&bin, ccsdata, data, len, dev, false);
if (rval) if (rval)
goto out_free; goto out_cleanup;
if (verbose && ccsdata->version) if (verbose && ccsdata->version)
print_ccs_data_version(dev, ccsdata->version); print_ccs_data_version(dev, ccsdata->version);
@ -965,15 +966,17 @@ int ccs_data_parse(struct ccs_data_container *ccsdata, const void *data,
rval = -EPROTO; rval = -EPROTO;
dev_dbg(dev, "parsing mismatch; base %p; now %p; end %p\n", dev_dbg(dev, "parsing mismatch; base %p; now %p; end %p\n",
bin.base, bin.now, bin.end); bin.base, bin.now, bin.end);
goto out_free; goto out_cleanup;
} }
ccsdata->backing = bin.base; ccsdata->backing = bin.base;
return 0; return 0;
out_free: out_cleanup:
kvfree(bin.base); kvfree(bin.base);
memset(ccsdata, 0, sizeof(*ccsdata));
dev_warn(dev, "failed to parse CCS static data: %d\n", rval);
return rval; return rval;
} }

View File

@ -8,6 +8,7 @@
* Copyright (c) 2023 Tomi Valkeinen <tomi.valkeinen@ideasonboard.com> * Copyright (c) 2023 Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>
*/ */
#include <linux/bitfield.h>
#include <linux/clk-provider.h> #include <linux/clk-provider.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/delay.h> #include <linux/delay.h>
@ -146,6 +147,19 @@ static int ub913_write(const struct ub913_data *priv, u8 reg, u8 val)
return ret; return ret;
} }
static int ub913_update_bits(const struct ub913_data *priv, u8 reg, u8 mask,
u8 val)
{
int ret;
ret = regmap_update_bits(priv->regmap, reg, mask, val);
if (ret < 0)
dev_err(&priv->client->dev,
"Cannot update register 0x%02x %d!\n", reg, ret);
return ret;
}
/* /*
* GPIO chip * GPIO chip
*/ */
@ -733,10 +747,13 @@ static int ub913_hw_init(struct ub913_data *priv)
if (ret) if (ret)
return dev_err_probe(dev, ret, "i2c master init failed\n"); return dev_err_probe(dev, ret, "i2c master init failed\n");
ub913_read(priv, UB913_REG_GENERAL_CFG, &v); ret = ub913_update_bits(priv, UB913_REG_GENERAL_CFG,
v &= ~UB913_REG_GENERAL_CFG_PCLK_RISING; UB913_REG_GENERAL_CFG_PCLK_RISING,
v |= priv->pclk_polarity_rising ? UB913_REG_GENERAL_CFG_PCLK_RISING : 0; FIELD_PREP(UB913_REG_GENERAL_CFG_PCLK_RISING,
ub913_write(priv, UB913_REG_GENERAL_CFG, v); priv->pclk_polarity_rising));
if (ret)
return ret;
return 0; return 0;
} }
@ -793,7 +810,6 @@ static void ub913_subdev_uninit(struct ub913_data *priv)
v4l2_async_unregister_subdev(&priv->sd); v4l2_async_unregister_subdev(&priv->sd);
ub913_v4l2_nf_unregister(priv); ub913_v4l2_nf_unregister(priv);
v4l2_subdev_cleanup(&priv->sd); v4l2_subdev_cleanup(&priv->sd);
fwnode_handle_put(priv->sd.fwnode);
media_entity_cleanup(&priv->sd.entity); media_entity_cleanup(&priv->sd.entity);
} }

View File

@ -65,6 +65,9 @@
#define UB953_REG_GPIO_INPUT_CTRL_OUT_EN(n) BIT(4 + (n)) #define UB953_REG_GPIO_INPUT_CTRL_OUT_EN(n) BIT(4 + (n))
#define UB953_REG_GPIO_INPUT_CTRL_INPUT_EN(n) BIT(0 + (n)) #define UB953_REG_GPIO_INPUT_CTRL_INPUT_EN(n) BIT(0 + (n))
#define UB953_REG_BC_CTRL 0x49
#define UB953_REG_BC_CTRL_CRC_ERR_CLR BIT(3)
#define UB953_REG_REV_MASK_ID 0x50 #define UB953_REG_REV_MASK_ID 0x50
#define UB953_REG_GENERAL_STATUS 0x52 #define UB953_REG_GENERAL_STATUS 0x52
@ -397,8 +400,13 @@ static int ub953_gpiochip_probe(struct ub953_data *priv)
int ret; int ret;
/* Set all GPIOs to local input mode */ /* Set all GPIOs to local input mode */
ub953_write(priv, UB953_REG_LOCAL_GPIO_DATA, 0); ret = ub953_write(priv, UB953_REG_LOCAL_GPIO_DATA, 0);
ub953_write(priv, UB953_REG_GPIO_INPUT_CTRL, 0xf); if (ret)
return ret;
ret = ub953_write(priv, UB953_REG_GPIO_INPUT_CTRL, 0xf);
if (ret)
return ret;
gc->label = dev_name(dev); gc->label = dev_name(dev);
gc->parent = dev; gc->parent = dev;
@ -618,6 +626,12 @@ static int ub953_log_status(struct v4l2_subdev *sd)
ub953_read(priv, UB953_REG_CRC_ERR_CNT2, &v2); ub953_read(priv, UB953_REG_CRC_ERR_CNT2, &v2);
dev_info(dev, "CRC error count %u\n", v1 | (v2 << 8)); dev_info(dev, "CRC error count %u\n", v1 | (v2 << 8));
/* Clear CRC error counter */
if (v1 || v2)
regmap_update_bits(priv->regmap, UB953_REG_BC_CTRL,
UB953_REG_BC_CTRL_CRC_ERR_CLR,
UB953_REG_BC_CTRL_CRC_ERR_CLR);
ub953_read(priv, UB953_REG_CSI_ERR_CNT, &v); ub953_read(priv, UB953_REG_CSI_ERR_CNT, &v);
dev_info(dev, "CSI error count %u\n", v); dev_info(dev, "CSI error count %u\n", v);
@ -958,10 +972,11 @@ static void ub953_calc_clkout_params(struct ub953_data *priv,
clkout_data->rate = clkout_rate; clkout_data->rate = clkout_rate;
} }
static void ub953_write_clkout_regs(struct ub953_data *priv, static int ub953_write_clkout_regs(struct ub953_data *priv,
const struct ub953_clkout_data *clkout_data) const struct ub953_clkout_data *clkout_data)
{ {
u8 clkout_ctrl0, clkout_ctrl1; u8 clkout_ctrl0, clkout_ctrl1;
int ret;
if (priv->hw_data->is_ub971) if (priv->hw_data->is_ub971)
clkout_ctrl0 = clkout_data->m; clkout_ctrl0 = clkout_data->m;
@ -971,8 +986,15 @@ static void ub953_write_clkout_regs(struct ub953_data *priv,
clkout_ctrl1 = clkout_data->n; clkout_ctrl1 = clkout_data->n;
ub953_write(priv, UB953_REG_CLKOUT_CTRL0, clkout_ctrl0); ret = ub953_write(priv, UB953_REG_CLKOUT_CTRL0, clkout_ctrl0);
ub953_write(priv, UB953_REG_CLKOUT_CTRL1, clkout_ctrl1); if (ret)
return ret;
ret = ub953_write(priv, UB953_REG_CLKOUT_CTRL1, clkout_ctrl1);
if (ret)
return ret;
return 0;
} }
static unsigned long ub953_clkout_recalc_rate(struct clk_hw *hw, static unsigned long ub953_clkout_recalc_rate(struct clk_hw *hw,
@ -1052,9 +1074,7 @@ static int ub953_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
dev_dbg(&priv->client->dev, "%s %lu (requested %lu)\n", __func__, dev_dbg(&priv->client->dev, "%s %lu (requested %lu)\n", __func__,
clkout_data.rate, rate); clkout_data.rate, rate);
ub953_write_clkout_regs(priv, &clkout_data); return ub953_write_clkout_regs(priv, &clkout_data);
return 0;
} }
static const struct clk_ops ub953_clkout_ops = { static const struct clk_ops ub953_clkout_ops = {
@ -1079,7 +1099,9 @@ static int ub953_register_clkout(struct ub953_data *priv)
/* Initialize clkout to 25MHz by default */ /* Initialize clkout to 25MHz by default */
ub953_calc_clkout_params(priv, UB953_DEFAULT_CLKOUT_RATE, &clkout_data); ub953_calc_clkout_params(priv, UB953_DEFAULT_CLKOUT_RATE, &clkout_data);
ub953_write_clkout_regs(priv, &clkout_data); ret = ub953_write_clkout_regs(priv, &clkout_data);
if (ret)
return ret;
priv->clkout_clk_hw.init = &init; priv->clkout_clk_hw.init = &init;
@ -1226,10 +1248,15 @@ static int ub953_hw_init(struct ub953_data *priv)
if (ret) if (ret)
return dev_err_probe(dev, ret, "i2c init failed\n"); return dev_err_probe(dev, ret, "i2c init failed\n");
ub953_write(priv, UB953_REG_GENERAL_CFG, v = 0;
(priv->non_continous_clk ? 0 : UB953_REG_GENERAL_CFG_CONT_CLK) | v |= priv->non_continous_clk ? 0 : UB953_REG_GENERAL_CFG_CONT_CLK;
((priv->num_data_lanes - 1) << UB953_REG_GENERAL_CFG_CSI_LANE_SEL_SHIFT) | v |= (priv->num_data_lanes - 1) <<
UB953_REG_GENERAL_CFG_CRC_TX_GEN_ENABLE); UB953_REG_GENERAL_CFG_CSI_LANE_SEL_SHIFT;
v |= UB953_REG_GENERAL_CFG_CRC_TX_GEN_ENABLE;
ret = ub953_write(priv, UB953_REG_GENERAL_CFG, v);
if (ret)
return ret;
return 0; return 0;
} }
@ -1288,7 +1315,6 @@ static void ub953_subdev_uninit(struct ub953_data *priv)
v4l2_async_unregister_subdev(&priv->sd); v4l2_async_unregister_subdev(&priv->sd);
ub953_v4l2_notifier_unregister(priv); ub953_v4l2_notifier_unregister(priv);
v4l2_subdev_cleanup(&priv->sd); v4l2_subdev_cleanup(&priv->sd);
fwnode_handle_put(priv->sd.fwnode);
media_entity_cleanup(&priv->sd.entity); media_entity_cleanup(&priv->sd.entity);
} }

View File

@ -43,6 +43,7 @@
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/units.h>
#include <linux/workqueue.h> #include <linux/workqueue.h>
#include <media/i2c/ds90ub9xx.h> #include <media/i2c/ds90ub9xx.h>
@ -51,7 +52,16 @@
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h> #include <media/v4l2-subdev.h>
#define MHZ(v) ((u32)((v) * 1000000U)) #define MHZ(v) ((u32)((v) * HZ_PER_MHZ))
/*
* If this is defined, the i2c addresses from UB960_DEBUG_I2C_RX_ID to
* UB960_DEBUG_I2C_RX_ID + 3 can be used to access the paged RX port registers
* directly.
*
* Only for debug purposes.
*/
/* #define UB960_DEBUG_I2C_RX_ID 0x40 */
#define UB960_POLL_TIME_MS 500 #define UB960_POLL_TIME_MS 500
@ -349,12 +359,13 @@
#define UB960_SR_FPD3_RX_ID(n) (0xf0 + (n)) #define UB960_SR_FPD3_RX_ID(n) (0xf0 + (n))
#define UB960_SR_FPD3_RX_ID_LEN 6 #define UB960_SR_FPD3_RX_ID_LEN 6
#define UB960_SR_I2C_RX_ID(n) (0xf8 + (n)) /* < UB960_FPD_RX_NPORTS */ #define UB960_SR_I2C_RX_ID(n) (0xf8 + (n))
#define UB9702_SR_REFCLK_FREQ 0x3d
/* Indirect register blocks */ /* Indirect register blocks */
#define UB960_IND_TARGET_PAT_GEN 0x00 #define UB960_IND_TARGET_PAT_GEN 0x00
#define UB960_IND_TARGET_RX_ANA(n) (0x01 + (n)) #define UB960_IND_TARGET_RX_ANA(n) (0x01 + (n))
#define UB960_IND_TARGET_CSI_CSIPLL_REG_1 0x92 /* UB9702 */
#define UB960_IND_TARGET_CSI_ANA 0x07 #define UB960_IND_TARGET_CSI_ANA 0x07
/* UB960_IR_PGEN_*: Indirect Registers for Test Pattern Generator */ /* UB960_IR_PGEN_*: Indirect Registers for Test Pattern Generator */
@ -568,11 +579,23 @@ struct ub960_format_info {
}; };
static const struct ub960_format_info ub960_formats[] = { static const struct ub960_format_info ub960_formats[] = {
{ .code = MEDIA_BUS_FMT_RGB888_1X24, .bpp = 24, .datatype = MIPI_CSI2_DT_RGB888, },
{ .code = MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, }, { .code = MEDIA_BUS_FMT_YUYV8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, },
{ .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, }, { .code = MEDIA_BUS_FMT_UYVY8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, },
{ .code = MEDIA_BUS_FMT_VYUY8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, }, { .code = MEDIA_BUS_FMT_VYUY8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, },
{ .code = MEDIA_BUS_FMT_YVYU8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, }, { .code = MEDIA_BUS_FMT_YVYU8_1X16, .bpp = 16, .datatype = MIPI_CSI2_DT_YUV422_8B, },
{ .code = MEDIA_BUS_FMT_SBGGR8_1X8, .bpp = 8, .datatype = MIPI_CSI2_DT_RAW8, },
{ .code = MEDIA_BUS_FMT_SGBRG8_1X8, .bpp = 8, .datatype = MIPI_CSI2_DT_RAW8, },
{ .code = MEDIA_BUS_FMT_SGRBG8_1X8, .bpp = 8, .datatype = MIPI_CSI2_DT_RAW8, },
{ .code = MEDIA_BUS_FMT_SRGGB8_1X8, .bpp = 8, .datatype = MIPI_CSI2_DT_RAW8, },
{ .code = MEDIA_BUS_FMT_SBGGR10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
{ .code = MEDIA_BUS_FMT_SGBRG10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
{ .code = MEDIA_BUS_FMT_SGRBG10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
{ .code = MEDIA_BUS_FMT_SRGGB10_1X10, .bpp = 10, .datatype = MIPI_CSI2_DT_RAW10, },
{ .code = MEDIA_BUS_FMT_SBGGR12_1X12, .bpp = 12, .datatype = MIPI_CSI2_DT_RAW12, }, { .code = MEDIA_BUS_FMT_SBGGR12_1X12, .bpp = 12, .datatype = MIPI_CSI2_DT_RAW12, },
{ .code = MEDIA_BUS_FMT_SGBRG12_1X12, .bpp = 12, .datatype = MIPI_CSI2_DT_RAW12, }, { .code = MEDIA_BUS_FMT_SGBRG12_1X12, .bpp = 12, .datatype = MIPI_CSI2_DT_RAW12, },
{ .code = MEDIA_BUS_FMT_SGRBG12_1X12, .bpp = 12, .datatype = MIPI_CSI2_DT_RAW12, }, { .code = MEDIA_BUS_FMT_SGRBG12_1X12, .bpp = 12, .datatype = MIPI_CSI2_DT_RAW12, },
@ -1552,7 +1575,12 @@ static int ub960_rxport_wait_locks(struct ub960_data *priv,
if (missing == 0) if (missing == 0)
break; break;
msleep(50); /*
* The sleep time of 10 ms was found by testing to give a lock
* with a few iterations. It can be decreased if on some setups
* the lock can be achieved much faster.
*/
fsleep(10 * USEC_PER_MSEC);
} }
if (lock_mask) if (lock_mask)
@ -1574,16 +1602,24 @@ static int ub960_rxport_wait_locks(struct ub960_data *priv,
ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v); ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v);
ret = ub960_rxport_get_strobe_pos(priv, nport, &strobe_pos); if (priv->hw_data->is_ub9702) {
if (ret) dev_dbg(dev, "\trx%u: locked, freq %llu Hz\n",
return ret; nport, ((u64)v * HZ_PER_MHZ) >> 8);
} else {
ret = ub960_rxport_get_strobe_pos(priv, nport,
&strobe_pos);
if (ret)
return ret;
ret = ub960_rxport_get_eq_level(priv, nport, &eq_level); ret = ub960_rxport_get_eq_level(priv, nport, &eq_level);
if (ret) if (ret)
return ret; return ret;
dev_dbg(dev, "\trx%u: locked, SP: %d, EQ: %u, freq %llu Hz\n", dev_dbg(dev,
nport, strobe_pos, eq_level, (v * 1000000ULL) >> 8); "\trx%u: locked, SP: %d, EQ: %u, freq %llu Hz\n",
nport, strobe_pos, eq_level,
((u64)v * HZ_PER_MHZ) >> 8);
}
} }
return 0; return 0;
@ -2412,7 +2448,6 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
} rx_data[UB960_MAX_RX_NPORTS] = {}; } rx_data[UB960_MAX_RX_NPORTS] = {};
u8 vc_map[UB960_MAX_RX_NPORTS] = {}; u8 vc_map[UB960_MAX_RX_NPORTS] = {};
struct v4l2_subdev_route *route; struct v4l2_subdev_route *route;
unsigned int nport;
int ret; int ret;
ret = ub960_validate_stream_vcs(priv); ret = ub960_validate_stream_vcs(priv);
@ -2482,7 +2517,8 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
*/ */
fwd_ctl = GENMASK(7, 4); fwd_ctl = GENMASK(7, 4);
for (nport = 0; nport < priv->hw_data->num_rxports; nport++) { for (unsigned int nport = 0; nport < priv->hw_data->num_rxports;
nport++) {
struct ub960_rxport *rxport = priv->rxports[nport]; struct ub960_rxport *rxport = priv->rxports[nport];
u8 vc = vc_map[nport]; u8 vc = vc_map[nport];
@ -2522,7 +2558,7 @@ static int ub960_configure_ports_for_streaming(struct ub960_data *priv,
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
ub960_rxport_write(priv, nport, ub960_rxport_write(priv, nport,
UB960_RR_VC_ID_MAP(i), UB960_RR_VC_ID_MAP(i),
nport); (nport << 4) | nport);
} }
break; break;
@ -2939,20 +2975,78 @@ static const struct v4l2_subdev_pad_ops ub960_pad_ops = {
.set_fmt = ub960_set_fmt, .set_fmt = ub960_set_fmt,
}; };
static void ub960_log_status_ub960_sp_eq(struct ub960_data *priv,
unsigned int nport)
{
struct device *dev = &priv->client->dev;
u8 eq_level;
s8 strobe_pos;
int ret;
u8 v;
/* Strobe */
ret = ub960_read(priv, UB960_XR_AEQ_CTL1, &v);
if (ret)
return;
dev_info(dev, "\t%s strobe\n",
(v & UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN) ? "Adaptive" :
"Manual");
if (v & UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN) {
ret = ub960_read(priv, UB960_XR_SFILTER_CFG, &v);
if (ret)
return;
dev_info(dev, "\tStrobe range [%d, %d]\n",
((v >> UB960_XR_SFILTER_CFG_SFILTER_MIN_SHIFT) & 0xf) - 7,
((v >> UB960_XR_SFILTER_CFG_SFILTER_MAX_SHIFT) & 0xf) - 7);
}
ret = ub960_rxport_get_strobe_pos(priv, nport, &strobe_pos);
if (ret)
return;
dev_info(dev, "\tStrobe pos %d\n", strobe_pos);
/* EQ */
ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_BYPASS, &v);
if (ret)
return;
dev_info(dev, "\t%s EQ\n",
(v & UB960_RR_AEQ_BYPASS_ENABLE) ? "Manual" :
"Adaptive");
if (!(v & UB960_RR_AEQ_BYPASS_ENABLE)) {
ret = ub960_rxport_read(priv, nport, UB960_RR_AEQ_MIN_MAX, &v);
if (ret)
return;
dev_info(dev, "\tEQ range [%u, %u]\n",
(v >> UB960_RR_AEQ_MIN_MAX_AEQ_FLOOR_SHIFT) & 0xf,
(v >> UB960_RR_AEQ_MIN_MAX_AEQ_MAX_SHIFT) & 0xf);
}
if (ub960_rxport_get_eq_level(priv, nport, &eq_level) == 0)
dev_info(dev, "\tEQ level %u\n", eq_level);
}
static int ub960_log_status(struct v4l2_subdev *sd) static int ub960_log_status(struct v4l2_subdev *sd)
{ {
struct ub960_data *priv = sd_to_ub960(sd); struct ub960_data *priv = sd_to_ub960(sd);
struct device *dev = &priv->client->dev; struct device *dev = &priv->client->dev;
struct v4l2_subdev_state *state; struct v4l2_subdev_state *state;
unsigned int nport; unsigned int nport;
unsigned int i;
u16 v16 = 0; u16 v16 = 0;
u8 v = 0; u8 v = 0;
u8 id[UB960_SR_FPD3_RX_ID_LEN]; u8 id[UB960_SR_FPD3_RX_ID_LEN];
state = v4l2_subdev_lock_and_get_active_state(sd); state = v4l2_subdev_lock_and_get_active_state(sd);
for (i = 0; i < sizeof(id); i++) for (unsigned int i = 0; i < sizeof(id); i++)
ub960_read(priv, UB960_SR_FPD3_RX_ID(i), &id[i]); ub960_read(priv, UB960_SR_FPD3_RX_ID(i), &id[i]);
dev_info(dev, "ID '%.*s'\n", (int)sizeof(id), id); dev_info(dev, "ID '%.*s'\n", (int)sizeof(id), id);
@ -2986,9 +3080,6 @@ static int ub960_log_status(struct v4l2_subdev *sd)
for (nport = 0; nport < priv->hw_data->num_rxports; nport++) { for (nport = 0; nport < priv->hw_data->num_rxports; nport++) {
struct ub960_rxport *rxport = priv->rxports[nport]; struct ub960_rxport *rxport = priv->rxports[nport];
u8 eq_level;
s8 strobe_pos;
unsigned int i;
dev_info(dev, "RX %u\n", nport); dev_info(dev, "RX %u\n", nport);
@ -3009,7 +3100,7 @@ static int ub960_log_status(struct v4l2_subdev *sd)
dev_info(dev, "\trx_port_sts2 %#02x\n", v); dev_info(dev, "\trx_port_sts2 %#02x\n", v);
ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v16); ub960_rxport_read16(priv, nport, UB960_RR_RX_FREQ_HIGH, &v16);
dev_info(dev, "\tlink freq %llu Hz\n", (v16 * 1000000ULL) >> 8); dev_info(dev, "\tlink freq %llu Hz\n", ((u64)v16 * HZ_PER_MHZ) >> 8);
ub960_rxport_read16(priv, nport, UB960_RR_RX_PAR_ERR_HI, &v16); ub960_rxport_read16(priv, nport, UB960_RR_RX_PAR_ERR_HI, &v16);
dev_info(dev, "\tparity errors %u\n", v16); dev_info(dev, "\tparity errors %u\n", v16);
@ -3023,47 +3114,11 @@ static int ub960_log_status(struct v4l2_subdev *sd)
ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER, &v); ub960_rxport_read(priv, nport, UB960_RR_CSI_ERR_COUNTER, &v);
dev_info(dev, "\tcsi_err_counter %u\n", v); dev_info(dev, "\tcsi_err_counter %u\n", v);
/* Strobe */ if (!priv->hw_data->is_ub9702)
ub960_log_status_ub960_sp_eq(priv, nport);
ub960_read(priv, UB960_XR_AEQ_CTL1, &v);
dev_info(dev, "\t%s strobe\n",
(v & UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN) ? "Adaptive" :
"Manual");
if (v & UB960_XR_AEQ_CTL1_AEQ_SFILTER_EN) {
ub960_read(priv, UB960_XR_SFILTER_CFG, &v);
dev_info(dev, "\tStrobe range [%d, %d]\n",
((v >> UB960_XR_SFILTER_CFG_SFILTER_MIN_SHIFT) & 0xf) - 7,
((v >> UB960_XR_SFILTER_CFG_SFILTER_MAX_SHIFT) & 0xf) - 7);
}
ub960_rxport_get_strobe_pos(priv, nport, &strobe_pos);
dev_info(dev, "\tStrobe pos %d\n", strobe_pos);
/* EQ */
ub960_rxport_read(priv, nport, UB960_RR_AEQ_BYPASS, &v);
dev_info(dev, "\t%s EQ\n",
(v & UB960_RR_AEQ_BYPASS_ENABLE) ? "Manual" :
"Adaptive");
if (!(v & UB960_RR_AEQ_BYPASS_ENABLE)) {
ub960_rxport_read(priv, nport, UB960_RR_AEQ_MIN_MAX, &v);
dev_info(dev, "\tEQ range [%u, %u]\n",
(v >> UB960_RR_AEQ_MIN_MAX_AEQ_FLOOR_SHIFT) & 0xf,
(v >> UB960_RR_AEQ_MIN_MAX_AEQ_MAX_SHIFT) & 0xf);
}
if (ub960_rxport_get_eq_level(priv, nport, &eq_level) == 0)
dev_info(dev, "\tEQ level %u\n", eq_level);
/* GPIOs */ /* GPIOs */
for (i = 0; i < UB960_NUM_BC_GPIOS; i++) { for (unsigned int i = 0; i < UB960_NUM_BC_GPIOS; i++) {
u8 ctl_reg; u8 ctl_reg;
u8 ctl_shift; u8 ctl_shift;
@ -3834,13 +3889,16 @@ static int ub960_enable_core_hw(struct ub960_data *priv)
if (ret) if (ret)
goto err_pd_gpio; goto err_pd_gpio;
ret = ub960_read(priv, UB960_XR_REFCLK_FREQ, &refclk_freq); if (priv->hw_data->is_ub9702)
ret = ub960_read(priv, UB9702_SR_REFCLK_FREQ, &refclk_freq);
else
ret = ub960_read(priv, UB960_XR_REFCLK_FREQ, &refclk_freq);
if (ret) if (ret)
goto err_pd_gpio; goto err_pd_gpio;
dev_dbg(dev, "refclk valid %u freq %u MHz (clk fw freq %lu MHz)\n", dev_dbg(dev, "refclk valid %u freq %u MHz (clk fw freq %lu MHz)\n",
!!(dev_sts & BIT(4)), refclk_freq, !!(dev_sts & BIT(4)), refclk_freq,
clk_get_rate(priv->refclk) / 1000000); clk_get_rate(priv->refclk) / HZ_PER_MHZ);
/* Disable all RX ports by default */ /* Disable all RX ports by default */
ret = ub960_write(priv, UB960_SR_RX_PORT_CTL, 0); ret = ub960_write(priv, UB960_SR_RX_PORT_CTL, 0);
@ -3974,6 +4032,12 @@ static int ub960_probe(struct i2c_client *client)
schedule_delayed_work(&priv->poll_work, schedule_delayed_work(&priv->poll_work,
msecs_to_jiffies(UB960_POLL_TIME_MS)); msecs_to_jiffies(UB960_POLL_TIME_MS));
#ifdef UB960_DEBUG_I2C_RX_ID
for (unsigned int i = 0; i < priv->hw_data->num_rxports; i++)
ub960_write(priv, UB960_SR_I2C_RX_ID(i),
(UB960_DEBUG_I2C_RX_ID + i) << 1);
#endif
return 0; return 0;
err_free_sers: err_free_sers:

View File

@ -814,7 +814,7 @@ out_unlock:
} }
static ssize_t otp_read(struct file *filp, struct kobject *kobj, static ssize_t otp_read(struct file *filp, struct kobject *kobj,
struct bin_attribute *bin_attr, const struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count) char *buf, loff_t off, size_t count)
{ {
struct i2c_client *client = to_i2c_client(kobj_to_dev(kobj)); struct i2c_client *client = to_i2c_client(kobj_to_dev(kobj));

View File

@ -170,12 +170,15 @@ enum imx290_model {
IMX290_MODEL_IMX290LQR, IMX290_MODEL_IMX290LQR,
IMX290_MODEL_IMX290LLR, IMX290_MODEL_IMX290LLR,
IMX290_MODEL_IMX327LQR, IMX290_MODEL_IMX327LQR,
IMX290_MODEL_IMX462LQR,
IMX290_MODEL_IMX462LLR,
}; };
struct imx290_model_info { struct imx290_model_info {
enum imx290_colour_variant colour_variant; enum imx290_colour_variant colour_variant;
const struct cci_reg_sequence *init_regs; const struct cci_reg_sequence *init_regs;
size_t init_regs_num; size_t init_regs_num;
unsigned int max_analog_gain;
const char *name; const char *name;
}; };
@ -267,7 +270,6 @@ static const struct cci_reg_sequence imx290_global_init_settings[] = {
{ IMX290_WINWV, 1097 }, { IMX290_WINWV, 1097 },
{ IMX290_XSOUTSEL, IMX290_XSOUTSEL_XVSOUTSEL_VSYNC | { IMX290_XSOUTSEL, IMX290_XSOUTSEL_XVSOUTSEL_VSYNC |
IMX290_XSOUTSEL_XHSOUTSEL_HSYNC }, IMX290_XSOUTSEL_XHSOUTSEL_HSYNC },
{ CCI_REG8(0x3011), 0x02 },
{ CCI_REG8(0x3012), 0x64 }, { CCI_REG8(0x3012), 0x64 },
{ CCI_REG8(0x3013), 0x00 }, { CCI_REG8(0x3013), 0x00 },
}; };
@ -275,6 +277,51 @@ static const struct cci_reg_sequence imx290_global_init_settings[] = {
static const struct cci_reg_sequence imx290_global_init_settings_290[] = { static const struct cci_reg_sequence imx290_global_init_settings_290[] = {
{ CCI_REG8(0x300f), 0x00 }, { CCI_REG8(0x300f), 0x00 },
{ CCI_REG8(0x3010), 0x21 }, { CCI_REG8(0x3010), 0x21 },
{ CCI_REG8(0x3011), 0x00 },
{ CCI_REG8(0x3016), 0x09 },
{ CCI_REG8(0x3070), 0x02 },
{ CCI_REG8(0x3071), 0x11 },
{ CCI_REG8(0x309b), 0x10 },
{ CCI_REG8(0x309c), 0x22 },
{ CCI_REG8(0x30a2), 0x02 },
{ CCI_REG8(0x30a6), 0x20 },
{ CCI_REG8(0x30a8), 0x20 },
{ CCI_REG8(0x30aa), 0x20 },
{ CCI_REG8(0x30ac), 0x20 },
{ CCI_REG8(0x30b0), 0x43 },
{ CCI_REG8(0x3119), 0x9e },
{ CCI_REG8(0x311c), 0x1e },
{ CCI_REG8(0x311e), 0x08 },
{ CCI_REG8(0x3128), 0x05 },
{ CCI_REG8(0x313d), 0x83 },
{ CCI_REG8(0x3150), 0x03 },
{ CCI_REG8(0x317e), 0x00 },
{ CCI_REG8(0x32b8), 0x50 },
{ CCI_REG8(0x32b9), 0x10 },
{ CCI_REG8(0x32ba), 0x00 },
{ CCI_REG8(0x32bb), 0x04 },
{ CCI_REG8(0x32c8), 0x50 },
{ CCI_REG8(0x32c9), 0x10 },
{ CCI_REG8(0x32ca), 0x00 },
{ CCI_REG8(0x32cb), 0x04 },
{ CCI_REG8(0x332c), 0xd3 },
{ CCI_REG8(0x332d), 0x10 },
{ CCI_REG8(0x332e), 0x0d },
{ CCI_REG8(0x3358), 0x06 },
{ CCI_REG8(0x3359), 0xe1 },
{ CCI_REG8(0x335a), 0x11 },
{ CCI_REG8(0x3360), 0x1e },
{ CCI_REG8(0x3361), 0x61 },
{ CCI_REG8(0x3362), 0x10 },
{ CCI_REG8(0x33b0), 0x50 },
{ CCI_REG8(0x33b2), 0x1a },
{ CCI_REG8(0x33b3), 0x04 },
};
static const struct cci_reg_sequence imx290_global_init_settings_462[] = {
{ CCI_REG8(0x300f), 0x00 },
{ CCI_REG8(0x3010), 0x21 },
{ CCI_REG8(0x3011), 0x02 },
{ CCI_REG8(0x3016), 0x09 }, { CCI_REG8(0x3016), 0x09 },
{ CCI_REG8(0x3070), 0x02 }, { CCI_REG8(0x3070), 0x02 },
{ CCI_REG8(0x3071), 0x11 }, { CCI_REG8(0x3071), 0x11 },
@ -328,6 +375,7 @@ static const struct cci_reg_sequence xclk_regs[][IMX290_NUM_CLK_REGS] = {
}; };
static const struct cci_reg_sequence imx290_global_init_settings_327[] = { static const struct cci_reg_sequence imx290_global_init_settings_327[] = {
{ CCI_REG8(0x3011), 0x02 },
{ CCI_REG8(0x309e), 0x4A }, { CCI_REG8(0x309e), 0x4A },
{ CCI_REG8(0x309f), 0x4A }, { CCI_REG8(0x309f), 0x4A },
{ CCI_REG8(0x313b), 0x61 }, { CCI_REG8(0x313b), 0x61 },
@ -876,14 +924,10 @@ static int imx290_ctrl_init(struct imx290 *imx290)
* up to 72.0dB (240) add further digital gain. Limit the range to * up to 72.0dB (240) add further digital gain. Limit the range to
* analog gain only, support for digital gain can be added separately * analog gain only, support for digital gain can be added separately
* if needed. * if needed.
*
* The IMX327 and IMX462 are largely compatible with the IMX290, but
* have an analog gain range of 0.0dB to 29.4dB and 42dB of digital
* gain. When support for those sensors gets added to the driver, the
* gain control should be adjusted accordingly.
*/ */
v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops, v4l2_ctrl_new_std(&imx290->ctrls, &imx290_ctrl_ops,
V4L2_CID_ANALOGUE_GAIN, 0, 100, 1, 0); V4L2_CID_ANALOGUE_GAIN, 0,
imx290->model->max_analog_gain, 1, 0);
/* /*
* Correct range will be determined through imx290_ctrl_update setting * Correct range will be determined through imx290_ctrl_update setting
@ -1441,20 +1485,37 @@ static const struct imx290_model_info imx290_models[] = {
.colour_variant = IMX290_VARIANT_COLOUR, .colour_variant = IMX290_VARIANT_COLOUR,
.init_regs = imx290_global_init_settings_290, .init_regs = imx290_global_init_settings_290,
.init_regs_num = ARRAY_SIZE(imx290_global_init_settings_290), .init_regs_num = ARRAY_SIZE(imx290_global_init_settings_290),
.max_analog_gain = 100,
.name = "imx290", .name = "imx290",
}, },
[IMX290_MODEL_IMX290LLR] = { [IMX290_MODEL_IMX290LLR] = {
.colour_variant = IMX290_VARIANT_MONO, .colour_variant = IMX290_VARIANT_MONO,
.init_regs = imx290_global_init_settings_290, .init_regs = imx290_global_init_settings_290,
.init_regs_num = ARRAY_SIZE(imx290_global_init_settings_290), .init_regs_num = ARRAY_SIZE(imx290_global_init_settings_290),
.max_analog_gain = 100,
.name = "imx290", .name = "imx290",
}, },
[IMX290_MODEL_IMX327LQR] = { [IMX290_MODEL_IMX327LQR] = {
.colour_variant = IMX290_VARIANT_COLOUR, .colour_variant = IMX290_VARIANT_COLOUR,
.init_regs = imx290_global_init_settings_327, .init_regs = imx290_global_init_settings_327,
.init_regs_num = ARRAY_SIZE(imx290_global_init_settings_327), .init_regs_num = ARRAY_SIZE(imx290_global_init_settings_327),
.max_analog_gain = 98,
.name = "imx327", .name = "imx327",
}, },
[IMX290_MODEL_IMX462LQR] = {
.colour_variant = IMX290_VARIANT_COLOUR,
.init_regs = imx290_global_init_settings_462,
.init_regs_num = ARRAY_SIZE(imx290_global_init_settings_462),
.max_analog_gain = 98,
.name = "imx462",
},
[IMX290_MODEL_IMX462LLR] = {
.colour_variant = IMX290_VARIANT_MONO,
.init_regs = imx290_global_init_settings_462,
.init_regs_num = ARRAY_SIZE(imx290_global_init_settings_462),
.max_analog_gain = 98,
.name = "imx462",
},
}; };
static int imx290_parse_dt(struct imx290 *imx290) static int imx290_parse_dt(struct imx290 *imx290)
@ -1653,6 +1714,12 @@ static const struct of_device_id imx290_of_match[] = {
}, { }, {
.compatible = "sony,imx327lqr", .compatible = "sony,imx327lqr",
.data = &imx290_models[IMX290_MODEL_IMX327LQR], .data = &imx290_models[IMX290_MODEL_IMX327LQR],
}, {
.compatible = "sony,imx462lqr",
.data = &imx290_models[IMX290_MODEL_IMX462LQR],
}, {
.compatible = "sony,imx462llr",
.data = &imx290_models[IMX290_MODEL_IMX462LLR],
}, },
{ /* sentinel */ }, { /* sentinel */ },
}; };

View File

@ -954,6 +954,8 @@ static int imx296_identify_model(struct imx296 *sensor)
return ret; return ret;
} }
usleep_range(2000, 5000);
ret = imx296_read(sensor, IMX296_SENSOR_INFO); ret = imx296_read(sensor, IMX296_SENSOR_INFO);
if (ret < 0) { if (ret < 0) {
dev_err(sensor->dev, "failed to read sensor information (%d)\n", dev_err(sensor->dev, "failed to read sensor information (%d)\n",

View File

@ -547,7 +547,7 @@ static int imx412_update_exp_gain(struct imx412 *imx412, u32 exposure, u32 gain)
lpfr = imx412->vblank + imx412->cur_mode->height; lpfr = imx412->vblank + imx412->cur_mode->height;
dev_dbg(imx412->dev, "Set exp %u, analog gain %u, lpfr %u", dev_dbg(imx412->dev, "Set exp %u, analog gain %u, lpfr %u\n",
exposure, gain, lpfr); exposure, gain, lpfr);
ret = imx412_write_reg(imx412, IMX412_REG_HOLD, 1, 1); ret = imx412_write_reg(imx412, IMX412_REG_HOLD, 1, 1);
@ -594,7 +594,7 @@ static int imx412_set_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_VBLANK: case V4L2_CID_VBLANK:
imx412->vblank = imx412->vblank_ctrl->val; imx412->vblank = imx412->vblank_ctrl->val;
dev_dbg(imx412->dev, "Received vblank %u, new lpfr %u", dev_dbg(imx412->dev, "Received vblank %u, new lpfr %u\n",
imx412->vblank, imx412->vblank,
imx412->vblank + imx412->cur_mode->height); imx412->vblank + imx412->cur_mode->height);
@ -613,7 +613,7 @@ static int imx412_set_ctrl(struct v4l2_ctrl *ctrl)
exposure = ctrl->val; exposure = ctrl->val;
analog_gain = imx412->again_ctrl->val; analog_gain = imx412->again_ctrl->val;
dev_dbg(imx412->dev, "Received exp %u, analog gain %u", dev_dbg(imx412->dev, "Received exp %u, analog gain %u\n",
exposure, analog_gain); exposure, analog_gain);
ret = imx412_update_exp_gain(imx412, exposure, analog_gain); ret = imx412_update_exp_gain(imx412, exposure, analog_gain);
@ -622,7 +622,7 @@ static int imx412_set_ctrl(struct v4l2_ctrl *ctrl)
break; break;
default: default:
dev_err(imx412->dev, "Invalid control %d", ctrl->id); dev_err(imx412->dev, "Invalid control %d\n", ctrl->id);
ret = -EINVAL; ret = -EINVAL;
} }
@ -803,14 +803,14 @@ static int imx412_start_streaming(struct imx412 *imx412)
ret = imx412_write_regs(imx412, reg_list->regs, ret = imx412_write_regs(imx412, reg_list->regs,
reg_list->num_of_regs); reg_list->num_of_regs);
if (ret) { if (ret) {
dev_err(imx412->dev, "fail to write initial registers"); dev_err(imx412->dev, "fail to write initial registers\n");
return ret; return ret;
} }
/* Setup handler will write actual exposure and gain */ /* Setup handler will write actual exposure and gain */
ret = __v4l2_ctrl_handler_setup(imx412->sd.ctrl_handler); ret = __v4l2_ctrl_handler_setup(imx412->sd.ctrl_handler);
if (ret) { if (ret) {
dev_err(imx412->dev, "fail to setup handler"); dev_err(imx412->dev, "fail to setup handler\n");
return ret; return ret;
} }
@ -821,7 +821,7 @@ static int imx412_start_streaming(struct imx412 *imx412)
ret = imx412_write_reg(imx412, IMX412_REG_MODE_SELECT, ret = imx412_write_reg(imx412, IMX412_REG_MODE_SELECT,
1, IMX412_MODE_STREAMING); 1, IMX412_MODE_STREAMING);
if (ret) { if (ret) {
dev_err(imx412->dev, "fail to start streaming"); dev_err(imx412->dev, "fail to start streaming\n");
return ret; return ret;
} }
@ -895,7 +895,7 @@ static int imx412_detect(struct imx412 *imx412)
return ret; return ret;
if (val != IMX412_ID) { if (val != IMX412_ID) {
dev_err(imx412->dev, "chip id mismatch: %x!=%x", dev_err(imx412->dev, "chip id mismatch: %x!=%x\n",
IMX412_ID, val); IMX412_ID, val);
return -ENXIO; return -ENXIO;
} }
@ -927,7 +927,7 @@ static int imx412_parse_hw_config(struct imx412 *imx412)
imx412->reset_gpio = devm_gpiod_get_optional(imx412->dev, "reset", imx412->reset_gpio = devm_gpiod_get_optional(imx412->dev, "reset",
GPIOD_OUT_LOW); GPIOD_OUT_LOW);
if (IS_ERR(imx412->reset_gpio)) { if (IS_ERR(imx412->reset_gpio)) {
dev_err(imx412->dev, "failed to get reset gpio %ld", dev_err(imx412->dev, "failed to get reset gpio %ld\n",
PTR_ERR(imx412->reset_gpio)); PTR_ERR(imx412->reset_gpio));
return PTR_ERR(imx412->reset_gpio); return PTR_ERR(imx412->reset_gpio);
} }
@ -935,13 +935,13 @@ static int imx412_parse_hw_config(struct imx412 *imx412)
/* Get sensor input clock */ /* Get sensor input clock */
imx412->inclk = devm_clk_get(imx412->dev, NULL); imx412->inclk = devm_clk_get(imx412->dev, NULL);
if (IS_ERR(imx412->inclk)) { if (IS_ERR(imx412->inclk)) {
dev_err(imx412->dev, "could not get inclk"); dev_err(imx412->dev, "could not get inclk\n");
return PTR_ERR(imx412->inclk); return PTR_ERR(imx412->inclk);
} }
rate = clk_get_rate(imx412->inclk); rate = clk_get_rate(imx412->inclk);
if (rate != IMX412_INCLK_RATE) { if (rate != IMX412_INCLK_RATE) {
dev_err(imx412->dev, "inclk frequency mismatch"); dev_err(imx412->dev, "inclk frequency mismatch\n");
return -EINVAL; return -EINVAL;
} }
@ -966,14 +966,14 @@ static int imx412_parse_hw_config(struct imx412 *imx412)
if (bus_cfg.bus.mipi_csi2.num_data_lanes != IMX412_NUM_DATA_LANES) { if (bus_cfg.bus.mipi_csi2.num_data_lanes != IMX412_NUM_DATA_LANES) {
dev_err(imx412->dev, dev_err(imx412->dev,
"number of CSI2 data lanes %d is not supported", "number of CSI2 data lanes %d is not supported\n",
bus_cfg.bus.mipi_csi2.num_data_lanes); bus_cfg.bus.mipi_csi2.num_data_lanes);
ret = -EINVAL; ret = -EINVAL;
goto done_endpoint_free; goto done_endpoint_free;
} }
if (!bus_cfg.nr_of_link_frequencies) { if (!bus_cfg.nr_of_link_frequencies) {
dev_err(imx412->dev, "no link frequencies defined"); dev_err(imx412->dev, "no link frequencies defined\n");
ret = -EINVAL; ret = -EINVAL;
goto done_endpoint_free; goto done_endpoint_free;
} }
@ -1034,7 +1034,7 @@ static int imx412_power_on(struct device *dev)
ret = clk_prepare_enable(imx412->inclk); ret = clk_prepare_enable(imx412->inclk);
if (ret) { if (ret) {
dev_err(imx412->dev, "fail to enable inclk"); dev_err(imx412->dev, "fail to enable inclk\n");
goto error_reset; goto error_reset;
} }
@ -1145,7 +1145,7 @@ static int imx412_init_controls(struct imx412 *imx412)
imx412->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY; imx412->hblank_ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
if (ctrl_hdlr->error) { if (ctrl_hdlr->error) {
dev_err(imx412->dev, "control init failed: %d", dev_err(imx412->dev, "control init failed: %d\n",
ctrl_hdlr->error); ctrl_hdlr->error);
v4l2_ctrl_handler_free(ctrl_hdlr); v4l2_ctrl_handler_free(ctrl_hdlr);
return ctrl_hdlr->error; return ctrl_hdlr->error;
@ -1183,7 +1183,7 @@ static int imx412_probe(struct i2c_client *client)
ret = imx412_parse_hw_config(imx412); ret = imx412_parse_hw_config(imx412);
if (ret) { if (ret) {
dev_err(imx412->dev, "HW configuration is not supported"); dev_err(imx412->dev, "HW configuration is not supported\n");
return ret; return ret;
} }
@ -1191,14 +1191,14 @@ static int imx412_probe(struct i2c_client *client)
ret = imx412_power_on(imx412->dev); ret = imx412_power_on(imx412->dev);
if (ret) { if (ret) {
dev_err(imx412->dev, "failed to power-on the sensor"); dev_err(imx412->dev, "failed to power-on the sensor\n");
goto error_mutex_destroy; goto error_mutex_destroy;
} }
/* Check module identity */ /* Check module identity */
ret = imx412_detect(imx412); ret = imx412_detect(imx412);
if (ret) { if (ret) {
dev_err(imx412->dev, "failed to find sensor: %d", ret); dev_err(imx412->dev, "failed to find sensor: %d\n", ret);
goto error_power_off; goto error_power_off;
} }
@ -1208,7 +1208,7 @@ static int imx412_probe(struct i2c_client *client)
ret = imx412_init_controls(imx412); ret = imx412_init_controls(imx412);
if (ret) { if (ret) {
dev_err(imx412->dev, "failed to init controls: %d", ret); dev_err(imx412->dev, "failed to init controls: %d\n", ret);
goto error_power_off; goto error_power_off;
} }
@ -1222,14 +1222,14 @@ static int imx412_probe(struct i2c_client *client)
imx412->pad.flags = MEDIA_PAD_FL_SOURCE; imx412->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&imx412->sd.entity, 1, &imx412->pad); ret = media_entity_pads_init(&imx412->sd.entity, 1, &imx412->pad);
if (ret) { if (ret) {
dev_err(imx412->dev, "failed to init entity pads: %d", ret); dev_err(imx412->dev, "failed to init entity pads: %d\n", ret);
goto error_handler_free; goto error_handler_free;
} }
ret = v4l2_async_register_subdev_sensor(&imx412->sd); ret = v4l2_async_register_subdev_sensor(&imx412->sd);
if (ret < 0) { if (ret < 0) {
dev_err(imx412->dev, dev_err(imx412->dev,
"failed to register async subdev: %d", ret); "failed to register async subdev: %d\n", ret);
goto error_media_entity; goto error_media_entity;
} }

View File

@ -11,6 +11,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/nvmem-provider.h> #include <linux/nvmem-provider.h>
#include <linux/regmap.h> #include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <media/v4l2-ctrls.h> #include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h> #include <media/v4l2-fwnode.h>
@ -76,6 +77,14 @@
/* OTP registers from sensor */ /* OTP registers from sensor */
#define OV2740_REG_OTP_CUSTOMER 0x7010 #define OV2740_REG_OTP_CUSTOMER 0x7010
static const char * const ov2740_supply_name[] = {
"AVDD",
"DOVDD",
"DVDD",
};
#define OV2740_NUM_SUPPLIES ARRAY_SIZE(ov2740_supply_name)
struct nvm_data { struct nvm_data {
struct nvmem_device *nvmem; struct nvmem_device *nvmem;
struct regmap *regmap; struct regmap *regmap;
@ -523,9 +532,11 @@ struct ov2740 {
struct v4l2_ctrl *hblank; struct v4l2_ctrl *hblank;
struct v4l2_ctrl *exposure; struct v4l2_ctrl *exposure;
/* GPIOs, clocks */ /* GPIOs, clocks, regulators */
struct gpio_desc *reset_gpio; struct gpio_desc *reset_gpio;
struct gpio_desc *powerdown_gpio;
struct clk *clk; struct clk *clk;
struct regulator_bulk_data supplies[OV2740_NUM_SUPPLIES];
/* Current mode */ /* Current mode */
const struct ov2740_mode *cur_mode; const struct ov2740_mode *cur_mode;
@ -644,6 +655,8 @@ static int ov2740_identify_module(struct ov2740 *ov2740)
return -ENXIO; return -ENXIO;
} }
dev_dbg(&client->dev, "chip id: %x\n", val);
ov2740->identified = true; ov2740->identified = true;
return 0; return 0;
@ -753,15 +766,17 @@ static const struct v4l2_ctrl_ops ov2740_ctrl_ops = {
static int ov2740_init_controls(struct ov2740 *ov2740) static int ov2740_init_controls(struct ov2740 *ov2740)
{ {
struct i2c_client *client = v4l2_get_subdevdata(&ov2740->sd);
struct v4l2_ctrl_handler *ctrl_hdlr; struct v4l2_ctrl_handler *ctrl_hdlr;
const struct ov2740_mode *cur_mode; const struct ov2740_mode *cur_mode;
s64 exposure_max, h_blank, pixel_rate; s64 exposure_max, h_blank, pixel_rate;
u32 vblank_min, vblank_max, vblank_default; u32 vblank_min, vblank_max, vblank_default;
struct v4l2_fwnode_device_properties props;
int size; int size;
int ret; int ret;
ctrl_hdlr = &ov2740->ctrl_handler; ctrl_hdlr = &ov2740->ctrl_handler;
ret = v4l2_ctrl_handler_init(ctrl_hdlr, 8); ret = v4l2_ctrl_handler_init(ctrl_hdlr, 10);
if (ret) if (ret)
return ret; return ret;
@ -811,6 +826,13 @@ static int ov2740_init_controls(struct ov2740 *ov2740)
V4L2_CID_TEST_PATTERN, V4L2_CID_TEST_PATTERN,
ARRAY_SIZE(ov2740_test_pattern_menu) - 1, ARRAY_SIZE(ov2740_test_pattern_menu) - 1,
0, 0, ov2740_test_pattern_menu); 0, 0, ov2740_test_pattern_menu);
ret = v4l2_fwnode_device_parse(&client->dev, &props);
if (ret)
return ret;
v4l2_ctrl_new_fwnode_properties(ctrl_hdlr, &ov2740_ctrl_ops, &props);
if (ctrl_hdlr->error) { if (ctrl_hdlr->error) {
v4l2_ctrl_handler_free(ctrl_hdlr); v4l2_ctrl_handler_free(ctrl_hdlr);
return ctrl_hdlr->error; return ctrl_hdlr->error;
@ -1295,7 +1317,9 @@ static int ov2740_suspend(struct device *dev)
struct ov2740 *ov2740 = to_ov2740(sd); struct ov2740 *ov2740 = to_ov2740(sd);
gpiod_set_value_cansleep(ov2740->reset_gpio, 1); gpiod_set_value_cansleep(ov2740->reset_gpio, 1);
gpiod_set_value_cansleep(ov2740->powerdown_gpio, 1);
clk_disable_unprepare(ov2740->clk); clk_disable_unprepare(ov2740->clk);
regulator_bulk_disable(OV2740_NUM_SUPPLIES, ov2740->supplies);
return 0; return 0;
} }
@ -1305,10 +1329,17 @@ static int ov2740_resume(struct device *dev)
struct ov2740 *ov2740 = to_ov2740(sd); struct ov2740 *ov2740 = to_ov2740(sd);
int ret; int ret;
ret = clk_prepare_enable(ov2740->clk); ret = regulator_bulk_enable(OV2740_NUM_SUPPLIES, ov2740->supplies);
if (ret) if (ret)
return ret; return ret;
ret = clk_prepare_enable(ov2740->clk);
if (ret) {
regulator_bulk_disable(OV2740_NUM_SUPPLIES, ov2740->supplies);
return ret;
}
gpiod_set_value_cansleep(ov2740->powerdown_gpio, 0);
gpiod_set_value_cansleep(ov2740->reset_gpio, 0); gpiod_set_value_cansleep(ov2740->reset_gpio, 0);
msleep(20); msleep(20);
@ -1320,7 +1351,7 @@ static int ov2740_probe(struct i2c_client *client)
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct ov2740 *ov2740; struct ov2740 *ov2740;
bool full_power; bool full_power;
int ret; int i, ret;
ov2740 = devm_kzalloc(&client->dev, sizeof(*ov2740), GFP_KERNEL); ov2740 = devm_kzalloc(&client->dev, sizeof(*ov2740), GFP_KERNEL);
if (!ov2740) if (!ov2740)
@ -1337,9 +1368,17 @@ static int ov2740_probe(struct i2c_client *client)
if (IS_ERR(ov2740->reset_gpio)) { if (IS_ERR(ov2740->reset_gpio)) {
return dev_err_probe(dev, PTR_ERR(ov2740->reset_gpio), return dev_err_probe(dev, PTR_ERR(ov2740->reset_gpio),
"failed to get reset GPIO\n"); "failed to get reset GPIO\n");
} else if (ov2740->reset_gpio) { }
ov2740->powerdown_gpio = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_HIGH);
if (IS_ERR(ov2740->powerdown_gpio)) {
return dev_err_probe(dev, PTR_ERR(ov2740->powerdown_gpio),
"failed to get powerdown GPIO\n");
}
if (ov2740->reset_gpio || ov2740->powerdown_gpio) {
/* /*
* Ensure reset is asserted for at least 20 ms before * Ensure reset/powerdown is asserted for at least 20 ms before
* ov2740_resume() deasserts it. * ov2740_resume() deasserts it.
*/ */
msleep(20); msleep(20);
@ -1350,6 +1389,13 @@ static int ov2740_probe(struct i2c_client *client)
return dev_err_probe(dev, PTR_ERR(ov2740->clk), return dev_err_probe(dev, PTR_ERR(ov2740->clk),
"failed to get clock\n"); "failed to get clock\n");
for (i = 0; i < OV2740_NUM_SUPPLIES; i++)
ov2740->supplies[i].supply = ov2740_supply_name[i];
ret = devm_regulator_bulk_get(dev, OV2740_NUM_SUPPLIES, ov2740->supplies);
if (ret)
return dev_err_probe(dev, ret, "failed to get regulators\n");
full_power = acpi_dev_state_d0(&client->dev); full_power = acpi_dev_state_d0(&client->dev);
if (full_power) { if (full_power) {
/* ACPI does not always clear the reset GPIO / enable the clock */ /* ACPI does not always clear the reset GPIO / enable the clock */

View File

@ -1982,6 +1982,7 @@ static int ov5640_get_light_freq(struct ov5640_dev *sensor)
light_freq = 50; light_freq = 50;
} else { } else {
/* 60Hz */ /* 60Hz */
light_freq = 60;
} }
} }

View File

@ -40,7 +40,7 @@
/* Exposure control */ /* Exposure control */
#define OV9282_REG_EXPOSURE 0x3500 #define OV9282_REG_EXPOSURE 0x3500
#define OV9282_EXPOSURE_MIN 1 #define OV9282_EXPOSURE_MIN 1
#define OV9282_EXPOSURE_OFFSET 12 #define OV9282_EXPOSURE_OFFSET 25
#define OV9282_EXPOSURE_STEP 1 #define OV9282_EXPOSURE_STEP 1
#define OV9282_EXPOSURE_DEFAULT 0x0282 #define OV9282_EXPOSURE_DEFAULT 0x0282

View File

@ -123,23 +123,6 @@ static int flexcop_dma_remap(struct flexcop_device *fc,
return 0; return 0;
} }
int flexcop_dma_control_size_irq(struct flexcop_device *fc,
flexcop_dma_index_t no,
int onoff)
{
flexcop_ibi_value v = fc->read_ibi_reg(fc, ctrl_208);
if (no & FC_DMA_1)
v.ctrl_208.DMA1_IRQ_Enable_sig = onoff;
if (no & FC_DMA_2)
v.ctrl_208.DMA2_IRQ_Enable_sig = onoff;
fc->write_ibi_reg(fc, ctrl_208, v);
return 0;
}
EXPORT_SYMBOL(flexcop_dma_control_size_irq);
int flexcop_dma_control_timer_irq(struct flexcop_device *fc, int flexcop_dma_control_timer_irq(struct flexcop_device *fc,
flexcop_dma_index_t no, flexcop_dma_index_t no,
int onoff) int onoff)

View File

@ -305,21 +305,6 @@ int cx18_gpio_register(struct cx18 *cx, u32 hw)
return v4l2_device_register_subdev(&cx->v4l2_dev, sd); return v4l2_device_register_subdev(&cx->v4l2_dev, sd);
} }
void cx18_reset_ir_gpio(void *data)
{
struct cx18 *cx = to_cx18(data);
if (cx->card->gpio_i2c_slave_reset.ir_reset_mask == 0)
return;
CX18_DEBUG_INFO("Resetting IR microcontroller\n");
v4l2_subdev_call(&cx->sd_resetctrl,
core, reset, CX18_GPIO_RESET_Z8F0811);
}
EXPORT_SYMBOL(cx18_reset_ir_gpio);
/* This symbol is exported for use by lirc_pvr150 for the IR-blaster */
/* Xceive tuner reset function */ /* Xceive tuner reset function */
int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value) int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value)
{ {

View File

@ -17,5 +17,4 @@ enum cx18_gpio_reset_type {
CX18_GPIO_RESET_XC2028 = 2, CX18_GPIO_RESET_XC2028 = 2,
}; };
void cx18_reset_ir_gpio(void *data);
int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value); int cx18_reset_tuner_gpio(void *dev, int component, int cmd, int value);

View File

@ -847,10 +847,10 @@ int ipu6_buttress_init(struct ipu6_device *isp)
INIT_LIST_HEAD(&b->constraints); INIT_LIST_HEAD(&b->constraints);
isp->secure_mode = ipu6_buttress_get_secure_mode(isp); isp->secure_mode = ipu6_buttress_get_secure_mode(isp);
dev_info(&isp->pdev->dev, "IPU6 in %s mode touch 0x%x mask 0x%x\n", dev_dbg(&isp->pdev->dev, "IPU6 in %s mode touch 0x%x mask 0x%x\n",
isp->secure_mode ? "secure" : "non-secure", isp->secure_mode ? "secure" : "non-secure",
readl(isp->base + BUTTRESS_REG_SECURITY_TOUCH), readl(isp->base + BUTTRESS_REG_SECURITY_TOUCH),
readl(isp->base + BUTTRESS_REG_CAMERA_MASK)); readl(isp->base + BUTTRESS_REG_CAMERA_MASK));
b->wdt_cached_value = readl(isp->base + BUTTRESS_REG_WDT); b->wdt_cached_value = readl(isp->base + BUTTRESS_REG_WDT);
writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_CLEAR); writel(BUTTRESS_IRQS, isp->base + BUTTRESS_REG_ISR_CLEAR);

View File

@ -275,7 +275,7 @@ static int ipu6_cpd_validate_moduledata(struct ipu6_device *isp,
return -EINVAL; return -EINVAL;
} }
dev_info(&isp->pdev->dev, "FW version: %x\n", mod_hdr->fw_pkg_date); dev_dbg(&isp->pdev->dev, "FW version: %x\n", mod_hdr->fw_pkg_date);
ret = ipu6_cpd_validate_cpd(isp, moduledata + mod_hdr->hdr_len, ret = ipu6_cpd_validate_cpd(isp, moduledata + mod_hdr->hdr_len,
moduledata_size - mod_hdr->hdr_len, moduledata_size - mod_hdr->hdr_len,
moduledata_size); moduledata_size);

View File

@ -1133,6 +1133,7 @@ static int isys_probe(struct auxiliary_device *auxdev,
free_fw_msg_bufs: free_fw_msg_bufs:
free_fw_msg_bufs(isys); free_fw_msg_bufs(isys);
out_remove_pkg_dir_shared_buffer: out_remove_pkg_dir_shared_buffer:
cpu_latency_qos_remove_request(&isys->pm_qos);
if (!isp->secure_mode) if (!isp->secure_mode)
ipu6_cpd_free_pkg_dir(adev); ipu6_cpd_free_pkg_dir(adev);
remove_shared_buffer: remove_shared_buffer:

View File

@ -40,7 +40,9 @@
#include "mgb4_trigger.h" #include "mgb4_trigger.h"
#include "mgb4_core.h" #include "mgb4_core.h"
#define MGB4_USER_IRQS 16 #define MGB4_USER_IRQS 16
#define MGB4_MGB4_BAR_ID 0
#define MGB4_XDMA_BAR_ID 1
#define DIGITEQ_VID 0x1ed8 #define DIGITEQ_VID 0x1ed8
#define T100_DID 0x0101 #define T100_DID 0x0101

View File

@ -18,9 +18,6 @@
#define MGB4_VIN_DEVICES 2 #define MGB4_VIN_DEVICES 2
#define MGB4_VOUT_DEVICES 2 #define MGB4_VOUT_DEVICES 2
#define MGB4_MGB4_BAR_ID 0
#define MGB4_XDMA_BAR_ID 1
#define MGB4_IS_GMSL(mgbdev) \ #define MGB4_IS_GMSL(mgbdev) \
((mgbdev)->module_version >> 4 == 2) ((mgbdev)->module_version >> 4 == 2)
#define MGB4_IS_FPDL3(mgbdev) \ #define MGB4_IS_FPDL3(mgbdev) \

View File

@ -333,7 +333,7 @@ static ssize_t hsync_width_show(struct device *dev,
struct video_device *vdev = to_video_device(dev); struct video_device *vdev = to_video_device(dev);
struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
u32 sig = mgb4_read_reg(&vindev->mgbdev->video, u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
vindev->config->regs.signal); vindev->config->regs.hsync);
return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16); return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16);
} }
@ -344,7 +344,7 @@ static ssize_t vsync_width_show(struct device *dev,
struct video_device *vdev = to_video_device(dev); struct video_device *vdev = to_video_device(dev);
struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
u32 sig = mgb4_read_reg(&vindev->mgbdev->video, u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
vindev->config->regs.signal2); vindev->config->regs.vsync);
return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16); return sprintf(buf, "%u\n", (sig & 0x00FF0000) >> 16);
} }
@ -355,7 +355,7 @@ static ssize_t hback_porch_show(struct device *dev,
struct video_device *vdev = to_video_device(dev); struct video_device *vdev = to_video_device(dev);
struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
u32 sig = mgb4_read_reg(&vindev->mgbdev->video, u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
vindev->config->regs.signal); vindev->config->regs.hsync);
return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8); return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8);
} }
@ -366,7 +366,7 @@ static ssize_t hfront_porch_show(struct device *dev,
struct video_device *vdev = to_video_device(dev); struct video_device *vdev = to_video_device(dev);
struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
u32 sig = mgb4_read_reg(&vindev->mgbdev->video, u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
vindev->config->regs.signal); vindev->config->regs.hsync);
return sprintf(buf, "%u\n", (sig & 0x000000FF)); return sprintf(buf, "%u\n", (sig & 0x000000FF));
} }
@ -377,7 +377,7 @@ static ssize_t vback_porch_show(struct device *dev,
struct video_device *vdev = to_video_device(dev); struct video_device *vdev = to_video_device(dev);
struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
u32 sig = mgb4_read_reg(&vindev->mgbdev->video, u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
vindev->config->regs.signal2); vindev->config->regs.vsync);
return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8); return sprintf(buf, "%u\n", (sig & 0x0000FF00) >> 8);
} }
@ -388,7 +388,7 @@ static ssize_t vfront_porch_show(struct device *dev,
struct video_device *vdev = to_video_device(dev); struct video_device *vdev = to_video_device(dev);
struct mgb4_vin_dev *vindev = video_get_drvdata(vdev); struct mgb4_vin_dev *vindev = video_get_drvdata(vdev);
u32 sig = mgb4_read_reg(&vindev->mgbdev->video, u32 sig = mgb4_read_reg(&vindev->mgbdev->video,
vindev->config->regs.signal2); vindev->config->regs.vsync);
return sprintf(buf, "%u\n", (sig & 0x000000FF)); return sprintf(buf, "%u\n", (sig & 0x000000FF));
} }

View File

@ -143,8 +143,8 @@ static int get_timings(struct mgb4_vin_dev *vindev,
u32 status = mgb4_read_reg(video, regs->status); u32 status = mgb4_read_reg(video, regs->status);
u32 pclk = mgb4_read_reg(video, regs->pclk); u32 pclk = mgb4_read_reg(video, regs->pclk);
u32 signal = mgb4_read_reg(video, regs->signal); u32 hsync = mgb4_read_reg(video, regs->hsync);
u32 signal2 = mgb4_read_reg(video, regs->signal2); u32 vsync = mgb4_read_reg(video, regs->vsync);
u32 resolution = mgb4_read_reg(video, regs->resolution); u32 resolution = mgb4_read_reg(video, regs->resolution);
if (!(status & (1U << 2))) if (!(status & (1U << 2)))
@ -161,12 +161,12 @@ static int get_timings(struct mgb4_vin_dev *vindev,
if (status & (1U << 13)) if (status & (1U << 13))
timings->bt.polarities |= V4L2_DV_VSYNC_POS_POL; timings->bt.polarities |= V4L2_DV_VSYNC_POS_POL;
timings->bt.pixelclock = pclk * 1000; timings->bt.pixelclock = pclk * 1000;
timings->bt.hsync = (signal & 0x00FF0000) >> 16; timings->bt.hsync = (hsync & 0x00FF0000) >> 16;
timings->bt.vsync = (signal2 & 0x00FF0000) >> 16; timings->bt.vsync = (vsync & 0x00FF0000) >> 16;
timings->bt.hbackporch = (signal & 0x0000FF00) >> 8; timings->bt.hbackporch = (hsync & 0x0000FF00) >> 8;
timings->bt.hfrontporch = signal & 0x000000FF; timings->bt.hfrontporch = hsync & 0x000000FF;
timings->bt.vbackporch = (signal2 & 0x0000FF00) >> 8; timings->bt.vbackporch = (vsync & 0x0000FF00) >> 8;
timings->bt.vfrontporch = signal2 & 0x000000FF; timings->bt.vfrontporch = vsync & 0x000000FF;
return 0; return 0;
} }
@ -864,9 +864,9 @@ static void create_debugfs(struct mgb4_vin_dev *vindev)
vindev->regs[5].name = "PCLK_FREQUENCY"; vindev->regs[5].name = "PCLK_FREQUENCY";
vindev->regs[5].offset = vindev->config->regs.pclk; vindev->regs[5].offset = vindev->config->regs.pclk;
vindev->regs[6].name = "VIDEO_PARAMS_1"; vindev->regs[6].name = "VIDEO_PARAMS_1";
vindev->regs[6].offset = vindev->config->regs.signal; vindev->regs[6].offset = vindev->config->regs.hsync;
vindev->regs[7].name = "VIDEO_PARAMS_2"; vindev->regs[7].name = "VIDEO_PARAMS_2";
vindev->regs[7].offset = vindev->config->regs.signal2; vindev->regs[7].offset = vindev->config->regs.vsync;
vindev->regs[8].name = "PADDING_PIXELS"; vindev->regs[8].name = "PADDING_PIXELS";
vindev->regs[8].offset = vindev->config->regs.padding; vindev->regs[8].offset = vindev->config->regs.padding;
if (has_timeperframe(video)) { if (has_timeperframe(video)) {

View File

@ -22,8 +22,8 @@ struct mgb4_vin_regs {
u32 frame_period; u32 frame_period;
u32 sync; u32 sync;
u32 pclk; u32 pclk;
u32 signal; u32 hsync;
u32 signal2; u32 vsync;
u32 padding; u32 padding;
u32 timer; u32 timer;
}; };

View File

@ -24,10 +24,6 @@
#include "mgb4_cmt.h" #include "mgb4_cmt.h"
#include "mgb4_vout.h" #include "mgb4_vout.h"
#define DEFAULT_WIDTH 1280
#define DEFAULT_HEIGHT 640
#define DEFAULT_PERIOD (MGB4_HW_FREQ / 60)
ATTRIBUTE_GROUPS(mgb4_fpdl3_out); ATTRIBUTE_GROUPS(mgb4_fpdl3_out);
ATTRIBUTE_GROUPS(mgb4_gmsl_out); ATTRIBUTE_GROUPS(mgb4_gmsl_out);
@ -180,7 +176,10 @@ static void stop_streaming(struct vb2_queue *vq)
xdma_disable_user_irq(mgbdev->xdev, irq); xdma_disable_user_irq(mgbdev->xdev, irq);
cancel_work_sync(&voutdev->dma_work); cancel_work_sync(&voutdev->dma_work);
mgb4_mask_reg(&mgbdev->video, voutdev->config->regs.config, 0x2, 0x0); mgb4_mask_reg(&mgbdev->video, voutdev->config->regs.config, 0x2, 0x0);
mgb4_write_reg(&mgbdev->video, voutdev->config->regs.padding, 0);
return_all_buffers(voutdev, VB2_BUF_STATE_ERROR); return_all_buffers(voutdev, VB2_BUF_STATE_ERROR);
} }
@ -196,6 +195,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count)
int rv; int rv;
u32 addr; u32 addr;
mgb4_write_reg(video, config->regs.padding, voutdev->padding);
mgb4_mask_reg(video, config->regs.config, 0x2, 0x2); mgb4_mask_reg(video, config->regs.config, 0x2, 0x2);
addr = mgb4_read_reg(video, config->regs.address); addr = mgb4_read_reg(video, config->regs.address);
@ -359,7 +359,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
voutdev->padding = (f->fmt.pix.bytesperline - (f->fmt.pix.width voutdev->padding = (f->fmt.pix.bytesperline - (f->fmt.pix.width
* pixelsize)) / pixelsize; * pixelsize)) / pixelsize;
mgb4_write_reg(video, voutdev->config->regs.padding, voutdev->padding);
return 0; return 0;
} }
@ -661,11 +660,10 @@ static void fpga_init(struct mgb4_vout_dev *voutdev)
const struct mgb4_vout_regs *regs = &voutdev->config->regs; const struct mgb4_vout_regs *regs = &voutdev->config->regs;
mgb4_write_reg(video, regs->config, 0x00000011); mgb4_write_reg(video, regs->config, 0x00000011);
mgb4_write_reg(video, regs->resolution, mgb4_write_reg(video, regs->resolution, (1280 << 16) | 640);
(DEFAULT_WIDTH << 16) | DEFAULT_HEIGHT);
mgb4_write_reg(video, regs->hsync, 0x00283232); mgb4_write_reg(video, regs->hsync, 0x00283232);
mgb4_write_reg(video, regs->vsync, 0x40141F1E); mgb4_write_reg(video, regs->vsync, 0x40141F1E);
mgb4_write_reg(video, regs->frame_limit, DEFAULT_PERIOD); mgb4_write_reg(video, regs->frame_limit, MGB4_HW_FREQ / 60);
mgb4_write_reg(video, regs->padding, 0x00000000); mgb4_write_reg(video, regs->padding, 0x00000000);
voutdev->freq = mgb4_cmt_set_vout_freq(voutdev, 61150 >> 1) << 1; voutdev->freq = mgb4_cmt_set_vout_freq(voutdev, 61150 >> 1) << 1;

View File

@ -77,9 +77,7 @@ static int saa7164_vbi_buffers_alloc(struct saa7164_port *port)
/* TODO: NTSC SPECIFIC */ /* TODO: NTSC SPECIFIC */
/* Init and establish defaults */ /* Init and establish defaults */
params->samplesperline = 1440; params->samplesperline = 1440;
params->numberoflines = 12;
params->numberoflines = 18; params->numberoflines = 18;
params->pitch = 1600;
params->pitch = 1440; params->pitch = 1440;
params->numpagetables = 2 + params->numpagetables = 2 +
((params->numberoflines * params->pitch) / PAGE_SIZE); ((params->numberoflines * params->pitch) / PAGE_SIZE);

View File

@ -362,7 +362,7 @@ static ssize_t sdram_offsets_show(struct device *dev,
} }
static ssize_t sdram_show(struct file *file, struct kobject *kobj, static ssize_t sdram_show(struct file *file, struct kobject *kobj,
struct bin_attribute *a, char *buf, const struct bin_attribute *a, char *buf,
loff_t off, size_t count) loff_t off, size_t count)
{ {
struct device *dev = kobj_to_dev(kobj); struct device *dev = kobj_to_dev(kobj);
@ -432,7 +432,7 @@ static int solo_sysfs_init(struct solo_dev *solo_dev)
sysfs_attr_init(&sdram_attr->attr); sysfs_attr_init(&sdram_attr->attr);
sdram_attr->attr.name = "sdram"; sdram_attr->attr.name = "sdram";
sdram_attr->attr.mode = 0440; sdram_attr->attr.mode = 0440;
sdram_attr->read = sdram_show; sdram_attr->read_new = sdram_show;
sdram_attr->size = solo_dev->sdram_size; sdram_attr->size = solo_dev->sdram_size;
if (device_create_bin_file(dev, sdram_attr)) { if (device_create_bin_file(dev, sdram_attr)) {

View File

@ -199,6 +199,7 @@ struct unicam_device {
/* subdevice async notifier */ /* subdevice async notifier */
struct v4l2_async_notifier notifier; struct v4l2_async_notifier notifier;
unsigned int sequence; unsigned int sequence;
bool frame_started;
/* Sensor node */ /* Sensor node */
struct { struct {
@ -546,7 +547,8 @@ unicam_find_format_by_fourcc(u32 fourcc, u32 pad)
} }
for (i = 0; i < num_formats; ++i) { for (i = 0; i < num_formats; ++i) {
if (formats[i].fourcc == fourcc) if (formats[i].fourcc == fourcc ||
formats[i].unpacked_fourcc == fourcc)
return &formats[i]; return &formats[i];
} }
@ -638,7 +640,14 @@ static inline void unicam_reg_write_field(struct unicam_device *unicam, u32 offs
static void unicam_wr_dma_addr(struct unicam_node *node, static void unicam_wr_dma_addr(struct unicam_node *node,
struct unicam_buffer *buf) struct unicam_buffer *buf)
{ {
dma_addr_t endaddr = buf->dma_addr + buf->size; /*
* Due to a HW bug causing buffer overruns in circular buffer mode under
* certain (not yet fully known) conditions, the dummy buffer allocation
* is set to a a single page size, but the hardware gets programmed with
* a buffer size of 0.
*/
dma_addr_t endaddr = buf->dma_addr +
(buf != &node->dummy_buf ? buf->size : 0);
if (node->id == UNICAM_IMAGE_NODE) { if (node->id == UNICAM_IMAGE_NODE) {
unicam_reg_write(node->dev, UNICAM_IBSA0, buf->dma_addr); unicam_reg_write(node->dev, UNICAM_IBSA0, buf->dma_addr);
@ -742,6 +751,8 @@ static irqreturn_t unicam_isr(int irq, void *dev)
* buffer forever. * buffer forever.
*/ */
if (fe) { if (fe) {
bool inc_seq = unicam->frame_started;
/* /*
* Ensure we have swapped buffers already as we can't * Ensure we have swapped buffers already as we can't
* stop the peripheral. If no buffer is available, use a * stop the peripheral. If no buffer is available, use a
@ -761,11 +772,24 @@ static irqreturn_t unicam_isr(int irq, void *dev)
* + FS + LS). In this case, we cannot signal the buffer * + FS + LS). In this case, we cannot signal the buffer
* as complete, as the HW will reuse that buffer. * as complete, as the HW will reuse that buffer.
*/ */
if (node->cur_frm && node->cur_frm != node->next_frm) if (node->cur_frm && node->cur_frm != node->next_frm) {
unicam_process_buffer_complete(node, sequence); unicam_process_buffer_complete(node, sequence);
inc_seq = true;
}
node->cur_frm = node->next_frm; node->cur_frm = node->next_frm;
} }
unicam->sequence++;
/*
* Increment the sequence number conditionally on either a FS
* having already occurred, or in the FE + FS condition as
* caught in the FE handler above. This ensures the sequence
* number corresponds to the frames generated by the sensor, not
* the frames dequeued to userland.
*/
if (inc_seq) {
unicam->sequence++;
unicam->frame_started = false;
}
} }
if (ista & UNICAM_FSI) { if (ista & UNICAM_FSI) {
@ -795,6 +819,7 @@ static irqreturn_t unicam_isr(int irq, void *dev)
} }
unicam_queue_event_sof(unicam); unicam_queue_event_sof(unicam);
unicam->frame_started = true;
} }
/* /*
@ -816,11 +841,6 @@ static irqreturn_t unicam_isr(int irq, void *dev)
} }
} }
if (unicam_reg_read(unicam, UNICAM_ICTL) & UNICAM_FCM) {
/* Switch out of trigger mode if selected */
unicam_reg_write_field(unicam, UNICAM_ICTL, 1, UNICAM_TFC);
unicam_reg_write_field(unicam, UNICAM_ICTL, 0, UNICAM_FCM);
}
return IRQ_HANDLED; return IRQ_HANDLED;
} }
@ -984,8 +1004,7 @@ static void unicam_start_rx(struct unicam_device *unicam,
unicam_reg_write_field(unicam, UNICAM_ANA, 0, UNICAM_DDL); unicam_reg_write_field(unicam, UNICAM_ANA, 0, UNICAM_DDL);
/* Always start in trigger frame capture mode (UNICAM_FCM set) */ val = UNICAM_FSIE | UNICAM_FEIE | UNICAM_IBOB;
val = UNICAM_FSIE | UNICAM_FEIE | UNICAM_FCM | UNICAM_IBOB;
line_int_freq = max(fmt->height >> 2, 128); line_int_freq = max(fmt->height >> 2, 128);
unicam_set_field(&val, line_int_freq, UNICAM_LCIE_MASK); unicam_set_field(&val, line_int_freq, UNICAM_LCIE_MASK);
unicam_reg_write(unicam, UNICAM_ICTL, val); unicam_reg_write(unicam, UNICAM_ICTL, val);
@ -1413,6 +1432,7 @@ static int unicam_sd_enable_streams(struct v4l2_subdev *sd,
if (unicam->pipe.nodes & BIT(UNICAM_METADATA_NODE)) if (unicam->pipe.nodes & BIT(UNICAM_METADATA_NODE))
unicam_start_metadata(unicam); unicam_start_metadata(unicam);
unicam->frame_started = false;
unicam_start_rx(unicam, state); unicam_start_rx(unicam, state);
} }

View File

@ -935,7 +935,12 @@ static int mclk_enable(struct clk_hw *hw)
ret = pm_runtime_resume_and_get(cam->dev); ret = pm_runtime_resume_and_get(cam->dev);
if (ret < 0) if (ret < 0)
return ret; return ret;
clk_enable(cam->clk[0]); ret = clk_enable(cam->clk[0]);
if (ret) {
pm_runtime_put(cam->dev);
return ret;
}
mcam_reg_write(cam, REG_CLKCTRL, (mclk_src << 29) | mclk_div); mcam_reg_write(cam, REG_CLKCTRL, (mclk_src << 29) | mclk_div);
mcam_ctlr_power_up(cam); mcam_ctlr_power_up(cam);

View File

@ -231,13 +231,23 @@ static int mmpcam_probe(struct platform_device *pdev)
mcam_init_clk(mcam); mcam_init_clk(mcam);
/*
* Register with V4L.
*/
ret = v4l2_device_register(mcam->dev, &mcam->v4l2_dev);
if (ret)
return ret;
/* /*
* Create a match of the sensor against its OF node. * Create a match of the sensor against its OF node.
*/ */
ep = fwnode_graph_get_next_endpoint(of_fwnode_handle(pdev->dev.of_node), ep = fwnode_graph_get_next_endpoint(of_fwnode_handle(pdev->dev.of_node),
NULL); NULL);
if (!ep) if (!ep) {
return -ENODEV; ret = -ENODEV;
goto out_v4l2_device_unregister;
}
v4l2_async_nf_init(&mcam->notifier, &mcam->v4l2_dev); v4l2_async_nf_init(&mcam->notifier, &mcam->v4l2_dev);
@ -246,7 +256,7 @@ static int mmpcam_probe(struct platform_device *pdev)
fwnode_handle_put(ep); fwnode_handle_put(ep);
if (IS_ERR(asd)) { if (IS_ERR(asd)) {
ret = PTR_ERR(asd); ret = PTR_ERR(asd);
goto out; goto out_v4l2_device_unregister;
} }
/* /*
@ -254,7 +264,7 @@ static int mmpcam_probe(struct platform_device *pdev)
*/ */
ret = mccic_register(mcam); ret = mccic_register(mcam);
if (ret) if (ret)
goto out; goto out_v4l2_device_unregister;
/* /*
* Add OF clock provider. * Add OF clock provider.
@ -283,6 +293,8 @@ static int mmpcam_probe(struct platform_device *pdev)
return 0; return 0;
out: out:
mccic_shutdown(mcam); mccic_shutdown(mcam);
out_v4l2_device_unregister:
v4l2_device_unregister(&mcam->v4l2_dev);
return ret; return ret;
} }
@ -293,6 +305,7 @@ static void mmpcam_remove(struct platform_device *pdev)
struct mcam_camera *mcam = &cam->mcam; struct mcam_camera *mcam = &cam->mcam;
mccic_shutdown(mcam); mccic_shutdown(mcam);
v4l2_device_unregister(&mcam->v4l2_dev);
pm_runtime_force_suspend(mcam->dev); pm_runtime_force_suspend(mcam->dev);
} }

View File

@ -114,19 +114,15 @@ static struct img_config *__get_config_offset(struct mdp_dev *mdp,
if (pp_idx >= mdp->mdp_data->pp_used) if (pp_idx >= mdp->mdp_data->pp_used)
goto err_param; goto err_param;
if (CFG_CHECK(MT8183, p_id)) if (CFG_CHECK(MT8183, p_id)) {
cfg_c = CFG_OFST(MT8183, param->config, pp_idx); cfg_c = CFG_OFST(MT8183, param->config, pp_idx);
else if (CFG_CHECK(MT8195, p_id))
cfg_c = CFG_OFST(MT8195, param->config, pp_idx);
else
goto err_param;
if (CFG_CHECK(MT8183, p_id))
cfg_n = CFG_OFST(MT8183, param->config, pp_idx + 1); cfg_n = CFG_OFST(MT8183, param->config, pp_idx + 1);
else if (CFG_CHECK(MT8195, p_id)) } else if (CFG_CHECK(MT8195, p_id)) {
cfg_c = CFG_OFST(MT8195, param->config, pp_idx);
cfg_n = CFG_OFST(MT8195, param->config, pp_idx + 1); cfg_n = CFG_OFST(MT8195, param->config, pp_idx + 1);
else } else {
goto err_param; goto err_param;
}
if ((long)cfg_n - (long)mdp->vpu.config > bound) { if ((long)cfg_n - (long)mdp->vpu.config > bound) {
dev_err(dev, "config offset %ld OOB %ld\n", (long)cfg_n, bound); dev_err(dev, "config offset %ld OOB %ld\n", (long)cfg_n, bound);
@ -325,8 +321,7 @@ static int mdp_path_config_subfrm(struct mdp_cmdq_cmd *cmd,
/* Enable mux settings */ /* Enable mux settings */
for (index = 0; index < ctrl->num_sets; index++) { for (index = 0; index < ctrl->num_sets; index++) {
set = &ctrl->sets[index]; set = &ctrl->sets[index];
cmdq_pkt_write_mask(&cmd->pkt, set->subsys_id, set->reg, cmdq_pkt_write(&cmd->pkt, set->subsys_id, set->reg, set->value);
set->value, 0xFFFFFFFF);
} }
/* Config sub-frame information */ /* Config sub-frame information */
for (index = (num_comp - 1); index >= 0; index--) { for (index = (num_comp - 1); index >= 0; index--) {
@ -381,8 +376,7 @@ static int mdp_path_config_subfrm(struct mdp_cmdq_cmd *cmd,
/* Disable mux settings */ /* Disable mux settings */
for (index = 0; index < ctrl->num_sets; index++) { for (index = 0; index < ctrl->num_sets; index++) {
set = &ctrl->sets[index]; set = &ctrl->sets[index];
cmdq_pkt_write_mask(&cmd->pkt, set->subsys_id, set->reg, cmdq_pkt_write(&cmd->pkt, set->subsys_id, set->reg, 0);
0, 0xFFFFFFFF);
} }
return 0; return 0;
@ -471,43 +465,6 @@ static int mdp_path_config(struct mdp_dev *mdp, struct mdp_cmdq_cmd *cmd,
return 0; return 0;
} }
static int mdp_cmdq_pkt_create(struct cmdq_client *client, struct cmdq_pkt *pkt,
size_t size)
{
struct device *dev;
dma_addr_t dma_addr;
pkt->va_base = kzalloc(size, GFP_KERNEL);
if (!pkt->va_base)
return -ENOMEM;
pkt->buf_size = size;
pkt->cl = (void *)client;
dev = client->chan->mbox->dev;
dma_addr = dma_map_single(dev, pkt->va_base, pkt->buf_size,
DMA_TO_DEVICE);
if (dma_mapping_error(dev, dma_addr)) {
dev_err(dev, "dma map failed, size=%u\n", (u32)(u64)size);
kfree(pkt->va_base);
return -ENOMEM;
}
pkt->pa_base = dma_addr;
return 0;
}
static void mdp_cmdq_pkt_destroy(struct cmdq_pkt *pkt)
{
struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
dma_unmap_single(client->chan->mbox->dev, pkt->pa_base, pkt->buf_size,
DMA_TO_DEVICE);
kfree(pkt->va_base);
pkt->va_base = NULL;
}
static void mdp_auto_release_work(struct work_struct *work) static void mdp_auto_release_work(struct work_struct *work)
{ {
struct mdp_cmdq_cmd *cmd; struct mdp_cmdq_cmd *cmd;
@ -538,7 +495,7 @@ static void mdp_auto_release_work(struct work_struct *work)
wake_up(&mdp->callback_wq); wake_up(&mdp->callback_wq);
} }
mdp_cmdq_pkt_destroy(&cmd->pkt); cmdq_pkt_destroy(mdp->cmdq_clt[cmd->pp_idx], &cmd->pkt);
kfree(cmd->comps); kfree(cmd->comps);
cmd->comps = NULL; cmd->comps = NULL;
kfree(cmd); kfree(cmd);
@ -578,7 +535,7 @@ static void mdp_handle_cmdq_callback(struct mbox_client *cl, void *mssg)
if (refcount_dec_and_test(&mdp->job_count)) if (refcount_dec_and_test(&mdp->job_count))
wake_up(&mdp->callback_wq); wake_up(&mdp->callback_wq);
mdp_cmdq_pkt_destroy(&cmd->pkt); cmdq_pkt_destroy(mdp->cmdq_clt[cmd->pp_idx], &cmd->pkt);
kfree(cmd->comps); kfree(cmd->comps);
cmd->comps = NULL; cmd->comps = NULL;
kfree(cmd); kfree(cmd);
@ -607,20 +564,13 @@ static struct mdp_cmdq_cmd *mdp_cmdq_prepare(struct mdp_dev *mdp,
goto err_uninit; goto err_uninit;
} }
if (CFG_CHECK(MT8183, p_id))
num_comp = CFG_GET(MT8183, config, num_components);
else if (CFG_CHECK(MT8195, p_id))
num_comp = CFG_GET(MT8195, config, num_components);
else
goto err_uninit;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
if (!cmd) { if (!cmd) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_uninit; goto err_uninit;
} }
ret = mdp_cmdq_pkt_create(mdp->cmdq_clt[pp_idx], &cmd->pkt, SZ_16K); ret = cmdq_pkt_create(mdp->cmdq_clt[pp_idx], &cmd->pkt, SZ_16K);
if (ret) if (ret)
goto err_free_cmd; goto err_free_cmd;
@ -632,6 +582,7 @@ static struct mdp_cmdq_cmd *mdp_cmdq_prepare(struct mdp_dev *mdp,
ret = -EINVAL; ret = -EINVAL;
goto err_destroy_pkt; goto err_destroy_pkt;
} }
comps = kcalloc(num_comp, sizeof(*comps), GFP_KERNEL); comps = kcalloc(num_comp, sizeof(*comps), GFP_KERNEL);
if (!comps) { if (!comps) {
ret = -ENOMEM; ret = -ENOMEM;
@ -676,7 +627,8 @@ static struct mdp_cmdq_cmd *mdp_cmdq_prepare(struct mdp_dev *mdp,
dev_err(dev, "mdp_path_config error %d\n", pp_idx); dev_err(dev, "mdp_path_config error %d\n", pp_idx);
goto err_free_path; goto err_free_path;
} }
cmdq_pkt_finalize(&cmd->pkt); cmdq_pkt_eoc(&cmd->pkt);
cmdq_pkt_jump_rel(&cmd->pkt, CMDQ_INST_SIZE, mdp->cmdq_shift_pa[pp_idx]);
for (i = 0; i < num_comp; i++) { for (i = 0; i < num_comp; i++) {
s32 inner_id = MDP_COMP_NONE; s32 inner_id = MDP_COMP_NONE;
@ -699,6 +651,7 @@ static struct mdp_cmdq_cmd *mdp_cmdq_prepare(struct mdp_dev *mdp,
cmd->comps = comps; cmd->comps = comps;
cmd->num_comps = num_comp; cmd->num_comps = num_comp;
cmd->mdp_ctx = param->mdp_ctx; cmd->mdp_ctx = param->mdp_ctx;
cmd->pp_idx = pp_idx;
kfree(path); kfree(path);
return cmd; return cmd;
@ -710,7 +663,7 @@ err_free_path:
err_free_comps: err_free_comps:
kfree(comps); kfree(comps);
err_destroy_pkt: err_destroy_pkt:
mdp_cmdq_pkt_destroy(&cmd->pkt); cmdq_pkt_destroy(mdp->cmdq_clt[pp_idx], &cmd->pkt);
err_free_cmd: err_free_cmd:
kfree(cmd); kfree(cmd);
err_uninit: err_uninit:

View File

@ -35,6 +35,7 @@ struct mdp_cmdq_cmd {
struct mdp_comp *comps; struct mdp_comp *comps;
void *mdp_ctx; void *mdp_ctx;
u8 num_comps; u8 num_comps;
u8 pp_idx;
}; };
struct mdp_dev; struct mdp_dev;

File diff suppressed because it is too large Load Diff

View File

@ -9,18 +9,18 @@
#include "mtk-mdp3-cmdq.h" #include "mtk-mdp3-cmdq.h"
#define MM_REG_WRITE_MASK(cmd, id, base, ofst, val, mask, ...) \ #define MM_REG_WRITE_MASK(cmd, id, base, ofst, val, mask) \
cmdq_pkt_write_mask(&((cmd)->pkt), id, \
(base) + (ofst), (val), (mask), ##__VA_ARGS__)
#define MM_REG_WRITE(cmd, id, base, ofst, val, mask, ...) \
do { \ do { \
typeof(mask) (m) = (mask); \ typeof(mask) (m) = (mask); \
MM_REG_WRITE_MASK(cmd, id, base, ofst, val, \ cmdq_pkt_write_mask(&((cmd)->pkt), id, (base) + (ofst), \
(val), \
(((m) & (ofst##_MASK)) == (ofst##_MASK)) ? \ (((m) & (ofst##_MASK)) == (ofst##_MASK)) ? \
(0xffffffff) : (m), ##__VA_ARGS__); \ (0xffffffff) : (m)); \
} while (0) } while (0)
#define MM_REG_WRITE(cmd, id, base, ofst, val) \
cmdq_pkt_write(&((cmd)->pkt), id, (base) + (ofst), (val))
#define MM_REG_WAIT(cmd, evt) \ #define MM_REG_WAIT(cmd, evt) \
do { \ do { \
typeof(cmd) (c) = (cmd); \ typeof(cmd) (c) = (cmd); \
@ -49,20 +49,17 @@ do { \
cmdq_pkt_set_event(&((c)->pkt), (e)); \ cmdq_pkt_set_event(&((c)->pkt), (e)); \
} while (0) } while (0)
#define MM_REG_POLL_MASK(cmd, id, base, ofst, val, _mask, ...) \ #define MM_REG_POLL_MASK(cmd, id, base, ofst, val, _mask) \
do { \ do { \
typeof(_mask) (_m) = (_mask); \ typeof(_mask) (_m) = (_mask); \
cmdq_pkt_poll_mask(&((cmd)->pkt), id, \ cmdq_pkt_poll_mask(&((cmd)->pkt), id, \
(base) + (ofst), (val), (_m), ##__VA_ARGS__); \ (base) + (ofst), (val), \
(((_m) & (ofst##_MASK)) == (ofst##_MASK)) ? \
(0xffffffff) : (_m)); \
} while (0) } while (0)
#define MM_REG_POLL(cmd, id, base, ofst, val, mask, ...) \ #define MM_REG_POLL(cmd, id, base, ofst, val) \
do { \ cmdq_pkt_poll(&((cmd)->pkt), id, (base) + (ofst), (val))
typeof(mask) (m) = (mask); \
MM_REG_POLL_MASK((cmd), id, base, ofst, val, \
(((m) & (ofst##_MASK)) == (ofst##_MASK)) ? \
(0xffffffff) : (m), ##__VA_ARGS__); \
} while (0)
enum mtk_mdp_comp_id { enum mtk_mdp_comp_id {
MDP_COMP_NONE = -1, /* Invalid engine */ MDP_COMP_NONE = -1, /* Invalid engine */

View File

@ -312,6 +312,8 @@ static int mdp_probe(struct platform_device *pdev)
ret = PTR_ERR(mdp->cmdq_clt[i]); ret = PTR_ERR(mdp->cmdq_clt[i]);
goto err_mbox_destroy; goto err_mbox_destroy;
} }
mdp->cmdq_shift_pa[i] = cmdq_get_shift_pa(mdp->cmdq_clt[i]->chan);
} }
init_waitqueue_head(&mdp->callback_wq); init_waitqueue_head(&mdp->callback_wq);

View File

@ -126,6 +126,7 @@ struct mdp_dev {
u32 id_count; u32 id_count;
struct ida mdp_ida; struct ida mdp_ida;
struct cmdq_client *cmdq_clt[MDP_PP_MAX]; struct cmdq_client *cmdq_clt[MDP_PP_MAX];
u8 cmdq_shift_pa[MDP_PP_MAX];
wait_queue_head_t callback_wq; wait_queue_head_t callback_wq;
struct v4l2_device v4l2_dev; struct v4l2_device v4l2_dev;

View File

@ -1665,9 +1665,9 @@ static int npcm_video_ece_init(struct npcm_video *video)
dev_info(dev, "Support HEXTILE pixel format\n"); dev_info(dev, "Support HEXTILE pixel format\n");
ece_pdev = of_find_device_by_node(ece_node); ece_pdev = of_find_device_by_node(ece_node);
if (IS_ERR(ece_pdev)) { if (!ece_pdev) {
dev_err(dev, "Failed to find ECE device\n"); dev_err(dev, "Failed to find ECE device\n");
return PTR_ERR(ece_pdev); return -ENODEV;
} }
of_node_put(ece_node); of_node_put(ece_node);

View File

@ -2677,11 +2677,12 @@ static void mxc_jpeg_detach_pm_domains(struct mxc_jpeg_dev *jpeg)
int i; int i;
for (i = 0; i < jpeg->num_domains; i++) { for (i = 0; i < jpeg->num_domains; i++) {
if (jpeg->pd_dev[i] && !pm_runtime_suspended(jpeg->pd_dev[i])) if (!IS_ERR_OR_NULL(jpeg->pd_dev[i]) &&
!pm_runtime_suspended(jpeg->pd_dev[i]))
pm_runtime_force_suspend(jpeg->pd_dev[i]); pm_runtime_force_suspend(jpeg->pd_dev[i]);
if (jpeg->pd_link[i] && !IS_ERR(jpeg->pd_link[i])) if (!IS_ERR_OR_NULL(jpeg->pd_link[i]))
device_link_del(jpeg->pd_link[i]); device_link_del(jpeg->pd_link[i]);
if (jpeg->pd_dev[i] && !IS_ERR(jpeg->pd_dev[i])) if (!IS_ERR_OR_NULL(jpeg->pd_dev[i]))
dev_pm_domain_detach(jpeg->pd_dev[i], true); dev_pm_domain_detach(jpeg->pd_dev[i], true);
jpeg->pd_dev[i] = NULL; jpeg->pd_dev[i] = NULL;
jpeg->pd_link[i] = NULL; jpeg->pd_link[i] = NULL;

View File

@ -307,6 +307,19 @@ static const struct mxc_isi_plat_data mxc_imx8mp_data = {
.has_36bit_dma = true, .has_36bit_dma = true,
}; };
static const struct mxc_isi_plat_data mxc_imx8ulp_data = {
.model = MXC_ISI_IMX8ULP,
.num_ports = 1,
.num_channels = 1,
.reg_offset = 0x0,
.ier_reg = &mxc_imx8_isi_ier_v2,
.set_thd = &mxc_imx8_isi_thd_v1,
.clks = mxc_imx8mn_clks,
.num_clks = ARRAY_SIZE(mxc_imx8mn_clks),
.buf_active_reverse = true,
.has_36bit_dma = false,
};
static const struct mxc_isi_plat_data mxc_imx93_data = { static const struct mxc_isi_plat_data mxc_imx93_data = {
.model = MXC_ISI_IMX93, .model = MXC_ISI_IMX93,
.num_ports = 1, .num_ports = 1,
@ -528,6 +541,7 @@ static void mxc_isi_remove(struct platform_device *pdev)
static const struct of_device_id mxc_isi_of_match[] = { static const struct of_device_id mxc_isi_of_match[] = {
{ .compatible = "fsl,imx8mn-isi", .data = &mxc_imx8mn_data }, { .compatible = "fsl,imx8mn-isi", .data = &mxc_imx8mn_data },
{ .compatible = "fsl,imx8mp-isi", .data = &mxc_imx8mp_data }, { .compatible = "fsl,imx8mp-isi", .data = &mxc_imx8mp_data },
{ .compatible = "fsl,imx8ulp-isi", .data = &mxc_imx8ulp_data },
{ .compatible = "fsl,imx93-isi", .data = &mxc_imx93_data }, { .compatible = "fsl,imx93-isi", .data = &mxc_imx93_data },
{ /* sentinel */ }, { /* sentinel */ },
}; };

View File

@ -158,6 +158,7 @@ struct mxc_gasket_ops {
enum model { enum model {
MXC_ISI_IMX8MN, MXC_ISI_IMX8MN,
MXC_ISI_IMX8MP, MXC_ISI_IMX8MP,
MXC_ISI_IMX8ULP,
MXC_ISI_IMX93, MXC_ISI_IMX93,
}; };

View File

@ -861,6 +861,7 @@ int mxc_isi_video_buffer_prepare(struct mxc_isi_dev *isi, struct vb2_buffer *vb2
const struct mxc_isi_format_info *info, const struct mxc_isi_format_info *info,
const struct v4l2_pix_format_mplane *pix) const struct v4l2_pix_format_mplane *pix)
{ {
struct vb2_v4l2_buffer *v4l2_buf = to_vb2_v4l2_buffer(vb2);
unsigned int i; unsigned int i;
for (i = 0; i < info->mem_planes; i++) { for (i = 0; i < info->mem_planes; i++) {
@ -875,6 +876,8 @@ int mxc_isi_video_buffer_prepare(struct mxc_isi_dev *isi, struct vb2_buffer *vb2
vb2_set_plane_payload(vb2, i, size); vb2_set_plane_payload(vb2, i, size);
} }
v4l2_buf->field = pix->field;
return 0; return 0;
} }

View File

@ -505,9 +505,9 @@ static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy,
u32 val; u32 val;
switch (csiphy->camss->res->version) { switch (csiphy->camss->res->version) {
case CAMSS_845: case CAMSS_7280:
r = &lane_regs_sdm845[0][0]; r = &lane_regs_sm8250[0][0];
array_size = ARRAY_SIZE(lane_regs_sdm845[0]); array_size = ARRAY_SIZE(lane_regs_sm8250[0]);
break; break;
case CAMSS_8250: case CAMSS_8250:
r = &lane_regs_sm8250[0][0]; r = &lane_regs_sm8250[0][0];
@ -517,6 +517,10 @@ static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy,
r = &lane_regs_sc8280xp[0][0]; r = &lane_regs_sc8280xp[0][0];
array_size = ARRAY_SIZE(lane_regs_sc8280xp[0]); array_size = ARRAY_SIZE(lane_regs_sc8280xp[0]);
break; break;
case CAMSS_845:
r = &lane_regs_sdm845[0][0];
array_size = ARRAY_SIZE(lane_regs_sdm845[0]);
break;
default: default:
WARN(1, "unknown cspi version\n"); WARN(1, "unknown cspi version\n");
return; return;
@ -557,9 +561,10 @@ static bool csiphy_is_gen2(u32 version)
bool ret = false; bool ret = false;
switch (version) { switch (version) {
case CAMSS_845: case CAMSS_7280:
case CAMSS_8250: case CAMSS_8250:
case CAMSS_8280XP: case CAMSS_8280XP:
case CAMSS_845:
ret = true; ret = true;
break; break;
} }

View File

@ -103,6 +103,11 @@ const struct csiphy_formats csiphy_formats_8x96 = {
.formats = formats_8x96 .formats = formats_8x96
}; };
const struct csiphy_formats csiphy_formats_sc7280 = {
.nformats = ARRAY_SIZE(formats_sdm845),
.formats = formats_sdm845
};
const struct csiphy_formats csiphy_formats_sdm845 = { const struct csiphy_formats csiphy_formats_sdm845 = {
.nformats = ARRAY_SIZE(formats_sdm845), .nformats = ARRAY_SIZE(formats_sdm845),
.formats = formats_sdm845 .formats = formats_sdm845

View File

@ -26,6 +26,12 @@ struct csiphy_lane {
u8 pol; u8 pol;
}; };
/**
* struct csiphy_lanes_cfg - CSIPHY lanes configuration
* @num_data: number of data lanes
* @data: data lanes configuration
* @clk: clock lane configuration (only for D-PHY)
*/
struct csiphy_lanes_cfg { struct csiphy_lanes_cfg {
int num_data; int num_data;
struct csiphy_lane *data; struct csiphy_lane *data;
@ -111,6 +117,7 @@ void msm_csiphy_unregister_entity(struct csiphy_device *csiphy);
extern const struct csiphy_formats csiphy_formats_8x16; extern const struct csiphy_formats csiphy_formats_8x16;
extern const struct csiphy_formats csiphy_formats_8x96; extern const struct csiphy_formats csiphy_formats_8x96;
extern const struct csiphy_formats csiphy_formats_sc7280;
extern const struct csiphy_formats csiphy_formats_sdm845; extern const struct csiphy_formats csiphy_formats_sdm845;
extern const struct csiphy_hw_ops csiphy_ops_2ph_1_0; extern const struct csiphy_hw_ops csiphy_ops_2ph_1_0;

View File

@ -334,11 +334,12 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
return sink_code; return sink_code;
} }
break; break;
case CAMSS_8x96:
case CAMSS_660: case CAMSS_660:
case CAMSS_845: case CAMSS_7280:
case CAMSS_8x96:
case CAMSS_8250: case CAMSS_8250:
case CAMSS_8280XP: case CAMSS_8280XP:
case CAMSS_845:
switch (sink_code) { switch (sink_code) {
case MEDIA_BUS_FMT_YUYV8_1X16: case MEDIA_BUS_FMT_YUYV8_1X16:
{ {
@ -1693,9 +1694,10 @@ static int vfe_bpl_align(struct vfe_device *vfe)
int ret = 8; int ret = 8;
switch (vfe->camss->res->version) { switch (vfe->camss->res->version) {
case CAMSS_845: case CAMSS_7280:
case CAMSS_8250: case CAMSS_8250:
case CAMSS_8280XP: case CAMSS_8280XP:
case CAMSS_845:
ret = 16; ret = 16;
break; break;
default: default:

View File

@ -1266,6 +1266,310 @@ static const struct resources_icc icc_res_sm8250[] = {
}, },
}; };
static const struct camss_subdev_resources csiphy_res_7280[] = {
/* CSIPHY0 */
{
.regulators = { "vdda-phy", "vdda-pll" },
.clock = { "csiphy0", "csiphy0_timer" },
.clock_rate = { { 300000000, 400000000 },
{ 300000000 } },
.reg = { "csiphy0" },
.interrupt = { "csiphy0" },
.csiphy = {
.hw_ops = &csiphy_ops_3ph_1_0,
.formats = &csiphy_formats_sc7280
}
},
/* CSIPHY1 */
{
.regulators = { "vdda-phy", "vdda-pll" },
.clock = { "csiphy1", "csiphy1_timer" },
.clock_rate = { { 300000000, 400000000 },
{ 300000000 } },
.reg = { "csiphy1" },
.interrupt = { "csiphy1" },
.csiphy = {
.hw_ops = &csiphy_ops_3ph_1_0,
.formats = &csiphy_formats_sc7280
}
},
/* CSIPHY2 */
{
.regulators = { "vdda-phy", "vdda-pll" },
.clock = { "csiphy2", "csiphy2_timer" },
.clock_rate = { { 300000000, 400000000 },
{ 300000000 } },
.reg = { "csiphy2" },
.interrupt = { "csiphy2" },
.csiphy = {
.hw_ops = &csiphy_ops_3ph_1_0,
.formats = &csiphy_formats_sc7280
}
},
/* CSIPHY3 */
{
.regulators = { "vdda-phy", "vdda-pll" },
.clock = { "csiphy3", "csiphy3_timer" },
.clock_rate = { { 300000000, 400000000 },
{ 300000000 } },
.reg = { "csiphy3" },
.interrupt = { "csiphy3" },
.csiphy = {
.hw_ops = &csiphy_ops_3ph_1_0,
.formats = &csiphy_formats_sc7280
}
},
/* CSIPHY4 */
{
.regulators = { "vdda-phy", "vdda-pll" },
.clock = { "csiphy4", "csiphy4_timer" },
.clock_rate = { { 300000000, 400000000 },
{ 300000000 } },
.reg = { "csiphy4" },
.interrupt = { "csiphy4" },
.csiphy = {
.hw_ops = &csiphy_ops_3ph_1_0,
.formats = &csiphy_formats_sc7280
}
},
};
static const struct camss_subdev_resources csid_res_7280[] = {
/* CSID0 */
{
.regulators = {},
.clock = { "vfe0_csid", "vfe0_cphy_rx", "vfe0" },
.clock_rate = { { 300000000, 400000000 },
{ 0 },
{ 380000000, 510000000, 637000000, 760000000 }
},
.reg = { "csid0" },
.interrupt = { "csid0" },
.csid = {
.is_lite = false,
.hw_ops = &csid_ops_gen2,
.parent_dev_ops = &vfe_parent_dev_ops,
.formats = &csid_formats_gen2
}
},
/* CSID1 */
{
.regulators = {},
.clock = { "vfe1_csid", "vfe1_cphy_rx", "vfe1" },
.clock_rate = { { 300000000, 400000000 },
{ 0 },
{ 380000000, 510000000, 637000000, 760000000 }
},
.reg = { "csid1" },
.interrupt = { "csid1" },
.csid = {
.is_lite = false,
.hw_ops = &csid_ops_gen2,
.parent_dev_ops = &vfe_parent_dev_ops,
.formats = &csid_formats_gen2
}
},
/* CSID2 */
{
.regulators = {},
.clock = { "vfe2_csid", "vfe2_cphy_rx", "vfe2" },
.clock_rate = { { 300000000, 400000000 },
{ 0 },
{ 380000000, 510000000, 637000000, 760000000 }
},
.reg = { "csid2" },
.interrupt = { "csid2" },
.csid = {
.is_lite = false,
.hw_ops = &csid_ops_gen2,
.parent_dev_ops = &vfe_parent_dev_ops,
.formats = &csid_formats_gen2
}
},
/* CSID3 */
{
.regulators = {},
.clock = { "vfe_lite0_csid", "vfe_lite0_cphy_rx", "vfe_lite0" },
.clock_rate = { { 300000000, 400000000 },
{ 0 },
{ 320000000, 400000000, 480000000, 600000000 }
},
.reg = { "csid_lite0" },
.interrupt = { "csid_lite0" },
.csid = {
.is_lite = true,
.hw_ops = &csid_ops_gen2,
.parent_dev_ops = &vfe_parent_dev_ops,
.formats = &csid_formats_gen2
}
},
/* CSID4 */
{
.regulators = {},
.clock = { "vfe_lite1_csid", "vfe_lite1_cphy_rx", "vfe_lite1" },
.clock_rate = { { 300000000, 400000000 },
{ 0 },
{ 320000000, 400000000, 480000000, 600000000 }
},
.reg = { "csid_lite1" },
.interrupt = { "csid_lite1" },
.csid = {
.is_lite = true,
.hw_ops = &csid_ops_gen2,
.parent_dev_ops = &vfe_parent_dev_ops,
.formats = &csid_formats_gen2
}
},
};
static const struct camss_subdev_resources vfe_res_7280[] = {
/* VFE0 */
{
.regulators = {},
.clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe0",
"vfe0_axi", "gcc_cam_hf_axi" },
.clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 },
{ 80000000 },
{ 0 },
{ 380000000, 510000000, 637000000, 760000000 },
{ 0 },
{ 0 } },
.reg = { "vfe0" },
.interrupt = { "vfe0" },
.vfe = {
.line_num = 3,
.is_lite = false,
.has_pd = true,
.pd_name = "ife0",
.hw_ops = &vfe_ops_170,
.formats_rdi = &vfe_formats_rdi_845,
.formats_pix = &vfe_formats_pix_845
}
},
/* VFE1 */
{
.regulators = {},
.clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe1",
"vfe1_axi", "gcc_cam_hf_axi" },
.clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 },
{ 80000000 },
{ 0 },
{ 380000000, 510000000, 637000000, 760000000 },
{ 0 },
{ 0 } },
.reg = { "vfe1" },
.interrupt = { "vfe1" },
.vfe = {
.line_num = 3,
.is_lite = false,
.has_pd = true,
.pd_name = "ife1",
.hw_ops = &vfe_ops_170,
.formats_rdi = &vfe_formats_rdi_845,
.formats_pix = &vfe_formats_pix_845
}
},
/* VFE2 */
{
.regulators = {},
.clock = { "camnoc_axi", "cpas_ahb", "icp_ahb", "vfe2",
"vfe2_axi", "gcc_cam_hf_axi" },
.clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 },
{ 80000000 },
{ 0 },
{ 380000000, 510000000, 637000000, 760000000 },
{ 0 },
{ 0 } },
.reg = { "vfe2" },
.interrupt = { "vfe2" },
.vfe = {
.line_num = 3,
.is_lite = false,
.hw_ops = &vfe_ops_170,
.has_pd = true,
.pd_name = "ife2",
.formats_rdi = &vfe_formats_rdi_845,
.formats_pix = &vfe_formats_pix_845
}
},
/* VFE3 (lite) */
{
.clock = { "camnoc_axi", "cpas_ahb", "icp_ahb",
"vfe_lite0", "gcc_cam_hf_axi" },
.clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 },
{ 80000000 },
{ 0 },
{ 320000000, 400000000, 480000000, 600000000 },
{ 0 } },
.regulators = {},
.reg = { "vfe_lite0" },
.interrupt = { "vfe_lite0" },
.vfe = {
.line_num = 4,
.is_lite = true,
.hw_ops = &vfe_ops_170,
.formats_rdi = &vfe_formats_rdi_845,
.formats_pix = &vfe_formats_pix_845
}
},
/* VFE4 (lite) */
{
.clock = { "camnoc_axi", "cpas_ahb", "icp_ahb",
"vfe_lite1", "gcc_cam_hf_axi" },
.clock_rate = { { 150000000, 240000000, 320000000, 400000000, 480000000 },
{ 80000000 },
{ 0 },
{ 320000000, 400000000, 480000000, 600000000 },
{ 0 } },
.regulators = {},
.reg = { "vfe_lite1" },
.interrupt = { "vfe_lite1" },
.vfe = {
.line_num = 4,
.is_lite = true,
.hw_ops = &vfe_ops_170,
.formats_rdi = &vfe_formats_rdi_845,
.formats_pix = &vfe_formats_pix_845
}
},
};
static const struct resources_icc icc_res_sc7280[] = {
{
.name = "ahb",
.icc_bw_tbl.avg = 38400,
.icc_bw_tbl.peak = 76800,
},
{
.name = "hf_0",
.icc_bw_tbl.avg = 2097152,
.icc_bw_tbl.peak = 2097152,
},
};
static const struct camss_subdev_resources csiphy_res_sc8280xp[] = { static const struct camss_subdev_resources csiphy_res_sc8280xp[] = {
/* CSIPHY0 */ /* CSIPHY0 */
{ {
@ -1993,6 +2297,24 @@ static int camss_init_subdevices(struct camss *camss)
return 0; return 0;
} }
/*
* camss_link_entities - Register subdev nodes and create links
* camss_link_err - print error in case link creation fails
* @src_name: name for source of the link
* @sink_name: name for sink of the link
*/
inline void camss_link_err(struct camss *camss,
const char *src_name,
const char *sink_name,
int ret)
{
dev_err(camss->dev,
"Failed to link %s->%s entities: %d\n",
src_name,
sink_name,
ret);
}
/* /*
* camss_link_entities - Register subdev nodes and create links * camss_link_entities - Register subdev nodes and create links
* @camss: CAMSS device * @camss: CAMSS device
@ -2012,11 +2334,10 @@ static int camss_link_entities(struct camss *camss)
MSM_CSID_PAD_SINK, MSM_CSID_PAD_SINK,
0); 0);
if (ret < 0) { if (ret < 0) {
dev_err(camss->dev, camss_link_err(camss,
"Failed to link %s->%s entities: %d\n", camss->csiphy[i].subdev.entity.name,
camss->csiphy[i].subdev.entity.name, camss->csid[j].subdev.entity.name,
camss->csid[j].subdev.entity.name, ret);
ret);
return ret; return ret;
} }
} }
@ -2031,11 +2352,10 @@ static int camss_link_entities(struct camss *camss)
MSM_ISPIF_PAD_SINK, MSM_ISPIF_PAD_SINK,
0); 0);
if (ret < 0) { if (ret < 0) {
dev_err(camss->dev, camss_link_err(camss,
"Failed to link %s->%s entities: %d\n", camss->csid[i].subdev.entity.name,
camss->csid[i].subdev.entity.name, camss->ispif->line[j].subdev.entity.name,
camss->ispif->line[j].subdev.entity.name, ret);
ret);
return ret; return ret;
} }
} }
@ -2053,11 +2373,9 @@ static int camss_link_entities(struct camss *camss)
MSM_VFE_PAD_SINK, MSM_VFE_PAD_SINK,
0); 0);
if (ret < 0) { if (ret < 0) {
dev_err(camss->dev, camss_link_err(camss, ispif->entity.name,
"Failed to link %s->%s entities: %d\n", vfe->entity.name,
ispif->entity.name, ret);
vfe->entity.name,
ret);
return ret; return ret;
} }
} }
@ -2074,11 +2392,9 @@ static int camss_link_entities(struct camss *camss)
MSM_VFE_PAD_SINK, MSM_VFE_PAD_SINK,
0); 0);
if (ret < 0) { if (ret < 0) {
dev_err(camss->dev, camss_link_err(camss, csid->entity.name,
"Failed to link %s->%s entities: %d\n", vfe->entity.name,
csid->entity.name, ret);
vfe->entity.name,
ret);
return ret; return ret;
} }
} }
@ -2227,9 +2543,9 @@ static int camss_subdev_notifier_complete(struct v4l2_async_notifier *async)
input, MSM_CSIPHY_PAD_SINK, input, MSM_CSIPHY_PAD_SINK,
MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
if (ret < 0) { if (ret < 0) {
dev_err(camss->dev, camss_link_err(camss, sensor->name,
"Failed to link %s->%s entities: %d\n", input->name,
sensor->name, input->name, ret); ret);
return ret; return ret;
} }
} }
@ -2622,14 +2938,29 @@ static const struct camss_resources sc8280xp_resources = {
.link_entities = camss_link_entities .link_entities = camss_link_entities
}; };
static const struct camss_resources sc7280_resources = {
.version = CAMSS_7280,
.pd_name = "top",
.csiphy_res = csiphy_res_7280,
.csid_res = csid_res_7280,
.vfe_res = vfe_res_7280,
.icc_res = icc_res_sc7280,
.icc_path_num = ARRAY_SIZE(icc_res_sc7280),
.csiphy_num = ARRAY_SIZE(csiphy_res_7280),
.csid_num = ARRAY_SIZE(csid_res_7280),
.vfe_num = ARRAY_SIZE(vfe_res_7280),
.link_entities = camss_link_entities
};
static const struct of_device_id camss_dt_match[] = { static const struct of_device_id camss_dt_match[] = {
{ .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources },
{ .compatible = "qcom,msm8953-camss", .data = &msm8953_resources }, { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources },
{ .compatible = "qcom,msm8996-camss", .data = &msm8996_resources }, { .compatible = "qcom,msm8996-camss", .data = &msm8996_resources },
{ .compatible = "qcom,sc7280-camss", .data = &sc7280_resources },
{ .compatible = "qcom,sc8280xp-camss", .data = &sc8280xp_resources },
{ .compatible = "qcom,sdm660-camss", .data = &sdm660_resources }, { .compatible = "qcom,sdm660-camss", .data = &sdm660_resources },
{ .compatible = "qcom,sdm845-camss", .data = &sdm845_resources }, { .compatible = "qcom,sdm845-camss", .data = &sdm845_resources },
{ .compatible = "qcom,sm8250-camss", .data = &sm8250_resources }, { .compatible = "qcom,sm8250-camss", .data = &sm8250_resources },
{ .compatible = "qcom,sc8280xp-camss", .data = &sc8280xp_resources },
{ } { }
}; };

View File

@ -77,13 +77,14 @@ enum pm_domain {
}; };
enum camss_version { enum camss_version {
CAMSS_660,
CAMSS_7280,
CAMSS_8x16, CAMSS_8x16,
CAMSS_8x53, CAMSS_8x53,
CAMSS_8x96, CAMSS_8x96,
CAMSS_660,
CAMSS_845,
CAMSS_8250, CAMSS_8250,
CAMSS_8280XP, CAMSS_8280XP,
CAMSS_845,
}; };
enum icc_count { enum icc_count {

View File

@ -3,6 +3,7 @@ config VIDEO_QCOM_VENUS
depends on V4L_MEM2MEM_DRIVERS depends on V4L_MEM2MEM_DRIVERS
depends on VIDEO_DEV && QCOM_SMEM depends on VIDEO_DEV && QCOM_SMEM
depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST
select OF_DYNAMIC if ARCH_QCOM
select QCOM_MDT_LOADER if ARCH_QCOM select QCOM_MDT_LOADER if ARCH_QCOM
select QCOM_SCM select QCOM_SCM
select VIDEOBUF2_DMA_CONTIG select VIDEOBUF2_DMA_CONTIG

View File

@ -286,6 +286,89 @@ static irqreturn_t venus_isr_thread(int irq, void *dev_id)
return ret; return ret;
} }
#if defined(CONFIG_OF_DYNAMIC)
static int venus_add_video_core(struct venus_core *core, const char *node_name,
const char *compat)
{
struct of_changeset *ocs = core->ocs;
struct device *dev = core->dev;
struct device_node *np, *enp;
int ret;
if (!node_name)
return 0;
enp = of_find_node_by_name(dev->of_node, node_name);
if (enp) {
of_node_put(enp);
return 0;
}
np = of_changeset_create_node(ocs, dev->of_node, node_name);
if (!np) {
dev_err(dev, "Unable to create new node\n");
return -ENODEV;
}
ret = of_changeset_add_prop_string(ocs, np, "compatible", compat);
if (ret)
dev_err(dev, "unable to add %s\n", compat);
of_node_put(np);
return ret;
}
static int venus_add_dynamic_nodes(struct venus_core *core)
{
struct device *dev = core->dev;
int ret;
core->ocs = kmalloc(sizeof(*core->ocs), GFP_KERNEL);
if (!core->ocs)
return -ENOMEM;
of_changeset_init(core->ocs);
ret = venus_add_video_core(core, core->res->dec_nodename, "venus-decoder");
if (ret)
goto err;
ret = venus_add_video_core(core, core->res->enc_nodename, "venus-encoder");
if (ret)
goto err;
ret = of_changeset_apply(core->ocs);
if (ret) {
dev_err(dev, "applying changeset fail ret %d\n", ret);
goto err;
}
return 0;
err:
of_changeset_destroy(core->ocs);
kfree(core->ocs);
core->ocs = NULL;
return ret;
}
static void venus_remove_dynamic_nodes(struct venus_core *core)
{
if (core->ocs) {
of_changeset_revert(core->ocs);
of_changeset_destroy(core->ocs);
kfree(core->ocs);
}
}
#else
static int venus_add_dynamic_nodes(struct venus_core *core)
{
return 0;
}
static void venus_remove_dynamic_nodes(struct venus_core *core) {}
#endif
static int venus_probe(struct platform_device *pdev) static int venus_probe(struct platform_device *pdev)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
@ -365,9 +448,15 @@ static int venus_probe(struct platform_device *pdev)
if (ret < 0) if (ret < 0)
goto err_runtime_disable; goto err_runtime_disable;
if (core->res->dec_nodename || core->res->enc_nodename) {
ret = venus_add_dynamic_nodes(core);
if (ret)
goto err_runtime_disable;
}
ret = of_platform_populate(dev->of_node, NULL, NULL, dev); ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
if (ret) if (ret)
goto err_runtime_disable; goto err_remove_dynamic_nodes;
ret = venus_firmware_init(core); ret = venus_firmware_init(core);
if (ret) if (ret)
@ -411,6 +500,8 @@ err_firmware_deinit:
venus_firmware_deinit(core); venus_firmware_deinit(core);
err_of_depopulate: err_of_depopulate:
of_platform_depopulate(dev); of_platform_depopulate(dev);
err_remove_dynamic_nodes:
venus_remove_dynamic_nodes(core);
err_runtime_disable: err_runtime_disable:
pm_runtime_put_noidle(dev); pm_runtime_put_noidle(dev);
pm_runtime_disable(dev); pm_runtime_disable(dev);
@ -443,6 +534,8 @@ static void venus_remove(struct platform_device *pdev)
venus_firmware_deinit(core); venus_firmware_deinit(core);
venus_remove_dynamic_nodes(core);
pm_runtime_put_sync(dev); pm_runtime_put_sync(dev);
pm_runtime_disable(dev); pm_runtime_disable(dev);
@ -506,18 +599,14 @@ err_cpucfg_path:
void venus_close_common(struct venus_inst *inst) void venus_close_common(struct venus_inst *inst)
{ {
/* /*
* First, remove the inst from the ->instances list, so that * Make sure we don't have IRQ/IRQ-thread currently running
* to_instance() will return NULL.
*/
hfi_session_destroy(inst);
/*
* Second, make sure we don't have IRQ/IRQ-thread currently running
* or pending execution, which would race with the inst destruction. * or pending execution, which would race with the inst destruction.
*/ */
synchronize_irq(inst->core->irq); synchronize_irq(inst->core->irq);
v4l2_m2m_ctx_release(inst->m2m_ctx); v4l2_m2m_ctx_release(inst->m2m_ctx);
v4l2_m2m_release(inst->m2m_dev); v4l2_m2m_release(inst->m2m_dev);
hfi_session_destroy(inst);
v4l2_fh_del(&inst->fh); v4l2_fh_del(&inst->fh);
v4l2_fh_exit(&inst->fh); v4l2_fh_exit(&inst->fh);
v4l2_ctrl_handler_free(&inst->ctrl_handler); v4l2_ctrl_handler_free(&inst->ctrl_handler);
@ -582,6 +671,8 @@ static const struct venus_resources msm8916_res = {
.vmem_addr = 0, .vmem_addr = 0,
.dma_mask = 0xddc00000 - 1, .dma_mask = 0xddc00000 - 1,
.fwname = "qcom/venus-1.8/venus.mbn", .fwname = "qcom/venus-1.8/venus.mbn",
.dec_nodename = "video-decoder",
.enc_nodename = "video-encoder",
}; };
static const struct freq_tbl msm8996_freq_table[] = { static const struct freq_tbl msm8996_freq_table[] = {
@ -791,6 +882,8 @@ static const struct venus_resources sdm845_res_v2 = {
.cp_nonpixel_start = 0x1000000, .cp_nonpixel_start = 0x1000000,
.cp_nonpixel_size = 0x24800000, .cp_nonpixel_size = 0x24800000,
.fwname = "qcom/venus-5.2/venus.mbn", .fwname = "qcom/venus-5.2/venus.mbn",
.dec_nodename = "video-core0",
.enc_nodename = "video-core1",
}; };
static const struct freq_tbl sc7180_freq_table[] = { static const struct freq_tbl sc7180_freq_table[] = {
@ -839,6 +932,8 @@ static const struct venus_resources sc7180_res = {
.cp_nonpixel_start = 0x1000000, .cp_nonpixel_start = 0x1000000,
.cp_nonpixel_size = 0x24800000, .cp_nonpixel_size = 0x24800000,
.fwname = "qcom/venus-5.4/venus.mbn", .fwname = "qcom/venus-5.4/venus.mbn",
.dec_nodename = "video-decoder",
.enc_nodename = "video-encoder",
}; };
static const struct freq_tbl sm8250_freq_table[] = { static const struct freq_tbl sm8250_freq_table[] = {
@ -894,6 +989,8 @@ static const struct venus_resources sm8250_res = {
.vmem_addr = 0, .vmem_addr = 0,
.dma_mask = 0xe0000000 - 1, .dma_mask = 0xe0000000 - 1,
.fwname = "qcom/vpu-1.0/venus.mbn", .fwname = "qcom/vpu-1.0/venus.mbn",
.dec_nodename = "video-decoder",
.enc_nodename = "video-encoder",
}; };
static const struct freq_tbl sc7280_freq_table[] = { static const struct freq_tbl sc7280_freq_table[] = {
@ -956,6 +1053,8 @@ static const struct venus_resources sc7280_res = {
.cp_nonpixel_start = 0x1000000, .cp_nonpixel_start = 0x1000000,
.cp_nonpixel_size = 0x24800000, .cp_nonpixel_size = 0x24800000,
.fwname = "qcom/vpu-2.0/venus.mbn", .fwname = "qcom/vpu-2.0/venus.mbn",
.dec_nodename = "video-decoder",
.enc_nodename = "video-encoder",
}; };
static const struct of_device_id venus_dt_match[] = { static const struct of_device_id venus_dt_match[] = {

View File

@ -90,6 +90,8 @@ struct venus_resources {
u32 cp_nonpixel_start; u32 cp_nonpixel_start;
u32 cp_nonpixel_size; u32 cp_nonpixel_size;
const char *fwname; const char *fwname;
const char *enc_nodename;
const char *dec_nodename;
}; };
enum venus_fmt { enum venus_fmt {
@ -169,6 +171,7 @@ struct venus_format {
* @root: debugfs root directory * @root: debugfs root directory
* @venus_ver: the venus firmware version * @venus_ver: the venus firmware version
* @dump_core: a flag indicating that a core dump is required * @dump_core: a flag indicating that a core dump is required
* @ocs: OF changeset pointer
*/ */
struct venus_core { struct venus_core {
void __iomem *base; void __iomem *base;
@ -231,6 +234,7 @@ struct venus_core {
u32 rev; u32 rev;
} venus_ver; } venus_ver;
unsigned long dump_core; unsigned long dump_core;
struct of_changeset *ocs;
}; };
struct vdec_controls { struct vdec_controls {

View File

@ -138,29 +138,6 @@ int hfi_core_trigger_ssr(struct venus_core *core, u32 type)
return core->ops->core_trigger_ssr(core, type); return core->ops->core_trigger_ssr(core, type);
} }
int hfi_core_ping(struct venus_core *core)
{
int ret;
mutex_lock(&core->lock);
ret = core->ops->core_ping(core, 0xbeef);
if (ret)
goto unlock;
ret = wait_for_completion_timeout(&core->done, TIMEOUT);
if (!ret) {
ret = -ETIMEDOUT;
goto unlock;
}
ret = 0;
if (core->error != HFI_ERR_NONE)
ret = -ENODEV;
unlock:
mutex_unlock(&core->lock);
return ret;
}
static int wait_session_msg(struct venus_inst *inst) static int wait_session_msg(struct venus_inst *inst)
{ {
int ret; int ret;

View File

@ -108,7 +108,6 @@ struct hfi_inst_ops {
struct hfi_ops { struct hfi_ops {
int (*core_init)(struct venus_core *core); int (*core_init)(struct venus_core *core);
int (*core_deinit)(struct venus_core *core); int (*core_deinit)(struct venus_core *core);
int (*core_ping)(struct venus_core *core, u32 cookie);
int (*core_trigger_ssr)(struct venus_core *core, u32 trigger_type); int (*core_trigger_ssr)(struct venus_core *core, u32 trigger_type);
int (*session_init)(struct venus_inst *inst, u32 session_type, int (*session_init)(struct venus_inst *inst, u32 session_type,
@ -152,7 +151,6 @@ int hfi_core_deinit(struct venus_core *core, bool blocking);
int hfi_core_suspend(struct venus_core *core); int hfi_core_suspend(struct venus_core *core);
int hfi_core_resume(struct venus_core *core, bool force); int hfi_core_resume(struct venus_core *core, bool force);
int hfi_core_trigger_ssr(struct venus_core *core, u32 type); int hfi_core_trigger_ssr(struct venus_core *core, u32 type);
int hfi_core_ping(struct venus_core *core);
int hfi_session_create(struct venus_inst *inst, const struct hfi_inst_ops *ops); int hfi_session_create(struct venus_inst *inst, const struct hfi_inst_ops *ops);
void hfi_session_destroy(struct venus_inst *inst); void hfi_session_destroy(struct venus_inst *inst);
int hfi_session_init(struct venus_inst *inst, u32 pixfmt); int hfi_session_init(struct venus_inst *inst, u32 pixfmt);

View File

@ -1178,16 +1178,6 @@ static int venus_core_deinit(struct venus_core *core)
return 0; return 0;
} }
static int venus_core_ping(struct venus_core *core, u32 cookie)
{
struct venus_hfi_device *hdev = to_hfi_priv(core);
struct hfi_sys_ping_pkt pkt;
pkt_sys_ping(&pkt, cookie);
return venus_iface_cmdq_write(hdev, &pkt, false);
}
static int venus_core_trigger_ssr(struct venus_core *core, u32 trigger_type) static int venus_core_trigger_ssr(struct venus_core *core, u32 trigger_type)
{ {
struct venus_hfi_device *hdev = to_hfi_priv(core); struct venus_hfi_device *hdev = to_hfi_priv(core);
@ -1639,7 +1629,6 @@ static int venus_suspend(struct venus_core *core)
static const struct hfi_ops venus_hfi_ops = { static const struct hfi_ops venus_hfi_ops = {
.core_init = venus_core_init, .core_init = venus_core_init,
.core_deinit = venus_core_deinit, .core_deinit = venus_core_deinit,
.core_ping = venus_core_ping,
.core_trigger_ssr = venus_core_trigger_ssr, .core_trigger_ssr = venus_core_trigger_ssr,
.session_init = venus_session_init, .session_init = venus_session_init,

View File

@ -1697,10 +1697,6 @@ static int vdec_open(struct file *file)
if (ret) if (ret)
goto err_free; goto err_free;
ret = hfi_session_create(inst, &vdec_hfi_ops);
if (ret)
goto err_ctrl_deinit;
vdec_inst_init(inst); vdec_inst_init(inst);
ida_init(&inst->dpb_ids); ida_init(&inst->dpb_ids);
@ -1712,15 +1708,19 @@ static int vdec_open(struct file *file)
inst->m2m_dev = v4l2_m2m_init(&vdec_m2m_ops); inst->m2m_dev = v4l2_m2m_init(&vdec_m2m_ops);
if (IS_ERR(inst->m2m_dev)) { if (IS_ERR(inst->m2m_dev)) {
ret = PTR_ERR(inst->m2m_dev); ret = PTR_ERR(inst->m2m_dev);
goto err_session_destroy; goto err_ctrl_deinit;
} }
inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init); inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init);
if (IS_ERR(inst->m2m_ctx)) { if (IS_ERR(inst->m2m_ctx)) {
ret = PTR_ERR(inst->m2m_ctx); ret = PTR_ERR(inst->m2m_ctx);
goto err_m2m_release; goto err_m2m_dev_release;
} }
ret = hfi_session_create(inst, &vdec_hfi_ops);
if (ret)
goto err_m2m_ctx_release;
v4l2_fh_init(&inst->fh, core->vdev_dec); v4l2_fh_init(&inst->fh, core->vdev_dec);
inst->fh.ctrl_handler = &inst->ctrl_handler; inst->fh.ctrl_handler = &inst->ctrl_handler;
@ -1730,10 +1730,10 @@ static int vdec_open(struct file *file)
return 0; return 0;
err_m2m_release: err_m2m_ctx_release:
v4l2_m2m_ctx_release(inst->m2m_ctx);
err_m2m_dev_release:
v4l2_m2m_release(inst->m2m_dev); v4l2_m2m_release(inst->m2m_dev);
err_session_destroy:
hfi_session_destroy(inst);
err_ctrl_deinit: err_ctrl_deinit:
v4l2_ctrl_handler_free(&inst->ctrl_handler); v4l2_ctrl_handler_free(&inst->ctrl_handler);
err_free: err_free:

View File

@ -1492,10 +1492,6 @@ static int venc_open(struct file *file)
if (ret) if (ret)
goto err_free; goto err_free;
ret = hfi_session_create(inst, &venc_hfi_ops);
if (ret)
goto err_ctrl_deinit;
venc_inst_init(inst); venc_inst_init(inst);
/* /*
@ -1505,15 +1501,19 @@ static int venc_open(struct file *file)
inst->m2m_dev = v4l2_m2m_init(&venc_m2m_ops); inst->m2m_dev = v4l2_m2m_init(&venc_m2m_ops);
if (IS_ERR(inst->m2m_dev)) { if (IS_ERR(inst->m2m_dev)) {
ret = PTR_ERR(inst->m2m_dev); ret = PTR_ERR(inst->m2m_dev);
goto err_session_destroy; goto err_ctrl_deinit;
} }
inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init); inst->m2m_ctx = v4l2_m2m_ctx_init(inst->m2m_dev, inst, m2m_queue_init);
if (IS_ERR(inst->m2m_ctx)) { if (IS_ERR(inst->m2m_ctx)) {
ret = PTR_ERR(inst->m2m_ctx); ret = PTR_ERR(inst->m2m_ctx);
goto err_m2m_release; goto err_m2m_dev_release;
} }
ret = hfi_session_create(inst, &venc_hfi_ops);
if (ret)
goto err_m2m_ctx_release;
v4l2_fh_init(&inst->fh, core->vdev_enc); v4l2_fh_init(&inst->fh, core->vdev_enc);
inst->fh.ctrl_handler = &inst->ctrl_handler; inst->fh.ctrl_handler = &inst->ctrl_handler;
@ -1523,10 +1523,10 @@ static int venc_open(struct file *file)
return 0; return 0;
err_m2m_release: err_m2m_ctx_release:
v4l2_m2m_ctx_release(inst->m2m_ctx);
err_m2m_dev_release:
v4l2_m2m_release(inst->m2m_dev); v4l2_m2m_release(inst->m2m_dev);
err_session_destroy:
hfi_session_destroy(inst);
err_ctrl_deinit: err_ctrl_deinit:
v4l2_ctrl_handler_free(&inst->ctrl_handler); v4l2_ctrl_handler_free(&inst->ctrl_handler);
err_free: err_free:

View File

@ -183,17 +183,19 @@ struct rcar_csi2;
#define V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(n) (0x23840 + ((n) * 2)) /* n = 0 - 11 */ #define V4H_CORE_DIG_IOCTRL_RW_AFE_CB_CTRL_2_REG(n) (0x23840 + ((n) * 2)) /* n = 0 - 11 */
#define V4H_CORE_DIG_RW_COMMON_REG(n) (0x23880 + ((n) * 2)) /* n = 0 - 15 */ #define V4H_CORE_DIG_RW_COMMON_REG(n) (0x23880 + ((n) * 2)) /* n = 0 - 15 */
#define V4H_CORE_DIG_ANACTRL_RW_COMMON_ANACTRL_REG(n) (0x239e0 + ((n) * 2)) /* n = 0 - 3 */ #define V4H_CORE_DIG_ANACTRL_RW_COMMON_ANACTRL_REG(n) (0x239e0 + ((n) * 2)) /* n = 0 - 3 */
#define V4H_CORE_DIG_CLANE_1_RW_CFG_0_REG 0x2a400
#define V4H_CORE_DIG_CLANE_1_RW_HS_TX_6_REG 0x2a60c #define V4H_CORE_DIG_CLANE_1_RW_HS_TX_6_REG 0x2a60c
/* V4H C-PHY */ /* V4H C-PHY */
#define V4H_CORE_DIG_RW_TRIO0_REG(n) (0x22100 + ((n) * 2)) /* n = 0 - 3 */ #define V4H_CORE_DIG_RW_TRIO0_REG(n) (0x22100 + ((n) * 2)) /* n = 0 - 3 */
#define V4H_CORE_DIG_RW_TRIO1_REG(n) (0x22500 + ((n) * 2)) /* n = 0 - 3 */ #define V4H_CORE_DIG_RW_TRIO1_REG(n) (0x22500 + ((n) * 2)) /* n = 0 - 3 */
#define V4H_CORE_DIG_RW_TRIO2_REG(n) (0x22900 + ((n) * 2)) /* n = 0 - 3 */ #define V4H_CORE_DIG_RW_TRIO2_REG(n) (0x22900 + ((n) * 2)) /* n = 0 - 3 */
#define V4H_CORE_DIG_CLANE_0_RW_CFG_0_REG 0x2a000
#define V4H_CORE_DIG_CLANE_0_RW_LP_0_REG 0x2a080 #define V4H_CORE_DIG_CLANE_0_RW_LP_0_REG 0x2a080
#define V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(n) (0x2a100 + ((n) * 2)) /* n = 0 - 6 */ #define V4H_CORE_DIG_CLANE_0_RW_HS_RX_REG(n) (0x2a100 + ((n) * 2)) /* n = 0 - 6 */
#define V4H_CORE_DIG_CLANE_1_RW_CFG_0_REG 0x2a400
#define V4H_CORE_DIG_CLANE_1_RW_LP_0_REG 0x2a480 #define V4H_CORE_DIG_CLANE_1_RW_LP_0_REG 0x2a480
#define V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(n) (0x2a500 + ((n) * 2)) /* n = 0 - 6 */ #define V4H_CORE_DIG_CLANE_1_RW_HS_RX_REG(n) (0x2a500 + ((n) * 2)) /* n = 0 - 6 */
#define V4H_CORE_DIG_CLANE_2_RW_CFG_0_REG 0x2a800
#define V4H_CORE_DIG_CLANE_2_RW_LP_0_REG 0x2a880 #define V4H_CORE_DIG_CLANE_2_RW_LP_0_REG 0x2a880
#define V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(n) (0x2a900 + ((n) * 2)) /* n = 0 - 6 */ #define V4H_CORE_DIG_CLANE_2_RW_HS_RX_REG(n) (0x2a900 + ((n) * 2)) /* n = 0 - 6 */
@ -672,6 +674,21 @@ static const struct rcar_csi2_format *rcsi2_code_to_fmt(unsigned int code)
return NULL; return NULL;
} }
struct rcsi2_cphy_line_order {
enum v4l2_mbus_csi2_cphy_line_orders_type order;
u16 cfg;
u16 ctrl29;
};
static const struct rcsi2_cphy_line_order rcsi2_cphy_line_orders[] = {
{ .order = V4L2_MBUS_CSI2_CPHY_LINE_ORDER_ABC, .cfg = 0x0, .ctrl29 = 0x0 },
{ .order = V4L2_MBUS_CSI2_CPHY_LINE_ORDER_ACB, .cfg = 0xa, .ctrl29 = 0x1 },
{ .order = V4L2_MBUS_CSI2_CPHY_LINE_ORDER_BAC, .cfg = 0xc, .ctrl29 = 0x1 },
{ .order = V4L2_MBUS_CSI2_CPHY_LINE_ORDER_BCA, .cfg = 0x5, .ctrl29 = 0x0 },
{ .order = V4L2_MBUS_CSI2_CPHY_LINE_ORDER_CAB, .cfg = 0x3, .ctrl29 = 0x0 },
{ .order = V4L2_MBUS_CSI2_CPHY_LINE_ORDER_CBA, .cfg = 0x9, .ctrl29 = 0x1 }
};
enum rcar_csi2_pads { enum rcar_csi2_pads {
RCAR_CSI2_SINK, RCAR_CSI2_SINK,
RCAR_CSI2_SOURCE_VC0, RCAR_CSI2_SOURCE_VC0,
@ -722,6 +739,7 @@ struct rcar_csi2 {
bool cphy; bool cphy;
unsigned short lanes; unsigned short lanes;
unsigned char lane_swap[4]; unsigned char lane_swap[4];
enum v4l2_mbus_csi2_cphy_line_orders_type line_orders[3];
}; };
static inline struct rcar_csi2 *sd_to_csi2(struct v4l2_subdev *sd) static inline struct rcar_csi2 *sd_to_csi2(struct v4l2_subdev *sd)
@ -754,11 +772,24 @@ static void rcsi2_write(struct rcar_csi2 *priv, unsigned int reg, u32 data)
iowrite32(data, priv->base + reg); iowrite32(data, priv->base + reg);
} }
static u16 rcsi2_read16(struct rcar_csi2 *priv, unsigned int reg)
{
return ioread16(priv->base + reg);
}
static void rcsi2_write16(struct rcar_csi2 *priv, unsigned int reg, u16 data) static void rcsi2_write16(struct rcar_csi2 *priv, unsigned int reg, u16 data)
{ {
iowrite16(data, priv->base + reg); iowrite16(data, priv->base + reg);
} }
static void rcsi2_modify16(struct rcar_csi2 *priv, unsigned int reg, u16 data, u16 mask)
{
u16 val;
val = rcsi2_read16(priv, reg) & ~mask;
rcsi2_write16(priv, reg, val | data);
}
static int rcsi2_phtw_write(struct rcar_csi2 *priv, u8 data, u8 code) static int rcsi2_phtw_write(struct rcar_csi2 *priv, u8 data, u8 code)
{ {
unsigned int timeout; unsigned int timeout;
@ -1112,6 +1143,26 @@ static int rcsi2_start_receiver_gen3(struct rcar_csi2 *priv,
return 0; return 0;
} }
static void rsci2_set_line_order(struct rcar_csi2 *priv,
enum v4l2_mbus_csi2_cphy_line_orders_type order,
unsigned int cfgreg, unsigned int ctrlreg)
{
const struct rcsi2_cphy_line_order *info = NULL;
for (unsigned int i = 0; i < ARRAY_SIZE(rcsi2_cphy_line_orders); i++) {
if (rcsi2_cphy_line_orders[i].order == order) {
info = &rcsi2_cphy_line_orders[i];
break;
}
}
if (!info)
return;
rcsi2_modify16(priv, cfgreg, info->cfg, 0x000f);
rcsi2_modify16(priv, ctrlreg, info->ctrl29, 0x0100);
}
static int rcsi2_wait_phy_start_v4h(struct rcar_csi2 *priv, u32 match) static int rcsi2_wait_phy_start_v4h(struct rcar_csi2 *priv, u32 match)
{ {
unsigned int timeout; unsigned int timeout;
@ -1189,12 +1240,18 @@ static int rcsi2_c_phy_setting_v4h(struct rcar_csi2 *priv, int msps)
rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO1_REG(1), conf->trio1); rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO1_REG(1), conf->trio1);
rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO2_REG(1), conf->trio1); rcsi2_write16(priv, V4H_CORE_DIG_RW_TRIO2_REG(1), conf->trio1);
/* /* Configure data line order. */
* Configure pin-swap. rsci2_set_line_order(priv, priv->line_orders[0],
* TODO: This registers is not documented yet, the values should depend V4H_CORE_DIG_CLANE_0_RW_CFG_0_REG,
* on the 'clock-lanes' and 'data-lanes' devicetree properties. V4H_CORE_DIG_IOCTRL_RW_AFE_LANE0_CTRL_2_REG(9));
*/ rsci2_set_line_order(priv, priv->line_orders[1],
rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_CFG_0_REG, 0xf5); V4H_CORE_DIG_CLANE_1_RW_CFG_0_REG,
V4H_CORE_DIG_IOCTRL_RW_AFE_LANE1_CTRL_2_REG(9));
rsci2_set_line_order(priv, priv->line_orders[2],
V4H_CORE_DIG_CLANE_2_RW_CFG_0_REG,
V4H_CORE_DIG_IOCTRL_RW_AFE_LANE2_CTRL_2_REG(9));
/* TODO: This registers is not documented. */
rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_TX_6_REG, 0x5000); rcsi2_write16(priv, V4H_CORE_DIG_CLANE_1_RW_HS_TX_6_REG, 0x5000);
/* Leave Shutdown mode */ /* Leave Shutdown mode */
@ -1349,15 +1406,15 @@ static int rcsi2_init_common_v4m(struct rcar_csi2 *priv, unsigned int mbps)
static const struct phtw_value step2[] = { static const struct phtw_value step2[] = {
{ .data = 0x00, .code = 0x00 }, { .data = 0x00, .code = 0x00 },
{ .data = 0x80, .code = 0xe0 }, { .data = 0x80, .code = 0xe0 },
{ .data = 0x01, .code = 0xe1 }, { .data = 0x31, .code = 0xe1 },
{ .data = 0x06, .code = 0x00 }, { .data = 0x06, .code = 0x00 },
{ .data = 0x0f, .code = 0x11 }, { .data = 0x11, .code = 0x11 },
{ .data = 0x08, .code = 0x00 }, { .data = 0x08, .code = 0x00 },
{ .data = 0x0f, .code = 0x11 }, { .data = 0x11, .code = 0x11 },
{ .data = 0x0a, .code = 0x00 }, { .data = 0x0a, .code = 0x00 },
{ .data = 0x0f, .code = 0x11 }, { .data = 0x11, .code = 0x11 },
{ .data = 0x0c, .code = 0x00 }, { .data = 0x0c, .code = 0x00 },
{ .data = 0x0f, .code = 0x11 }, { .data = 0x11, .code = 0x11 },
{ .data = 0x01, .code = 0x00 }, { .data = 0x01, .code = 0x00 },
{ .data = 0x31, .code = 0xaa }, { .data = 0x31, .code = 0xaa },
{ .data = 0x05, .code = 0x00 }, { .data = 0x05, .code = 0x00 },
@ -1370,6 +1427,11 @@ static int rcsi2_init_common_v4m(struct rcar_csi2 *priv, unsigned int mbps)
{ .data = 0x05, .code = 0x09 }, { .data = 0x05, .code = 0x09 },
}; };
static const struct phtw_value step3[] = {
{ .data = 0x01, .code = 0x00 },
{ .data = 0x06, .code = 0xab },
};
if (priv->info->hsfreqrange) { if (priv->info->hsfreqrange) {
ret = rcsi2_set_phypll(priv, mbps); ret = rcsi2_set_phypll(priv, mbps);
if (ret) if (ret)
@ -1400,7 +1462,7 @@ static int rcsi2_init_common_v4m(struct rcar_csi2 *priv, unsigned int mbps)
return ret; return ret;
} }
return ret; return rcsi2_phtw_write_array(priv, step3, ARRAY_SIZE(step3));
} }
static int rcsi2_start_receiver_v4m(struct rcar_csi2 *priv, static int rcsi2_start_receiver_v4m(struct rcar_csi2 *priv,
@ -1732,6 +1794,9 @@ static int rcsi2_parse_v4l2(struct rcar_csi2 *priv,
} }
} }
for (i = 0; i < ARRAY_SIZE(priv->line_orders); i++)
priv->line_orders[i] = vep->bus.mipi_csi2.line_orders[i];
return 0; return 0;
} }

View File

@ -558,7 +558,7 @@ static int rzg2l_cru_start_streaming_vq(struct vb2_queue *vq, unsigned int count
goto assert_aresetn; goto assert_aresetn;
} }
/* Allocate scratch buffer. */ /* Allocate scratch buffer */
cru->scratch = dma_alloc_coherent(cru->dev, cru->format.sizeimage, cru->scratch = dma_alloc_coherent(cru->dev, cru->format.sizeimage,
&cru->scratch_phys, GFP_KERNEL); &cru->scratch_phys, GFP_KERNEL);
if (!cru->scratch) { if (!cru->scratch) {

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (C) 2017 Fuzhou Rockchip Electronics Co.Ltd * Copyright (C) 2017 Rockchip Electronics Co., Ltd.
* Author: Jacob Chen <jacob-chen@iotwrt.com> * Author: Jacob Chen <jacob-chen@iotwrt.com>
*/ */

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (C) Fuzhou Rockchip Electronics Co.Ltd * Copyright (C) Rockchip Electronics Co., Ltd.
* Author: Jacob Chen <jacob-chen@iotwrt.com> * Author: Jacob Chen <jacob-chen@iotwrt.com>
*/ */

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* SPDX-License-Identifier: GPL-2.0-only */
/* /*
* Copyright (C) Fuzhou Rockchip Electronics Co.Ltd * Copyright (C) Rockchip Electronics Co., Ltd.
* Author: Jacob Chen <jacob-chen@iotwrt.com> * Author: Jacob Chen <jacob-chen@iotwrt.com>
*/ */
#ifndef __RGA_HW_H__ #ifndef __RGA_HW_H__

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // SPDX-License-Identifier: GPL-2.0-only
/* /*
* Copyright (C) Fuzhou Rockchip Electronics Co.Ltd * Copyright (C) Rockchip Electronics Co., Ltd.
* Author: Jacob Chen <jacob-chen@iotwrt.com> * Author: Jacob Chen <jacob-chen@iotwrt.com>
*/ */

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