* [PATCH 0/6] media: qcom: camss: Add support for Nord CAMSS
@ 2026-09-15 9:34 Wenmeng Liu
2026-09-15 9:34 ` [PATCH 1/6] dt-bindings: media: Add bindings for qcom,nord-camss Wenmeng Liu
` (5 more replies)
0 siblings, 6 replies; 9+ messages in thread
From: Wenmeng Liu @ 2026-09-15 9:34 UTC (permalink / raw)
To: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain,
Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Bryan O'Donoghue
Cc: linux-media, linux-arm-msm, devicetree, linux-kernel,
Wenmeng Liu, Hangxiang Ma, Atiya Kailany
Add camera subsystem support for the Qualcomm Nord platform.
Nord exposes:
- 3 x TPG (Test Pattern Generator, v2.5.0)
- 3 x CSID + 10 x CSID Lite (v900, driven by csid_ops_900)
- 3 x VFE + 10 x VFE Lite (v900, driven by vfe_ops_gen4)
The VFE reuses the gen4 (Kaanapali) driver with a VFE 900 variant for
the different bus register base, CSID900 uses a separate file.
This version only supports TPG and does not yet include CSIPHY support.
We currently do not have suitable hardware available for sensor testing
and validation. The required hardware is expected to become available in
Q4 or later, after which we plan to add CSIPHY and sensor support.
On Nord the CSID domain ID must be programmed to a non-zero value:
a domain ID of 0 selects an unmapped SMMU SID, so RDI writes never reach
memory and frames are dropped. Only the full IFE path is affected.
The domain ID registers are marked as secure. The workaround I used to
validate that the full CSID path works (programming the domain ID from
CAMSS on stream-on) is here:
https://github.com/qualcomm-linux/kernel/pull/1022/changes
The preferred solution is to initialize the value correctly in TZ, and
we're currently working on implementing that.
Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com>
---
Hangxiang Ma (1):
media: qcom: camss: vfe: Add support for VFE gen4
Wenmeng Liu (5):
dt-bindings: media: Add bindings for qcom,nord-camss
media: qcom: camss: csid: Add support for CSID 900
media: qcom: camss: vfe: Add support for VFE 900
media: qcom: camss: tpg: Add support for TPG v2.5.0
media: qcom: camss: Add support for nord camss
.../devicetree/bindings/media/qcom,nord-camss.yaml | 393 ++++++++++++++
drivers/media/platform/qcom/camss/Makefile | 2 +
drivers/media/platform/qcom/camss/camss-csid-900.c | 361 ++++++++++++
drivers/media/platform/qcom/camss/camss-csid.h | 9 +-
drivers/media/platform/qcom/camss/camss-tpg-gen1.c | 21 +-
drivers/media/platform/qcom/camss/camss-vfe-gen4.c | 283 ++++++++++
drivers/media/platform/qcom/camss/camss-vfe.c | 9 +-
drivers/media/platform/qcom/camss/camss-vfe.h | 2 +
drivers/media/platform/qcom/camss/camss.c | 602 +++++++++++++++++++++
drivers/media/platform/qcom/camss/camss.h | 1 +
10 files changed, 1676 insertions(+), 7 deletions(-)
---
base-commit: f2bfbc3554ca6919484030729424b9dee2942d24
change-id: 20260911-nord-89ab581afd75
Best regards,
--
Wenmeng Liu <wenmeng.liu@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 1/6] dt-bindings: media: Add bindings for qcom,nord-camss 2026-09-15 9:34 [PATCH 0/6] media: qcom: camss: Add support for Nord CAMSS Wenmeng Liu @ 2026-09-15 9:34 ` Wenmeng Liu 2026-09-17 10:13 ` Krzysztof Kozlowski 2026-09-15 9:34 ` [PATCH 2/6] media: qcom: camss: csid: Add support for CSID 900 Wenmeng Liu ` (4 subsequent siblings) 5 siblings, 1 reply; 9+ messages in thread From: Wenmeng Liu @ 2026-09-15 9:34 UTC (permalink / raw) To: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bryan O'Donoghue Cc: linux-media, linux-arm-msm, devicetree, linux-kernel, Wenmeng Liu Add bindings for the camera subsystem (CAMSS) on the Qualcomm Nord platform. The Nord platform provides: - 3 x TPG (Test Pattern Generator) - 3 x CSID (CSI Decoder) - 10 x CSID Lite - 3 x VFE (Video Front End) - 10 x VFE Lite Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com> --- .../devicetree/bindings/media/qcom,nord-camss.yaml | 393 +++++++++++++++++++++ 1 file changed, 393 insertions(+) diff --git a/Documentation/devicetree/bindings/media/qcom,nord-camss.yaml b/Documentation/devicetree/bindings/media/qcom,nord-camss.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ba724ecffa6cee9fcaca6a116f3785d76597def2 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,nord-camss.yaml @@ -0,0 +1,393 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,nord-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Nord Camera Subsystem (CAMSS) + +maintainers: + - Wenmeng Liu <wenmeng.liu@oss.qualcomm.com> + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,nord-camss + + reg: + maxItems: 29 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_lite2 + - const: csid_lite3 + - const: csid_lite4 + - const: csid_lite5 + - const: csid_lite6 + - const: csid_lite7 + - const: csid_lite8 + - const: csid_lite9 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + - const: vfe_lite2 + - const: vfe_lite3 + - const: vfe_lite4 + - const: vfe_lite5 + - const: vfe_lite6 + - const: vfe_lite7 + - const: vfe_lite8 + - const: vfe_lite9 + + clocks: + maxItems: 22 + + clock-names: + items: + - const: camnoc_rt_axi + - const: csid + - const: csid_csiphy_rx + - const: gcc_axi_hf + - const: top_ahb + - const: top_fast_ahb + - const: top_ife0 + - const: top_ife1 + - const: top_ife2 + - const: top_ife_lite + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe2 + - const: vfe2_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + - const: tpg_csiphy_rx + - const: qdss_debug_xo + + interrupts: + maxItems: 26 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_lite2 + - const: csid_lite3 + - const: csid_lite4 + - const: csid_lite5 + - const: csid_lite6 + - const: csid_lite7 + - const: csid_lite8 + - const: csid_lite9 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + - const: vfe_lite2 + - const: vfe_lite3 + - const: vfe_lite4 + - const: vfe_lite5 + - const: vfe_lite6 + - const: vfe_lite7 + - const: vfe_lite8 + - const: vfe_lite9 + + interconnects: + maxItems: 2 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + + iommus: + items: + - description: S1 HLOS IFE non-protected + - description: S1 HLOS IFE_LITE non-protected + + 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 Top GDSC - Titan ISP Block, Global Distributed Switch Controller. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: ife2 + - const: top + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-4]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + + description: + Input port for receiving CSI data. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + +additionalProperties: false + +examples: + - | + #include <dt-bindings/interrupt-controller/arm-gic.h> + #include <dt-bindings/clock/qcom,nord-camcc.h> + #include <dt-bindings/clock/qcom,nord-nwgcc.h> + #include <dt-bindings/interconnect/qcom,icc.h> + #include <dt-bindings/interconnect/qcom,nord-rpmh.h> + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@9b32000 { + compatible = "qcom,nord-camss"; + + reg = <0 0x09b32000 0 0x2000>, + <0 0x09b38800 0 0x2000>, + <0 0x09b3f000 0 0x2000>, + <0 0x09c32000 0 0x1000>, + <0 0x09c37000 0 0x1000>, + <0 0x09c3c000 0 0x1000>, + <0 0x09c41000 0 0x1000>, + <0 0x09c46000 0 0x1000>, + <0 0x09c4b000 0 0x1000>, + <0 0x09c50000 0 0x1000>, + <0 0x09c55000 0 0x1000>, + <0 0x09c5a000 0 0x1000>, + <0 0x09c5f000 0 0x1000>, + <0 0x09a92000 0 0x400>, + <0 0x09a93000 0 0x400>, + <0 0x09a94000 0 0x400>, + <0 0x09ab1000 0 0x4000>, + <0 0x09ad1000 0 0x4000>, + <0 0x09af1000 0 0x4000>, + <0 0x09c34000 0 0x2000>, + <0 0x09c39000 0 0x2000>, + <0 0x09c3e000 0 0x2000>, + <0 0x09c43000 0 0x2000>, + <0 0x09c48000 0 0x2000>, + <0 0x09c4d000 0 0x2000>, + <0 0x09c52000 0 0x2000>, + <0 0x09c57000 0 0x2000>, + <0 0x09c5c000 0 0x2000>, + <0 0x09c61000 0 0x2000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_lite2", + "csid_lite3", + "csid_lite4", + "csid_lite5", + "csid_lite6", + "csid_lite7", + "csid_lite8", + "csid_lite9", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1", + "vfe_lite2", + "vfe_lite3", + "vfe_lite4", + "vfe_lite5", + "vfe_lite6", + "vfe_lite7", + "vfe_lite8", + "vfe_lite9"; + + clocks = <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&nwgcc NW_GCC_CAMERA_HF_AXI_CLK>, + <&camcc CAM_CC_TOP_AHB_CLK>, + <&camcc CAM_CC_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_TOP_IFE_0_CLK>, + <&camcc CAM_CC_TOP_IFE_1_CLK>, + <&camcc CAM_CC_TOP_IFE_2_CLK>, + <&camcc CAM_CC_TOP_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_0_MAIN_CLK>, + <&camcc CAM_CC_IFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_MAIN_CLK>, + <&camcc CAM_CC_IFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_2_MAIN_CLK>, + <&camcc CAM_CC_IFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_TPG_CSIPHY_RX_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_rt_axi", + "csid", + "csid_csiphy_rx", + "gcc_axi_hf", + "top_ahb", + "top_fast_ahb", + "top_ife0", + "top_ife1", + "top_ife2", + "top_ife_lite", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "tpg_csiphy_rx", + "qdss_debug_xo"; + + interrupts = <GIC_SPI 601 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 603 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 431 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 605 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 376 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 19 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 17 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 15 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 13 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 11 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 9 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 7 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 5 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 22 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 21 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 20 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 606 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 377 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 18 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 16 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 14 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 12 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 10 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 8 IRQ_TYPE_EDGE_RISING>, + <GIC_ESPI 6 IRQ_TYPE_EDGE_RISING>, + <GIC_SPI 795 IRQ_TYPE_EDGE_RISING>; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_lite2", + "csid_lite3", + "csid_lite4", + "csid_lite5", + "csid_lite6", + "csid_lite7", + "csid_lite8", + "csid_lite9", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1", + "vfe_lite2", + "vfe_lite3", + "vfe_lite4", + "vfe_lite5", + "vfe_lite6", + "vfe_lite7", + "vfe_lite8", + "vfe_lite9"; + + interconnects = <&hscnoc MASTER_APPSS_PROC QCOM_ICC_TAG_ACTIVE_ONLY + &config_noc 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_mnoc"; + + iommus = <&apps_smmu_2 0x1401 0x20>, + <&apps_smmu_2 0x1460 0x00>; + + 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"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + endpoint { + data-lanes = <0 1 2 3>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; -- 2.34.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/6] dt-bindings: media: Add bindings for qcom,nord-camss 2026-09-15 9:34 ` [PATCH 1/6] dt-bindings: media: Add bindings for qcom,nord-camss Wenmeng Liu @ 2026-09-17 10:13 ` Krzysztof Kozlowski 2026-09-17 12:37 ` Wenmeng Liu 0 siblings, 1 reply; 9+ messages in thread From: Krzysztof Kozlowski @ 2026-09-17 10:13 UTC (permalink / raw) To: Wenmeng Liu Cc: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bryan O'Donoghue, linux-media, linux-arm-msm, devicetree, linux-kernel On Tue, Sep 15, 2026 at 05:34:11PM +0800, Wenmeng Liu wrote: > Add bindings for the camera subsystem (CAMSS) on the Qualcomm Nord > platform. > > The Nord platform provides: > - 3 x TPG (Test Pattern Generator) > - 3 x CSID (CSI Decoder) > - 10 x CSID Lite > - 3 x VFE (Video Front End) > - 10 x VFE Lite > > Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com> > --- > .../devicetree/bindings/media/qcom,nord-camss.yaml | 393 +++++++++++++++++++++ > 1 file changed, 393 insertions(+) A nit, subject: drop second/last, redundant "bindings for". The "dt-bindings" prefix is already stating that these are bindings. See also: https://elixir.bootlin.com/linux/v7.1-rc7/source/Documentation/devicetree/bindings/submitting-patches.rst#L23 ... > + description: > + Input port for receiving CSI data. > + > + properties: > + endpoint: > + $ref: video-interfaces.yaml# > + unevaluatedProperties: false > + > + properties: > + data-lanes: > + minItems: 1 > + maxItems: 4 > + > + bus-type: > + enum: > + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY > + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY > + > + required: > + - data-lanes > + Missing supplies, altough maybe this is related to some other ongoing work, so would be useful to see explanation in commit msg. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/6] dt-bindings: media: Add bindings for qcom,nord-camss 2026-09-17 10:13 ` Krzysztof Kozlowski @ 2026-09-17 12:37 ` Wenmeng Liu 0 siblings, 0 replies; 9+ messages in thread From: Wenmeng Liu @ 2026-09-17 12:37 UTC (permalink / raw) To: Krzysztof Kozlowski Cc: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bryan O'Donoghue, linux-media, linux-arm-msm, devicetree, linux-kernel Hi Krzysztof, On 9/17/2026 6:13 PM, Krzysztof Kozlowski wrote: > On Tue, Sep 15, 2026 at 05:34:11PM +0800, Wenmeng Liu wrote: >> Add bindings for the camera subsystem (CAMSS) on the Qualcomm Nord >> platform. >> >> The Nord platform provides: >> - 3 x TPG (Test Pattern Generator) >> - 3 x CSID (CSI Decoder) >> - 10 x CSID Lite >> - 3 x VFE (Video Front End) >> - 10 x VFE Lite >> >> Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com> >> --- >> .../devicetree/bindings/media/qcom,nord-camss.yaml | 393 +++++++++++++++++++++ >> 1 file changed, 393 insertions(+) > > A nit, subject: drop second/last, redundant "bindings for". The > "dt-bindings" prefix is already stating that these are bindings. > See also: > https://elixir.bootlin.com/linux/v7.1-rc7/source/Documentation/devicetree/bindings/submitting-patches.rst#L23 > ACK > ... > >> + description: >> + Input port for receiving CSI data. >> + >> + properties: >> + endpoint: >> + $ref: video-interfaces.yaml# >> + unevaluatedProperties: false >> + >> + properties: >> + data-lanes: >> + minItems: 1 >> + maxItems: 4 >> + >> + bus-type: >> + enum: >> + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY >> + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY >> + >> + required: >> + - data-lanes >> + > > Missing supplies, altough maybe this is related to some other ongoing > work, so would be useful to see explanation in commit msg. At the moment, the Nord platform only supports TPG. Perhaps I should remove this part of the change for now and reintroduce it later when CSIPHY support is available, once the EVK board is ready. Anyway, I will explanation in commit msg next version. Thanks, Wenmeng ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/6] media: qcom: camss: csid: Add support for CSID 900 2026-09-15 9:34 [PATCH 0/6] media: qcom: camss: Add support for Nord CAMSS Wenmeng Liu 2026-09-15 9:34 ` [PATCH 1/6] dt-bindings: media: Add bindings for qcom,nord-camss Wenmeng Liu @ 2026-09-15 9:34 ` Wenmeng Liu 2026-09-15 9:34 ` [PATCH 3/6] media: qcom: camss: vfe: Add support for VFE gen4 Wenmeng Liu ` (3 subsequent siblings) 5 siblings, 0 replies; 9+ messages in thread From: Wenmeng Liu @ 2026-09-15 9:34 UTC (permalink / raw) To: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bryan O'Donoghue Cc: linux-media, linux-arm-msm, devicetree, linux-kernel, Wenmeng Liu Add a CSID driver for the "900" revision on the Nord SoC. It shares the CSI-2 RX helpers and the split RUP/AUP command model of the gen3/980 lineage, but uses a single register map for both the full and lite instances, so add a separate file rather than a variant of an existing CSID. The write master buffers are enqueued to the CSID: for every enabled RDI an AUP_UPDATE is issued once per initial buffer, followed by a single RUP_UPDATE, matching the number of buffers handed to the write master when it is enabled. Nord has 3 CSID and 10 CSID Lite instances, all driven by csid_ops_900. Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com> --- drivers/media/platform/qcom/camss/Makefile | 1 + drivers/media/platform/qcom/camss/camss-csid-900.c | 361 +++++++++++++++++++++ drivers/media/platform/qcom/camss/camss-csid.h | 9 +- 3 files changed, 370 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index 27898b3cc7d3c8f275567f81f0952e2a0e18f189..ddda81b6a3ee141e0ed5bee61d5970a0d7ee6116 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -8,6 +8,7 @@ qcom-camss-objs += \ camss-csid-4-7.o \ camss-csid-340.o \ camss-csid-680.o \ + camss-csid-900.o \ camss-csid-gen2.o \ camss-csid-gen3.o \ camss-csiphy.o \ diff --git a/drivers/media/platform/qcom/camss/camss-csid-900.c b/drivers/media/platform/qcom/camss/camss-csid-900.c new file mode 100644 index 0000000000000000000000000000000000000000..921ddb7aca37f449dae7b9e3a7b12e5a601c633c --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-900.c @@ -0,0 +1,361 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-csid-900.c + * + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module 900 + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include <linux/completion.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/of.h> +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen3.h" + +#define CSID_RST_CFG 0xC +#define RST_MODE BIT(0) +#define RST_LOCATION BIT(4) + +#define CSID_RST_CMD 0x10 +#define SELECT_HW_RST BIT(0) +#define SELECT_IRQ_RST BIT(2) +#define CSID_IRQ_CMD 0x14 +#define IRQ_CMD_CLEAR BIT(0) + +#define CSID_RUP_CMD 0x18 +#define CSID_AUP_CMD 0x1C +#define CSID_RUP_AUP_RDI(rdi) (BIT(8) << (rdi)) +#define CSID_RUP_AUP_CMD 0x20 +#define RUP_SET BIT(0) +#define MUP BIT(4) + +#define CSID_TOP_IRQ_STATUS 0x84 +#define CSID_TOP_IRQ_MASK 0x88 +#define CSID_TOP_IRQ_CLEAR 0x8C +#define CSID_TOP_IRQ_SET 0x90 +#define INFO_RST_DONE BIT(0) +#define CSI2_RX_IRQ_STATUS BIT(2) +#define BUF_DONE_IRQ_STATUS BIT(3) + +#define CSID_BUF_DONE_IRQ_STATUS 0xA4 +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET 16 +#define CSID_BUF_DONE_IRQ_MASK 0xA8 +#define CSID_BUF_DONE_IRQ_CLEAR 0xAC +#define CSID_BUF_DONE_IRQ_SET 0xB0 + +#define CSID_CSI2_RX_IRQ_STATUS 0xB4 +#define CSID_CSI2_RX_IRQ_MASK 0xB8 +#define CSID_CSI2_RX_IRQ_CLEAR 0xBC +#define CSID_CSI2_RX_IRQ_SET 0xC0 + +#define CSID_CSI2_RX_CFG0 0x400 +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_DL0_INPUT_SEL 4 +#define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 +#define CSI2_RX_CFG0_TPG_MUX_EN BIT(27) +#define CSI2_RX_CFG0_TPG_MUX_SEL GENMASK(29, 28) +#define CSID_CSI2_RX_CFG1 0x404 +#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_VC_MODE BIT(2) + +#define MSM_CSID_MAX_SRC_STREAMS_900 (csid_is_lite(csid) ? 4 : 5) + +#define CSID_RDI_BASE (csid_is_lite(csid) ? 0x600 : 0x1300) +#define CSID_RDI_CFG0(rdi) (CSID_RDI_BASE + 0x0 + 0x200 * (rdi)) +#define RDI_CFG0_RETIME_DIS BIT(5) +#define RDI_CFG0_TIMESTAMP_EN BIT(6) +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) +#define RDI_CFG0_DECODE_FORMAT 12 +#define RDI_CFG0_DT 16 +#define RDI_CFG0_VC 22 +#define RDI_CFG0_EN BIT(31) + +#define CSID_RDI_CTRL(rdi) (CSID_RDI_BASE + 0x4 + 0x200 * (rdi)) +#define RDI_CTRL_START_CMD BIT(0) + +#define CSID_RDI_CFG1(rdi) (CSID_RDI_BASE + 0x10 + 0x200 * (rdi)) +#define RDI_CFG1_DROP_H_EN BIT(5) +#define RDI_CFG1_DROP_V_EN BIT(6) +#define RDI_CFG1_CROP_H_EN BIT(7) +#define RDI_CFG1_CROP_V_EN BIT(8) +#define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) + +#define CSID_RDI_PIX_STORE_CFG0(rdi) (CSID_RDI_BASE + 0x14 + 0x200 * (rdi)) +#define RDI_PIX_STORE_CFG0_EN BIT(0) +#define RDI_PIX_STORE_CFG0_MIN_HBI 1 + +#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) (0x114 + 0x10 * (rdi)) +#define CSID_CSI2_RDIN_IRQ_MASK(rdi) (0x118 + 0x10 * (rdi)) +#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) (0x11C + 0x10 * (rdi)) +#define INFO_RUP_DONE BIT(23) + +static void __csid_aup_rup_trigger(struct csid_device *csid) +{ + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD); +} + +static void __csid_aup_update(struct csid_device *csid, int port_id) +{ + csid->aup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->aup_update, csid->base + CSID_AUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_rup_update(struct csid_device *csid, int port_id) +{ + csid->rup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->rup_update, csid->base + CSID_RUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_aup_rup_clear(struct csid_device *csid, int port_id) +{ + /* Hardware clears the registers upon consuming the settings */ + csid->aup_update &= ~CSID_RUP_AUP_RDI(port_id); + csid->rup_update &= ~CSID_RUP_AUP_RDI(port_id); +} + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy) +{ + struct camss *camss = csid->camss; + int val; + + val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; + val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; + + if (camss->tpg && csid->tpg_linked && + camss->tpg[phy->csiphy_id].testgen.mode != TPG_PAYLOAD_MODE_DISABLED) { + val |= FIELD_PREP(CSI2_RX_CFG0_TPG_MUX_SEL, phy->csiphy_id + 1); + val |= CSI2_RX_CFG0_TPG_MUX_EN; + } else { + val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) + << CSI2_RX_CFG0_PHY_NUM_SEL; + } + writel(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_ECC_CORRECTION_EN; + writel(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_configure_rx_vc(struct csid_device *csid, int vc) +{ + int val; + + if (vc > 3) { + val = readl(csid->base + CSID_CSI2_RX_CFG1); + val |= CSI2_RX_CFG1_VC_MODE; + writel(val, csid->base + CSID_CSI2_RX_CFG1); + } +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + int val = 0; + u32 rdi_ctrl_offset = CSID_RDI_CTRL(rdi); + + if (enable) + val = RDI_CTRL_START_CMD; + + writel(val, csid->base + rdi_ctrl_offset); +} + +static void __csid_configure_rdi_pix_store(struct csid_device *csid, u8 rdi) +{ + u32 val; + + /* + * Configure pixel store to allow absorption of hblanking or idle time. + * This helps with horizontal crop and prevents line buffer conflicts. + * Reset state is 0x8 which has MIN_HBI=4, we keep the default MIN_HBI + * and just enable the pixel store functionality. + */ + val = (4 << RDI_PIX_STORE_CFG0_MIN_HBI) | RDI_PIX_STORE_CFG0_EN; + writel(val, csid->base + CSID_RDI_PIX_STORE_CFG0(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc) +{ + u32 val; + u8 lane_cnt = csid->phy.lane_cnt; + + /* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + + if (!lane_cnt) + lane_cnt = 4; + + u32 rdi_cfg0_offset = CSID_RDI_CFG0(port); + u32 rdi_cfg1_offset = CSID_RDI_CFG1(port); + u32 rdi_ctrl_offset = CSID_RDI_CTRL(port); + + val = RDI_CFG0_TIMESTAMP_EN; + val |= RDI_CFG0_TIMESTAMP_STB_SEL; + val |= RDI_CFG0_RETIME_DIS; + + /* note: for non-RDI path, this should be format->decode_format */ + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; + val |= vc << RDI_CFG0_VC; + val |= format->data_type << RDI_CFG0_DT; + writel(val, csid->base + rdi_cfg0_offset); + + val = RDI_CFG1_PACKING_FORMAT_MIPI; + writel(val, csid->base + rdi_cfg1_offset); + + if (!csid_is_lite(csid)) + __csid_configure_rdi_pix_store(csid, port); + + val = 0; + writel(val, csid->base + rdi_ctrl_offset); + + val = readl(csid->base + rdi_cfg0_offset); + + if (enable) + val |= RDI_CFG0_EN; + + writel(val, csid->base + rdi_cfg0_offset); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + u8 i, k; + + __csid_configure_rx(csid, &csid->phy); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_900; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i, 0); + __csid_configure_rx_vc(csid, 0); + + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++) + __csid_aup_update(csid, i); + + __csid_rup_update(csid, i); + + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return 0; +} + +static void csid_subdev_reg_update(struct csid_device *csid, int port_id, + bool clear) +{ + if (clear) + __csid_aup_rup_clear(csid, port_id); + else + __csid_aup_update(csid, port_id); +} + +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val, buf_done_val; + u8 reset_done; + int i; + + val = readl(csid->base + CSID_TOP_IRQ_STATUS); + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + + reset_done = val & INFO_RST_DONE; + + buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS); + writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_900; i++) { + if (csid->phy.en_vc & BIT(i)) { + val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); + writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); + + if (val & INFO_RUP_DONE) + csid_subdev_reg_update(csid, i, true); + + if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) + camss_buf_done(csid->camss, csid->id, i); + } + } + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + if (reset_done) + complete(&csid->reset_complete); + + return IRQ_HANDLED; +} + +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + u32 val; + int i; + + reinit_completion(&csid->reset_complete); + + val = INFO_RST_DONE | BUF_DONE_IRQ_STATUS; + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + writel(val, csid->base + CSID_TOP_IRQ_MASK); + + val = 0; + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_900; i++) { + if (csid->phy.en_vc & BIT(i)) { + /* + * Only need to clear buf done IRQ status here, + * RUP done IRQ status will be cleared once isr + * strobe generated by CSID_RST_CMD + */ + val |= BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i); + } + } + writel(val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + writel(val, csid->base + CSID_BUF_DONE_IRQ_MASK); + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + val = RST_LOCATION | RST_MODE; + writel(val, csid->base + CSID_RST_CFG); + + val = SELECT_HW_RST | SELECT_IRQ_RST; + writel(val, csid->base + CSID_RST_CMD); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + + if (!time) { + dev_err(csid->camss->dev, "CSID reset timeout\n"); + return -EIO; + } + + return 0; +} + +static void csid_subdev_init(struct csid_device *csid) +{ + csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; +} + +const struct csid_hw_ops csid_ops_900 = { + .configure_stream = csid_configure_stream, + .configure_testgen_pattern = csid_configure_testgen_pattern, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, + .reg_update = csid_subdev_reg_update, +}; diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index 5296b10f6bac839a3faa1039bdbf0fbbbe9456ac..0c8933d564b495403d4f8b1949049ff53568c8df 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -154,7 +154,13 @@ struct csid_device { void __iomem *base; u32 irq; char irq_name[30]; - u32 reg_update; + union { + u32 reg_update; + struct { + u32 rup_update; + u32 aup_update; + }; + }; struct camss_clock *clock; int nclocks; struct regulator_bulk_data *supplies; @@ -216,6 +222,7 @@ extern const struct csid_hw_ops csid_ops_4_1; extern const struct csid_hw_ops csid_ops_4_7; extern const struct csid_hw_ops csid_ops_340; extern const struct csid_hw_ops csid_ops_680; +extern const struct csid_hw_ops csid_ops_900; extern const struct csid_hw_ops csid_ops_gen2; extern const struct csid_hw_ops csid_ops_gen3; -- 2.34.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/6] media: qcom: camss: vfe: Add support for VFE gen4 2026-09-15 9:34 [PATCH 0/6] media: qcom: camss: Add support for Nord CAMSS Wenmeng Liu 2026-09-15 9:34 ` [PATCH 1/6] dt-bindings: media: Add bindings for qcom,nord-camss Wenmeng Liu 2026-09-15 9:34 ` [PATCH 2/6] media: qcom: camss: csid: Add support for CSID 900 Wenmeng Liu @ 2026-09-15 9:34 ` Wenmeng Liu 2026-09-15 9:34 ` [PATCH 4/6] media: qcom: camss: vfe: Add support for VFE 900 Wenmeng Liu ` (2 subsequent siblings) 5 siblings, 0 replies; 9+ messages in thread From: Wenmeng Liu @ 2026-09-15 9:34 UTC (permalink / raw) To: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bryan O'Donoghue Cc: linux-media, linux-arm-msm, devicetree, linux-kernel, Wenmeng Liu, Hangxiang Ma, Atiya Kailany From: Hangxiang Ma <hangxiang.ma@oss.qualcomm.com> Add support for the VFE (Video Front End) Gen4 found on Kaanapali SoC. In the Kaanapali camera subsystem, the front-end blocks are referred to as TFEs (Thin Front Ends). This driver continues to use the VFE naming in some places to preserve consistency with the existing code and avoid unnecessary renaming. Support is currently limited to three output lines, matching the constraints of the CAMSS framework. Kaanapali requires REG_UPDATE and AUP_UPDATE to be issued only after all CSID configuration has completed. In addition, the number of AUP_UPDATE requests must match the number of buffers queued to the write master while it is being enabled. Although real-time TFE traffic is routed through RT_CAMNOC, both camnoc_rt_axi and camnoc_nrt_axi clocks must be enabled. This ensures that the PDX_NOC, which sits downstream of both RT and NRT NOCs, exits reset in a fully idle state. Co-developed-by: Atiya Kailany <atiya.kailany@oss.qualcomm.com> Signed-off-by: Atiya Kailany <atiya.kailany@oss.qualcomm.com> Signed-off-by: Hangxiang Ma <hangxiang.ma@oss.qualcomm.com> Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com> --- drivers/media/platform/qcom/camss/Makefile | 1 + drivers/media/platform/qcom/camss/camss-vfe-gen4.c | 197 +++++++++++++++++++++ drivers/media/platform/qcom/camss/camss-vfe.c | 7 +- drivers/media/platform/qcom/camss/camss-vfe.h | 2 + 4 files changed, 205 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index ddda81b6a3ee141e0ed5bee61d5970a0d7ee6116..76bcd43c5c8770488da13ddaa3249878edf6ffc6 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -28,6 +28,7 @@ qcom-camss-objs += \ camss-vfe-680.o \ camss-vfe-gen1.o \ camss-vfe-gen3.o \ + camss-vfe-gen4.o \ camss-vfe-vbif.o \ camss-video.o diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c new file mode 100644 index 0000000000000000000000000000000000000000..d73d70898710a2127c606ac8459a1d8c747a2f7c --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-vfe-gen4.c + * + * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module gen4 + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include <linux/interrupt.h> +#include <linux/io.h> +#include <linux/iopoll.h> + +#include "camss.h" +#include "camss-vfe.h" + +/* VFE-gen4 Bus Register Base Addresses */ +#define BUS_REG_BASE (vfe_is_lite(vfe) ? 0x800 : 0x1000) + +#define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) +#define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) + +#define VFE_BUS_WM_TEST_BUS_CTRL (BUS_REG_BASE + 0x128) + +#define VFE_BUS_WM_CFG(n) (BUS_REG_BASE + 0x500 + (n) * 0x100) +#define WM_CFG_EN BIT(0) +#define WM_VIR_FRM_EN BIT(1) +#define WM_CFG_MODE BIT(16) +#define VFE_BUS_WM_IMAGE_ADDR(n) (BUS_REG_BASE + 0x504 + (n) * 0x100) +#define VFE_BUS_WM_FRAME_INCR(n) (BUS_REG_BASE + 0x508 + (n) * 0x100) +#define VFE_BUS_WM_IMAGE_CFG_0(n) (BUS_REG_BASE + 0x50C + (n) * 0x100) +#define WM_IMAGE_CFG_0_DEFAULT_WIDTH (0xFFFF) +#define VFE_BUS_WM_IMAGE_CFG_2(n) (BUS_REG_BASE + 0x514 + (n) * 0x100) +#define WM_IMAGE_CFG_2_DEFAULT_STRIDE (0xFFFF) +#define VFE_BUS_WM_PACKER_CFG(n) (BUS_REG_BASE + 0x518 + (n) * 0x100) + +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(n) (BUS_REG_BASE + 0x530 + (n) * 0x100) +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(n) (BUS_REG_BASE + 0x534 + (n) * 0x100) + +/* VFE lite has no such registers */ +#define VFE_BUS_WM_FRAMEDROP_PERIOD(n) (BUS_REG_BASE + 0x538 + (n) * 0x100) +#define VFE_BUS_WM_FRAMEDROP_PATTERN(n) (BUS_REG_BASE + 0x53C + (n) * 0x100) + +#define VFE_BUS_WM_MMU_PREFETCH_CFG(n) (BUS_REG_BASE + 0x560 + (n) * 0x100) +#define VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(n) (BUS_REG_BASE + 0x564 + (n) * 0x100) + +/* + * IFE write master client IDs + * + * VIDEO_FULL 0 + * VIDEO_DC4_Y 1 + * VIDEO_DC4_C 2 + * VIDEO_DC16_Y 3 + * VIDEO_DC16_C 4 + * DISPLAY_DS2_Y 5 + * DISPLAY_DS2_C 6 + * FD_Y 7 + * FD_C 8 + * PIXEL_RAW 9 + * STATS_AEC_BG 10 + * STATS_AEC_BHIST 11 + * STATS_TINTLESS_BG 12 + * STATS_AWB_BG 13 + * STATS_AWB_BFW 14 + * STATS_AF_BHIST 15 + * STATS_ALSC_BG 16 + * STATS_FLICKER_BAYERRS 17 + * STATS_TMC_BHIST 18 + * PDAF_0 19 + * PDAF_1 20 + * PDAF_2 21 + * PDAF_3 22 + * RDI0 23 + * RDI1 24 + * RDI2 25 + * RDI3 26 + * RDI4 27 + * + * IFE Lite write master client IDs + * + * RDI0 0 + * RDI1 1 + * RDI2 2 + * RDI3 3 + * GAMMA 4 + * STATES_BE 5 + */ +#define RDI_WM(n) ((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n)) + +static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) +{ + struct v4l2_pix_format_mplane *pix = + &line->video_out.active_fmt.fmt.pix_mp; + + wm = RDI_WM(wm); + + /* no clock gating at bus input */ + writel(WM_CGC_OVERRIDE_ALL, vfe->base + VFE_BUS_WM_CGC_OVERRIDE); + + writel(0x0, vfe->base + VFE_BUS_WM_TEST_BUS_CTRL); + + writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height >> 8, + vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); + writel((WM_IMAGE_CFG_0_DEFAULT_WIDTH & 0xFFFF), + vfe->base + VFE_BUS_WM_IMAGE_CFG_0(wm)); + writel(WM_IMAGE_CFG_2_DEFAULT_STRIDE, + vfe->base + VFE_BUS_WM_IMAGE_CFG_2(wm)); + writel(0, vfe->base + VFE_BUS_WM_PACKER_CFG(wm)); + + /* no dropped frames, one irq per frame */ + if (!vfe_is_lite(vfe)) { + writel(0, vfe->base + VFE_BUS_WM_FRAMEDROP_PERIOD(wm)); + writel(1, vfe->base + VFE_BUS_WM_FRAMEDROP_PATTERN(wm)); + } + + writel(0, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(wm)); + writel(1, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(wm)); + + writel(1, vfe->base + VFE_BUS_WM_MMU_PREFETCH_CFG(wm)); + writel(0xFFFFFFFF, vfe->base + VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(wm)); + + writel(WM_CFG_EN | WM_CFG_MODE, vfe->base + VFE_BUS_WM_CFG(wm)); +} + +static void vfe_wm_stop(struct vfe_device *vfe, u8 wm) +{ + wm = RDI_WM(wm); + writel(0, vfe->base + VFE_BUS_WM_CFG(wm)); +} + +static void vfe_wm_update(struct vfe_device *vfe, u8 wm, u32 addr, + struct vfe_line *line) +{ + wm = RDI_WM(wm); + writel(addr >> 8, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); + + dev_dbg(vfe->camss->dev, "wm:%d, image buf addr:0x%x\n", wm, addr); +} + +static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) +{ + int port_id = line_id; + + camss_reg_update(vfe->camss, vfe->id, port_id, false); +} + +static inline void vfe_reg_update_clear(struct vfe_device *vfe, + enum vfe_line_id line_id) +{ + int port_id = line_id; + + camss_reg_update(vfe->camss, vfe->id, port_id, true); +} + +static const struct camss_video_ops vfe_video_ops_gen4 = { + .queue_buffer = vfe_queue_buffer_v2, + .flush_buffers = vfe_flush_buffers, +}; + +static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) +{ + vfe->video_ops = vfe_video_ops_gen4; +} + +static void vfe_global_reset(struct vfe_device *vfe) +{ + vfe_isr_reset_ack(vfe); +} + +static irqreturn_t vfe_isr(int irq, void *dev) +{ + /* nop */ + return IRQ_HANDLED; +} + +static int vfe_halt(struct vfe_device *vfe) +{ + /* rely on vfe_disable_output() to stop the VFE */ + return 0; +} + +const struct vfe_hw_ops vfe_ops_gen4 = { + .global_reset = vfe_global_reset, + .hw_version = vfe_hw_version, + .isr = vfe_isr, + .pm_domain_off = vfe_pm_domain_off, + .pm_domain_on = vfe_pm_domain_on, + .reg_update = vfe_reg_update, + .reg_update_clear = vfe_reg_update_clear, + .subdev_init = vfe_subdev_init, + .vfe_disable = vfe_disable, + .vfe_enable = vfe_enable_v2, + .vfe_halt = vfe_halt, + .vfe_wm_start = vfe_wm_start, + .vfe_wm_stop = vfe_wm_stop, + .vfe_buf_done = vfe_buf_done, + .vfe_wm_update = vfe_wm_update, +}; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 319d191589884777bced456867e5a2a4211a2770..11f616ae035c1814e21ae2a01c5e1131022da236 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -525,7 +525,8 @@ int vfe_enable_output_v2(struct vfe_line *line) spin_lock_irqsave(&vfe->output_lock, flags); - ops->reg_update_clear(vfe, line->id); + if (ops->reg_update_clear) + ops->reg_update_clear(vfe, line->id); if (output->state > VFE_OUTPUT_RESERVED) { dev_err(vfe->camss->dev, @@ -552,7 +553,9 @@ int vfe_enable_output_v2(struct vfe_line *line) output->gen2.active_num++; ops->vfe_wm_update(vfe, output->wm_idx[0], output->buf[i]->addr[0], line); - ops->reg_update(vfe, line->id); + + if (!vfe->res->reg_update_after_csid_config) + ops->reg_update(vfe, line->id); } spin_unlock_irqrestore(&vfe->output_lock, flags); diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h index ae9dad353a3783cc0c9945e58167573b48441067..c402ef170c81bf3b9a26ff3d92db1d3a1b44329a 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.h +++ b/drivers/media/platform/qcom/camss/camss-vfe.h @@ -133,6 +133,7 @@ struct vfe_isr_ops { struct vfe_subdev_resources { bool is_lite; + bool reg_update_after_csid_config; u8 line_num; bool has_pd; char *pd_name; @@ -249,6 +250,7 @@ extern const struct vfe_hw_ops vfe_ops_340; extern const struct vfe_hw_ops vfe_ops_480; extern const struct vfe_hw_ops vfe_ops_680; extern const struct vfe_hw_ops vfe_ops_gen3; +extern const struct vfe_hw_ops vfe_ops_gen4; int vfe_get(struct vfe_device *vfe); void vfe_put(struct vfe_device *vfe); -- 2.34.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/6] media: qcom: camss: vfe: Add support for VFE 900 2026-09-15 9:34 [PATCH 0/6] media: qcom: camss: Add support for Nord CAMSS Wenmeng Liu ` (2 preceding siblings ...) 2026-09-15 9:34 ` [PATCH 3/6] media: qcom: camss: vfe: Add support for VFE gen4 Wenmeng Liu @ 2026-09-15 9:34 ` Wenmeng Liu 2026-09-15 9:34 ` [PATCH 5/6] media: qcom: camss: tpg: Add support for TPG v2.5.0 Wenmeng Liu 2026-09-15 9:34 ` [PATCH 6/6] media: qcom: camss: Add support for nord camss Wenmeng Liu 5 siblings, 0 replies; 9+ messages in thread From: Wenmeng Liu @ 2026-09-15 9:34 UTC (permalink / raw) To: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bryan O'Donoghue Cc: linux-media, linux-arm-msm, devicetree, linux-kernel, Wenmeng Liu The VFE on the Nord platform reuses the gen4 VFE driver but places its bus registers at a different base and does not implement the write master CGC override register. Add a VFE 900 variant to the gen4 driver to handle the different bus register base, the separate location of the test bus control register, and to skip the missing CGC override register. In addition, the v900 ADDR_IMAGE register takes a full byte address rather than the 256-byte-unit encoding used by the gen4 baseline, and the full IFE write master client map places the RDI clients at index 28 (the lite instances keep RDI0 at client 0). Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com> --- drivers/media/platform/qcom/camss/camss-vfe-gen4.c | 102 +++++++++++++++++++-- drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 95 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c index d73d70898710a2127c606ac8459a1d8c747a2f7c..f1429a6d2be54c415175a0129778f4b3a232564f 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c @@ -13,13 +13,77 @@ #include "camss.h" #include "camss-vfe.h" +struct vfe_gen4_hw_info { + u32 bus_reg_base; + u32 bus_reg_base_lite; + s32 test_bus_ctrl_offset; /* relative to the bus register base */ + u8 rdi_wm_offset; + u8 rdi_wm_offset_lite; + u8 addr_shift; /* ADDR_IMAGE address unit */ + bool has_wm_cgc_override; +}; + +static const struct vfe_gen4_hw_info vfe_900_hw_info = { + .bus_reg_base = 0xA00, + .bus_reg_base_lite = 0x700, + .test_bus_ctrl_offset = -0x1BC, + .rdi_wm_offset = 0x1C, + .rdi_wm_offset_lite = 0x0, + .addr_shift = 0, + .has_wm_cgc_override = false, +}; + +static const struct vfe_gen4_hw_info vfe_1080_hw_info = { + .bus_reg_base = 0x1000, + .bus_reg_base_lite = 0x800, + .test_bus_ctrl_offset = 0x128, + .rdi_wm_offset = 0x17, + .rdi_wm_offset_lite = 0x0, + .addr_shift = 8, + .has_wm_cgc_override = true, +}; + +static inline const struct vfe_gen4_hw_info * +vfe_gen4_get_hw_info(struct vfe_device *vfe) +{ + switch (vfe->camss->res->version) { + case CAMSS_NORD: + return &vfe_900_hw_info; + default: + return &vfe_1080_hw_info; + } +} + +static inline u32 vfe_gen4_bus_reg_base(struct vfe_device *vfe) +{ + const struct vfe_gen4_hw_info *hw_info = vfe_gen4_get_hw_info(vfe); + + return vfe_is_lite(vfe) ? hw_info->bus_reg_base_lite : + hw_info->bus_reg_base; +} + +static inline u32 vfe_gen4_test_bus_ctrl(struct vfe_device *vfe) +{ + const struct vfe_gen4_hw_info *hw_info = vfe_gen4_get_hw_info(vfe); + + return vfe_gen4_bus_reg_base(vfe) + hw_info->test_bus_ctrl_offset; +} + +static inline u8 vfe_gen4_rdi_wm(struct vfe_device *vfe, u8 rdi) +{ + const struct vfe_gen4_hw_info *hw_info = vfe_gen4_get_hw_info(vfe); + + return rdi + (vfe_is_lite(vfe) ? hw_info->rdi_wm_offset_lite : + hw_info->rdi_wm_offset); +} + /* VFE-gen4 Bus Register Base Addresses */ -#define BUS_REG_BASE (vfe_is_lite(vfe) ? 0x800 : 0x1000) +#define BUS_REG_BASE (vfe_gen4_bus_reg_base(vfe)) #define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) #define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) -#define VFE_BUS_WM_TEST_BUS_CTRL (BUS_REG_BASE + 0x128) +#define VFE_BUS_WM_TEST_BUS_CTRL (vfe_gen4_test_bus_ctrl(vfe)) #define VFE_BUS_WM_CFG(n) (BUS_REG_BASE + 0x500 + (n) * 0x100) #define WM_CFG_EN BIT(0) @@ -83,18 +147,36 @@ * RDI3 3 * GAMMA 4 * STATES_BE 5 + * + * v900 full IFE write master client map: the RDI clients start at 28, + * after the 28 image/stats clients (0-27): + * + * MAIN C0/C1/C2/UV 0-3 + * PIXEL_RAW 4 + * W_IR 5 + * AI_1 C0/C1/C2/UV 6-9 + * AI_2 C0/C1/C2/UV 10-13 + * HV_DS16 / HV_DS4 14-15 + * STATS BG_IR..BLTM 16-27 + * RDI0 28 + * RDI1 29 + * RDI2 30 + * ... RDI11 39 + * + * v900 IFE Lite matches the generic map above (RDI0 at client 0). */ -#define RDI_WM(n) ((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n)) static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) { struct v4l2_pix_format_mplane *pix = &line->video_out.active_fmt.fmt.pix_mp; - wm = RDI_WM(wm); + wm = vfe_gen4_rdi_wm(vfe, wm); /* no clock gating at bus input */ - writel(WM_CGC_OVERRIDE_ALL, vfe->base + VFE_BUS_WM_CGC_OVERRIDE); + if (vfe_gen4_get_hw_info(vfe)->has_wm_cgc_override) + writel(WM_CGC_OVERRIDE_ALL, + vfe->base + VFE_BUS_WM_CGC_OVERRIDE); writel(0x0, vfe->base + VFE_BUS_WM_TEST_BUS_CTRL); @@ -123,15 +205,19 @@ static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) static void vfe_wm_stop(struct vfe_device *vfe, u8 wm) { - wm = RDI_WM(wm); + wm = vfe_gen4_rdi_wm(vfe, wm); writel(0, vfe->base + VFE_BUS_WM_CFG(wm)); } static void vfe_wm_update(struct vfe_device *vfe, u8 wm, u32 addr, struct vfe_line *line) { - wm = RDI_WM(wm); - writel(addr >> 8, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); + const struct vfe_gen4_hw_info *hw_info = vfe_gen4_get_hw_info(vfe); + + wm = vfe_gen4_rdi_wm(vfe, wm); + + writel(addr >> hw_info->addr_shift, + vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); dev_dbg(vfe->camss->dev, "wm:%d, image buf addr:0x%x\n", wm, addr); } diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 93d691c8ac63b2a47dbb234856b627d8911a1851..487b8ec0f7cdbfe2e2da0e46cb4431b1e6b4c475 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -96,6 +96,7 @@ enum camss_version { CAMSS_8550, CAMSS_8650, CAMSS_8775P, + CAMSS_NORD, CAMSS_X1E80100, }; -- 2.34.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 5/6] media: qcom: camss: tpg: Add support for TPG v2.5.0 2026-09-15 9:34 [PATCH 0/6] media: qcom: camss: Add support for Nord CAMSS Wenmeng Liu ` (3 preceding siblings ...) 2026-09-15 9:34 ` [PATCH 4/6] media: qcom: camss: vfe: Add support for VFE 900 Wenmeng Liu @ 2026-09-15 9:34 ` Wenmeng Liu 2026-09-15 9:34 ` [PATCH 6/6] media: qcom: camss: Add support for nord camss Wenmeng Liu 5 siblings, 0 replies; 9+ messages in thread From: Wenmeng Liu @ 2026-09-15 9:34 UTC (permalink / raw) To: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bryan O'Donoghue Cc: linux-media, linux-arm-msm, devicetree, linux-kernel, Wenmeng Liu Add support for TPG v2.5.0, which moves the stream enable bit out of TPG_CTRL into a dedicated command register (TPG_CTRL_CMD). Branch tpg_stream_on() on the runtime hw_version so the generator is enabled through the command register on v2.5.0 and through TPG_CTRL on earlier revisions; the reset bit is unchanged. Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com> --- drivers/media/platform/qcom/camss/camss-tpg-gen1.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-tpg-gen1.c b/drivers/media/platform/qcom/camss/camss-tpg-gen1.c index d29de5f93c18ee3c1778dc0626e8c198f354eb1f..de7ef5b8ff5fbd22e5659e5c896c5484a5c818b0 100644 --- a/drivers/media/platform/qcom/camss/camss-tpg-gen1.c +++ b/drivers/media/platform/qcom/camss/camss-tpg-gen1.c @@ -22,6 +22,7 @@ #define TPG_HW_VER_2_0_0 TPG_HW_VER(2, 0, 0) #define TPG_HW_VER_2_1_0 TPG_HW_VER(2, 1, 0) +#define TPG_HW_VER_2_5_0 TPG_HW_VER(2, 5, 0) #define TPG_HW_STATUS 0x4 @@ -33,7 +34,14 @@ # define TPG_CTRL_OVERLAP_SHDR_EN BIT(10) # define TPG_CTRL_NUM_ACTIVE_VC GENMASK(31, 30) -#define TPG_CLEAR 0x1F4 +/* + * Command register at 0x1F4. Earlier TPG revisions only expose HW_RESET[0] + * here; v2.5.0 adds TEST_EN[4], moving the generator enable out of TPG_CTRL. + * HW_RESET[0] is unchanged, so the reset path is revision-independent. + */ +#define TPG_CTRL_CMD 0x1F4 +# define TPG_CTRL_CMD_HW_RESET BIT(0) +# define TPG_CTRL_CMD_TEST_EN BIT(4) /* TPG VC-based registers */ #define TPG_VC_n_GAIN_CFG(n) (0x60 + (n) * 0x60) @@ -164,18 +172,23 @@ static int tpg_stream_on(struct tpg_device *tpg) } /* Global TPG control */ - val = FIELD_PREP(TPG_CTRL_TEST_EN, 1) | - FIELD_PREP(TPG_CTRL_NUM_ACTIVE_LANES, lane_cnt - 1) | + val = FIELD_PREP(TPG_CTRL_NUM_ACTIVE_LANES, lane_cnt - 1) | FIELD_PREP(TPG_CTRL_NUM_ACTIVE_VC, last_vc); + if (tpg->hw_version < TPG_HW_VER_2_5_0) + val |= FIELD_PREP(TPG_CTRL_TEST_EN, 1); writel(val, tpg->base + TPG_CTRL); + /* v2.5.0 enables the generator through the command register */ + if (tpg->hw_version >= TPG_HW_VER_2_5_0) + writel(TPG_CTRL_CMD_TEST_EN, tpg->base + TPG_CTRL_CMD); + return 0; } static int tpg_reset(struct tpg_device *tpg) { writel(0, tpg->base + TPG_CTRL); - writel(1, tpg->base + TPG_CLEAR); + writel(TPG_CTRL_CMD_HW_RESET, tpg->base + TPG_CTRL_CMD); return 0; } -- 2.34.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 6/6] media: qcom: camss: Add support for nord camss 2026-09-15 9:34 [PATCH 0/6] media: qcom: camss: Add support for Nord CAMSS Wenmeng Liu ` (4 preceding siblings ...) 2026-09-15 9:34 ` [PATCH 5/6] media: qcom: camss: tpg: Add support for TPG v2.5.0 Wenmeng Liu @ 2026-09-15 9:34 ` Wenmeng Liu 5 siblings, 0 replies; 9+ messages in thread From: Wenmeng Liu @ 2026-09-15 9:34 UTC (permalink / raw) To: Bryan O'Donoghue, Vladimir Zapolskiy, Loic Poulain, Mauro Carvalho Chehab, Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bryan O'Donoghue Cc: linux-media, linux-arm-msm, devicetree, linux-kernel, Wenmeng Liu Add support for the camera subsystem on the Qualcomm Nord platform. Enumerate the module-level resources (clocks, register regions, interrupts) and the bus bandwidth votes, and wire up the compatible. Nord exposes 3 TPG, 3 CSID plus 10 CSID Lite (driven by csid_ops_900) and 3 VFE plus 10 VFE Lite (driven by vfe_ops_gen4 with the VFE 900 variant). Signed-off-by: Wenmeng Liu <wenmeng.liu@oss.qualcomm.com> --- drivers/media/platform/qcom/camss/camss-vfe.c | 2 + drivers/media/platform/qcom/camss/camss.c | 602 ++++++++++++++++++++++++++ 2 files changed, 604 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 11f616ae035c1814e21ae2a01c5e1131022da236..d5077c502f04cf4e7677e86da1befeca0033e339 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -353,6 +353,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_8550: case CAMSS_8650: case CAMSS_8775P: + case CAMSS_NORD: case CAMSS_X1E80100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: @@ -2016,6 +2017,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_8550: case CAMSS_8650: case CAMSS_8775P: + case CAMSS_NORD: case CAMSS_X1E80100: ret = 16; break; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 2123f6388e3d7eafe669efd6b033e22d8eb5cf79..5899f64a3c0a2f7f6829d73636aae4deda42aaea 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4536,6 +4536,594 @@ static const struct resources_wrapper csid_wrapper_res_x1e80100 = { .reg = "csid_wrapper", }; +static const struct camss_subdev_resources tpg_res_nord[] = { + /* TPG0 */ + { + .clock = { "top_ahb", "tpg_csiphy_rx" }, + .clock_rate = { { 0 }, + { 400000000, 480000000 } }, + .reg = { "csitpg0" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, + /* TPG1 */ + { + .clock = { "top_ahb", "tpg_csiphy_rx" }, + .clock_rate = { { 0 }, + { 400000000, 480000000 } }, + .reg = { "csitpg1" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, + /* TPG2 */ + { + .clock = { "top_ahb", "tpg_csiphy_rx" }, + .clock_rate = { { 0 }, + { 400000000, 480000000 } }, + .reg = { "csitpg2" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, +}; + +static const struct camss_subdev_resources csid_res_nord[] = { + /* CSID0 */ + { + .clock = { "csid", "csid_csiphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .clock = { "csid", "csid_csiphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .clock = { "csid", "csid_csiphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE1 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE2 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite2" }, + .interrupt = { "csid_lite2" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE3 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite3" }, + .interrupt = { "csid_lite3" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE4 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite4" }, + .interrupt = { "csid_lite4" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE5 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite5" }, + .interrupt = { "csid_lite5" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE6 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite6" }, + .interrupt = { "csid_lite6" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE7 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite7" }, + .interrupt = { "csid_lite7" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE8 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite8" }, + .interrupt = { "csid_lite8" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE9 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx", "top_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 }, + { 0 } }, + .reg = { "csid_lite9" }, + .interrupt = { "csid_lite9" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_900, + .formats = &csid_formats_gen2 + } + } +}; + +static const struct camss_subdev_resources vfe_res_nord[] = { + /* VFE0 - IFE Full */ + { + .clock = { "gcc_axi_hf", "vfe0_fast_ahb", "vfe0", + "top_ahb", "top_fast_ahb", + "top_ife0", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 - IFE Full */ + { + .clock = { "gcc_axi_hf", "vfe1_fast_ahb", "vfe1", + "top_ahb", "top_fast_ahb", + "top_ife1", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 - IFE Full */ + { + .clock = { "gcc_axi_hf", "vfe2_fast_ahb", "vfe2", + "top_ahb", "top_fast_ahb", + "top_ife2", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE0 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE1 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE2 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite2" }, + .interrupt = { "vfe_lite2" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE3 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite3" }, + .interrupt = { "vfe_lite3" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE4 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite4" }, + .interrupt = { "vfe_lite4" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE5 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite5" }, + .interrupt = { "vfe_lite5" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE6 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite6" }, + .interrupt = { "vfe_lite6" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE7 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite7" }, + .interrupt = { "vfe_lite7" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE8 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite8" }, + .interrupt = { "vfe_lite8" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE9 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "top_ahb", "top_fast_ahb", + "top_ife_lite", "camnoc_rt_axi", + "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 } }, + .reg = { "vfe_lite9" }, + .interrupt = { "vfe_lite9" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + } +}; + +static const struct resources_icc icc_res_nord[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + /* Based on 4096 x 3072 30 FPS 2496 Mbps mode */ + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 471860, + .icc_bw_tbl.peak = 925857, + }, +}; + /* * camss_add_clock_margin - Add margin to clock frequency rate * @rate: Clock frequency rate @@ -5553,6 +6141,19 @@ static const struct camss_resources msm8996_resources = { .vfe_num = ARRAY_SIZE(vfe_res_8x96), }; +static const struct camss_resources nord_resources = { + .version = CAMSS_NORD, + .pd_name = "top", + .tpg_res = tpg_res_nord, + .csid_res = csid_res_nord, + .vfe_res = vfe_res_nord, + .icc_res = icc_res_nord, + .icc_path_num = ARRAY_SIZE(icc_res_nord), + .tpg_num = ARRAY_SIZE(tpg_res_nord), + .csid_num = ARRAY_SIZE(csid_res_nord), + .vfe_num = ARRAY_SIZE(vfe_res_nord), +}; + static const struct camss_resources qcm2290_resources = { .version = CAMSS_2290, .csiphy_res = csiphy_res_2290, @@ -5744,6 +6345,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,msm8939-camss", .data = &msm8939_resources }, { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources }, { .compatible = "qcom,msm8996-camss", .data = &msm8996_resources }, + { .compatible = "qcom,nord-camss", .data = &nord_resources }, { .compatible = "qcom,qcm2290-camss", .data = &qcm2290_resources }, { .compatible = "qcom,qcs8300-camss", .data = &qcs8300_resources }, { .compatible = "qcom,sa8775p-camss", .data = &sa8775p_resources }, -- 2.34.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-09-17 12:37 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-09-15 9:34 [PATCH 0/6] media: qcom: camss: Add support for Nord CAMSS Wenmeng Liu 2026-09-15 9:34 ` [PATCH 1/6] dt-bindings: media: Add bindings for qcom,nord-camss Wenmeng Liu 2026-09-17 10:13 ` Krzysztof Kozlowski 2026-09-17 12:37 ` Wenmeng Liu 2026-09-15 9:34 ` [PATCH 2/6] media: qcom: camss: csid: Add support for CSID 900 Wenmeng Liu 2026-09-15 9:34 ` [PATCH 3/6] media: qcom: camss: vfe: Add support for VFE gen4 Wenmeng Liu 2026-09-15 9:34 ` [PATCH 4/6] media: qcom: camss: vfe: Add support for VFE 900 Wenmeng Liu 2026-09-15 9:34 ` [PATCH 5/6] media: qcom: camss: tpg: Add support for TPG v2.5.0 Wenmeng Liu 2026-09-15 9:34 ` [PATCH 6/6] media: qcom: camss: Add support for nord camss Wenmeng Liu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®