From 2833d9247723c566d7d08292f15d8297aa3ba10e Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:43:10 +0800 Subject: [PATCH 01/49] Revert "FROMLIST: arm64: dts: qcom: x1e80100-lenovo-yoga-slim7x: Add pm8010 camera PMIC with voltage levels for IR and RGB camera" This reverts commit 7a52ef7e9b46ec49351947a2aa2389c41223ad1d. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- .../dts/qcom/x1e80100-lenovo-yoga-slim7x.dts | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index c36457f1cb6d4..4bacc33360aa5 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -795,57 +795,6 @@ regulator-initial-mode = ; }; }; - - regulators-8 { - compatible = "qcom,pm8010-rpmh-regulators"; - qcom,pmic-id = "m"; - - vdd-l1-l2-supply = <&vreg_s5j_1p2>; - vdd-l3-l4-supply = <&vreg_s4c_1p8>; - vdd-l7-supply = <&vreg_bob1>; - - vreg_l1m_1p2: ldo1 { - regulator-name = "vreg_l1m_1p2"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1260000>; - regulator-initial-mode = ; - }; - - vreg_l2m_1p2: ldo2 { - regulator-name = "vreg_l2m_1p2"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1260000>; - regulator-initial-mode = ; - }; - - vreg_l3m_1p8: ldo3 { - regulator-name = "vreg_l3m_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1900000>; - regulator-initial-mode = ; - }; - - vreg_l4m_1p8: ldo4 { - regulator-name = "vreg_l4m_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1900000>; - regulator-initial-mode = ; - }; - - vreg_l5m_2p8: ldo5 { - regulator-name = "vreg_l5m_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <3072000>; - regulator-initial-mode = ; - }; - - vreg_l7m_2p8: ldo7 { - regulator-name = "vreg_l7m_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <3072000>; - regulator-initial-mode = ; - }; - }; }; &gpu { From 85d186afb50153cba1654a5703d3f5c7b9c149ba Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:45:58 +0800 Subject: [PATCH 02/49] Revert "FROMLIST: arm64: dts: qcom: x1e80100-t14s: Add on ov02c10 RGB sensor on CSIPHY4" This reverts commit 3020335ffef5af30c1869fd73b9dbb341e238bdf. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- .../qcom/x1e78100-lenovo-thinkpad-t14s.dtsi | 77 ------------------- 1 file changed, 77 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi index 968342ec53422..81fd524e863af 100644 --- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -780,66 +779,6 @@ }; -&camss { - status = "okay"; - - ports { - /* - * port0 => csiphy0 - * port1 => csiphy1 - * port2 => csiphy2 - * port3 => csiphy4 - */ - port@3 { - camss_csiphy4_inep0: endpoint@0 { - clock-lanes = <7>; - data-lanes = <0 1>; - remote-endpoint = <&ov02c10_ep>; - }; - }; - }; -}; - -&cci1 { - status = "okay"; -}; - -&cci1_i2c1 { - camera@36 { - compatible = "ovti,ov02c10"; - reg = <0x36>; - - reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; - pinctrl-names = "default"; - pinctrl-0 = <&cam_rgb_default>; - - clocks = <&camcc CAM_CC_MCLK4_CLK>; - assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; - assigned-clock-rates = <19200000>; - - orientation = <0>; /* front facing */ - - avdd-supply = <&vreg_l7m_2p8>; - dvdd-supply = <&vreg_l2m_1p2>; - dovdd-supply = <&vreg_l4m_1p8>; - - port { - ov02c10_ep: endpoint { - data-lanes = <1 2>; - link-frequencies = /bits/ 64 <400000000>; - remote-endpoint = <&camss_csiphy4_inep0>; - }; - }; - }; -}; - -&csiphy4 { - vdda-0p8-supply = <&vreg_l2c_0p8>; - vdda-1p2-supply = <&vreg_l1c_1p2>; - - status = "okay"; -}; - &gpu { status = "okay"; @@ -1413,22 +1352,6 @@ <72 2>, /* Secure EC I2C connection (?) */ <238 1>; /* UFS Reset */ - cam_rgb_default: cam-rgb-default-state { - mclk-pins { - pins = "gpio100"; - function = "cam_aon"; - drive-strength = <16>; - bias-disable; - }; - - reset-n-pins { - pins = "gpio237"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - }; - ec_int_n_default: ec-int-n-state { pins = "gpio66"; function = "gpio"; From 2904f825ecda4a5b6540bd441cb33101dda39a78 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:46:07 +0800 Subject: [PATCH 03/49] Revert "FROMLIST: arm64: dts: qcom: x1e80100-t14s: Add pm8010 camera PMIC with voltage levels for IR and RGB camera" This reverts commit e008c74b1d2c9dd24d215810e78c40b7a5046731. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- .../qcom/x1e78100-lenovo-thinkpad-t14s.dtsi | 59 ------------------- 1 file changed, 59 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi index 81fd524e863af..261e59de654d3 100644 --- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi @@ -475,13 +475,6 @@ regulator-initial-mode = ; }; - vreg_l7b_2p8: ldo7 { - regulator-name = "vreg_l7b_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <2800000>; - regulator-initial-mode = ; - }; - vreg_l8b_3p0: ldo8 { regulator-name = "vreg_l8b_3p0"; regulator-min-microvolt = <3072000>; @@ -725,58 +718,6 @@ regulator-initial-mode = ; }; }; - - regulators-8 { - compatible = "qcom,pm8010-rpmh-regulators"; - qcom,pmic-id = "m"; - - vdd-l1-l2-supply = <&vreg_s5j_1p2>; - vdd-l3-l4-supply = <&vreg_s4c_1p8>; - vdd-l7-supply = <&vreg_bob1>; - - vreg_l1m_1p2: ldo1 { - regulator-name = "vreg_l1m_1p2"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1260000>; - regulator-initial-mode = ; - }; - - vreg_l2m_1p2: ldo2 { - regulator-name = "vreg_l2m_1p2"; - regulator-min-microvolt = <1200000>; - regulator-max-microvolt = <1260000>; - regulator-initial-mode = ; - }; - - vreg_l3m_1p8: ldo3 { - regulator-name = "vreg_l3m_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1900000>; - regulator-initial-mode = ; - }; - - vreg_l4m_1p8: ldo4 { - regulator-name = "vreg_l4m_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1900000>; - regulator-initial-mode = ; - }; - - vreg_l5m_2p8: ldo5 { - regulator-name = "vreg_l5m_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <3072000>; - regulator-initial-mode = ; - }; - - vreg_l7m_2p8: ldo7 { - regulator-name = "vreg_l7m_2p8"; - regulator-min-microvolt = <2800000>; - regulator-max-microvolt = <3072000>; - regulator-initial-mode = ; - }; - }; - }; &gpu { From fe34ce5713e2579fabc1a8324d1321f203f45567 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:46:14 +0800 Subject: [PATCH 04/49] Revert "FROMLIST: arm64: dts: qcom: x1e80100-crd: Add ov08x40 RGB sensor on CSIPHY4" This reverts commit d8927474f8b243a1bafbe7f1f63e4bd3505802cb. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 76 ---------------------------- 1 file changed, 76 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/x1-crd.dtsi b/arch/arm64/boot/dts/qcom/x1-crd.dtsi index 982e9c14605c6..9ed3e6530062e 100644 --- a/arch/arm64/boot/dts/qcom/x1-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-crd.dtsi @@ -6,7 +6,6 @@ #include #include #include -#include #include #include @@ -895,65 +894,6 @@ status = "okay"; }; -&camss { - status = "okay"; - - ports { - /* - * port0 => csiphy0 - * port1 => csiphy1 - * port2 => csiphy2 - * port3 => csiphy4 - */ - port@3 { - camss_csiphy4_inep0: endpoint@0 { - clock-lanes = <7>; - data-lanes = <0 1 2 3>; - remote-endpoint = <&ov08x40_ep>; - }; - }; - }; -}; - -&cci1 { - status = "okay"; -}; - -&cci1_i2c1 { - camera@36 { - compatible = "ovti,ov08x40"; - reg = <0x36>; - - reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; - pinctrl-0 = <&cam_rgb_default>; - pinctrl-names = "default"; - - clocks = <&camcc CAM_CC_MCLK4_CLK>; - assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; - assigned-clock-rates = <19200000>; - - orientation = <0>; /* front facing */ - - avdd-supply = <&vreg_l7b_2p8>; - dovdd-supply = <&vreg_l3m_1p8>; - - port { - ov08x40_ep: endpoint { - data-lanes = <1 2 3 4>; - link-frequencies = /bits/ 64 <400000000>; - remote-endpoint = <&camss_csiphy4_inep0>; - }; - }; - }; -}; - -&csiphy4 { - vdda-0p8-supply = <&vreg_l2c_0p8>; - vdda-1p2-supply = <&vreg_l1c_1p2>; - - status = "okay"; -}; - &i2c0 { clock-frequency = <400000>; @@ -1568,22 +1508,6 @@ <44 4>, /* SPI (TPM) */ <238 1>; /* UFS Reset */ - cam_rgb_default: cam-rgb-default-state { - mclk-pins { - pins = "gpio100"; - function = "cam_aon"; - drive-strength = <16>; - bias-disable; - }; - - reset-n-pins { - pins = "gpio237"; - function = "gpio"; - drive-strength = <2>; - bias-disable; - }; - }; - edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; From 631a3bf68d909601a596be03aed11135c6137727 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:46:22 +0800 Subject: [PATCH 05/49] Revert "FROMLIST: arm64: dts: qcom: x1e80100-crd: Add pm8010 CRD pmic,id=m regulators" This reverts commit f4615f9f164897fc959b90fe06342c406cf2cbd0. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 30 ---------------------------- 1 file changed, 30 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/x1-crd.dtsi b/arch/arm64/boot/dts/qcom/x1-crd.dtsi index 9ed3e6530062e..5e324f35547a4 100644 --- a/arch/arm64/boot/dts/qcom/x1-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-crd.dtsi @@ -858,36 +858,6 @@ regulator-initial-mode = ; }; }; - - regulators-8 { - compatible = "qcom,pm8010-rpmh-regulators"; - qcom,pmic-id = "m"; - - vdd-l1-l2-supply = <&vreg_s5j_1p2>; - vdd-l3-l4-supply = <&vreg_s4c_1p8>; - vdd-l7-supply = <&vreg_bob1>; - - vreg_l3m_1p8: ldo3 { - regulator-name = "vreg_l3m_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1808000>; - regulator-initial-mode = ; - }; - - vreg_l4m_1p8: ldo4 { - regulator-name = "vreg_l4m_1p8"; - regulator-min-microvolt = <1800000>; - regulator-max-microvolt = <1808000>; - regulator-initial-mode = ; - }; - - vreg_l7m_2p9: ldo7 { - regulator-name = "vreg_l7m_2p9"; - regulator-min-microvolt = <2912000>; - regulator-max-microvolt = <2912000>; - regulator-initial-mode = ; - }; - }; }; &gpu { From 7772de9793c777b2027edd23b942a18a0d7e3822 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:48:30 +0800 Subject: [PATCH 06/49] Revert "FROMLIST: arm64: dts: qcom: x1e80100: Add CAMSS block definition" This reverts commit bbbb1d919cf3a6438a79b2948c92f80e227bde5c. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 202 ---------------------------- 1 file changed, 202 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 05995e8264634..1fd116184567e 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -5641,208 +5641,6 @@ }; }; - camss: isp@acb7000 { - compatible = "qcom,x1e80100-camss"; - - reg = <0 0x0acb7000 0 0x2000>, - <0 0x0acb9000 0 0x2000>, - <0 0x0acbb000 0 0x2000>, - <0 0x0acc6000 0 0x1000>, - <0 0x0acca000 0 0x1000>, - <0 0x0acb6000 0 0x1000>, - <0 0x0ace4000 0 0x1000>, - <0 0x0ace6000 0 0x1000>, - <0 0x0ace8000 0 0x1000>, - <0 0x0acec000 0 0x4000>, - <0 0x0acf6000 0 0x1000>, - <0 0x0acf7000 0 0x1000>, - <0 0x0acf8000 0 0x1000>, - <0 0x0ac62000 0 0x4000>, - <0 0x0ac71000 0 0x4000>, - <0 0x0acc7000 0 0x2000>, - <0 0x0accb000 0 0x2000>; - - reg-names = "csid0", - "csid1", - "csid2", - "csid_lite0", - "csid_lite1", - "csid_wrapper", - "csiphy0", - "csiphy1", - "csiphy2", - "csiphy4", - "csitpg0", - "csitpg1", - "csitpg2", - "vfe0", - "vfe1", - "vfe_lite0", - "vfe_lite1"; - - clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, - <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, - <&camcc CAM_CC_CORE_AHB_CLK>, - <&camcc CAM_CC_CPAS_AHB_CLK>, - <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, - <&camcc CAM_CC_CPAS_IFE_0_CLK>, - <&camcc CAM_CC_CPAS_IFE_1_CLK>, - <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, - <&camcc CAM_CC_CPHY_RX_CLK_SRC>, - <&camcc CAM_CC_CSID_CLK>, - <&camcc CAM_CC_CSID_CSIPHY_RX_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_CSIPHY4_CLK>, - <&camcc CAM_CC_CSI4PHYTIMER_CLK>, - <&gcc GCC_CAMERA_HF_AXI_CLK>, - <&gcc GCC_CAMERA_SF_AXI_CLK>, - <&camcc CAM_CC_IFE_0_CLK>, - <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, - <&camcc CAM_CC_IFE_1_CLK>, - <&camcc CAM_CC_IFE_1_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>; - - clock-names = "camnoc_nrt_axi", - "camnoc_rt_axi", - "core_ahb", - "cpas_ahb", - "cpas_fast_ahb", - "cpas_vfe0", - "cpas_vfe1", - "cpas_vfe_lite", - "cphy_rx_clk_src", - "csid", - "csid_csiphy_rx", - "csiphy0", - "csiphy0_timer", - "csiphy1", - "csiphy1_timer", - "csiphy2", - "csiphy2_timer", - "csiphy4", - "csiphy4_timer", - "gcc_axi_hf", - "gcc_axi_sf", - "vfe0", - "vfe0_fast_ahb", - "vfe1", - "vfe1_fast_ahb", - "vfe_lite", - "vfe_lite_ahb", - "vfe_lite_cphy_rx", - "vfe_lite_csid"; - - interrupts = , - , - , - , - , - , - , - , - , - , - , - , - ; - - interrupt-names = "csid0", - "csid1", - "csid2", - "csid_lite0", - "csid_lite1", - "csiphy0", - "csiphy1", - "csiphy2", - "csiphy4", - "vfe0", - "vfe1", - "vfe_lite0", - "vfe_lite1"; - - interconnects = <&gem_noc 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>, - <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS - &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, - <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS - &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; - interconnect-names = "ahb", - "hf_mnoc", - "sf_mnoc", - "sf_icp_mnoc"; - - iommus = <&apps_smmu 0x800 0x60>, - <&apps_smmu 0x860 0x60>, - <&apps_smmu 0x1860 0x60>, - <&apps_smmu 0x18e0 0x00>, - <&apps_smmu 0x19a0 0x20>; - - phys = <&csiphy0 PHY_TYPE_DPHY>, <&csiphy1 PHY_TYPE_DPHY>, - <&csiphy2 PHY_TYPE_DPHY>, <&csiphy4 PHY_TYPE_DPHY>; - phy-names = "csiphy0", "csiphy1", - "csiphy2", "csiphy4"; - - power-domains = <&camcc CAM_CC_IFE_0_GDSC>, - <&camcc CAM_CC_IFE_1_GDSC>, - <&camcc CAM_CC_TITAN_TOP_GDSC>; - power-domain-names = "ife0", - "ife1", - "top"; - - status = "disabled"; - - ports { - #address-cells = <1>; - #size-cells = <0>; - - port@0 { - reg = <0>; - #address-cells = <1>; - #size-cells = <0>; - camss_csiphy0_inep0: endpoint@0 { - reg = <0>; - }; - }; - - port@1 { - reg = <1>; - #address-cells = <1>; - #size-cells = <0>; - camss_csiphy1_inep0: endpoint@0 { - reg = <0>; - }; - }; - - port@2 { - reg = <2>; - #address-cells = <1>; - #size-cells = <0>; - camss_csiphy2_inep0: endpoint@0 { - reg = <0>; - }; - }; - - port@3 { - reg = <3>; - #address-cells = <1>; - #size-cells = <0>; - camss_csiphy4_inep0: endpoint@0 { - reg = <0>; - }; - }; - }; - }; - csiphy0: csiphy@ace4000 { compatible = "qcom,x1e80100-csi2-phy"; reg = <0 0x0ace4000 0 0x2000>; From 9bfa69450680fe45c5a2cb9cbedadded49d0cdcb Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:48:40 +0800 Subject: [PATCH 07/49] Revert "FROMLIST: arm64: dts: qcom: x1e80100: Add MIPI CSI PHY nodes" This reverts commit bf65bd5598f500bc2b3597dd04355fdc8efa8489. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 115 ---------------------------- 1 file changed, 115 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 1fd116184567e..80db3cf6b7528 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -733,25 +733,6 @@ }; }; - csiphy_opp_table: opp-table-csiphy { - compatible = "operating-points-v2"; - - opp-300000000 { - opp-hz = /bits/ 64 <300000000>; - required-opps = <&rpmhpd_opp_low_svs_d1>; - }; - - opp-400000000 { - opp-hz = /bits/ 64 <400000000>; - required-opps = <&rpmhpd_opp_low_svs>; - }; - - opp-480000000 { - opp-hz = /bits/ 64 <480000000>; - required-opps = <&rpmhpd_opp_low_svs>; - }; - }; - qup_opp_table_100mhz: opp-table-qup100mhz { compatible = "operating-points-v2"; @@ -5641,102 +5622,6 @@ }; }; - csiphy0: csiphy@ace4000 { - compatible = "qcom,x1e80100-csi2-phy"; - reg = <0 0x0ace4000 0 0x2000>; - - clocks = <&camcc CAM_CC_CSIPHY0_CLK>, - <&camcc CAM_CC_CSI0PHYTIMER_CLK>, - <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, - <&camcc CAM_CC_CPAS_AHB_CLK>; - clock-names = "csiphy", - "csiphy_timer", - "camnoc_axi", - "cpas_ahb"; - - operating-points-v2 = <&csiphy_opp_table>; - - interrupts = ; - - power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - - #phy-cells = <1>; - - status = "disabled"; - }; - - csiphy1: csiphy@ace6000 { - compatible = "qcom,x1e80100-csi2-phy"; - reg = <0 0x0ace6000 0 0x2000>; - - clocks = <&camcc CAM_CC_CSIPHY1_CLK>, - <&camcc CAM_CC_CSI1PHYTIMER_CLK>, - <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, - <&camcc CAM_CC_CPAS_AHB_CLK>; - clock-names = "csiphy", - "csiphy_timer", - "camnoc_axi", - "cpas_ahb"; - - operating-points-v2 = <&csiphy_opp_table>; - - interrupts = ; - - power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - - #phy-cells = <1>; - - status = "disabled"; - }; - - csiphy2: csiphy@ace8000 { - compatible = "qcom,x1e80100-csi2-phy"; - reg = <0 0x0ace8000 0 0x2000>; - - clocks = <&camcc CAM_CC_CSIPHY2_CLK>, - <&camcc CAM_CC_CSI2PHYTIMER_CLK>, - <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, - <&camcc CAM_CC_CPAS_AHB_CLK>; - clock-names = "csiphy", - "csiphy_timer", - "camnoc_axi", - "cpas_ahb"; - - operating-points-v2 = <&csiphy_opp_table>; - - interrupts = ; - - power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - - #phy-cells = <1>; - - status = "disabled"; - }; - - csiphy4: csiphy@acec000 { - compatible = "qcom,x1e80100-csi2-phy"; - reg = <0 0x0acec000 0 0x2000>; - - clocks = <&camcc CAM_CC_CSIPHY4_CLK>, - <&camcc CAM_CC_CSI4PHYTIMER_CLK>, - <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, - <&camcc CAM_CC_CPAS_AHB_CLK>; - clock-names = "csiphy", - "csiphy_timer", - "camnoc_axi", - "cpas_ahb"; - - operating-points-v2 = <&csiphy_opp_table>; - - interrupts = ; - - power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - - #phy-cells = <1>; - - status = "disabled"; - }; - camcc: clock-controller@ade0000 { compatible = "qcom,x1e80100-camcc"; reg = <0 0x0ade0000 0 0x20000>; From 7d726fd28128e297198270355b448c548c1ac2f9 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:48:48 +0800 Subject: [PATCH 08/49] Revert "FROMLIST: arm64: dts: qcom: x1e80100: Add CCI definitions" This reverts commit c4f6fafa5c5593f362ce1152e41f05e6cb4658a8. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 149 ---------------------------- 1 file changed, 149 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 80db3cf6b7528..4e28563f9cd77 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -5544,83 +5544,6 @@ #power-domain-cells = <1>; }; - cci0: cci@ac15000 { - compatible = "qcom,x1e80100-cci", "qcom,msm8996-cci"; - reg = <0 0x0ac15000 0 0x1000>; - - interrupts = ; - - clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, - <&camcc CAM_CC_CPAS_AHB_CLK>, - <&camcc CAM_CC_CCI_0_CLK>; - clock-names = "camnoc_axi", - "cpas_ahb", - "cci"; - - power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - - pinctrl-0 = <&cci0_default>; - pinctrl-1 = <&cci0_sleep>; - pinctrl-names = "default", "sleep"; - - #address-cells = <1>; - #size-cells = <0>; - - status = "disabled"; - - cci0_i2c0: i2c-bus@0 { - reg = <0>; - clock-frequency = <1000000>; - #address-cells = <1>; - #size-cells = <0>; - }; - - cci0_i2c1: i2c-bus@1 { - reg = <1>; - clock-frequency = <1000000>; - #address-cells = <1>; - #size-cells = <0>; - }; - }; - - cci1: cci@ac16000 { - compatible = "qcom,x1e80100-cci", "qcom,msm8996-cci"; - reg = <0 0x0ac16000 0 0x1000>; - - interrupts = ; - - clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, - <&camcc CAM_CC_CPAS_AHB_CLK>, - <&camcc CAM_CC_CCI_1_CLK>; - clock-names = "camnoc_axi", - "cpas_ahb", - "cci"; - - power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - - pinctrl-0 = <&cci1_default>; - pinctrl-1 = <&cci1_sleep>; - pinctrl-names = "default", "sleep"; - - #address-cells = <1>; - #size-cells = <0>; - - status = "disabled"; - - cci1_i2c0: i2c-bus@0 { - reg = <0>; - clock-frequency = <1000000>; - #address-cells = <1>; - #size-cells = <0>; - }; - - cci1_i2c1: i2c-bus@1 { - reg = <1>; - clock-frequency = <1000000>; - #address-cells = <1>; - #size-cells = <0>; - }; - }; camcc: clock-controller@ade0000 { compatible = "qcom,x1e80100-camcc"; @@ -6270,78 +6193,6 @@ gpio-ranges = <&tlmm 0 0 239>; wakeup-parent = <&pdc>; - cci0_default: cci0-default-state { - cci0_i2c0_default: cci0-i2c0-default-pins { - /* cci_i2c_sda0, cci_i2c_scl0 */ - pins = "gpio101", "gpio102"; - function = "cci_i2c"; - drive-strength = <2>; - bias-pull-up; - }; - - cci0_i2c1_default: cci0-i2c1-default-pins { - /* cci_i2c_sda1, cci_i2c_scl1 */ - pins = "gpio103", "gpio104"; - function = "cci_i2c"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - cci0_sleep: cci0-sleep-state { - cci0_i2c0_sleep: cci0-i2c0-sleep-pins { - /* cci_i2c_sda0, cci_i2c_scl0 */ - pins = "gpio101", "gpio102"; - function = "cci_i2c"; - drive-strength = <2>; - bias-pull-down; - }; - - cci0_i2c1_sleep: cci0-i2c1-sleep-pins { - /* cci_i2c_sda1, cci_i2c_scl1 */ - pins = "gpio103", "gpio104"; - function = "cci_i2c"; - drive-strength = <2>; - bias-pull-down; - }; - }; - - cci1_default: cci1-default-state { - cci1_i2c0_default: cci1-i2c0-default-pins { - /* cci_i2c_sda2, cci_i2c_scl2 */ - pins = "gpio105", "gpio106"; - function = "cci_i2c"; - drive-strength = <2>; - bias-pull-up; - }; - - cci1_i2c1_default: cci1-i2c1-default-pins { - /* aon_cci_i2c_sda3, aon_cci_i2c_scl3 */ - pins = "gpio235", "gpio236"; - function = "aon_cci"; - drive-strength = <2>; - bias-pull-up; - }; - }; - - cci1_sleep: cci1-sleep-state { - cci1_i2c0_sleep: cci1-i2c0-sleep-pins { - /* cci_i2c_sda2, cci_i2c_scl2 */ - pins = "gpio105", "gpio106"; - function = "cci_i2c"; - drive-strength = <2>; - bias-pull-down; - }; - - cci1_i2c1_sleep: cci1-i2c1-sleep-pins { - /* aon_cci_i2c_sda3, aon_cci_i2c_scl3 */ - pins = "gpio235", "gpio236"; - function = "aon_cci"; - drive-strength = <2>; - bias-pull-down; - }; - }; - edp0_hpd_default: edp0-hpd-default-state { pins = "gpio119"; function = "edp0_hot"; From a416b0a420b7b2626fd7a112ea1598c1aed4f1de Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:48:55 +0800 Subject: [PATCH 09/49] Revert "FROMLIST: arm64: dts: qcom: x1e80100: Add CAMCC block definition" This reverts commit 05d8e136363f09cde4270de6865143a2fd193f9c. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 4e28563f9cd77..81897f11a1fcd 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -6,7 +6,6 @@ #include #include #include -#include #include #include #include @@ -5544,23 +5543,6 @@ #power-domain-cells = <1>; }; - - camcc: clock-controller@ade0000 { - compatible = "qcom,x1e80100-camcc"; - reg = <0 0x0ade0000 0 0x20000>; - clocks = <&gcc GCC_CAMERA_AHB_CLK>, - <&bi_tcxo_div2>, - <&bi_tcxo_ao_div2>, - <&sleep_clk>; - power-domains = <&rpmhpd RPMHPD_MXC>, - <&rpmhpd RPMHPD_MMCX>; - required-opps = <&rpmhpd_opp_low_svs>, - <&rpmhpd_opp_low_svs>; - #clock-cells = <1>; - #reset-cells = <1>; - #power-domain-cells = <1>; - }; - mdss: display-subsystem@ae00000 { compatible = "qcom,x1e80100-mdss"; reg = <0 0x0ae00000 0 0x1000>; From fe207b2c3fc576c88672d3ca8fbacc184524de4c Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:49:03 +0800 Subject: [PATCH 10/49] Revert "FROMLIST: media: qcom: camss: Drop legacy PHY descriptions from x1e" This reverts commit 100784f6cc13ff4c28999e01adb40d2f38f17db2. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- drivers/media/platform/qcom/camss/camss.c | 37 +++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 4ce1e2962c383..2c127265f559e 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -3895,6 +3895,15 @@ static const struct resources_icc icc_res_sa8775p[] = { static const struct camss_subdev_resources csiphy_res_x1e80100[] = { /* CSIPHY0 */ { + .regulators = { + { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, + { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } + }, + .clock = { "csiphy0", "csiphy0_timer" }, + .clock_rate = { { 300000000, 400000000, 480000000 }, + { 266666667, 400000000 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, .csiphy = { .id = 0, .hw_ops = &csiphy_ops_3ph_1_0, @@ -3903,6 +3912,15 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY1 */ { + .regulators = { + { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, + { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } + }, + .clock = { "csiphy1", "csiphy1_timer" }, + .clock_rate = { { 300000000, 400000000, 480000000 }, + { 266666667, 400000000 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, .csiphy = { .id = 1, .hw_ops = &csiphy_ops_3ph_1_0, @@ -3911,6 +3929,15 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY2 */ { + .regulators = { + { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, + { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } + }, + .clock = { "csiphy2", "csiphy2_timer" }, + .clock_rate = { { 300000000, 400000000, 480000000 }, + { 266666667, 400000000 } }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, .csiphy = { .id = 2, .hw_ops = &csiphy_ops_3ph_1_0, @@ -3919,6 +3946,15 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY4 */ { + .regulators = { + { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, + { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } + }, + .clock = { "csiphy4", "csiphy4_timer" }, + .clock_rate = { { 300000000, 400000000, 480000000 }, + { 266666667, 400000000 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, .csiphy = { .id = 4, .hw_ops = &csiphy_ops_3ph_1_0, @@ -5326,6 +5362,7 @@ static const struct camss_resources sm8650_resources = { static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_x1e80100, .csid_res = csid_res_x1e80100, .vfe_res = vfe_res_x1e80100, From a3df63a0ea99fc3987330c927185efd8c32da888 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:49:18 +0800 Subject: [PATCH 11/49] Revert "FROMLIST: media: qcom: camss: Add support for PHY API devices" This reverts commit f617c6960cb450be5923c765dce4e5edc536a753. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- drivers/media/platform/qcom/camss/Kconfig | 1 - .../media/platform/qcom/camss/camss-csiphy.c | 185 ++---------------- .../media/platform/qcom/camss/camss-csiphy.h | 7 - drivers/media/platform/qcom/camss/camss.c | 72 ++----- 4 files changed, 30 insertions(+), 235 deletions(-) diff --git a/drivers/media/platform/qcom/camss/Kconfig b/drivers/media/platform/qcom/camss/Kconfig index 1edc5e5a1829e..4eda48cb1adf0 100644 --- a/drivers/media/platform/qcom/camss/Kconfig +++ b/drivers/media/platform/qcom/camss/Kconfig @@ -7,4 +7,3 @@ config VIDEO_QCOM_CAMSS select VIDEO_V4L2_SUBDEV_API select VIDEOBUF2_DMA_SG select V4L2_FWNODE - select PHY_QCOM_MIPI_CSI2 diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c index b8bfbf2fef8fa..62623393f4144 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy.c @@ -7,14 +7,12 @@ * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. * Copyright (C) 2016-2018 Linaro Ltd. */ -#include #include #include #include #include #include #include -#include #include #include #include @@ -133,10 +131,10 @@ static u8 csiphy_get_bpp(const struct csiphy_format_info *formats, } /* - * csiphy_set_clock_rates_legacy - Calculate and set clock rates on CSIPHY module + * csiphy_set_clock_rates - Calculate and set clock rates on CSIPHY module * @csiphy: CSIPHY device */ -static int csiphy_set_clock_rates_legacy(struct csiphy_device *csiphy) +static int csiphy_set_clock_rates(struct csiphy_device *csiphy) { struct device *dev = csiphy->camss->dev; s64 link_freq; @@ -202,7 +200,7 @@ static int csiphy_set_clock_rates_legacy(struct csiphy_device *csiphy) * * Return 0 on success or a negative error code otherwise */ -static int csiphy_set_power_legacy(struct v4l2_subdev *sd, int on) +static int csiphy_set_power(struct v4l2_subdev *sd, int on) { struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); struct device *dev = csiphy->camss->dev; @@ -221,7 +219,7 @@ static int csiphy_set_power_legacy(struct v4l2_subdev *sd, int on) return ret; } - ret = csiphy_set_clock_rates_legacy(csiphy); + ret = csiphy_set_clock_rates(csiphy); if (ret < 0) { regulator_bulk_disable(csiphy->num_supplies, csiphy->supplies); @@ -256,7 +254,7 @@ static int csiphy_set_power_legacy(struct v4l2_subdev *sd, int on) } /* - * csiphy_stream_on_legacy - Enable streaming on CSIPHY module + * csiphy_stream_on - Enable streaming on CSIPHY module * @csiphy: CSIPHY device * * Helper function to enable streaming on CSIPHY module. @@ -264,7 +262,7 @@ static int csiphy_set_power_legacy(struct v4l2_subdev *sd, int on) * * Return 0 on success or a negative error code otherwise */ -static int csiphy_stream_on_legacy(struct csiphy_device *csiphy) +static int csiphy_stream_on(struct csiphy_device *csiphy) { struct csiphy_config *cfg = &csiphy->cfg; s64 link_freq; @@ -302,62 +300,6 @@ static int csiphy_stream_on_legacy(struct csiphy_device *csiphy) return 0; } -/* - * csiphy_stream_off - Disable streaming on CSIPHY module - * @csiphy: CSIPHY device - * - * Helper function to disable streaming on CSIPHY module - */ -static void csiphy_stream_off_legacy(struct csiphy_device *csiphy) -{ - csiphy->res->hw_ops->lanes_disable(csiphy, &csiphy->cfg); -} - -/* - * csiphy_stream_on - Enable streaming on CSIPHY module - * @csiphy: CSIPHY device - * - * Helper function to enable streaming on CSIPHY module. - * Main configuration of CSIPHY module is also done here. - * - * Return 0 on success or a negative error code otherwise - */ -static int csiphy_stream_on(struct csiphy_device *csiphy) -{ - u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats, - csiphy->fmt[MSM_CSIPHY_PAD_SINK].code); - u8 num_lanes = csiphy->cfg.csi2->lane_cfg.num_data; - struct phy_configure_opts_mipi_dphy *dphy_cfg; - union phy_configure_opts dphy_opts = { 0 }; - struct device *dev = csiphy->camss->dev; - s64 link_freq; - int ret; - - dphy_cfg = &dphy_opts.mipi_dphy; - - link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes); - - if (link_freq < 0) { - dev_err(dev, - "Cannot get CSI2 transmitter's link frequency\n"); - return -EINVAL; - } - - phy_mipi_dphy_get_default_config_for_hsclk(link_freq, num_lanes, dphy_cfg); - - phy_set_mode(csiphy->phy, PHY_MODE_MIPI_DPHY); - ret = phy_configure(csiphy->phy, &dphy_opts); - if (ret) { - dev_err(dev, "failed to configure MIPI D-PHY\n"); - goto error; - } - - return phy_power_on(csiphy->phy); - -error: - return ret; -} - /* * csiphy_stream_off - Disable streaming on CSIPHY module * @csiphy: CSIPHY device @@ -366,28 +308,9 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) */ static void csiphy_stream_off(struct csiphy_device *csiphy) { - phy_power_off(csiphy->phy); + csiphy->res->hw_ops->lanes_disable(csiphy, &csiphy->cfg); } -/* - * csiphy_set_stream - Enable/disable streaming on CSIPHY module - * @sd: CSIPHY V4L2 subdevice - * @enable: Requested streaming state - * - * Return 0 on success or a negative error code otherwise - */ -static int csiphy_set_stream_legacy(struct v4l2_subdev *sd, int enable) -{ - struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); - int ret = 0; - - if (enable) - ret = csiphy_stream_on_legacy(csiphy); - else - csiphy_stream_off_legacy(csiphy); - - return ret; -} /* * csiphy_set_stream - Enable/disable streaming on CSIPHY module @@ -645,16 +568,16 @@ static bool csiphy_match_clock_name(const char *clock_name, const char *format, } /* - * msm_csiphy_subdev_init_legacy - Initialize CSIPHY device structure and resources + * msm_csiphy_subdev_init - Initialize CSIPHY device structure and resources * @csiphy: CSIPHY device * @res: CSIPHY module resources table * @id: CSIPHY module id * * Return 0 on success or a negative error code otherwise */ -int msm_csiphy_subdev_init_legacy(struct camss *camss, - struct csiphy_device *csiphy, - const struct camss_subdev_resources *res, u8 id) +int msm_csiphy_subdev_init(struct camss *camss, + struct csiphy_device *csiphy, + const struct camss_subdev_resources *res, u8 id) { struct device *dev = camss->dev; struct platform_device *pdev = to_platform_device(dev); @@ -782,69 +705,6 @@ int msm_csiphy_subdev_init_legacy(struct camss *camss, return ret; } -/* - * msm_csiphy_subdev_init - Initialize CSIPHY device structure and resources - * @csiphy: CSIPHY device - * @res: CSIPHY module resources table - * @id: CSIPHY module id - * - * Return 0 on success or a negative error code otherwise - */ -int msm_csiphy_subdev_init(struct camss *camss, - struct csiphy_device *csiphy, - const struct camss_subdev_resources *res, u8 id) -{ - struct device *dev = camss->dev; - struct of_phandle_args args; - u8 combo_mode; - int idx; - int ret; - - snprintf(csiphy->name, ARRAY_SIZE(csiphy->name), "csiphy%d", id); - - idx = of_property_match_string(dev->of_node, "phy-names", csiphy->name); - if (idx < 0) { - dev_err(dev, "%s not found\n", csiphy->name); - return idx; - } - - ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells", idx, &args); - if (ret < 0) { - dev_err(dev, "unable to parse phys args %s\n", csiphy->name); - return ret; - } - - if (!of_device_is_available(args.np)) - goto put_np; - - combo_mode = args.args[0]; - if (combo_mode != PHY_TYPE_DPHY) { - dev_err(dev, "%s mode %d not supported\n", csiphy->name, combo_mode); - ret = -EOPNOTSUPP; - goto put_np; - } - - csiphy->phy = devm_phy_get(dev, csiphy->name); - if (IS_ERR(csiphy->phy)) { - ret = PTR_ERR(csiphy->phy); - goto put_np; - } - - csiphy->camss = camss; - csiphy->id = id; - csiphy->cfg.combo_mode = combo_mode; - csiphy->res = &res->csiphy; - - ret = phy_init(csiphy->phy); - if (ret) - dev_err(dev, "phy %s init fail %d\n", csiphy->name, ret); - -put_np: - of_node_put(args.np); - - return ret; -} - /* * csiphy_link_setup - Setup CSIPHY connections * @entity: Pointer to media entity structure @@ -879,12 +739,8 @@ static int csiphy_link_setup(struct media_entity *entity, return 0; } -static const struct v4l2_subdev_core_ops csiphy_core_ops_legacy = { - .s_power = csiphy_set_power_legacy, -}; - -static const struct v4l2_subdev_video_ops csiphy_video_ops_legacy = { - .s_stream = csiphy_set_stream_legacy, +static const struct v4l2_subdev_core_ops csiphy_core_ops = { + .s_power = csiphy_set_power, }; static const struct v4l2_subdev_video_ops csiphy_video_ops = { @@ -898,13 +754,8 @@ static const struct v4l2_subdev_pad_ops csiphy_pad_ops = { .set_fmt = csiphy_set_format, }; -static const struct v4l2_subdev_ops csiphy_v4l2_ops_legacy = { - .core = &csiphy_core_ops_legacy, - .video = &csiphy_video_ops_legacy, - .pad = &csiphy_pad_ops, -}; - static const struct v4l2_subdev_ops csiphy_v4l2_ops = { + .core = &csiphy_core_ops, .video = &csiphy_video_ops, .pad = &csiphy_pad_ops, }; @@ -933,11 +784,7 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, struct device *dev = csiphy->camss->dev; int ret; - if (IS_ERR(csiphy->phy)) - v4l2_subdev_init(sd, &csiphy_v4l2_ops_legacy); - else - v4l2_subdev_init(sd, &csiphy_v4l2_ops); - + v4l2_subdev_init(sd, &csiphy_v4l2_ops); sd->internal_ops = &csiphy_v4l2_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d", @@ -976,8 +823,6 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, */ void msm_csiphy_unregister_entity(struct csiphy_device *csiphy) { - if (!IS_ERR(csiphy->phy)) - phy_exit(csiphy->phy); v4l2_device_unregister_subdev(&csiphy->subdev); media_entity_cleanup(&csiphy->subdev.entity); } diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h index 25b803c06e8bf..2d5054819df7f 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.h +++ b/drivers/media/platform/qcom/camss/camss-csiphy.h @@ -12,7 +12,6 @@ #include #include -#include #include #include #include @@ -96,7 +95,6 @@ struct csiphy_device_regs { struct csiphy_device { struct camss *camss; - struct phy *phy; u8 id; struct v4l2_subdev subdev; struct media_pad pads[MSM_CSIPHY_PADS_NUM]; @@ -104,7 +102,6 @@ struct csiphy_device { void __iomem *base_clk_mux; u32 irq; char irq_name[30]; - char name[16]; struct camss_clock *clock; bool *rate_set; int nclocks; @@ -119,10 +116,6 @@ struct csiphy_device { struct camss_subdev_resources; -int msm_csiphy_subdev_init_legacy(struct camss *camss, - struct csiphy_device *csiphy, - const struct camss_subdev_resources *res, u8 id); - int msm_csiphy_subdev_init(struct camss *camss, struct csiphy_device *csiphy, const struct camss_subdev_resources *res, u8 id); diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 2c127265f559e..24c1e5d9cf1c2 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4450,35 +4450,14 @@ static int camss_parse_endpoint_node(struct device *dev, static int camss_parse_ports(struct camss *camss) { struct device *dev = camss->dev; - const struct camss_resources *res = camss->res; struct fwnode_handle *fwnode = dev_fwnode(dev), *ep; int ret; fwnode_graph_for_each_endpoint(fwnode, ep) { struct camss_async_subdev *csd; - struct fwnode_handle *remote; - - if (!fwnode_device_is_available(ep)) - continue; - - if (res->legacy_phy) { - csd = v4l2_async_nf_add_fwnode_remote(&camss->notifier, ep, - typeof(*csd)); - } else { - /* - * For non-legacy PHY, the CSIPHY is a separate device. - * Register the remote endpoint (CSIPHY's endpoint) as - * the async subdev, not the remote port parent. - */ - remote = fwnode_graph_get_remote_endpoint(ep); - if (!remote) - continue; - - csd = v4l2_async_nf_add_fwnode(&camss->notifier, remote, - struct camss_async_subdev); - fwnode_handle_put(remote); - } + csd = v4l2_async_nf_add_fwnode_remote(&camss->notifier, ep, + typeof(*csd)); if (IS_ERR(csd)) { ret = PTR_ERR(csd); goto err_cleanup; @@ -4510,26 +4489,15 @@ static int camss_init_subdevices(struct camss *camss) unsigned int i; int ret; - if (!res->legacy_phy) { - for (i = 0; i < camss->res->csiphy_num; i++) { - ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i], - &res->csiphy_res[i], - res->csiphy_res[i].csiphy.id); - if (ret < 0) - return ret; - } - } else { - for (i = 0; i < camss->res->csiphy_num; i++) { - ret = msm_csiphy_subdev_init_legacy(camss, &camss->csiphy[i], - &res->csiphy_res[i], - res->csiphy_res[i].csiphy.id); - if (ret < 0) { - dev_err(camss->dev, - "Failed to init csiphy%d sub-device: %d\n", - i, ret); - return ret; - } - camss->csiphy[i].phy = ERR_PTR(-ENODEV); + for (i = 0; i < camss->res->csiphy_num; i++) { + ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i], + &res->csiphy_res[i], + res->csiphy_res[i].csiphy.id); + if (ret < 0) { + dev_err(camss->dev, + "Failed to init csiphy%d sub-device: %d\n", + i, ret); + return ret; } } @@ -4606,9 +4574,6 @@ static int camss_link_entities(struct camss *camss) for (i = 0; i < camss->res->csiphy_num; i++) { for (j = 0; j < camss->res->csid_num; j++) { - if (!camss->csiphy[i].phy) - continue; - ret = media_create_pad_link(&camss->csiphy[i].subdev.entity, MSM_CSIPHY_PAD_SRC, &camss->csid[j].subdev.entity, @@ -4718,9 +4683,6 @@ static int camss_register_entities(struct camss *camss) int ret; for (i = 0; i < camss->res->csiphy_num; i++) { - if (!camss->csiphy[i].phy) - continue; - ret = msm_csiphy_register_entity(&camss->csiphy[i], &camss->v4l2_dev); if (ret < 0) { @@ -4776,10 +4738,8 @@ static int camss_register_entities(struct camss *camss) i = camss->res->csiphy_num; err_reg_csiphy: - for (i--; i >= 0; i--) { - if (camss->csiphy[i].phy) - msm_csiphy_unregister_entity(&camss->csiphy[i]); - } + for (i--; i >= 0; i--) + msm_csiphy_unregister_entity(&camss->csiphy[i]); return ret; } @@ -4794,10 +4754,8 @@ static void camss_unregister_entities(struct camss *camss) { unsigned int i; - for (i = 0; i < camss->res->csiphy_num; i++) { - if (camss->csiphy[i].phy) - msm_csiphy_unregister_entity(&camss->csiphy[i]); - } + for (i = 0; i < camss->res->csiphy_num; i++) + msm_csiphy_unregister_entity(&camss->csiphy[i]); for (i = 0; i < camss->res->csid_num; i++) msm_csid_unregister_entity(&camss->csid[i]); From 2b9dafc38288ecd00fc3c9d5db75a89cb73301b4 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:49:29 +0800 Subject: [PATCH 12/49] Revert "FROMLIST: media: qcom: camss: Add legacy_phy flag to SoC definition structures" This reverts commit 9ee2b9b5364d8b37c51f5769038a1c999b852953. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- drivers/media/platform/qcom/camss/camss.c | 17 ----------------- drivers/media/platform/qcom/camss/camss.h | 1 - 2 files changed, 18 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 24c1e5d9cf1c2..c0f836146798a 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5104,7 +5104,6 @@ static void camss_remove(struct platform_device *pdev) static const struct camss_resources msm8916_resources = { .version = CAMSS_8x16, - .legacy_phy = true, .csiphy_res = csiphy_res_8x16, .csid_res = csid_res_8x16, .ispif_res = &ispif_res_8x16, @@ -5116,7 +5115,6 @@ static const struct camss_resources msm8916_resources = { static const struct camss_resources msm8939_resources = { .version = CAMSS_8x39, - .legacy_phy = true, .csiphy_res = csiphy_res_8x39, .csid_res = csid_res_8x39, .ispif_res = &ispif_res_8x39, @@ -5128,7 +5126,6 @@ static const struct camss_resources msm8939_resources = { static const struct camss_resources msm8953_resources = { .version = CAMSS_8x53, - .legacy_phy = true, .icc_res = icc_res_8x53, .icc_path_num = ARRAY_SIZE(icc_res_8x53), .csiphy_res = csiphy_res_8x96, @@ -5142,7 +5139,6 @@ static const struct camss_resources msm8953_resources = { static const struct camss_resources msm8996_resources = { .version = CAMSS_8x96, - .legacy_phy = true, .csiphy_res = csiphy_res_8x96, .csid_res = csid_res_8x96, .ispif_res = &ispif_res_8x96, @@ -5154,7 +5150,6 @@ static const struct camss_resources msm8996_resources = { static const struct camss_resources qcm2290_resources = { .version = CAMSS_2290, - .legacy_phy = true, .csiphy_res = csiphy_res_2290, .csid_res = csid_res_2290, .vfe_res = vfe_res_2290, @@ -5168,7 +5163,6 @@ static const struct camss_resources qcm2290_resources = { static const struct camss_resources qcs8300_resources = { .version = CAMSS_8300, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_8300, .csid_res = csid_res_8775p, .csid_wrapper_res = &csid_wrapper_res_sm8550, @@ -5183,7 +5177,6 @@ static const struct camss_resources qcs8300_resources = { static const struct camss_resources sa8775p_resources = { .version = CAMSS_8775P, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_8775p, .csid_res = csid_res_8775p, .csid_wrapper_res = &csid_wrapper_res_sm8550, @@ -5197,7 +5190,6 @@ static const struct camss_resources sa8775p_resources = { static const struct camss_resources sdm660_resources = { .version = CAMSS_660, - .legacy_phy = true, .csiphy_res = csiphy_res_660, .csid_res = csid_res_660, .ispif_res = &ispif_res_660, @@ -5209,7 +5201,6 @@ static const struct camss_resources sdm660_resources = { static const struct camss_resources sdm670_resources = { .version = CAMSS_845, - .legacy_phy = true, .csiphy_res = csiphy_res_670, .csid_res = csid_res_670, .vfe_res = vfe_res_670, @@ -5221,7 +5212,6 @@ static const struct camss_resources sdm670_resources = { static const struct camss_resources sdm845_resources = { .version = CAMSS_845, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_845, .csid_res = csid_res_845, .vfe_res = vfe_res_845, @@ -5233,7 +5223,6 @@ static const struct camss_resources sdm845_resources = { static const struct camss_resources sm6150_resources = { .version = CAMSS_6150, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_sm6150, .csid_res = csid_res_sm6150, .vfe_res = vfe_res_sm6150, @@ -5247,7 +5236,6 @@ static const struct camss_resources sm6150_resources = { static const struct camss_resources sm8250_resources = { .version = CAMSS_8250, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_8250, .csid_res = csid_res_8250, .vfe_res = vfe_res_8250, @@ -5261,7 +5249,6 @@ static const struct camss_resources sm8250_resources = { static const struct camss_resources sc8280xp_resources = { .version = CAMSS_8280XP, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_sc8280xp, .csid_res = csid_res_sc8280xp, .ispif_res = NULL, @@ -5276,7 +5263,6 @@ static const struct camss_resources sc8280xp_resources = { static const struct camss_resources sc7280_resources = { .version = CAMSS_7280, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_7280, .csid_res = csid_res_7280, .vfe_res = vfe_res_7280, @@ -5290,7 +5276,6 @@ static const struct camss_resources sc7280_resources = { static const struct camss_resources sm8550_resources = { .version = CAMSS_8550, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_8550, .csid_res = csid_res_8550, .vfe_res = vfe_res_8550, @@ -5305,7 +5290,6 @@ static const struct camss_resources sm8550_resources = { static const struct camss_resources sm8650_resources = { .version = CAMSS_8650, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_sm8650, .csid_res = csid_res_sm8650, .csid_wrapper_res = &csid_wrapper_res_sm8550, @@ -5320,7 +5304,6 @@ static const struct camss_resources sm8650_resources = { static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_x1e80100, .csid_res = csid_res_x1e80100, .vfe_res = vfe_res_x1e80100, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 24ec3ad7990e7..6d048414c919e 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -104,7 +104,6 @@ enum icc_count { struct camss_resources { enum camss_version version; const char *pd_name; - const bool legacy_phy; const struct camss_subdev_resources *csiphy_res; const struct camss_subdev_resources *csid_res; const struct camss_subdev_resources *ispif_res; From 0256c5cb6992e829c7b4ac5d09626164947cf7a9 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:49:36 +0800 Subject: [PATCH 13/49] Revert "FROMLIST: dt-bindings: media: qcom,x1e80100-camss: Allow CSIPHY supplies to be optional" This reverts commit f82a8662c9608395bcfc71c44dfc9222a131e442. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- .../devicetree/bindings/media/qcom,x1e80100-camss.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml index 2e9e0eeedb506..891dd1b5a16b8 100644 --- a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml @@ -243,6 +243,8 @@ required: - iommus - power-domains - power-domain-names + - vdd-csiphy-0p8-supply + - vdd-csiphy-1p2-supply - ports additionalProperties: false From fd5d04fd1727841bdd3058f52523702dc54923d8 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:49:45 +0800 Subject: [PATCH 14/49] Revert "FROMLIST: dt-bindings: media: qcom,x1e80100-camss: Add iommus minItems: 5" This reverts commit 47343ac78505c3e217b461f51a5962ac18bc8ca1. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- .../devicetree/bindings/media/qcom,x1e80100-camss.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml index 891dd1b5a16b8..fde577b66ea28 100644 --- a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml @@ -104,7 +104,6 @@ properties: - const: sf_icp_mnoc iommus: - minItems: 5 maxItems: 8 power-domains: @@ -405,8 +404,11 @@ examples: iommus = <&apps_smmu 0x800 0x60>, <&apps_smmu 0x860 0x60>, + <&apps_smmu 0x1800 0x60>, <&apps_smmu 0x1860 0x60>, <&apps_smmu 0x18e0 0x00>, + <&apps_smmu 0x1980 0x20>, + <&apps_smmu 0x1900 0x00>, <&apps_smmu 0x19a0 0x20>; power-domains = <&camcc CAM_CC_IFE_0_GDSC>, From 78f92c40567df97dd6de16dd89b00e88d7881ec4 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:49:53 +0800 Subject: [PATCH 15/49] Revert "FROMLIST: dt-bindings: media: qcom,x1e80100-camss: Add support for combo-mode endpoints" This reverts commit 33e6c2d82536f24a3901df3acc97074ecd39cb82. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- .../bindings/media/qcom,x1e80100-camss.yaml | 69 ++----------------- 1 file changed, 4 insertions(+), 65 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml index fde577b66ea28..31ca257d29b22 100644 --- a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml @@ -140,8 +140,7 @@ properties: $ref: /schemas/graph.yaml#/properties/ports description: - CSI input ports. Supports either standard single sensor mode or - Qualcomm's combo mode with one sensor in 2x1 + 1x1 data-lane, clock-lane mode. + CSI input ports. patternProperties: "^port@[0-3]$": @@ -149,86 +148,26 @@ properties: unevaluatedProperties: false description: - Input port for receiving CSI data. + Input port for receiving CSI data from a CSIPHY. properties: - endpoint@0: + endpoint: $ref: video-interfaces.yaml# unevaluatedProperties: false - description: - Endpoint for receiving a single sensor input (or first leg of combo). - properties: data-lanes: minItems: 1 - maxItems: 4 # Base max allows 4 (for D-PHY) - - clock-lanes: - maxItems: 1 + maxItems: 4 bus-type: enum: - 1 # MEDIA_BUS_TYPE_CSI2_CPHY - 4 # MEDIA_BUS_TYPE_CSI2_DPHY - endpoint@1: - $ref: video-interfaces.yaml# - unevaluatedProperties: false - - description: - Endpoint for receiving the second leg of a combo sensor input. - - properties: - data-lanes: - maxItems: 1 - - clock-lanes: - maxItems: 1 - - bus-type: - const: 4 # Combo is D-PHY specific - required: - data-lanes - allOf: - # Case 1: Combo Mode (endpoint@1 is present) - # If endpoint@1 exists, we restrict endpoint@0 to 2 lanes (D-PHY split) - - if: - required: - - endpoint@1 - then: - properties: - endpoint@0: - properties: - data-lanes: - minItems: 2 - maxItems: 2 - bus-type: - const: 4 - endpoint@1: - properties: - data-lanes: - minItems: 1 - maxItems: 1 - bus-type: - const: 4 - - # Case 2: Single Mode (endpoint@1 is missing) - # We explicitly allow up to 4 lanes here to cover the D-PHY use case. - - if: - not: - required: - - endpoint@1 - then: - properties: - endpoint@0: - properties: - data-lanes: - minItems: 1 - maxItems: 4 - required: - compatible - reg From c2f1c9f57a20717ab30393a45f9e99ac57faa4db Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:50:00 +0800 Subject: [PATCH 16/49] Revert "FROMLIST: dt-bindings: media: qcom,x1e80100-camss: Add optional PHY handle definitions" This reverts commit 6240f0eedcc9ec2c40a9bc1fd1033c108f14fb81. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- .../bindings/media/qcom,x1e80100-camss.yaml | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml index 31ca257d29b22..b075341caafc1 100644 --- a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml @@ -126,16 +126,6 @@ properties: description: Phandle to 1.8V regulator supply to a PHY. - phys: - maxItems: 4 - - phy-names: - items: - - const: csiphy0 - - const: csiphy1 - - const: csiphy2 - - const: csiphy4 - ports: $ref: /schemas/graph.yaml#/properties/ports @@ -361,11 +351,6 @@ examples: vdd-csiphy-0p8-supply = <&csiphy_0p8_supply>; vdd-csiphy-1p2-supply = <&csiphy_1p2_supply>; - phys = <&csiphy0>, <&csiphy1>, - <&csiphy2>, <&csiphy4>; - phy-names = "csiphy0", "csiphy1", - "csiphy2", "csiphy4"; - ports { #address-cells = <1>; #size-cells = <0>; From 02fe8a665ad4594a6693e8659ce00fc8a1bf54a5 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:50:10 +0800 Subject: [PATCH 17/49] Revert "FROMLIST: phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver" This reverts commit 84d8594c8817b2416cc4ae747402b9bea4043f35. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- MAINTAINERS | 11 - drivers/phy/qualcomm/Kconfig | 13 - drivers/phy/qualcomm/Makefile | 5 - .../qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 384 ------------------ .../phy/qualcomm/phy-qcom-mipi-csi2-core.c | 307 -------------- drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 102 ----- 6 files changed, 822 deletions(-) delete mode 100644 drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c delete mode 100644 drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c delete mode 100644 drivers/phy/qualcomm/phy-qcom-mipi-csi2.h diff --git a/MAINTAINERS b/MAINTAINERS index 6a2023b6d56df..bbd71f255c02d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21252,17 +21252,6 @@ S: Maintained F: Documentation/devicetree/bindings/media/qcom,*-iris.yaml F: drivers/media/platform/qcom/iris/ -QUALCOMM MIPI CSI2 PHY DRIVER -M: Bryan O'Donoghue -L: linux-phy@lists.infradead.org -L: linux-media@vger.kernel.org -L: linux-arm-msm@vger.kernel.org -S: Supported -F: Documentation/devicetree/bindings/phy/qcom,*-csi2-phy.yaml -F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.c -F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.h -F: include/dt-bindings/phy/phy-qcom-mipi-csi2* - QUALCOMM NAND CONTROLLER DRIVER M: Manivannan Sadhasivam L: linux-mtd@lists.infradead.org diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index ea33025a40fd0..60a0ead127fa9 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -28,19 +28,6 @@ config PHY_QCOM_EDP Enable this driver to support the Qualcomm eDP PHY found in various Qualcomm chipsets. -config PHY_QCOM_MIPI_CSI2 - tristate "Qualcomm MIPI CSI2 PHY driver" - depends on ARCH_QCOM || COMPILE_TEST - depends on OF - depends on COMMON_CLK - select GENERIC_PHY - select GENERIC_PHY_MIPI_DPHY - help - Enable this to support the MIPI CSI2 PHY driver found in various - Qualcomm chipsets. This PHY is used to connect MIPI CSI2 - camera sensors to the CSI Decoder in the Qualcomm Camera Subsystem - CAMSS. - config PHY_QCOM_IPQ4019_USB tristate "Qualcomm IPQ4019 USB PHY driver" depends on OF && (ARCH_QCOM || COMPILE_TEST) diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index 382cb594b06b6..b71a6a0bed3f1 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -6,11 +6,6 @@ obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o obj-$(CONFIG_PHY_QCOM_M31_EUSB) += phy-qcom-m31-eusb2.o - -phy-qcom-mipi-csi2-objs += phy-qcom-mipi-csi2-core.o \ - phy-qcom-mipi-csi2-3ph-dphy.o -obj-$(CONFIG_PHY_QCOM_MIPI_CSI2) += phy-qcom-mipi-csi2.o - obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c deleted file mode 100644 index f9f3451e9a5e1..0000000000000 --- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c +++ /dev/null @@ -1,384 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * camss-phy_qcom_mipi_csi2-3ph-1-0.c - * - * Qualcomm MSM Camera Subsystem - CSIPHY Module 3phase v1.0 - * - * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. - * Copyright (C) 2016-2025 Linaro Ltd. - */ - -#include -#include -#include -#include - -#include "phy-qcom-mipi-csi2.h" - -#define CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(offset, n) ((offset) + 0x4 * (n)) -#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET BIT(0) -#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE BIT(7) -#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B BIT(0) -#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID BIT(1) -#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL10_IRQ_CLEAR_CMD BIT(0) -#define CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(offset, n) ((offset) + 0xb0 + 0x4 * (n)) - -/* - * 3 phase CSI has 19 common status regs with only 0-10 being used - * and 11-18 being reserved. - */ -#define CSI_COMMON_STATUS_NUM 11 -/* - * There are a number of common control registers - * The offset to clear the CSIPHY IRQ status starts @ 22 - * So to clear CSI_COMMON_STATUS0 this is CSI_COMMON_CONTROL22, STATUS1 is - * CONTROL23 and so on - */ -#define CSI_CTRL_STATUS_INDEX 22 - -/* - * There are 43 COMMON_CTRL registers with regs after # 33 being reserved - */ -#define CSI_CTRL_MAX 33 - -#define CSIPHY_DEFAULT_PARAMS 0 -#define CSIPHY_LANE_ENABLE 1 -#define CSIPHY_SETTLE_CNT_LOWER_BYTE 2 -#define CSIPHY_SETTLE_CNT_HIGHER_BYTE 3 -#define CSIPHY_DNP_PARAMS 4 -#define CSIPHY_2PH_REGS 5 -#define CSIPHY_3PH_REGS 6 -#define CSIPHY_SKEW_CAL 7 - -/* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */ -static const struct -mipi_csi2phy_lane_regs lane_regs_x1e80100[] = { - /* Power up lanes 2ph mode */ - {.reg_addr = 0x1014, .reg_data = 0xD5, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x101C, .reg_data = 0x7A, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x1018, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, - - {.reg_addr = 0x0094, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x00A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0090, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0098, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0094, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0030, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0000, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0038, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x002C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0034, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x001C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0014, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x003C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0004, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0020, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0008, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {.reg_addr = 0x0010, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0094, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x005C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x0060, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x0064, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, - - {.reg_addr = 0x0E94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0EA0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E28, .reg_data = 0x04, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E00, .reg_data = 0x80, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E0C, .reg_data = 0xFF, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E38, .reg_data = 0x1F, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E2C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E34, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E1C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E3C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E04, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0E08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {.reg_addr = 0x0E10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, - - {.reg_addr = 0x0494, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x04A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0490, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0498, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0494, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0430, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0400, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0438, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x042C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0434, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x041C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0414, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x043C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0404, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0420, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0408, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {.reg_addr = 0x0410, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0494, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x045C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x0460, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x0464, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, - - {.reg_addr = 0x0894, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x08A0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0890, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0898, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0894, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0830, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0800, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0838, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x082C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0834, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x081C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0814, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x083C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0804, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0820, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0808, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {.reg_addr = 0x0810, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0894, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x085C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x0860, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x0864, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, - - {.reg_addr = 0x0C94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0CA0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C00, .reg_data = 0x8E, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C38, .reg_data = 0xFE, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C2C, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C34, .reg_data = 0x0F, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C1C, .reg_data = 0x0A, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C3C, .reg_data = 0xB8, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C04, .reg_data = 0x0C, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, - {.reg_addr = 0x0C10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, - {.reg_addr = 0x0C94, .reg_data = 0xD7, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x0C5C, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x0C60, .reg_data = 0xBD, .param_type = CSIPHY_SKEW_CAL}, - {.reg_addr = 0x0C64, .reg_data = 0x7F, .param_type = CSIPHY_SKEW_CAL}, -}; - -static inline const struct mipi_csi2phy_device_regs * -csi2phy_dev_to_regs(struct mipi_csi2phy_device *csi2phy) -{ - return &csi2phy->soc_cfg->reg_info; -} - -static void phy_qcom_mipi_csi2_hw_version_read(struct mipi_csi2phy_device *csi2phy) -{ - const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); - u32 tmp; - - writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID, csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); - - tmp = readl_relaxed(csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 12)); - csi2phy->hw_version = tmp; - - tmp = readl_relaxed(csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 13)); - csi2phy->hw_version |= (tmp << 8) & 0xFF00; - - tmp = readl_relaxed(csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 14)); - csi2phy->hw_version |= (tmp << 16) & 0xFF0000; - - tmp = readl_relaxed(csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 15)); - csi2phy->hw_version |= (tmp << 24) & 0xFF000000; - - dev_dbg_once(csi2phy->dev, "CSIPHY 3PH HW Version = 0x%08x\n", csi2phy->hw_version); -} - -/* - * phy_qcom_mipi_csi2_reset - Perform software reset on CSIPHY module - * @phy_qcom_mipi_csi2: CSIPHY device - */ -static void phy_qcom_mipi_csi2_reset(struct mipi_csi2phy_device *csi2phy) -{ - const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); - - writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET, - csi2phy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); - usleep_range(5000, 8000); - writel(0x0, csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); -} - -/* - * phy_qcom_mipi_csi2_settle_cnt_calc - Calculate settle count value - * - * Helper function to calculate settle count value. This is - * based on the CSI2 T_hs_settle parameter which in turn - * is calculated based on the CSI2 transmitter link frequency. - * - * Return settle count value or 0 if the CSI2 link frequency - * is not available - */ -static u8 phy_qcom_mipi_csi2_settle_cnt_calc(s64 link_freq, u32 timer_clk_rate) -{ - u32 t_hs_prepare_max_ps; - u32 timer_period_ps; - u32 t_hs_settle_ps; - u8 settle_cnt; - u32 ui_ps; - - if (link_freq <= 0) - return 0; - - ui_ps = div_u64(PSEC_PER_SEC, link_freq); - ui_ps /= 2; - t_hs_prepare_max_ps = 85000 + 6 * ui_ps; - t_hs_settle_ps = t_hs_prepare_max_ps; - - timer_period_ps = div_u64(PSEC_PER_SEC, timer_clk_rate); - settle_cnt = t_hs_settle_ps / timer_period_ps - 6; - - return settle_cnt; -} - -static void -phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy, - u8 settle_cnt) -{ - const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); - const struct mipi_csi2phy_lane_regs *r = regs->init_seq; - int i, array_size = regs->lane_array_size; - u32 val; - - for (i = 0; i < array_size; i++, r++) { - switch (r->param_type) { - case CSIPHY_SETTLE_CNT_LOWER_BYTE: - val = settle_cnt & 0xff; - break; - case CSIPHY_SKEW_CAL: - /* TODO: support application of skew from dt flag */ - continue; - default: - val = r->reg_data; - break; - } - writel(val, csi2phy->base + r->reg_addr); - if (r->delay_us) - udelay(r->delay_us); - } -} - -static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy, - struct mipi_csi2phy_stream_cfg *cfg) -{ - const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); - struct mipi_csi2phy_lanes_cfg *lane_cfg = &cfg->lane_cfg; - u8 settle_cnt; - u8 val; - int i; - - settle_cnt = phy_qcom_mipi_csi2_settle_cnt_calc(cfg->link_freq, csi2phy->timer_clk_rate); - - val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; - for (i = 0; i < cfg->num_data_lanes; i++) - val |= BIT(lane_cfg->data[i].pos * 2); - - writel(val, csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); - - val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B; - writel(val, csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); - - val = 0x02; - writel(val, csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 7)); - - val = 0x00; - writel(val, csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); - - phy_qcom_mipi_csi2_gen2_config_lanes(csi2phy, settle_cnt); - - /* IRQ_MASK registers - disable all interrupts */ - for (i = CSI_COMMON_STATUS_NUM; i < CSI_CTRL_STATUS_INDEX; i++) { - writel(0, csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, i)); - } - - return 0; -} - -static void -phy_qcom_mipi_csi2_lanes_disable(struct mipi_csi2phy_device *csi2phy, - struct mipi_csi2phy_stream_cfg *cfg) -{ - const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); - - writel(0, csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); - - writel(0, csi2phy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); -} - -static const struct mipi_csi2phy_hw_ops phy_qcom_mipi_csi2_ops_3ph_1_0 = { - .hw_version_read = phy_qcom_mipi_csi2_hw_version_read, - .reset = phy_qcom_mipi_csi2_reset, - .lanes_enable = phy_qcom_mipi_csi2_lanes_enable, - .lanes_disable = phy_qcom_mipi_csi2_lanes_disable, -}; - -static const struct mipi_csi2phy_clk_freq zero = { 0 }; - -static const struct mipi_csi2phy_clk_freq dphy_4nm_x1e_csiphy = { - .freq = { - 300000000, 400000000, 480000000 - }, - .num_freq = 3, -}; - -static const struct mipi_csi2phy_clk_freq dphy_4nm_x1e_csiphy_timer = { - .freq = { - 266666667, 400000000 - }, - .num_freq = 2, -}; - -static const char * const x1e_clks[] = { - "camnoc_axi", - "cpas_ahb", - "csiphy", - "csiphy_timer" -}; - -const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e = { - .ops = &phy_qcom_mipi_csi2_ops_3ph_1_0, - .reg_info = { - .init_seq = lane_regs_x1e80100, - .lane_array_size = ARRAY_SIZE(lane_regs_x1e80100), - .common_regs_offset = 0x1000, - .generation = GEN2, - }, - .supply_names = (const char *[]){ - "vdda-0p8", - "vdda-1p2" - }, - .num_supplies = 2, - .clk_names = (const char **)x1e_clks, - .num_clk = ARRAY_SIZE(x1e_clks), - .opp_clk = x1e_clks[2], - .timer_clk = x1e_clks[3], - .clk_freq = { - zero, - zero, - dphy_4nm_x1e_csiphy, - dphy_4nm_x1e_csiphy_timer, - }, -}; diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c deleted file mode 100644 index 454144f81b719..0000000000000 --- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c +++ /dev/null @@ -1,307 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Copyright (c) 2025, Linaro Ltd. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "phy-qcom-mipi-csi2.h" - -#define CAMSS_CLOCK_MARGIN_NUMERATOR 105 -#define CAMSS_CLOCK_MARGIN_DENOMINATOR 100 - -static inline void phy_qcom_mipi_csi2_add_clock_margin(u64 *rate) -{ - *rate *= CAMSS_CLOCK_MARGIN_NUMERATOR; - *rate = div_u64(*rate, CAMSS_CLOCK_MARGIN_DENOMINATOR); -} - -static int -phy_qcom_mipi_csi2_set_clock_rates(struct mipi_csi2phy_device *csi2phy, - s64 link_freq) -{ - const struct mipi_csi2phy_soc_cfg *soc_cfg = csi2phy->soc_cfg; - unsigned long rates[MAX_CSI2PHY_CLKS] = {0}; - struct device *dev = csi2phy->dev; - unsigned long vote_freq = 0; - int i, j; - int ret; - - for (i = 0; i < soc_cfg->num_clk; i++) { - const struct mipi_csi2phy_clk_freq *clk_freq = &soc_cfg->clk_freq[i]; - const char *clk_name = soc_cfg->clk_names[i]; - struct clk *clk = csi2phy->clks[i].clk; - u64 min_rate = link_freq / 4; - long round_rate; - - phy_qcom_mipi_csi2_add_clock_margin(&min_rate); - - /* This clock should be enabled only not set */ - if (!clk_freq->num_freq) - continue; - - for (j = 0; j < clk_freq->num_freq; j++) - if (min_rate < clk_freq->freq[j]) - break; - - if (j == clk_freq->num_freq) { - dev_err(dev, - "Pixel clock %llu is too high for %s\n", - min_rate, clk_name); - return -EINVAL; - } - - /* if sensor pixel clock is not available - * set highest possible CSIPHY clock rate - */ - if (min_rate == 0) - j = clk_freq->num_freq - 1; - - round_rate = clk_round_rate(clk, clk_freq->freq[j]); - if (round_rate < 0) { - dev_err(dev, "clk round rate failed: %ld\n", - round_rate); - return -EINVAL; - } - - rates[i] = round_rate; - - if (!strcmp(clk_name, soc_cfg->timer_clk)) - csi2phy->timer_clk_rate = round_rate; - - if (!strcmp(clk_name, soc_cfg->opp_clk)) - vote_freq = round_rate; - } - - if (!vote_freq) { - dev_err(dev, "Unable to find operating point frequency\n"); - return -ENODEV; - }; - - dev_dbg(dev, "OPP freq: %lu Hz\n", vote_freq); - - ret = dev_pm_opp_set_rate(dev, vote_freq); - if (ret < 0) { - dev_err(dev, "Failed to set OPP rate: %d\n", ret); - return ret; - } - - for (i = 0; i < soc_cfg->num_clk; i++) { - if (rates[i] == 0) - continue; - - dev_dbg(dev, "Setting clk %s to %lu Hz\n", - soc_cfg->clk_names[i], rates[i]); - - ret = clk_set_rate(csi2phy->clks[i].clk, rates[i]); - if (ret < 0) { - dev_err(dev, "clk_set_rate failed for %s: %d\n", - soc_cfg->clk_names[i], ret); - return ret; - } - } - - return 0; -} - -static int phy_qcom_mipi_csi2_configure(struct phy *phy, - union phy_configure_opts *opts) -{ - struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); - struct phy_configure_opts_mipi_dphy *dphy_cfg_opts = &opts->mipi_dphy; - struct mipi_csi2phy_stream_cfg *stream_cfg = &csi2phy->stream_cfg; - int ret; - int i; - - ret = phy_mipi_dphy_config_validate(dphy_cfg_opts); - if (ret) - return ret; - - if (dphy_cfg_opts->lanes < 1 || dphy_cfg_opts->lanes > CSI2_MAX_DATA_LANES) - return -EINVAL; - - stream_cfg->combo_mode = 0; - stream_cfg->link_freq = dphy_cfg_opts->hs_clk_rate; - stream_cfg->num_data_lanes = dphy_cfg_opts->lanes; - - /* - * phy_configure_opts_mipi_dphy.lanes starts from zero to - * the maximum number of enabled lanes. - * - * TODO: add support for bitmask of enabled lanes and polarities - * of those lanes to the phy_configure_opts_mipi_dphy struct. - * For now take the polarities as zero and the position as fixed - * this is fine as no current upstream implementation maps otherwise. - */ - for (i = 0; i < stream_cfg->num_data_lanes; i++) { - stream_cfg->lane_cfg.data[i].pol = 0; - stream_cfg->lane_cfg.data[i].pos = i; - } - - stream_cfg->lane_cfg.clk.pol = 0; - stream_cfg->lane_cfg.clk.pos = 7; - - return 0; -} - -static int phy_qcom_mipi_csi2_power_on(struct phy *phy) -{ - struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); - const struct mipi_csi2phy_hw_ops *ops = csi2phy->soc_cfg->ops; - struct device *dev = &phy->dev; - int ret; - - ret = regulator_bulk_enable(csi2phy->soc_cfg->num_supplies, - csi2phy->supplies); - if (ret) - return ret; - - ret = phy_qcom_mipi_csi2_set_clock_rates(csi2phy, csi2phy->stream_cfg.link_freq); - if (ret) - goto poweroff_phy; - - ret = clk_bulk_prepare_enable(csi2phy->soc_cfg->num_clk, - csi2phy->clks); - if (ret) { - dev_err(dev, "failed to enable clocks, %d\n", ret); - goto poweroff_phy; - } - - ops->reset(csi2phy); - - ops->hw_version_read(csi2phy); - - return ops->lanes_enable(csi2phy, &csi2phy->stream_cfg); - -poweroff_phy: - regulator_bulk_disable(csi2phy->soc_cfg->num_supplies, - csi2phy->supplies); - - return ret; -} - -static int phy_qcom_mipi_csi2_power_off(struct phy *phy) -{ - struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); - - clk_bulk_disable_unprepare(csi2phy->soc_cfg->num_clk, - csi2phy->clks); - regulator_bulk_disable(csi2phy->soc_cfg->num_supplies, - csi2phy->supplies); - - return 0; -} - -static const struct phy_ops phy_qcom_mipi_csi2_ops = { - .configure = phy_qcom_mipi_csi2_configure, - .power_on = phy_qcom_mipi_csi2_power_on, - .power_off = phy_qcom_mipi_csi2_power_off, - .owner = THIS_MODULE, -}; - -static int phy_qcom_mipi_csi2_probe(struct platform_device *pdev) -{ - unsigned int i, num_clk, num_supplies; - struct mipi_csi2phy_device *csi2phy; - struct phy_provider *phy_provider; - struct device *dev = &pdev->dev; - struct phy *generic_phy; - int ret; - - csi2phy = devm_kzalloc(dev, sizeof(*csi2phy), GFP_KERNEL); - if (!csi2phy) - return -ENOMEM; - - csi2phy->dev = dev; - csi2phy->soc_cfg = device_get_match_data(&pdev->dev); - - if (!csi2phy->soc_cfg) - return -EINVAL; - - num_clk = csi2phy->soc_cfg->num_clk; - csi2phy->clks = devm_kzalloc(dev, sizeof(*csi2phy->clks) * num_clk, GFP_KERNEL); - if (!csi2phy->clks) - return -ENOMEM; - - for (i = 0; i < num_clk; i++) - csi2phy->clks[i].id = csi2phy->soc_cfg->clk_names[i]; - - ret = devm_clk_bulk_get(dev, num_clk, csi2phy->clks); - if (ret) - return dev_err_probe(dev, ret, "Failed to get clocks\n"); - - ret = devm_pm_opp_set_clkname(dev, csi2phy->soc_cfg->opp_clk); - if (ret) - return dev_err_probe(dev, ret, "Failed to set opp clkname\n"); - - ret = devm_pm_opp_of_add_table(dev); - if (ret && ret != -ENODEV) - return dev_err_probe(dev, ret, "invalid OPP table in device tree\n"); - - num_supplies = csi2phy->soc_cfg->num_supplies; - csi2phy->supplies = devm_kzalloc(dev, sizeof(*csi2phy->supplies) * num_supplies, - GFP_KERNEL); - if (!csi2phy->supplies) - return -ENOMEM; - - for (i = 0; i < num_supplies; i++) - csi2phy->supplies[i].supply = csi2phy->soc_cfg->supply_names[i]; - - ret = devm_regulator_bulk_get(dev, num_supplies, csi2phy->supplies); - if (ret) - return dev_err_probe(dev, ret, - "failed to get regulator supplies\n"); - - csi2phy->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(csi2phy->base)) - return PTR_ERR(csi2phy->base); - - generic_phy = devm_phy_create(dev, NULL, &phy_qcom_mipi_csi2_ops); - if (IS_ERR(generic_phy)) { - ret = PTR_ERR(generic_phy); - return dev_err_probe(dev, ret, "failed to create phy\n"); - } - csi2phy->phy = generic_phy; - - phy_set_drvdata(generic_phy, csi2phy); - - phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); - if (!IS_ERR(phy_provider)) - dev_dbg(dev, "Registered MIPI CSI2 PHY device\n"); - - return PTR_ERR_OR_ZERO(phy_provider); -} - -static const struct of_device_id phy_qcom_mipi_csi2_of_match_table[] = { - { .compatible = "qcom,x1e80100-csi2-phy", .data = &mipi_csi2_dphy_4nm_x1e }, - { } -}; -MODULE_DEVICE_TABLE(of, phy_qcom_mipi_csi2_of_match_table); - -static struct platform_driver phy_qcom_mipi_csi2_driver = { - .probe = phy_qcom_mipi_csi2_probe, - .driver = { - .name = "qcom-mipi-csi2-phy", - .of_match_table = phy_qcom_mipi_csi2_of_match_table, - }, -}; - -module_platform_driver(phy_qcom_mipi_csi2_driver); - -MODULE_DESCRIPTION("Qualcomm MIPI CSI2 PHY driver"); -MODULE_AUTHOR("Bryan O'Donoghue "); -MODULE_LICENSE("GPL"); diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h deleted file mode 100644 index 4f3a245ba6a53..0000000000000 --- a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * - * Qualcomm MIPI CSI2 CPHY/DPHY driver - * - * Copyright (C) 2025 Linaro Ltd. - */ -#ifndef __PHY_QCOM_MIPI_CSI2_H__ -#define __PHY_QCOM_MIPI_CSI2_H__ - -#include - -#define CSI2_MAX_DATA_LANES 4 - -struct mipi_csi2phy_lane { - u8 pos; - u8 pol; -}; - -struct mipi_csi2phy_lanes_cfg { - struct mipi_csi2phy_lane data[CSI2_MAX_DATA_LANES]; - struct mipi_csi2phy_lane clk; -}; - -struct mipi_csi2phy_stream_cfg { - u8 combo_mode; - s64 link_freq; - u8 num_data_lanes; - struct mipi_csi2phy_lanes_cfg lane_cfg; -}; - -struct mipi_csi2phy_device; - -struct mipi_csi2phy_hw_ops { - void (*hw_version_read)(struct mipi_csi2phy_device *csi2phy_dev); - void (*reset)(struct mipi_csi2phy_device *csi2phy_dev); - int (*lanes_enable)(struct mipi_csi2phy_device *csi2phy_dev, - struct mipi_csi2phy_stream_cfg *cfg); - void (*lanes_disable)(struct mipi_csi2phy_device *csi2phy_dev, - struct mipi_csi2phy_stream_cfg *cfg); -}; - -struct mipi_csi2phy_lane_regs { - const s32 reg_addr; - const s32 reg_data; - const u32 delay_us; - const u32 param_type; -}; - -struct mipi_csi2phy_device_regs { - const struct mipi_csi2phy_lane_regs *init_seq; - const int lane_array_size; - const u32 common_regs_offset; - enum { - GEN1 = 0, - GEN1_660, - GEN1_670, - GEN2, - } generation; -}; - -#define MAX_CSI2PHY_CLKS 8 -struct mipi_csi2phy_clk_freq { - u32 num_freq; - u32 freq[MAX_CSI2PHY_CLKS]; -}; - -struct mipi_csi2phy_soc_cfg { - const struct mipi_csi2phy_hw_ops *ops; - const struct mipi_csi2phy_device_regs reg_info; - - const char ** const supply_names; - const unsigned int num_supplies; - - const char ** const clk_names; - const unsigned int num_clk; - - const char * const opp_clk; - const char * const timer_clk; - - const struct mipi_csi2phy_clk_freq clk_freq[]; -}; - -struct mipi_csi2phy_device { - struct device *dev; - - struct phy *phy; - void __iomem *base; - - struct clk_bulk_data *clks; - struct regulator_bulk_data *supplies; - u32 timer_clk_rate; - - const struct mipi_csi2phy_soc_cfg *soc_cfg; - struct mipi_csi2phy_stream_cfg stream_cfg; - - u32 hw_version; -}; - -extern const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e; - -#endif /* __PHY_QCOM_MIPI_CSI2_H__ */ From e5541761897d5255e67fdc8b029125fa60cb76a8 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Wed, 22 Apr 2026 14:50:17 +0800 Subject: [PATCH 18/49] Revert "FROMLIST: dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema" This reverts commit 1f7ef5528b05d81d56ff382e7070d96f736c6b36. This patch is reverted because it is superseded by a newer revision. Subsequent Purwa changes are based on the updated version. Signed-off-by: Wenmeng Liu --- .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 114 ------------------ 1 file changed, 114 deletions(-) delete mode 100644 Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml deleted file mode 100644 index c937d26ccbda9..0000000000000 --- a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml +++ /dev/null @@ -1,114 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/phy/qcom,x1e80100-csi2-phy.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Qualcomm CSI2 PHY - -maintainers: - - Bryan O'Donoghue - -description: - Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 sensors - to Qualcomm's Camera CSI Decoder. The PHY supports both C-PHY and D-PHY - modes. - -properties: - compatible: - const: qcom,x1e80100-csi2-phy - - reg: - maxItems: 1 - - "#phy-cells": - const: 1 - - clocks: - maxItems: 4 - - clock-names: - items: - - const: csiphy - - const: csiphy_timer - - const: camnoc_axi - - const: cpas_ahb - - interrupts: - maxItems: 1 - - operating-points-v2: - maxItems: 1 - - power-domains: - maxItems: 1 - - vdda-0p8-supply: - description: Phandle to a 0.8V regulator supply to a PHY. - - vdda-1p2-supply: - description: Phandle to 1.2V regulator supply to a PHY. - -required: - - compatible - - reg - - "#phy-cells" - - clocks - - clock-names - - interrupts - - operating-points-v2 - - power-domains - - vdda-0p8-supply - - vdda-1p2-supply - -additionalProperties: false - -examples: - - | - #include - #include - #include - #include - - csiphy@ace4000 { - compatible = "qcom,x1e80100-csi2-phy"; - reg = <0x0ace4000 0x2000>; - #phy-cells = <1>; - - clocks = <&camcc CAM_CC_CSIPHY0_CLK>, - <&camcc CAM_CC_CSI0PHYTIMER_CLK>, - <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, - <&camcc CAM_CC_CPAS_AHB_CLK>; - clock-names = "csiphy", - "csiphy_timer", - "camnoc_axi", - "cpas_ahb"; - - operating-points-v2 = <&csiphy_opp_table>; - - interrupts = ; - - power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; - - vdda-0p8-supply = <&vreg_l2c_0p8>; - vdda-1p2-supply = <&vreg_l1c_1p2>; - }; - - csiphy_opp_table: opp-table-csiphy { - compatible = "operating-points-v2"; - - opp-300000000 { - opp-hz = /bits/ 64 <300000000>; - required-opps = <&rpmhpd_opp_low_svs_d1>; - }; - - opp-400000000 { - opp-hz = /bits/ 64 <400000000>; - required-opps = <&rpmhpd_opp_low_svs>; - }; - - opp-480000000 { - opp-hz = /bits/ 64 <480000000>; - required-opps = <&rpmhpd_opp_low_svs>; - }; - }; From 5b82ebd44b6606a6ef353399f7d63625656c95ce Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:47:57 +0000 Subject: [PATCH 19/49] FROMLIST: phy: dphy: Add lane_positions to DPHY config struct Add lane_positions to the DPHY configuration struct. This data-field represents the physical positions of the data-lanes indexed by lane number. Link: https://lore.kernel.org/all/20260325-dphy-params-extension-v1-1-c6df5599284a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- include/linux/phy/phy-mipi-dphy.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h index 1ac128d78dfeb..c7eb11c41d7ec 100644 --- a/include/linux/phy/phy-mipi-dphy.h +++ b/include/linux/phy/phy-mipi-dphy.h @@ -6,6 +6,8 @@ #ifndef __PHY_MIPI_DPHY_H_ #define __PHY_MIPI_DPHY_H_ +#define PHY_MIPI_DPHY_MAX_DATA_LANES 4 + /** * struct phy_configure_opts_mipi_dphy - MIPI D-PHY configuration set * @@ -269,10 +271,19 @@ struct phy_configure_opts_mipi_dphy { /** * @lanes: * - * Number of active, consecutive, data lanes, starting from - * lane 0, used for the transmissions. + * Number of active data lanes used for the transmission. + * When @lane_positions is not populated, lanes are consecutive + * starting from lane 0. */ unsigned char lanes; + + /** + * @lane_positions: + * + * Array representing the physical positions of the data-lanes. + * Indexed by logical lane number. + */ + unsigned char lane_positions[PHY_MIPI_DPHY_MAX_DATA_LANES]; }; int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, From bdad344fa42e167092b31305e1996e96706388b5 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:47:58 +0000 Subject: [PATCH 20/49] FROMLIST: phy: dphy: Add lane_polarities to DPHY config struct Pass an array of data-lane polarities from controller to PHY. A true value means the lane polarity is inverted. Link: https://lore.kernel.org/all/20260325-dphy-params-extension-v1-2-c6df5599284a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- include/linux/phy/phy-mipi-dphy.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h index c7eb11c41d7ec..3e0333b5a1a71 100644 --- a/include/linux/phy/phy-mipi-dphy.h +++ b/include/linux/phy/phy-mipi-dphy.h @@ -284,6 +284,14 @@ struct phy_configure_opts_mipi_dphy { * Indexed by logical lane number. */ unsigned char lane_positions[PHY_MIPI_DPHY_MAX_DATA_LANES]; + + /** + * @lane_polarities: + * + * Array representing data-lane polarities. True means inverted. + * Indexed by logical lane number. + */ + bool lane_polarities[PHY_MIPI_DPHY_MAX_DATA_LANES]; }; int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, From 072c5dd0343a252afe3d8be778876b198fdae51e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:47:59 +0000 Subject: [PATCH 21/49] FROMLIST: phy: dphy: Add clock_lane_position to DPHY config struct We need to identify which lane is the clock-lane as many different PHYs allow for a range of lanes, potentially any of the lanes to be the clock input lane on a PHY. Link: https://lore.kernel.org/all/20260325-dphy-params-extension-v1-3-c6df5599284a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- include/linux/phy/phy-mipi-dphy.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h index 3e0333b5a1a71..76d41580e225a 100644 --- a/include/linux/phy/phy-mipi-dphy.h +++ b/include/linux/phy/phy-mipi-dphy.h @@ -292,6 +292,13 @@ struct phy_configure_opts_mipi_dphy { * Indexed by logical lane number. */ bool lane_polarities[PHY_MIPI_DPHY_MAX_DATA_LANES]; + + /** + * @clock_lane_position: + * + * Physical lane number used as the clock lane. + */ + unsigned char clock_lane_position; }; int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, From 2101142b46df6b390baef8b5e48bd6fd81620485 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:48:00 +0000 Subject: [PATCH 22/49] FROMLIST: phy: dphy: Add clock_lane_polarity to DPHY config struct Specify the polarity of the clock lane in DPHY mode. When true this bool means the polarity is inverted. Link: https://lore.kernel.org/all/20260325-dphy-params-extension-v1-4-c6df5599284a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- include/linux/phy/phy-mipi-dphy.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/phy/phy-mipi-dphy.h b/include/linux/phy/phy-mipi-dphy.h index 76d41580e225a..f7b4ad29e6f83 100644 --- a/include/linux/phy/phy-mipi-dphy.h +++ b/include/linux/phy/phy-mipi-dphy.h @@ -299,6 +299,13 @@ struct phy_configure_opts_mipi_dphy { * Physical lane number used as the clock lane. */ unsigned char clock_lane_position; + + /** + * @clock_lane_polarity: + * + * Clock lane polarity. True means inverted. + */ + bool clock_lane_polarity; }; int phy_mipi_dphy_get_default_config(unsigned long pixel_clock, From 3a74e1346318d937024b3db65f83802fa665cf73 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:04:43 +0000 Subject: [PATCH 23/49] FROMLIST: dt-bindings: phy: qcom: Add CSI2 C-PHY/DPHY schema Add a base schema initially compatible with x1e80100 to describe MIPI CSI2 PHY devices. The hardware can support both CPHY, DPHY and a special split-mode DPHY. We capture those modes as: - PHY_QCOM_CSI2_MODE_DPHY - PHY_QCOM_CSI2_MODE_CPHY - PHY_QCOM_CSI2_MODE_SPLIT_DPHY The CSIPHY devices have their own pinouts on the SoC as well as their own individual voltage rails. The need to model voltage rails on a per-PHY basis leads us to define CSIPHY devices as individual nodes. Two nice outcomes in terms of schema and DT arise from this change. 1. The ability to define on a per-PHY basis voltage rails. 2. The ability to require those voltage. We have had a complete bodge upstream for this where a single set of voltage rail for all CSIPHYs has been buried inside of CAMSS. Much like the I2C bus which is dedicated to Camera sensors - the CCI bus in CAMSS parlance, the CSIPHY devices should be individually modelled. Link: https://lore.kernel.org/all/20260326-x1e-csi2-phy-v5-1-0c0fc7f5c01b@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../bindings/phy/qcom,x1e80100-csi2-phy.yaml | 130 ++++++++++++++++++ include/dt-bindings/phy/phy-qcom-mipi-csi2.h | 15 ++ 2 files changed, 145 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml create mode 100644 include/dt-bindings/phy/phy-qcom-mipi-csi2.h diff --git a/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml new file mode 100644 index 0000000000000..63114151104b4 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/qcom,x1e80100-csi2-phy.yaml @@ -0,0 +1,130 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/phy/qcom,x1e80100-csi2-phy.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm CSI2 PHY + +maintainers: + - Bryan O'Donoghue + +description: + Qualcomm MIPI CSI2 C-PHY/D-PHY combination PHY. Connects MIPI CSI2 sensors + to Qualcomm's Camera CSI Decoder. The PHY supports both C-PHY and D-PHY + modes. + +properties: + compatible: + const: qcom,x1e80100-csi2-phy + + reg: + maxItems: 1 + + "#phy-cells": + const: 1 + description: + The single cell specifies the PHY operating mode. + See include/dt-bindings/phy/phy-qcom-mipi-csi2.h for valid values. + + clocks: + maxItems: 2 + + clock-names: + items: + - const: core + - const: timer + + interrupts: + maxItems: 1 + + operating-points-v2: + maxItems: 1 + + power-domains: + items: + - description: MXC or MXA voltage rail + - description: MMCX voltage rail + + power-domain-names: + items: + - const: mx + - const: mmcx + + vdda-0p9-supply: + description: Phandle to a 0.9V regulator supply to a PHY. + + vdda-1p2-supply: + description: Phandle to 1.2V regulator supply to a PHY. + +required: + - compatible + - reg + - "#phy-cells" + - clocks + - clock-names + - interrupts + - operating-points-v2 + - power-domains + - power-domain-names + - vdda-0p9-supply + - vdda-1p2-supply + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + + csiphy4: csiphy@ace4000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0x0ace4000 0x2000>; + #phy-cells = <1>; + + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MX>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + }; + + csiphy_opp_table: opp-table { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + + isp@acb7000 { + phys = <&csiphy4 PHY_QCOM_CSI2_MODE_DPHY>; + }; diff --git a/include/dt-bindings/phy/phy-qcom-mipi-csi2.h b/include/dt-bindings/phy/phy-qcom-mipi-csi2.h new file mode 100644 index 0000000000000..fa48fd75c58d8 --- /dev/null +++ b/include/dt-bindings/phy/phy-qcom-mipi-csi2.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ +/* + * Qualcomm MIPI CSI2 PHY constants + * + * Copyright (C) 2026 Linaro Limited + */ + +#ifndef __DT_BINDINGS_PHY_MIPI_CSI2__ +#define __DT_BINDINGS_PHY_MIPI_CSI2__ + +#define PHY_QCOM_CSI2_MODE_DPHY 0 +#define PHY_QCOM_CSI2_MODE_CPHY 1 +#define PHY_QCOM_CSI2_MODE_SPLIT_DPHY 2 + +#endif /* __DT_BINDINGS_PHY_MIPI_CSI2__ */ From b591d0afe7c9eb81223863be24a9b1ae094c4f7e Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:04:44 +0000 Subject: [PATCH 24/49] FROMLIST: phy: qcom-mipi-csi2: Add a CSI2 MIPI DPHY driver Add a new MIPI CSI2 driver in DPHY mode initially. The entire set of existing CAMSS CSI PHY init sequences are imported in order to save time and effort in later patches. The following devices are supported in this drop: "qcom,x1e80100-csi2-phy" In-line with other PHY drivers the process node is included in the name. Data-lane and clock lane positioning and polarity selection via newly amended struct phy_configure_opts_mipi_dphy{} is supported. The Qualcomm 3PH class of PHYs can do both DPHY and CPHY mode. For now only DPHY is supported. In porting some of the logic over from camss-csiphy*.c to here its also possible to rationalise some of the code. In particular use of regulator_bulk and clk_bulk as well as dropping the seemingly useless and unused interrupt handler. The PHY sequences and a lot of the logic that goes with them are well proven in CAMSS and mature so the main thing to watch out for here is how to get the right sequencing of regulators, clocks and register-writes. The register init sequence table is imported verbatim from the existing CAMSS csiphy driver. A follow-up series will rework the table to extract the repetitive per-lane pattern into a loop. Link: https://lore.kernel.org/all/20260326-x1e-csi2-phy-v5-2-0c0fc7f5c01b@linaro.org/ Signed-off-by: Bryan O'Donoghue --- MAINTAINERS | 11 + drivers/phy/qualcomm/Kconfig | 13 + drivers/phy/qualcomm/Makefile | 5 + .../qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c | 361 ++++++++++++++++++ .../phy/qualcomm/phy-qcom-mipi-csi2-core.c | 298 +++++++++++++++ drivers/phy/qualcomm/phy-qcom-mipi-csi2.h | 95 +++++ 6 files changed, 783 insertions(+) create mode 100644 drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c create mode 100644 drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c create mode 100644 drivers/phy/qualcomm/phy-qcom-mipi-csi2.h diff --git a/MAINTAINERS b/MAINTAINERS index bbd71f255c02d..6a2023b6d56df 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -21252,6 +21252,17 @@ S: Maintained F: Documentation/devicetree/bindings/media/qcom,*-iris.yaml F: drivers/media/platform/qcom/iris/ +QUALCOMM MIPI CSI2 PHY DRIVER +M: Bryan O'Donoghue +L: linux-phy@lists.infradead.org +L: linux-media@vger.kernel.org +L: linux-arm-msm@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/phy/qcom,*-csi2-phy.yaml +F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.c +F: drivers/phy/qualcomm/phy-qcom-mipi-csi2*.h +F: include/dt-bindings/phy/phy-qcom-mipi-csi2* + QUALCOMM NAND CONTROLLER DRIVER M: Manivannan Sadhasivam L: linux-mtd@lists.infradead.org diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index 60a0ead127fa9..ea33025a40fd0 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -28,6 +28,19 @@ config PHY_QCOM_EDP Enable this driver to support the Qualcomm eDP PHY found in various Qualcomm chipsets. +config PHY_QCOM_MIPI_CSI2 + tristate "Qualcomm MIPI CSI2 PHY driver" + depends on ARCH_QCOM || COMPILE_TEST + depends on OF + depends on COMMON_CLK + select GENERIC_PHY + select GENERIC_PHY_MIPI_DPHY + help + Enable this to support the MIPI CSI2 PHY driver found in various + Qualcomm chipsets. This PHY is used to connect MIPI CSI2 + camera sensors to the CSI Decoder in the Qualcomm Camera Subsystem + CAMSS. + config PHY_QCOM_IPQ4019_USB tristate "Qualcomm IPQ4019 USB PHY driver" depends on OF && (ARCH_QCOM || COMPILE_TEST) diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index b71a6a0bed3f1..382cb594b06b6 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -6,6 +6,11 @@ obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o obj-$(CONFIG_PHY_QCOM_M31_EUSB) += phy-qcom-m31-eusb2.o + +phy-qcom-mipi-csi2-objs += phy-qcom-mipi-csi2-core.o \ + phy-qcom-mipi-csi2-3ph-dphy.o +obj-$(CONFIG_PHY_QCOM_MIPI_CSI2) += phy-qcom-mipi-csi2.o + obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o phy-qcom-qmp-usbc.o diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c new file mode 100644 index 0000000000000..b1eb2b28b2da2 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-3ph-dphy.c @@ -0,0 +1,361 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Qualcomm MSM Camera Subsystem - CSIPHY Module 3phase v1.0 + * + * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. + * Copyright (C) 2016-2025 Linaro Ltd. + */ + +#include +#include +#include +#include + +#include "phy-qcom-mipi-csi2.h" + +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(offset, n) ((offset) + 0x4 * (n)) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET BIT(0) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE BIT(7) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B BIT(0) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID BIT(1) +#define CSIPHY_3PH_CMN_CSI_COMMON_CTRL10_IRQ_CLEAR_CMD BIT(0) +#define CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(offset, n) ((offset) + 0xb0 + 0x4 * (n)) + +/* + * 3 phase CSI has 19 common status regs with only 0-10 being used + * and 11-18 being reserved. + */ +#define CSI_COMMON_STATUS_NUM 11 +/* + * There are a number of common control registers + * The offset to clear the CSIPHY IRQ status starts @ 22 + * So to clear CSI_COMMON_STATUS0 this is CSI_COMMON_CONTROL22, STATUS1 is + * CONTROL23 and so on + */ +#define CSI_CTRL_STATUS_INDEX 22 + +/* + * There are 43 COMMON_CTRL registers with regs after # 33 being reserved + */ +#define CSI_CTRL_MAX 33 + +#define CSIPHY_DEFAULT_PARAMS 0 +#define CSIPHY_SETTLE_CNT_LOWER_BYTE 2 +#define CSIPHY_SKEW_CAL 7 + +/* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */ +static const struct +mipi_csi2phy_lane_regs lane_regs_x1e80100[] = { + /* Power up lanes 2ph mode */ + {.reg_addr = 0x1014, .reg_data = 0xd5, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x101c, .reg_data = 0x7a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x1018, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + + {.reg_addr = 0x0094, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x00a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0090, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0098, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0094, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0030, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0000, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0038, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x002c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0034, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x001c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0014, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x003c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0004, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0020, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0008, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0010, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0094, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x005c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0060, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0064, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0e94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0ea0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e28, .reg_data = 0x04, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e00, .reg_data = 0x80, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e0c, .reg_data = 0xff, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e38, .reg_data = 0x1f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e2c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e34, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e1c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e3c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e04, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0e08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0e10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + + {.reg_addr = 0x0494, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x04a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0490, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0498, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0494, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0430, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0400, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0438, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x042c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0434, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x041c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0414, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x043c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0404, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0420, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0408, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0410, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0494, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x045c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0460, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0464, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0894, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x08a0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0890, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0898, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0894, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0830, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0800, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0838, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x082c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0834, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x081c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0814, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x083c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0804, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0820, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0808, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0810, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0894, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x085c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0860, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0864, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, + + {.reg_addr = 0x0c94, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0ca0, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c90, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c98, .reg_data = 0x08, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c94, .reg_data = 0x07, .delay_us = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c30, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c00, .reg_data = 0x8e, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c38, .reg_data = 0xfe, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c2c, .reg_data = 0x01, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c34, .reg_data = 0x0f, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c1c, .reg_data = 0x0a, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c14, .reg_data = 0x60, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c3c, .reg_data = 0xb8, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c04, .reg_data = 0x0c, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c20, .reg_data = 0x00, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c08, .reg_data = 0x10, .param_type = CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {.reg_addr = 0x0c10, .reg_data = 0x52, .param_type = CSIPHY_DEFAULT_PARAMS}, + {.reg_addr = 0x0c94, .reg_data = 0xd7, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0c5c, .reg_data = 0x00, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0c60, .reg_data = 0xbd, .param_type = CSIPHY_SKEW_CAL}, + {.reg_addr = 0x0c64, .reg_data = 0x7f, .param_type = CSIPHY_SKEW_CAL}, +}; + +static inline const struct mipi_csi2phy_device_regs * +csi2phy_dev_to_regs(struct mipi_csi2phy_device *csi2phy) +{ + return &csi2phy->soc_cfg->reg_info; +} + +static void phy_qcom_mipi_csi2_hw_version_read(struct mipi_csi2phy_device *csi2phy) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + u32 tmp; + + writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_SHOW_REV_ID, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 12)); + csi2phy->hw_version = tmp; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 13)); + csi2phy->hw_version |= (tmp << 8) & 0xFF00; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 14)); + csi2phy->hw_version |= (tmp << 16) & 0xFF0000; + + tmp = readl_relaxed(csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(regs->common_regs_offset, 15)); + csi2phy->hw_version |= (tmp << 24) & 0xFF000000; + + dev_dbg_once(csi2phy->dev, "CSIPHY 3PH HW Version = 0x%08x\n", csi2phy->hw_version); +} + +/* + * phy_qcom_mipi_csi2_reset - Perform software reset on CSIPHY module + * @phy_qcom_mipi_csi2: CSIPHY device + */ +static void phy_qcom_mipi_csi2_reset(struct mipi_csi2phy_device *csi2phy) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + + writel(CSIPHY_3PH_CMN_CSI_COMMON_CTRL0_PHY_SW_RESET, + csi2phy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); + usleep_range(5000, 8000); + writel(0x0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); +} + +/* + * phy_qcom_mipi_csi2_settle_cnt_calc - Calculate settle count value + * + * Helper function to calculate settle count value. This is + * based on the CSI2 T_hs_settle parameter which in turn + * is calculated based on the CSI2 transmitter link frequency. + * + * Return settle count value or 0 if the CSI2 link frequency + * is not available + */ +static u8 phy_qcom_mipi_csi2_settle_cnt_calc(s64 link_freq, u32 timer_clk_rate) +{ + u32 t_hs_prepare_max_ps; + u32 timer_period_ps; + u32 t_hs_settle_ps; + u8 settle_cnt; + u32 ui_ps; + + if (link_freq <= 0) + return 0; + + ui_ps = div_u64(PSEC_PER_SEC, link_freq); + ui_ps /= 2; + t_hs_prepare_max_ps = 85000 + 6 * ui_ps; + t_hs_settle_ps = t_hs_prepare_max_ps; + + timer_period_ps = div_u64(PSEC_PER_SEC, timer_clk_rate); + settle_cnt = t_hs_settle_ps / timer_period_ps - 6; + + return settle_cnt; +} + +static void +phy_qcom_mipi_csi2_gen2_config_lanes(struct mipi_csi2phy_device *csi2phy, + u8 settle_cnt) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + const struct mipi_csi2phy_lane_regs *r = regs->init_seq; + int i, array_size = regs->lane_array_size; + u32 val; + + for (i = 0; i < array_size; i++, r++) { + switch (r->param_type) { + case CSIPHY_SETTLE_CNT_LOWER_BYTE: + val = settle_cnt & 0xff; + break; + case CSIPHY_SKEW_CAL: + /* TODO: support application of skew from dt flag */ + continue; + default: + val = r->reg_data; + break; + } + writel(val, csi2phy->base + r->reg_addr); + if (r->delay_us) + udelay(r->delay_us); + } +} + +static int phy_qcom_mipi_csi2_lanes_enable(struct mipi_csi2phy_device *csi2phy, + struct mipi_csi2phy_stream_cfg *cfg) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + struct mipi_csi2phy_lanes_cfg *lane_cfg = &cfg->lane_cfg; + u8 settle_cnt; + u8 val; + int i; + + settle_cnt = phy_qcom_mipi_csi2_settle_cnt_calc(cfg->link_freq, csi2phy->timer_clk_rate); + + val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; + for (i = 0; i < cfg->num_data_lanes; i++) + val |= BIT(lane_cfg->data[i].pos * 2); + + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); + + val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL6_COMMON_PWRDN_B; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); + + val = 0x02; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 7)); + + val = 0x00; + writel(val, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 0)); + + phy_qcom_mipi_csi2_gen2_config_lanes(csi2phy, settle_cnt); + + /* IRQ_MASK registers - disable all interrupts */ + for (i = CSI_COMMON_STATUS_NUM; i < CSI_CTRL_STATUS_INDEX; i++) { + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, i)); + } + + return 0; +} + +static void +phy_qcom_mipi_csi2_lanes_disable(struct mipi_csi2phy_device *csi2phy, + struct mipi_csi2phy_stream_cfg *cfg) +{ + const struct mipi_csi2phy_device_regs *regs = csi2phy_dev_to_regs(csi2phy); + + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 5)); + + writel(0, csi2phy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->common_regs_offset, 6)); +} + +static const struct mipi_csi2phy_hw_ops phy_qcom_mipi_csi2_ops_3ph_1_0 = { + .hw_version_read = phy_qcom_mipi_csi2_hw_version_read, + .reset = phy_qcom_mipi_csi2_reset, + .lanes_enable = phy_qcom_mipi_csi2_lanes_enable, + .lanes_disable = phy_qcom_mipi_csi2_lanes_disable, +}; + +static const char * const x1e_clks[] = { + "core", + "timer" +}; + +static const char * const x1e_supplies[] = { + "vdda-0p9", + "vdda-1p2" +}; + +static const char * const x1e_genpd_names[] = { + "mx", + "mmcx", +}; + +const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e = { + .ops = &phy_qcom_mipi_csi2_ops_3ph_1_0, + .reg_info = { + .init_seq = lane_regs_x1e80100, + .lane_array_size = ARRAY_SIZE(lane_regs_x1e80100), + .common_regs_offset = 0x1000, + }, + .supply_names = (const char **)x1e_supplies, + .num_supplies = ARRAY_SIZE(x1e_supplies), + .clk_names = (const char **)x1e_clks, + .num_clk = ARRAY_SIZE(x1e_clks), + .opp_clk = x1e_clks[0], + .timer_clk = x1e_clks[1], + .genpd_names = (const char **)x1e_genpd_names, + .num_genpd_names = ARRAY_SIZE(x1e_genpd_names), +}; diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c new file mode 100644 index 0000000000000..47acf0d586a15 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2-core.c @@ -0,0 +1,298 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2025, Linaro Ltd. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "phy-qcom-mipi-csi2.h" + +static int +phy_qcom_mipi_csi2_set_clock_rates(struct mipi_csi2phy_device *csi2phy, + s64 link_freq) +{ + struct device *dev = csi2phy->dev; + unsigned long opp_rate = link_freq / 4; + struct dev_pm_opp *opp; + long timer_rate; + int ret; + + opp = dev_pm_opp_find_freq_ceil(dev, &opp_rate); + if (IS_ERR(opp)) { + dev_err(csi2phy->dev, "Couldn't find ceiling for %lld Hz\n", + link_freq); + return PTR_ERR(opp); + } + + for (int i = 0; i < csi2phy->num_pds; i++) { + unsigned int perf = dev_pm_opp_get_required_pstate(opp, i); + + ret = dev_pm_genpd_set_performance_state(csi2phy->pds[i], perf); + if (ret) { + dev_err(csi2phy->dev, "Couldn't set perf state %u\n", + perf); + dev_pm_opp_put(opp); + return ret; + } + } + dev_pm_opp_put(opp); + + ret = dev_pm_opp_set_rate(dev, opp_rate); + if (ret) { + dev_err(csi2phy->dev, "dev_pm_opp_set_rate() fail\n"); + return ret; + } + + timer_rate = clk_round_rate(csi2phy->timer_clk, link_freq / 4); + if (timer_rate < 0) + return timer_rate; + + ret = clk_set_rate(csi2phy->timer_clk, timer_rate); + if (ret) + return ret; + + csi2phy->timer_clk_rate = timer_rate; + + return 0; +} + +static int phy_qcom_mipi_csi2_configure(struct phy *phy, + union phy_configure_opts *opts) +{ + struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); + struct phy_configure_opts_mipi_dphy *dphy_cfg = &opts->mipi_dphy; + struct mipi_csi2phy_stream_cfg *stream_cfg = &csi2phy->stream_cfg; + int ret; + int i; + + ret = phy_mipi_dphy_config_validate(dphy_cfg); + if (ret) + return ret; + + if (dphy_cfg->lanes < 1 || dphy_cfg->lanes > CSI2_MAX_DATA_LANES) + return -EINVAL; + + stream_cfg->link_freq = dphy_cfg->hs_clk_rate; + stream_cfg->num_data_lanes = dphy_cfg->lanes; + + for (i = 0; i < stream_cfg->num_data_lanes; i++) { + stream_cfg->lane_cfg.data[i].pol = dphy_cfg->lane_polarities[i]; + stream_cfg->lane_cfg.data[i].pos = dphy_cfg->lane_positions[i]; + } + + stream_cfg->lane_cfg.clk.pol = dphy_cfg->clock_lane_polarity; + stream_cfg->lane_cfg.clk.pos = dphy_cfg->clock_lane_position; + + return 0; +} + +static int phy_qcom_mipi_csi2_power_on(struct phy *phy) +{ + struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); + const struct mipi_csi2phy_hw_ops *ops = csi2phy->soc_cfg->ops; + struct device *dev = &phy->dev; + int ret; + + ret = regulator_bulk_enable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + if (ret) + return ret; + + ret = phy_qcom_mipi_csi2_set_clock_rates(csi2phy, csi2phy->stream_cfg.link_freq); + if (ret) + goto poweroff_phy; + + ret = clk_bulk_prepare_enable(csi2phy->soc_cfg->num_clk, + csi2phy->clks); + if (ret) { + dev_err(dev, "failed to enable clocks, %d\n", ret); + goto poweroff_phy; + } + + ops->reset(csi2phy); + + ops->hw_version_read(csi2phy); + + return ops->lanes_enable(csi2phy, &csi2phy->stream_cfg); + +poweroff_phy: + regulator_bulk_disable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + + return ret; +} + +static int phy_qcom_mipi_csi2_power_off(struct phy *phy) +{ + struct mipi_csi2phy_device *csi2phy = phy_get_drvdata(phy); + int i; + + for (i = 0; i < csi2phy->num_pds; i++) + dev_pm_genpd_set_performance_state(csi2phy->pds[i], 0); + + clk_bulk_disable_unprepare(csi2phy->soc_cfg->num_clk, + csi2phy->clks); + regulator_bulk_disable(csi2phy->soc_cfg->num_supplies, + csi2phy->supplies); + + return 0; +} + +static const struct phy_ops phy_qcom_mipi_csi2_ops = { + .configure = phy_qcom_mipi_csi2_configure, + .power_on = phy_qcom_mipi_csi2_power_on, + .power_off = phy_qcom_mipi_csi2_power_off, + .owner = THIS_MODULE, +}; + +static struct phy *qcom_csi2_phy_xlate(struct device *dev, + const struct of_phandle_args *args) +{ + struct mipi_csi2phy_device *csi2phy = dev_get_drvdata(dev); + + if (args->args[0] != PHY_QCOM_CSI2_MODE_DPHY) { + dev_err(csi2phy->dev, "mode %d -EOPNOTSUPP\n", args->args[0]); + return ERR_PTR(-EOPNOTSUPP); + } + + csi2phy->phy_mode = args->args[0]; + + return csi2phy->phy; +} + +static int phy_qcom_mipi_csi2_probe(struct platform_device *pdev) +{ + unsigned int i, num_clk, num_supplies, num_pds; + struct mipi_csi2phy_device *csi2phy; + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + struct phy *generic_phy; + int ret; + + csi2phy = devm_kzalloc(dev, sizeof(*csi2phy), GFP_KERNEL); + if (!csi2phy) + return -ENOMEM; + + csi2phy->dev = dev; + dev_set_drvdata(dev, csi2phy); + + csi2phy->soc_cfg = device_get_match_data(&pdev->dev); + + if (!csi2phy->soc_cfg) + return -EINVAL; + + num_clk = csi2phy->soc_cfg->num_clk; + csi2phy->clks = devm_kzalloc(dev, sizeof(*csi2phy->clks) * num_clk, GFP_KERNEL); + if (!csi2phy->clks) + return -ENOMEM; + + num_pds = csi2phy->soc_cfg->num_genpd_names; + if (!num_pds) + return -EINVAL; + + csi2phy->pds = devm_kzalloc(dev, sizeof(*csi2phy->pds) * num_pds, GFP_KERNEL); + if (!csi2phy->pds) + return -ENOMEM; + + for (i = 0; i < num_pds; i++) { + csi2phy->pds[i] = dev_pm_domain_attach_by_name(dev, + csi2phy->soc_cfg->genpd_names[i]); + if (IS_ERR(csi2phy->pds[i])) { + return dev_err_probe(dev, PTR_ERR(csi2phy->pds[i]), + "Failed to attach %s\n", + csi2phy->soc_cfg->genpd_names[i]); + } + } + csi2phy->num_pds = num_pds; + + for (i = 0; i < num_clk; i++) + csi2phy->clks[i].id = csi2phy->soc_cfg->clk_names[i]; + + ret = devm_clk_bulk_get(dev, num_clk, csi2phy->clks); + if (ret) + return dev_err_probe(dev, ret, "Failed to get clocks\n"); + + csi2phy->timer_clk = devm_clk_get(dev, csi2phy->soc_cfg->timer_clk); + if (IS_ERR(csi2phy->timer_clk)) { + return dev_err_probe(dev, PTR_ERR(csi2phy->timer_clk), + "Failed to get timer clock\n"); + } + + ret = devm_pm_opp_set_clkname(dev, csi2phy->soc_cfg->opp_clk); + if (ret) + return dev_err_probe(dev, ret, "Failed to set opp clkname\n"); + + ret = devm_pm_opp_of_add_table(dev); + if (ret && ret != -ENODEV) + return dev_err_probe(dev, ret, "invalid OPP table in device tree\n"); + + num_supplies = csi2phy->soc_cfg->num_supplies; + csi2phy->supplies = devm_kzalloc(dev, sizeof(*csi2phy->supplies) * num_supplies, + GFP_KERNEL); + if (!csi2phy->supplies) + return -ENOMEM; + + for (i = 0; i < num_supplies; i++) + csi2phy->supplies[i].supply = csi2phy->soc_cfg->supply_names[i]; + + ret = devm_regulator_bulk_get(dev, num_supplies, csi2phy->supplies); + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulator supplies\n"); + + csi2phy->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(csi2phy->base)) + return PTR_ERR(csi2phy->base); + + generic_phy = devm_phy_create(dev, NULL, &phy_qcom_mipi_csi2_ops); + if (IS_ERR(generic_phy)) { + ret = PTR_ERR(generic_phy); + return dev_err_probe(dev, ret, "failed to create phy\n"); + } + csi2phy->phy = generic_phy; + + phy_set_drvdata(generic_phy, csi2phy); + + phy_provider = devm_of_phy_provider_register(dev, qcom_csi2_phy_xlate); + if (!IS_ERR(phy_provider)) + dev_dbg(dev, "Registered MIPI CSI2 PHY device\n"); + + return PTR_ERR_OR_ZERO(phy_provider); +} + +static const struct of_device_id phy_qcom_mipi_csi2_of_match_table[] = { + { .compatible = "qcom,x1e80100-csi2-phy", .data = &mipi_csi2_dphy_4nm_x1e }, + { } +}; +MODULE_DEVICE_TABLE(of, phy_qcom_mipi_csi2_of_match_table); + +static struct platform_driver phy_qcom_mipi_csi2_driver = { + .probe = phy_qcom_mipi_csi2_probe, + .driver = { + .name = "qcom-mipi-csi2-phy", + .of_match_table = phy_qcom_mipi_csi2_of_match_table, + }, +}; + +module_platform_driver(phy_qcom_mipi_csi2_driver); + +MODULE_DESCRIPTION("Qualcomm MIPI CSI2 PHY driver"); +MODULE_AUTHOR("Bryan O'Donoghue "); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h new file mode 100644 index 0000000000000..27607dea412f1 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-mipi-csi2.h @@ -0,0 +1,95 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * + * Qualcomm MIPI CSI2 CPHY/DPHY driver + * + * Copyright (C) 2025 Linaro Ltd. + */ +#ifndef __PHY_QCOM_MIPI_CSI2_H__ +#define __PHY_QCOM_MIPI_CSI2_H__ + +#include + +#define CSI2_MAX_DATA_LANES 4 + +struct mipi_csi2phy_lane { + u8 pos; + u8 pol; +}; + +struct mipi_csi2phy_lanes_cfg { + struct mipi_csi2phy_lane data[CSI2_MAX_DATA_LANES]; + struct mipi_csi2phy_lane clk; +}; + +struct mipi_csi2phy_stream_cfg { + s64 link_freq; + u8 num_data_lanes; + struct mipi_csi2phy_lanes_cfg lane_cfg; +}; + +struct mipi_csi2phy_device; + +struct mipi_csi2phy_hw_ops { + void (*hw_version_read)(struct mipi_csi2phy_device *csi2phy_dev); + void (*reset)(struct mipi_csi2phy_device *csi2phy_dev); + int (*lanes_enable)(struct mipi_csi2phy_device *csi2phy_dev, + struct mipi_csi2phy_stream_cfg *cfg); + void (*lanes_disable)(struct mipi_csi2phy_device *csi2phy_dev, + struct mipi_csi2phy_stream_cfg *cfg); +}; + +struct mipi_csi2phy_lane_regs { + const s32 reg_addr; + const s32 reg_data; + const u32 delay_us; + const u32 param_type; +}; + +struct mipi_csi2phy_device_regs { + const struct mipi_csi2phy_lane_regs *init_seq; + const int lane_array_size; + const u32 common_regs_offset; +}; + +struct mipi_csi2phy_soc_cfg { + const struct mipi_csi2phy_hw_ops *ops; + const struct mipi_csi2phy_device_regs reg_info; + + const char ** const supply_names; + const unsigned int num_supplies; + + const char ** const clk_names; + const unsigned int num_clk; + + const char * const opp_clk; + const char * const timer_clk; + + const char ** const genpd_names; + const unsigned int num_genpd_names; +}; + +struct mipi_csi2phy_device { + struct device *dev; + u8 phy_mode; + + struct phy *phy; + void __iomem *base; + + struct clk_bulk_data *clks; + struct clk *timer_clk; + u32 timer_clk_rate; + + struct regulator_bulk_data *supplies; + struct device **pds; + unsigned int num_pds; + + const struct mipi_csi2phy_soc_cfg *soc_cfg; + struct mipi_csi2phy_stream_cfg stream_cfg; + + u32 hw_version; +}; + +extern const struct mipi_csi2phy_soc_cfg mipi_csi2_dphy_4nm_x1e; + +#endif /* __PHY_QCOM_MIPI_CSI2_H__ */ From 6a25f6267da49057a1d81cbd657fec5fa1680450 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:29 +0000 Subject: [PATCH 25/49] FROMLIST: dt-bindings: media: qcom,x1e80100-camss: Add optional PHY handle definitions Add optional PHY handle definitions. This will allow for supporting both legacy PHY definitions as well as supporting the optional new handle based approach. Drop the legacy high-level 0p8 and 1p2 supplies as required, each PHY has its own individual rails. The old binding is still valid but with individual nodes we define the rails in the CSIPHY sub-nodes. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-1-5b93415be6dd@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../bindings/media/qcom,x1e80100-camss.yaml | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml index b075341caafc1..c8bd0495f2fb4 100644 --- a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml @@ -39,6 +39,14 @@ properties: - const: vfe_lite0 - const: vfe_lite1 + '#address-cells': + const: 2 + + '#size-cells': + const: 2 + + ranges: true + clocks: maxItems: 29 @@ -126,6 +134,16 @@ properties: description: Phandle to 1.8V regulator supply to a PHY. + phys: + maxItems: 4 + + phy-names: + items: + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy4 + ports: $ref: /schemas/graph.yaml#/properties/ports @@ -158,6 +176,14 @@ properties: required: - data-lanes +patternProperties: + "^phy@[0-9a-f]+$": + $ref: /schemas/phy/qcom,x1e80100-csi2-phy.yaml + unevaluatedProperties: false + + "^opp-table(-.*)?$": + type: object + required: - compatible - reg @@ -171,8 +197,6 @@ required: - iommus - power-domains - power-domain-names - - vdd-csiphy-0p8-supply - - vdd-csiphy-1p2-supply - ports additionalProperties: false @@ -184,6 +208,7 @@ examples: #include #include #include + #include #include soc { @@ -229,6 +254,10 @@ examples: "vfe_lite0", "vfe_lite1"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, <&camcc CAM_CC_CORE_AHB_CLK>, From e84bc87f25363edeb4f3a0ddabd3652f48440c7d Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:30 +0000 Subject: [PATCH 26/49] FROMLIST: dt-bindings: media: qcom,x1e80100-camss: Add support for combo-mode endpoints Qualcomm CSI2 PHYs support a mode where two sensors may be attached to the one CSIPHY. When we have one endpoint we may have - DPHY 1, 2 or 4 data lanes + 1 clock lane - CPHY 3 wire data lane When we have two endpoints this indicates the special fixed combo-mode. - DPHY endpoint0 => 2+1 and endpoint1 => 1+1 data-lane/clock-lane combination. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-2-5b93415be6dd@linaro.org/ Reviewed-by: Christopher Obbard Signed-off-by: Bryan O'Donoghue --- .../bindings/media/qcom,x1e80100-camss.yaml | 69 +++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml index c8bd0495f2fb4..9d010e0119dd7 100644 --- a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml @@ -148,7 +148,8 @@ properties: $ref: /schemas/graph.yaml#/properties/ports description: - CSI input ports. + CSI input ports. Supports either standard single sensor mode or + Qualcomm's combo mode with one sensor in 2x1 + 1x1 data-lane, clock-lane mode. patternProperties: "^port@[0-3]$": @@ -156,26 +157,86 @@ properties: unevaluatedProperties: false description: - Input port for receiving CSI data from a CSIPHY. + Input port for receiving CSI data. properties: - endpoint: + endpoint@0: $ref: video-interfaces.yaml# unevaluatedProperties: false + description: + Endpoint for receiving a single sensor input (or first leg of combo). + properties: data-lanes: minItems: 1 - maxItems: 4 + maxItems: 4 # Base max allows 4 (for D-PHY) + + clock-lanes: + maxItems: 1 bus-type: enum: - 1 # MEDIA_BUS_TYPE_CSI2_CPHY - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + endpoint@1: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + description: + Endpoint for receiving the second leg of a combo sensor input. + + properties: + data-lanes: + maxItems: 1 + + clock-lanes: + maxItems: 1 + + bus-type: + const: 4 # Combo is D-PHY specific + required: - data-lanes + allOf: + # Case 1: Combo Mode (endpoint@1 is present) + # If endpoint@1 exists, we restrict endpoint@0 to 2 lanes (D-PHY split) + - if: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 2 + maxItems: 2 + bus-type: + const: 4 + endpoint@1: + properties: + data-lanes: + minItems: 1 + maxItems: 1 + bus-type: + const: 4 + + # Case 2: Single Mode (endpoint@1 is missing) + # We explicitly allow up to 4 lanes here to cover the D-PHY use case. + - if: + not: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 1 + maxItems: 4 + patternProperties: "^phy@[0-9a-f]+$": $ref: /schemas/phy/qcom,x1e80100-csi2-phy.yaml From 3145c4b51bd41bd145c79b882a4f427d18e6f958 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:31 +0000 Subject: [PATCH 27/49] FROMLIST: dt-bindings: media: qcom,x1e80100-camss: Describe iommu entries The original iommus list included entries for ICP and BPS/IPE S1 contexts. Only the five S1 HLOS stream IDs are required by the CAMSS ISP hardware: IFE/IFE_LITE read and write, SFE read and write, and CDM IFE. The remaining entries serve other hardware blocks which will be described in their own nodes as support is added. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-3-5b93415be6dd@linaro.org/ Reviewed-by: Krzysztof Kozlowski Signed-off-by: Bryan O'Donoghue --- .../bindings/media/qcom,x1e80100-camss.yaml | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml index 9d010e0119dd7..94a9fac227dd8 100644 --- a/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml +++ b/Documentation/devicetree/bindings/media/qcom,x1e80100-camss.yaml @@ -112,7 +112,22 @@ properties: - const: sf_icp_mnoc iommus: - maxItems: 8 + oneOf: + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected + - description: Legacy slot 0 - do not use + - description: Legacy slot 1 - do not use + - description: Legacy slot 2 - do not use + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected power-domains: items: @@ -422,13 +437,10 @@ examples: "sf_icp_mnoc"; iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>, + <&apps_smmu 0x840 0x60>, <&apps_smmu 0x860 0x60>, - <&apps_smmu 0x1800 0x60>, - <&apps_smmu 0x1860 0x60>, - <&apps_smmu 0x18e0 0x00>, - <&apps_smmu 0x1980 0x20>, - <&apps_smmu 0x1900 0x00>, - <&apps_smmu 0x19a0 0x20>; + <&apps_smmu 0x18a0 0x0>; power-domains = <&camcc CAM_CC_IFE_0_GDSC>, <&camcc CAM_CC_IFE_1_GDSC>, From 0f712241b13804f0c9483bcae77f6e8cb54249ea Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:32 +0000 Subject: [PATCH 28/49] FROMLIST: media: qcom: camss: Add support to populate sub-devices Use devm_of_platform_populate() to populate subs in the tree. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-4-5b93415be6dd@linaro.org/ Signed-off-by: Bryan O'Donoghue Reviewed-by: Loic Poulain --- drivers/media/platform/qcom/camss/camss.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index c0f836146798a..0f77efb1b2203 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -4964,6 +4965,8 @@ static int camss_probe(struct platform_device *pdev) if (!camss) return -ENOMEM; + devm_of_platform_populate(dev); + camss->res = of_device_get_match_data(dev); atomic_set(&camss->ref_count, 0); From a4ac8577344fb572907dbdbe8c0ff3828c940500 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:33 +0000 Subject: [PATCH 29/49] FROMLIST: media: qcom: camss: Add legacy_phy flag to SoC definition structures Flag which SoCs have legacy - builtin PHY code. This will be useful in subsequent patches to inform PHY bringup logic if legacy bindings are available. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-5-5b93415be6dd@linaro.org/ Reviewed-by: Christopher Obbard Tested-by: Christopher Obbard Signed-off-by: Bryan O'Donoghue Reviewed-by: Loic Poulain --- drivers/media/platform/qcom/camss/camss.c | 17 +++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 18 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 0f77efb1b2203..1db213ea089ba 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5107,6 +5107,7 @@ static void camss_remove(struct platform_device *pdev) static const struct camss_resources msm8916_resources = { .version = CAMSS_8x16, + .legacy_phy = true, .csiphy_res = csiphy_res_8x16, .csid_res = csid_res_8x16, .ispif_res = &ispif_res_8x16, @@ -5118,6 +5119,7 @@ static const struct camss_resources msm8916_resources = { static const struct camss_resources msm8939_resources = { .version = CAMSS_8x39, + .legacy_phy = true, .csiphy_res = csiphy_res_8x39, .csid_res = csid_res_8x39, .ispif_res = &ispif_res_8x39, @@ -5129,6 +5131,7 @@ static const struct camss_resources msm8939_resources = { static const struct camss_resources msm8953_resources = { .version = CAMSS_8x53, + .legacy_phy = true, .icc_res = icc_res_8x53, .icc_path_num = ARRAY_SIZE(icc_res_8x53), .csiphy_res = csiphy_res_8x96, @@ -5142,6 +5145,7 @@ static const struct camss_resources msm8953_resources = { static const struct camss_resources msm8996_resources = { .version = CAMSS_8x96, + .legacy_phy = true, .csiphy_res = csiphy_res_8x96, .csid_res = csid_res_8x96, .ispif_res = &ispif_res_8x96, @@ -5153,6 +5157,7 @@ static const struct camss_resources msm8996_resources = { static const struct camss_resources qcm2290_resources = { .version = CAMSS_2290, + .legacy_phy = true, .csiphy_res = csiphy_res_2290, .csid_res = csid_res_2290, .vfe_res = vfe_res_2290, @@ -5166,6 +5171,7 @@ static const struct camss_resources qcm2290_resources = { static const struct camss_resources qcs8300_resources = { .version = CAMSS_8300, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8300, .csid_res = csid_res_8775p, .csid_wrapper_res = &csid_wrapper_res_sm8550, @@ -5180,6 +5186,7 @@ static const struct camss_resources qcs8300_resources = { static const struct camss_resources sa8775p_resources = { .version = CAMSS_8775P, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8775p, .csid_res = csid_res_8775p, .csid_wrapper_res = &csid_wrapper_res_sm8550, @@ -5193,6 +5200,7 @@ static const struct camss_resources sa8775p_resources = { static const struct camss_resources sdm660_resources = { .version = CAMSS_660, + .legacy_phy = true, .csiphy_res = csiphy_res_660, .csid_res = csid_res_660, .ispif_res = &ispif_res_660, @@ -5204,6 +5212,7 @@ static const struct camss_resources sdm660_resources = { static const struct camss_resources sdm670_resources = { .version = CAMSS_845, + .legacy_phy = true, .csiphy_res = csiphy_res_670, .csid_res = csid_res_670, .vfe_res = vfe_res_670, @@ -5215,6 +5224,7 @@ static const struct camss_resources sdm670_resources = { static const struct camss_resources sdm845_resources = { .version = CAMSS_845, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_845, .csid_res = csid_res_845, .vfe_res = vfe_res_845, @@ -5226,6 +5236,7 @@ static const struct camss_resources sdm845_resources = { static const struct camss_resources sm6150_resources = { .version = CAMSS_6150, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_sm6150, .csid_res = csid_res_sm6150, .vfe_res = vfe_res_sm6150, @@ -5239,6 +5250,7 @@ static const struct camss_resources sm6150_resources = { static const struct camss_resources sm8250_resources = { .version = CAMSS_8250, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8250, .csid_res = csid_res_8250, .vfe_res = vfe_res_8250, @@ -5252,6 +5264,7 @@ static const struct camss_resources sm8250_resources = { static const struct camss_resources sc8280xp_resources = { .version = CAMSS_8280XP, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_sc8280xp, .csid_res = csid_res_sc8280xp, .ispif_res = NULL, @@ -5266,6 +5279,7 @@ static const struct camss_resources sc8280xp_resources = { static const struct camss_resources sc7280_resources = { .version = CAMSS_7280, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_7280, .csid_res = csid_res_7280, .vfe_res = vfe_res_7280, @@ -5279,6 +5293,7 @@ static const struct camss_resources sc7280_resources = { static const struct camss_resources sm8550_resources = { .version = CAMSS_8550, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_8550, .csid_res = csid_res_8550, .vfe_res = vfe_res_8550, @@ -5293,6 +5308,7 @@ static const struct camss_resources sm8550_resources = { static const struct camss_resources sm8650_resources = { .version = CAMSS_8650, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_sm8650, .csid_res = csid_res_sm8650, .csid_wrapper_res = &csid_wrapper_res_sm8550, @@ -5307,6 +5323,7 @@ static const struct camss_resources sm8650_resources = { static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", + .legacy_phy = true, .csiphy_res = csiphy_res_x1e80100, .csid_res = csid_res_x1e80100, .vfe_res = vfe_res_x1e80100, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 6d048414c919e..24ec3ad7990e7 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -104,6 +104,7 @@ enum icc_count { struct camss_resources { enum camss_version version; const char *pd_name; + const bool legacy_phy; const struct camss_subdev_resources *csiphy_res; const struct camss_subdev_resources *csid_res; const struct camss_subdev_resources *ispif_res; From 76f6bf5445c319a73c724ac44262e0f0c5af014f Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:34 +0000 Subject: [PATCH 30/49] FROMLIST: media: qcom: camss: Add support for PHY API devices Add the ability to use a PHY pointer which interacts with the standard PHY API. In the first instance the code will try to use the new PHY interface. If no PHYs are present in the DT then the legacy method will be attempted. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-6-5b93415be6dd@linaro.org/ Reviewed-by: Christopher Obbard Tested-by: Christopher Obbard Signed-off-by: Bryan O'Donoghue --- drivers/media/platform/qcom/camss/Kconfig | 1 + .../media/platform/qcom/camss/camss-csiphy.c | 189 ++++++++++++++++-- .../media/platform/qcom/camss/camss-csiphy.h | 7 + drivers/media/platform/qcom/camss/camss.c | 72 +++++-- 4 files changed, 239 insertions(+), 30 deletions(-) diff --git a/drivers/media/platform/qcom/camss/Kconfig b/drivers/media/platform/qcom/camss/Kconfig index 4eda48cb1adf0..1edc5e5a1829e 100644 --- a/drivers/media/platform/qcom/camss/Kconfig +++ b/drivers/media/platform/qcom/camss/Kconfig @@ -7,3 +7,4 @@ config VIDEO_QCOM_CAMSS select VIDEO_V4L2_SUBDEV_API select VIDEOBUF2_DMA_SG select V4L2_FWNODE + select PHY_QCOM_MIPI_CSI2 diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c index 62623393f4144..478938165dd7b 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy.c @@ -7,12 +7,14 @@ * Copyright (c) 2011-2015, The Linux Foundation. All rights reserved. * Copyright (C) 2016-2018 Linaro Ltd. */ +#include #include #include #include #include #include #include +#include #include #include #include @@ -131,10 +133,10 @@ static u8 csiphy_get_bpp(const struct csiphy_format_info *formats, } /* - * csiphy_set_clock_rates - Calculate and set clock rates on CSIPHY module + * csiphy_set_clock_rates_legacy - Calculate and set clock rates on CSIPHY module * @csiphy: CSIPHY device */ -static int csiphy_set_clock_rates(struct csiphy_device *csiphy) +static int csiphy_set_clock_rates_legacy(struct csiphy_device *csiphy) { struct device *dev = csiphy->camss->dev; s64 link_freq; @@ -200,7 +202,7 @@ static int csiphy_set_clock_rates(struct csiphy_device *csiphy) * * Return 0 on success or a negative error code otherwise */ -static int csiphy_set_power(struct v4l2_subdev *sd, int on) +static int csiphy_set_power_legacy(struct v4l2_subdev *sd, int on) { struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); struct device *dev = csiphy->camss->dev; @@ -219,7 +221,7 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) return ret; } - ret = csiphy_set_clock_rates(csiphy); + ret = csiphy_set_clock_rates_legacy(csiphy); if (ret < 0) { regulator_bulk_disable(csiphy->num_supplies, csiphy->supplies); @@ -254,7 +256,7 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) } /* - * csiphy_stream_on - Enable streaming on CSIPHY module + * csiphy_stream_on_legacy - Enable streaming on CSIPHY module * @csiphy: CSIPHY device * * Helper function to enable streaming on CSIPHY module. @@ -262,7 +264,7 @@ static int csiphy_set_power(struct v4l2_subdev *sd, int on) * * Return 0 on success or a negative error code otherwise */ -static int csiphy_stream_on(struct csiphy_device *csiphy) +static int csiphy_stream_on_legacy(struct csiphy_device *csiphy) { struct csiphy_config *cfg = &csiphy->cfg; s64 link_freq; @@ -306,11 +308,99 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) * * Helper function to disable streaming on CSIPHY module */ -static void csiphy_stream_off(struct csiphy_device *csiphy) +static void csiphy_stream_off_legacy(struct csiphy_device *csiphy) { csiphy->res->hw_ops->lanes_disable(csiphy, &csiphy->cfg); } +/* + * csiphy_stream_on - Enable streaming on CSIPHY module + * @csiphy: CSIPHY device + * + * Helper function to enable streaming on CSIPHY module. + * Main configuration of CSIPHY module is also done here. + * + * Return 0 on success or a negative error code otherwise + */ +static int csiphy_stream_on(struct csiphy_device *csiphy) +{ + u8 bpp = csiphy_get_bpp(csiphy->res->formats->formats, csiphy->res->formats->nformats, + csiphy->fmt[MSM_CSIPHY_PAD_SINK].code); + struct csiphy_lanes_cfg *lncfg = &csiphy->cfg.csi2->lane_cfg; + struct phy_configure_opts_mipi_dphy *dphy_cfg; + union phy_configure_opts dphy_opts = { 0 }; + struct device *dev = csiphy->camss->dev; + u8 num_lanes = lncfg->num_data; + s64 link_freq; + int i; + int ret; + + dphy_cfg = &dphy_opts.mipi_dphy; + + link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes); + + if (link_freq < 0) { + dev_err(dev, + "Cannot get CSI2 transmitter's link frequency\n"); + return -EINVAL; + } + + phy_mipi_dphy_get_default_config_for_hsclk(link_freq, num_lanes, dphy_cfg); + + /* Set clock lane id and polarity */ + dphy_cfg->clock_lane_position = lncfg->clk.pos; + dphy_cfg->clock_lane_polarity = lncfg->clk.pol; + + /* Set data lane_mask and lane_polarities */ + for (i = 0; i < num_lanes; i++) { + dphy_cfg->lane_positions[i] = lncfg->data[i].pos; + dphy_cfg->lane_polarities[i] = lncfg->data[i].pol; + } + + phy_set_mode(csiphy->phy, PHY_MODE_MIPI_DPHY); + + ret = phy_configure(csiphy->phy, &dphy_opts); + if (ret) { + dev_err(dev, "failed to configure MIPI D-PHY\n"); + goto error; + } + + return phy_power_on(csiphy->phy); + +error: + return ret; +} + +/* + * csiphy_stream_off - Disable streaming on CSIPHY module + * @csiphy: CSIPHY device + * + * Helper function to disable streaming on CSIPHY module + */ +static void csiphy_stream_off(struct csiphy_device *csiphy) +{ + phy_power_off(csiphy->phy); +} + +/* + * csiphy_set_stream - Enable/disable streaming on CSIPHY module + * @sd: CSIPHY V4L2 subdevice + * @enable: Requested streaming state + * + * Return 0 on success or a negative error code otherwise + */ +static int csiphy_set_stream_legacy(struct v4l2_subdev *sd, int enable) +{ + struct csiphy_device *csiphy = v4l2_get_subdevdata(sd); + int ret = 0; + + if (enable) + ret = csiphy_stream_on_legacy(csiphy); + else + csiphy_stream_off_legacy(csiphy); + + return ret; +} /* * csiphy_set_stream - Enable/disable streaming on CSIPHY module @@ -568,16 +658,16 @@ static bool csiphy_match_clock_name(const char *clock_name, const char *format, } /* - * msm_csiphy_subdev_init - Initialize CSIPHY device structure and resources + * msm_csiphy_subdev_init_legacy - Initialize CSIPHY device structure and resources * @csiphy: CSIPHY device * @res: CSIPHY module resources table * @id: CSIPHY module id * * Return 0 on success or a negative error code otherwise */ -int msm_csiphy_subdev_init(struct camss *camss, - struct csiphy_device *csiphy, - const struct camss_subdev_resources *res, u8 id) +int msm_csiphy_subdev_init_legacy(struct camss *camss, + struct csiphy_device *csiphy, + const struct camss_subdev_resources *res, u8 id) { struct device *dev = camss->dev; struct platform_device *pdev = to_platform_device(dev); @@ -705,6 +795,60 @@ int msm_csiphy_subdev_init(struct camss *camss, return ret; } +/* + * msm_csiphy_subdev_init - Initialize CSIPHY device structure and resources + * @csiphy: CSIPHY device + * @res: CSIPHY module resources table + * @id: CSIPHY module id + * + * Return 0 on success or a negative error code otherwise + */ +int msm_csiphy_subdev_init(struct camss *camss, + struct csiphy_device *csiphy, + const struct camss_subdev_resources *res, u8 id) +{ + struct device *dev = camss->dev; + struct of_phandle_args args; + int idx; + int ret; + + snprintf(csiphy->name, ARRAY_SIZE(csiphy->name), "csiphy%d", id); + + idx = of_property_match_string(dev->of_node, "phy-names", csiphy->name); + if (idx < 0) { + dev_err(dev, "%s not found\n", csiphy->name); + return idx; + } + + ret = of_parse_phandle_with_args(dev->of_node, "phys", "#phy-cells", idx, &args); + if (ret < 0) { + dev_err(dev, "unable to parse phys args %s\n", csiphy->name); + return ret; + } + + if (!of_device_is_available(args.np)) + goto put_np; + + csiphy->phy = devm_phy_get(dev, csiphy->name); + if (IS_ERR(csiphy->phy)) { + ret = PTR_ERR(csiphy->phy); + goto put_np; + } + + csiphy->camss = camss; + csiphy->id = id; + csiphy->res = &res->csiphy; + + ret = phy_init(csiphy->phy); + if (ret) + dev_err(dev, "phy %s init fail %d\n", csiphy->name, ret); + +put_np: + of_node_put(args.np); + + return ret; +} + /* * csiphy_link_setup - Setup CSIPHY connections * @entity: Pointer to media entity structure @@ -739,8 +883,12 @@ static int csiphy_link_setup(struct media_entity *entity, return 0; } -static const struct v4l2_subdev_core_ops csiphy_core_ops = { - .s_power = csiphy_set_power, +static const struct v4l2_subdev_core_ops csiphy_core_ops_legacy = { + .s_power = csiphy_set_power_legacy, +}; + +static const struct v4l2_subdev_video_ops csiphy_video_ops_legacy = { + .s_stream = csiphy_set_stream_legacy, }; static const struct v4l2_subdev_video_ops csiphy_video_ops = { @@ -754,8 +902,13 @@ static const struct v4l2_subdev_pad_ops csiphy_pad_ops = { .set_fmt = csiphy_set_format, }; +static const struct v4l2_subdev_ops csiphy_v4l2_ops_legacy = { + .core = &csiphy_core_ops_legacy, + .video = &csiphy_video_ops_legacy, + .pad = &csiphy_pad_ops, +}; + static const struct v4l2_subdev_ops csiphy_v4l2_ops = { - .core = &csiphy_core_ops, .video = &csiphy_video_ops, .pad = &csiphy_pad_ops, }; @@ -784,7 +937,11 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, struct device *dev = csiphy->camss->dev; int ret; - v4l2_subdev_init(sd, &csiphy_v4l2_ops); + if (IS_ERR(csiphy->phy)) + v4l2_subdev_init(sd, &csiphy_v4l2_ops_legacy); + else + v4l2_subdev_init(sd, &csiphy_v4l2_ops); + sd->internal_ops = &csiphy_v4l2_internal_ops; sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d", @@ -823,6 +980,8 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, */ void msm_csiphy_unregister_entity(struct csiphy_device *csiphy) { + if (!IS_ERR(csiphy->phy)) + phy_exit(csiphy->phy); v4l2_device_unregister_subdev(&csiphy->subdev); media_entity_cleanup(&csiphy->subdev.entity); } diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h index 2d5054819df7f..25b803c06e8bf 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.h +++ b/drivers/media/platform/qcom/camss/camss-csiphy.h @@ -12,6 +12,7 @@ #include #include +#include #include #include #include @@ -95,6 +96,7 @@ struct csiphy_device_regs { struct csiphy_device { struct camss *camss; + struct phy *phy; u8 id; struct v4l2_subdev subdev; struct media_pad pads[MSM_CSIPHY_PADS_NUM]; @@ -102,6 +104,7 @@ struct csiphy_device { void __iomem *base_clk_mux; u32 irq; char irq_name[30]; + char name[16]; struct camss_clock *clock; bool *rate_set; int nclocks; @@ -116,6 +119,10 @@ struct csiphy_device { struct camss_subdev_resources; +int msm_csiphy_subdev_init_legacy(struct camss *camss, + struct csiphy_device *csiphy, + const struct camss_subdev_resources *res, u8 id); + int msm_csiphy_subdev_init(struct camss *camss, struct csiphy_device *csiphy, const struct camss_subdev_resources *res, u8 id); diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 1db213ea089ba..4ab67c3815529 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4451,14 +4451,35 @@ static int camss_parse_endpoint_node(struct device *dev, static int camss_parse_ports(struct camss *camss) { struct device *dev = camss->dev; + const struct camss_resources *res = camss->res; struct fwnode_handle *fwnode = dev_fwnode(dev), *ep; int ret; fwnode_graph_for_each_endpoint(fwnode, ep) { struct camss_async_subdev *csd; + struct fwnode_handle *remote; + + if (!fwnode_device_is_available(ep)) + continue; + + if (res->legacy_phy) { + csd = v4l2_async_nf_add_fwnode_remote(&camss->notifier, ep, + typeof(*csd)); + } else { + /* + * For non-legacy PHY, the CSIPHY is a separate device. + * Register the remote endpoint (CSIPHY's endpoint) as + * the async subdev, not the remote port parent. + */ + remote = fwnode_graph_get_remote_endpoint(ep); + if (!remote) + continue; + + csd = v4l2_async_nf_add_fwnode(&camss->notifier, remote, + struct camss_async_subdev); + fwnode_handle_put(remote); + } - csd = v4l2_async_nf_add_fwnode_remote(&camss->notifier, ep, - typeof(*csd)); if (IS_ERR(csd)) { ret = PTR_ERR(csd); goto err_cleanup; @@ -4490,15 +4511,26 @@ static int camss_init_subdevices(struct camss *camss) unsigned int i; int ret; - for (i = 0; i < camss->res->csiphy_num; i++) { - ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i], - &res->csiphy_res[i], - res->csiphy_res[i].csiphy.id); - if (ret < 0) { - dev_err(camss->dev, - "Failed to init csiphy%d sub-device: %d\n", - i, ret); - return ret; + if (!res->legacy_phy) { + for (i = 0; i < camss->res->csiphy_num; i++) { + ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i], + &res->csiphy_res[i], + res->csiphy_res[i].csiphy.id); + if (ret < 0) + return ret; + } + } else { + for (i = 0; i < camss->res->csiphy_num; i++) { + ret = msm_csiphy_subdev_init_legacy(camss, &camss->csiphy[i], + &res->csiphy_res[i], + res->csiphy_res[i].csiphy.id); + if (ret < 0) { + dev_err(camss->dev, + "Failed to init csiphy%d sub-device: %d\n", + i, ret); + return ret; + } + camss->csiphy[i].phy = ERR_PTR(-ENODEV); } } @@ -4575,6 +4607,9 @@ static int camss_link_entities(struct camss *camss) for (i = 0; i < camss->res->csiphy_num; i++) { for (j = 0; j < camss->res->csid_num; j++) { + if (!camss->csiphy[i].phy) + continue; + ret = media_create_pad_link(&camss->csiphy[i].subdev.entity, MSM_CSIPHY_PAD_SRC, &camss->csid[j].subdev.entity, @@ -4684,6 +4719,9 @@ static int camss_register_entities(struct camss *camss) int ret; for (i = 0; i < camss->res->csiphy_num; i++) { + if (!camss->csiphy[i].phy) + continue; + ret = msm_csiphy_register_entity(&camss->csiphy[i], &camss->v4l2_dev); if (ret < 0) { @@ -4739,8 +4777,10 @@ static int camss_register_entities(struct camss *camss) i = camss->res->csiphy_num; err_reg_csiphy: - for (i--; i >= 0; i--) - msm_csiphy_unregister_entity(&camss->csiphy[i]); + for (i--; i >= 0; i--) { + if (camss->csiphy[i].phy) + msm_csiphy_unregister_entity(&camss->csiphy[i]); + } return ret; } @@ -4755,8 +4795,10 @@ static void camss_unregister_entities(struct camss *camss) { unsigned int i; - for (i = 0; i < camss->res->csiphy_num; i++) - msm_csiphy_unregister_entity(&camss->csiphy[i]); + for (i = 0; i < camss->res->csiphy_num; i++) { + if (camss->csiphy[i].phy) + msm_csiphy_unregister_entity(&camss->csiphy[i]); + } for (i = 0; i < camss->res->csid_num; i++) msm_csid_unregister_entity(&camss->csid[i]); From c52576ef9cdfc9dbc0afca8760eba8ec0eb677bb Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:35 +0000 Subject: [PATCH 31/49] FROMLIST: media: qcom: camss: Drop legacy PHY descriptions from x1e x1e is the first CAMSS SoC to use the new PHY interface. Drop the redundant legacy CSIPHY descriptions. Link: https://lore.kernel.org/all/20260326-b4-linux-next-25-03-13-dtsi-x1e80100-camss-v11-7-5b93415be6dd@linaro.org/ Reviewed-by: Christopher Obbard Tested-by: Christopher Obbard Signed-off-by: Bryan O'Donoghue Reviewed-by: Loic Poulain --- drivers/media/platform/qcom/camss/camss.c | 37 ----------------------- 1 file changed, 37 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 4ab67c3815529..7a3b9947105ca 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -3896,15 +3896,6 @@ static const struct resources_icc icc_res_sa8775p[] = { static const struct camss_subdev_resources csiphy_res_x1e80100[] = { /* CSIPHY0 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy0", "csiphy0_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy0" }, - .interrupt = { "csiphy0" }, .csiphy = { .id = 0, .hw_ops = &csiphy_ops_3ph_1_0, @@ -3913,15 +3904,6 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY1 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy1", "csiphy1_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy1" }, - .interrupt = { "csiphy1" }, .csiphy = { .id = 1, .hw_ops = &csiphy_ops_3ph_1_0, @@ -3930,15 +3912,6 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY2 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy2", "csiphy2_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy2" }, - .interrupt = { "csiphy2" }, .csiphy = { .id = 2, .hw_ops = &csiphy_ops_3ph_1_0, @@ -3947,15 +3920,6 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, /* CSIPHY4 */ { - .regulators = { - { .supply = "vdd-csiphy-0p8", .init_load_uA = 105000 }, - { .supply = "vdd-csiphy-1p2", .init_load_uA = 58900 } - }, - .clock = { "csiphy4", "csiphy4_timer" }, - .clock_rate = { { 300000000, 400000000, 480000000 }, - { 266666667, 400000000 } }, - .reg = { "csiphy4" }, - .interrupt = { "csiphy4" }, .csiphy = { .id = 4, .hw_ops = &csiphy_ops_3ph_1_0, @@ -5365,7 +5329,6 @@ static const struct camss_resources sm8650_resources = { static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", - .legacy_phy = true, .csiphy_res = csiphy_res_x1e80100, .csid_res = csid_res_x1e80100, .vfe_res = vfe_res_x1e80100, From 7c16d191d6480a7a87ef49b071dc343707e6f3ef Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Tue, 17 Mar 2026 18:05:45 +0800 Subject: [PATCH 32/49] FROMLIST: media: qcom: camss: Add common TPG support Introduce a new common Test Pattern Generator (TPG) implementation for Qualcomm CAMSS. This module provides a generic interface for pattern generation that can be reused by multiple platforms. Unlike CSID-integrated TPG, this TPG acts as a standalone block that emulates both CSIPHY and sensor behavior, enabling flexible test patterns without external hardware. Link: https://lore.kernel.org/all/20260317-camss_tpg-v10-1-b4cfa85c2e1b@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Tested-by: Bryan O'Donoghue # Dell Inpsiron14p Signed-off-by: Wenmeng Liu --- drivers/media/platform/qcom/camss/Makefile | 11 +- drivers/media/platform/qcom/camss/camss-tpg.c | 519 ++++++++++++++++++ drivers/media/platform/qcom/camss/camss-tpg.h | 118 ++++ drivers/media/platform/qcom/camss/camss.h | 5 + 4 files changed, 648 insertions(+), 5 deletions(-) create mode 100644 drivers/media/platform/qcom/camss/camss-tpg.c create mode 100644 drivers/media/platform/qcom/camss/camss-tpg.h diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index 5e349b4915130..d747aa7db3c12 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -10,10 +10,13 @@ qcom-camss-objs += \ camss-csid-680.o \ camss-csid-gen2.o \ camss-csid-gen3.o \ + camss-csiphy.o \ camss-csiphy-2ph-1-0.o \ camss-csiphy-3ph-1-0.o \ - camss-csiphy.o \ + camss-format.o \ camss-ispif.o \ + camss-tpg.o \ + camss-vfe.o \ camss-vfe-4-1.o \ camss-vfe-4-7.o \ camss-vfe-4-8.o \ @@ -21,11 +24,9 @@ qcom-camss-objs += \ camss-vfe-340.o \ camss-vfe-480.o \ camss-vfe-680.o \ - camss-vfe-gen3.o \ camss-vfe-gen1.o \ + camss-vfe-gen3.o \ camss-vfe-vbif.o \ - camss-vfe.o \ - camss-video.o \ - camss-format.o \ + camss-video.o obj-$(CONFIG_VIDEO_QCOM_CAMSS) += qcom-camss.o diff --git a/drivers/media/platform/qcom/camss/camss-tpg.c b/drivers/media/platform/qcom/camss/camss-tpg.c new file mode 100644 index 0000000000000..c5b75132add44 --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-tpg.c @@ -0,0 +1,519 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * + * Qualcomm MSM Camera Subsystem - TPG Module + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "camss-tpg.h" +#include "camss.h" + +static const struct tpg_format_info formats_gen1[] = { + { + MEDIA_BUS_FMT_SBGGR8_1X8, + MIPI_CSI2_DT_RAW8, + ENCODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + }, + { + MEDIA_BUS_FMT_SGBRG8_1X8, + MIPI_CSI2_DT_RAW8, + ENCODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + }, + { + MEDIA_BUS_FMT_SGRBG8_1X8, + MIPI_CSI2_DT_RAW8, + ENCODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + }, + { + MEDIA_BUS_FMT_SRGGB8_1X8, + MIPI_CSI2_DT_RAW8, + ENCODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + }, + { + MEDIA_BUS_FMT_SBGGR10_1X10, + MIPI_CSI2_DT_RAW10, + ENCODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + }, + { + MEDIA_BUS_FMT_SGBRG10_1X10, + MIPI_CSI2_DT_RAW10, + ENCODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + }, + { + MEDIA_BUS_FMT_SGRBG10_1X10, + MIPI_CSI2_DT_RAW10, + ENCODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + }, + { + MEDIA_BUS_FMT_SRGGB10_1X10, + MIPI_CSI2_DT_RAW10, + ENCODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + }, + { + MEDIA_BUS_FMT_SBGGR12_1X12, + MIPI_CSI2_DT_RAW12, + ENCODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + }, + { + MEDIA_BUS_FMT_SGBRG12_1X12, + MIPI_CSI2_DT_RAW12, + ENCODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + }, + { + MEDIA_BUS_FMT_SGRBG12_1X12, + MIPI_CSI2_DT_RAW12, + ENCODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + }, + { + MEDIA_BUS_FMT_SRGGB12_1X12, + MIPI_CSI2_DT_RAW12, + ENCODE_FORMAT_UNCOMPRESSED_12_BIT, + 12, + }, + { + MEDIA_BUS_FMT_Y8_1X8, + MIPI_CSI2_DT_RAW8, + ENCODE_FORMAT_UNCOMPRESSED_8_BIT, + 8, + }, + { + MEDIA_BUS_FMT_Y10_1X10, + MIPI_CSI2_DT_RAW10, + ENCODE_FORMAT_UNCOMPRESSED_10_BIT, + 10, + }, +}; + +const struct tpg_formats tpg_formats_gen1 = { + .nformats = ARRAY_SIZE(formats_gen1), + .formats = formats_gen1 +}; + +const struct tpg_format_info *tpg_get_fmt_entry(const struct tpg_format_info *formats, + unsigned int nformats, + u32 code) +{ + unsigned int i; + + for (i = 0; i < nformats; i++) + if (code == formats[i].code) + return &formats[i]; + + return ERR_PTR(-EINVAL); +} + +static int tpg_set_clock_rates(struct tpg_device *tpg) +{ + struct device *dev = tpg->camss->dev; + int i, ret; + + for (i = 0; i < tpg->nclocks; i++) { + struct camss_clock *clock = &tpg->clock[i]; + long round_rate; + + if (clock->freq) { + round_rate = clk_round_rate(clock->clk, clock->freq[0]); + if (round_rate < 0) { + dev_err(dev, "clk round rate failed: %ld\n", + round_rate); + return -EINVAL; + } + + ret = clk_set_rate(clock->clk, round_rate); + if (ret < 0) { + dev_err(dev, "clk set rate failed: %d\n", ret); + return ret; + } + } + } + + return 0; +} + +static int tpg_set_power(struct v4l2_subdev *sd, int on) +{ + struct tpg_device *tpg = v4l2_get_subdevdata(sd); + struct device *dev = tpg->camss->dev; + + if (on) { + int ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return ret; + + ret = tpg_set_clock_rates(tpg); + if (ret < 0) { + pm_runtime_put_sync(dev); + return ret; + } + + ret = camss_enable_clocks(tpg->nclocks, tpg->clock, dev); + if (ret < 0) { + pm_runtime_put_sync(dev); + return ret; + } + + tpg->res->hw_ops->reset(tpg); + + tpg->res->hw_ops->hw_version(tpg); + } else { + camss_disable_clocks(tpg->nclocks, tpg->clock); + + pm_runtime_put_sync(dev); + } + + return 0; +} + +static int tpg_set_stream(struct v4l2_subdev *sd, int enable) +{ + struct tpg_device *tpg = v4l2_get_subdevdata(sd); + int ret; + + if (enable) { + ret = v4l2_ctrl_handler_setup(&tpg->ctrls); + if (ret < 0) { + dev_err(tpg->camss->dev, + "could not sync v4l2 controls: %d\n", ret); + return ret; + } + } + + return tpg->res->hw_ops->configure_stream(tpg, enable); +} + +static struct v4l2_mbus_framefmt * +__tpg_get_format(struct tpg_device *tpg, + struct v4l2_subdev_state *sd_state, + unsigned int pad, + enum v4l2_subdev_format_whence which) +{ + if (which == V4L2_SUBDEV_FORMAT_TRY) + return v4l2_subdev_state_get_format(sd_state, + pad); + + return &tpg->fmt; +} + +static void tpg_try_format(struct tpg_device *tpg, + struct v4l2_mbus_framefmt *fmt) +{ + unsigned int i; + + for (i = 0; i < tpg->res->formats->nformats; i++) + if (tpg->res->formats->formats[i].code == fmt->code) + break; + + if (i >= tpg->res->formats->nformats) + fmt->code = MEDIA_BUS_FMT_SBGGR8_1X8; + + fmt->width = clamp_t(u32, fmt->width, TPG_MIN_WIDTH, TPG_MAX_WIDTH); + fmt->height = clamp_t(u32, fmt->height, TPG_MIN_HEIGHT, TPG_MAX_HEIGHT); + fmt->field = V4L2_FIELD_NONE; + fmt->colorspace = V4L2_COLORSPACE_SRGB; +} + +static int tpg_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_mbus_code_enum *code) +{ + struct tpg_device *tpg = v4l2_get_subdevdata(sd); + + if (code->index >= tpg->res->formats->nformats) + return -EINVAL; + + code->code = tpg->res->formats->formats[code->index].code; + + return 0; +} + +static int tpg_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_frame_size_enum *fse) +{ + struct tpg_device *tpg = v4l2_get_subdevdata(sd); + unsigned int i; + + if (fse->index != 0) + return -EINVAL; + + for (i = 0; i < tpg->res->formats->nformats; i++) + if (tpg->res->formats->formats[i].code == fse->code) + break; + + if (i >= tpg->res->formats->nformats) + return -EINVAL; + + fse->min_width = TPG_MIN_WIDTH; + fse->min_height = TPG_MIN_HEIGHT; + fse->max_width = TPG_MAX_WIDTH; + fse->max_height = TPG_MAX_HEIGHT; + + return 0; +} + +static int tpg_get_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct tpg_device *tpg = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + format = __tpg_get_format(tpg, sd_state, fmt->pad, fmt->which); + if (!format) + return -EINVAL; + + fmt->format = *format; + + return 0; +} + +static int tpg_set_format(struct v4l2_subdev *sd, + struct v4l2_subdev_state *sd_state, + struct v4l2_subdev_format *fmt) +{ + struct tpg_device *tpg = v4l2_get_subdevdata(sd); + struct v4l2_mbus_framefmt *format; + + format = __tpg_get_format(tpg, sd_state, fmt->pad, fmt->which); + if (!format) + return -EINVAL; + + tpg_try_format(tpg, &fmt->format); + *format = fmt->format; + + return 0; +} + +static int tpg_init_formats(struct v4l2_subdev *sd, + struct v4l2_subdev_fh *fh) +{ + struct v4l2_subdev_format format = { + .pad = MSM_TPG_PAD_SRC, + .which = fh ? V4L2_SUBDEV_FORMAT_TRY : + V4L2_SUBDEV_FORMAT_ACTIVE, + .format = { + .code = MEDIA_BUS_FMT_SBGGR8_1X8, + .width = 1920, + .height = 1080, + } + }; + + return tpg_set_format(sd, fh ? fh->state : NULL, &format); +} + +static int tpg_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct tpg_device *tpg = container_of(ctrl->handler, + struct tpg_device, ctrls); + int ret = -EINVAL; + + switch (ctrl->id) { + case V4L2_CID_TEST_PATTERN: + ret = tpg->res->hw_ops->configure_testgen_pattern(tpg, ctrl->val); + break; + } + + return ret; +} + +static const struct v4l2_ctrl_ops tpg_ctrl_ops = { + .s_ctrl = tpg_s_ctrl, +}; + +int msm_tpg_subdev_init(struct camss *camss, + struct tpg_device *tpg, + const struct camss_subdev_resources *res, u8 id) +{ + struct platform_device *pdev; + struct device *dev; + int i, j; + + dev = camss->dev; + pdev = to_platform_device(dev); + + tpg->camss = camss; + tpg->id = id; + tpg->res = &res->tpg; + tpg->res->hw_ops->subdev_init(tpg); + + tpg->base = devm_platform_ioremap_resource_byname(pdev, res->reg[0]); + if (IS_ERR(tpg->base)) + return PTR_ERR(tpg->base); + + tpg->nclocks = 0; + while (res->clock[tpg->nclocks]) + tpg->nclocks++; + + if (!tpg->nclocks) + return 0; + + tpg->clock = devm_kcalloc(dev, tpg->nclocks, + sizeof(*tpg->clock), GFP_KERNEL); + if (!tpg->clock) + return -ENOMEM; + + for (i = 0; i < tpg->nclocks; i++) { + struct camss_clock *clock = &tpg->clock[i]; + + clock->clk = devm_clk_get(dev, res->clock[i]); + if (IS_ERR(clock->clk)) + return PTR_ERR(clock->clk); + + clock->name = res->clock[i]; + + clock->nfreqs = 0; + while (res->clock_rate[i][clock->nfreqs]) + clock->nfreqs++; + + if (!clock->nfreqs) { + clock->freq = NULL; + continue; + } + + clock->freq = devm_kcalloc(dev, clock->nfreqs, + sizeof(*clock->freq), GFP_KERNEL); + if (!clock->freq) + return -ENOMEM; + + for (j = 0; j < clock->nfreqs; j++) + clock->freq[j] = res->clock_rate[i][j]; + } + + return 0; +} + +static int tpg_link_setup(struct media_entity *entity, + const struct media_pad *local, + const struct media_pad *remote, u32 flags) +{ + if (flags & MEDIA_LNK_FL_ENABLED) + if (media_pad_remote_pad_first(local)) + return -EBUSY; + + return 0; +} + +static const struct v4l2_subdev_core_ops tpg_core_ops = { + .s_power = tpg_set_power, +}; + +static const struct v4l2_subdev_video_ops tpg_video_ops = { + .s_stream = tpg_set_stream, +}; + +static const struct v4l2_subdev_pad_ops tpg_pad_ops = { + .enum_mbus_code = tpg_enum_mbus_code, + .enum_frame_size = tpg_enum_frame_size, + .get_fmt = tpg_get_format, + .set_fmt = tpg_set_format, +}; + +static const struct v4l2_subdev_ops tpg_v4l2_ops = { + .core = &tpg_core_ops, + .video = &tpg_video_ops, + .pad = &tpg_pad_ops, +}; + +static const struct v4l2_subdev_internal_ops tpg_v4l2_internal_ops = { + .open = tpg_init_formats, +}; + +static const struct media_entity_operations tpg_media_ops = { + .link_setup = tpg_link_setup, + .link_validate = v4l2_subdev_link_validate, +}; + +int msm_tpg_register_entity(struct tpg_device *tpg, + struct v4l2_device *v4l2_dev) +{ + struct v4l2_subdev *sd = &tpg->subdev; + struct device *dev = tpg->camss->dev; + int ret; + + v4l2_subdev_init(sd, &tpg_v4l2_ops); + sd->internal_ops = &tpg_v4l2_internal_ops; + sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE | + V4L2_SUBDEV_FL_HAS_EVENTS; + snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d", + "msm_tpg", tpg->id); + sd->grp_id = TPG_GRP_ID; + v4l2_set_subdevdata(sd, tpg); + + ret = v4l2_ctrl_handler_init(&tpg->ctrls, 1); + if (ret < 0) { + dev_err(dev, "Failed to init ctrl handler: %d\n", ret); + return ret; + } + + tpg->testgen_mode = v4l2_ctrl_new_std_menu_items(&tpg->ctrls, + &tpg_ctrl_ops, V4L2_CID_TEST_PATTERN, + tpg->testgen.nmodes, 0, 0, + tpg->testgen.modes); + if (tpg->ctrls.error) { + dev_err(dev, "Failed to init ctrl: %d\n", tpg->ctrls.error); + ret = tpg->ctrls.error; + goto free_ctrl; + } + + tpg->subdev.ctrl_handler = &tpg->ctrls; + + ret = tpg_init_formats(sd, NULL); + if (ret < 0) { + dev_err(dev, "Failed to init format: %d\n", ret); + goto free_ctrl; + } + + tpg->pad.flags = MEDIA_PAD_FL_SOURCE; + + sd->entity.ops = &tpg_media_ops; + ret = media_entity_pads_init(&sd->entity, 1, &tpg->pad); + if (ret < 0) { + dev_err(dev, "Failed to init media entity: %d\n", ret); + goto free_ctrl; + } + + ret = v4l2_device_register_subdev(v4l2_dev, sd); + if (ret < 0) { + dev_err(dev, "Failed to register subdev: %d\n", ret); + media_entity_cleanup(&sd->entity); + goto free_ctrl; + } + + return 0; + +free_ctrl: + v4l2_ctrl_handler_free(&tpg->ctrls); + + return ret; +} + +void msm_tpg_unregister_entity(struct tpg_device *tpg) +{ + v4l2_device_unregister_subdev(&tpg->subdev); + media_entity_cleanup(&tpg->subdev.entity); + v4l2_ctrl_handler_free(&tpg->ctrls); +} diff --git a/drivers/media/platform/qcom/camss/camss-tpg.h b/drivers/media/platform/qcom/camss/camss-tpg.h new file mode 100644 index 0000000000000..7fb35a97dd068 --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-tpg.h @@ -0,0 +1,118 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * camss-tpg.h + * + * Qualcomm MSM Camera Subsystem - TPG Module + * + * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved. + */ +#ifndef QC_MSM_CAMSS_TPG_H +#define QC_MSM_CAMSS_TPG_H + +#include +#include +#include +#include +#include +#include +#include + +#define ENCODE_FORMAT_UNCOMPRESSED_8_BIT 0x1 +#define ENCODE_FORMAT_UNCOMPRESSED_10_BIT 0x2 +#define ENCODE_FORMAT_UNCOMPRESSED_12_BIT 0x3 +#define ENCODE_FORMAT_UNCOMPRESSED_14_BIT 0x4 +#define ENCODE_FORMAT_UNCOMPRESSED_16_BIT 0x5 +#define ENCODE_FORMAT_UNCOMPRESSED_20_BIT 0x6 +#define ENCODE_FORMAT_UNCOMPRESSED_24_BIT 0x7 + +#define MSM_TPG_PAD_SRC 0 +#define MSM_TPG_ACTIVE_VC 0 +#define MSM_TPG_ACTIVE_DT 0 + +#define TPG_MIN_WIDTH 1 +#define TPG_MIN_HEIGHT 1 +#define TPG_MAX_WIDTH 8191 +#define TPG_MAX_HEIGHT 8191 + +#define TPG_GRP_ID 0 + +enum tpg_testgen_mode { + TPG_PAYLOAD_MODE_DISABLED = 0, + TPG_PAYLOAD_MODE_INCREMENTING = 1, + TPG_PAYLOAD_MODE_ALTERNATING_55_AA = 2, + TPG_PAYLOAD_MODE_RANDOM = 5, + TPG_PAYLOAD_MODE_USER_SPECIFIED = 6, + TPG_PAYLOAD_MODE_COLOR_BARS = 9, + TPG_PAYLOAD_MODE_NUM_SUPPORTED_GEN1 = 9, +}; + +struct tpg_testgen_config { + enum tpg_testgen_mode mode; + const char * const*modes; + u8 nmodes; +}; + +struct tpg_format_info { + u32 code; + u8 data_type; + u8 encode_format; + u8 bpp; +}; + +struct tpg_formats { + unsigned int nformats; + const struct tpg_format_info *formats; +}; + +struct tpg_device; + +struct tpg_hw_ops { + int (*configure_stream)(struct tpg_device *tpg, u8 enable); + int (*configure_testgen_pattern)(struct tpg_device *tpg, s32 val); + u32 (*hw_version)(struct tpg_device *tpg); + int (*reset)(struct tpg_device *tpg); + void (*subdev_init)(struct tpg_device *tpg); +}; + +struct tpg_subdev_resources { + u8 lane_cnt; + const struct tpg_formats *formats; + const struct tpg_hw_ops *hw_ops; +}; + +struct tpg_device { + struct camss *camss; + u8 id; + struct v4l2_subdev subdev; + struct media_pad pad; + void __iomem *base; + struct camss_clock *clock; + int nclocks; + struct tpg_testgen_config testgen; + struct v4l2_mbus_framefmt fmt; + struct v4l2_ctrl_handler ctrls; + struct v4l2_ctrl *testgen_mode; + const struct tpg_subdev_resources *res; + u32 hw_version; +}; + +struct camss_subdev_resources; + +const struct tpg_format_info *tpg_get_fmt_entry(const struct tpg_format_info *formats, + unsigned int nformats, + u32 code); + +int msm_tpg_subdev_init(struct camss *camss, + struct tpg_device *tpg, + const struct camss_subdev_resources *res, u8 id); + +int msm_tpg_register_entity(struct tpg_device *tpg, + struct v4l2_device *v4l2_dev); + +void msm_tpg_unregister_entity(struct tpg_device *tpg); + +extern const struct tpg_formats tpg_formats_gen1; + +extern const struct tpg_hw_ops tpg_ops_gen1; + +#endif /* QC_MSM_CAMSS_TPG_H */ diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 24ec3ad7990e7..315d4ee87bf22 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -21,6 +21,7 @@ #include "camss-csid.h" #include "camss-csiphy.h" #include "camss-ispif.h" +#include "camss-tpg.h" #include "camss-vfe.h" #include "camss-format.h" @@ -52,6 +53,7 @@ struct camss_subdev_resources { char *interrupt[CAMSS_RES_MAX]; union { struct csiphy_subdev_resources csiphy; + struct tpg_subdev_resources tpg; struct csid_subdev_resources csid; struct vfe_subdev_resources vfe; }; @@ -106,6 +108,7 @@ struct camss_resources { const char *pd_name; const bool legacy_phy; const struct camss_subdev_resources *csiphy_res; + const struct camss_subdev_resources *tpg_res; const struct camss_subdev_resources *csid_res; const struct camss_subdev_resources *ispif_res; const struct camss_subdev_resources *vfe_res; @@ -113,6 +116,7 @@ struct camss_resources { const struct resources_icc *icc_res; const unsigned int icc_path_num; const unsigned int csiphy_num; + const unsigned int tpg_num; const unsigned int csid_num; const unsigned int vfe_num; }; @@ -123,6 +127,7 @@ struct camss { struct media_device media_dev; struct device *dev; struct csiphy_device *csiphy; + struct tpg_device *tpg; struct csid_device *csid; struct ispif_device *ispif; struct vfe_device *vfe; From 31060c0d39e0b2e49de6c1bf623d6020d09519d6 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Tue, 17 Mar 2026 18:05:46 +0800 Subject: [PATCH 33/49] FROMLIST: media: qcom: camss: Add link support for TPG TPG is connected to the csid as an entity, the link needs to be adapted. Link: https://lore.kernel.org/all/20260317-camss_tpg-v10-2-b4cfa85c2e1b@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Tested-by: Bryan O'Donoghue # Dell Inpsiron14p Signed-off-by: Wenmeng Liu --- .../media/platform/qcom/camss/camss-csid.c | 45 ++++++++++----- .../media/platform/qcom/camss/camss-csid.h | 1 + .../media/platform/qcom/camss/camss-csiphy.c | 1 + .../media/platform/qcom/camss/camss-csiphy.h | 2 + drivers/media/platform/qcom/camss/camss.c | 55 +++++++++++++++++++ 5 files changed, 90 insertions(+), 14 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c index ed1820488c987..48459b46a981b 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.c +++ b/drivers/media/platform/qcom/camss/camss-csid.c @@ -35,6 +35,8 @@ #define HW_VERSION_REVISION 16 #define HW_VERSION_GENERATION 28 +#define LANE_CFG_BITWIDTH 4 + #define MSM_CSID_NAME "msm_csid" const char * const csid_testgen_modes[] = { @@ -1215,18 +1217,22 @@ void msm_csid_get_csid_id(struct media_entity *entity, u8 *id) } /* - * csid_get_lane_assign - Calculate CSI2 lane assign configuration parameter - * @lane_cfg - CSI2 lane configuration + * csid_get_lane_assign - Calculate lane assign by csiphy/tpg lane num + * @lane_cfg: CSI2 lane configuration + * @num_lanes: lane num * * Return lane assign */ -static u32 csid_get_lane_assign(struct csiphy_lanes_cfg *lane_cfg) +static u32 csid_get_lane_assign(struct csiphy_lanes_cfg *lane_cfg, int num_lanes) { u32 lane_assign = 0; + int pos; int i; - for (i = 0; i < lane_cfg->num_data; i++) - lane_assign |= lane_cfg->data[i].pos << (i * 4); + for (i = 0; i < num_lanes; i++) { + pos = lane_cfg ? lane_cfg->data[i].pos : i; + lane_assign |= pos << (i * LANE_CFG_BITWIDTH); + } return lane_assign; } @@ -1251,6 +1257,7 @@ static int csid_link_setup(struct media_entity *entity, if ((local->flags & MEDIA_PAD_FL_SINK) && (flags & MEDIA_LNK_FL_ENABLED)) { struct v4l2_subdev *sd; + struct tpg_device *tpg; struct csid_device *csid; struct csiphy_device *csiphy; struct csiphy_lanes_cfg *lane_cfg; @@ -1265,18 +1272,28 @@ static int csid_link_setup(struct media_entity *entity, return -EBUSY; sd = media_entity_to_v4l2_subdev(remote->entity); - csiphy = v4l2_get_subdevdata(sd); + if (sd->grp_id == TPG_GRP_ID) { + tpg = v4l2_get_subdevdata(sd); - /* If a sensor is not linked to CSIPHY */ - /* do no allow a link from CSIPHY to CSID */ - if (!csiphy->cfg.csi2) - return -EPERM; + csid->phy.lane_cnt = tpg->res->lane_cnt; + csid->phy.csiphy_id = tpg->id; + csid->phy.lane_assign = csid_get_lane_assign(NULL, csid->phy.lane_cnt); + csid->tpg_linked = true; + } else { + csiphy = v4l2_get_subdevdata(sd); - csid->phy.csiphy_id = csiphy->id; + /* If a sensor is not linked to CSIPHY */ + /* do no allow a link from CSIPHY to CSID */ + if (!csiphy->cfg.csi2) + return -EPERM; - lane_cfg = &csiphy->cfg.csi2->lane_cfg; - csid->phy.lane_cnt = lane_cfg->num_data; - csid->phy.lane_assign = csid_get_lane_assign(lane_cfg); + csid->phy.csiphy_id = csiphy->id; + + lane_cfg = &csiphy->cfg.csi2->lane_cfg; + csid->phy.lane_cnt = lane_cfg->num_data; + csid->phy.lane_assign = csid_get_lane_assign(lane_cfg, lane_cfg->num_data); + csid->tpg_linked = false; + } } /* Decide which virtual channels to enable based on which source pads are enabled */ if (local->flags & MEDIA_PAD_FL_SOURCE) { diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index aedc96ed84b2f..5296b10f6bac8 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -161,6 +161,7 @@ struct csid_device { int num_supplies; struct completion reset_complete; struct csid_testgen_config testgen; + bool tpg_linked; struct csid_phy_config phy; struct v4l2_mbus_framefmt fmt[MSM_CSID_PADS_NUM]; struct v4l2_ctrl_handler ctrls; diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c index 478938165dd7b..b9f7d6573a0f0 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy.c @@ -946,6 +946,7 @@ int msm_csiphy_register_entity(struct csiphy_device *csiphy, sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; snprintf(sd->name, ARRAY_SIZE(sd->name), "%s%d", MSM_CSIPHY_NAME, csiphy->id); + sd->grp_id = CSIPHY_GRP_ID; v4l2_set_subdevdata(sd, csiphy); ret = csiphy_init_formats(sd, NULL); diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h index 25b803c06e8bf..1879826034aac 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.h +++ b/drivers/media/platform/qcom/camss/camss-csiphy.h @@ -22,6 +22,8 @@ #define MSM_CSIPHY_PAD_SRC 1 #define MSM_CSIPHY_PADS_NUM 2 +#define CSIPHY_GRP_ID 1 + struct csiphy_lane { u8 pos; u8 pol; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 7a3b9947105ca..ea04d48efe24f 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4498,6 +4498,19 @@ static int camss_init_subdevices(struct camss *camss) } } + if (camss->tpg) { + for (i = 0; i < camss->res->tpg_num; i++) { + ret = msm_tpg_subdev_init(camss, &camss->tpg[i], + &res->tpg_res[i], i); + if (ret < 0) { + dev_err(camss->dev, + "Failed to init tpg%d sub-device: %d\n", + i, ret); + return ret; + } + } + } + /* note: SM8250 requires VFE to be initialized before CSID */ for (i = 0; i < camss->res->vfe_num; i++) { ret = msm_vfe_subdev_init(camss, &camss->vfe[i], @@ -4589,6 +4602,23 @@ static int camss_link_entities(struct camss *camss) } } + for (i = 0; i < camss->res->tpg_num; i++) { + for (j = 0; j < camss->res->csid_num; j++) { + ret = media_create_pad_link(&camss->tpg[i].subdev.entity, + MSM_TPG_PAD_SRC, + &camss->csid[j].subdev.entity, + MSM_CSID_PAD_SINK, + 0); + if (ret < 0) { + camss_link_err(camss, + camss->tpg[i].subdev.entity.name, + camss->csid[j].subdev.entity.name, + ret); + return ret; + } + } + } + if (camss->ispif) { for (i = 0; i < camss->res->csid_num; i++) { for (j = 0; j < camss->ispif->line_num; j++) { @@ -4696,6 +4726,19 @@ static int camss_register_entities(struct camss *camss) } } + if (camss->tpg) { + for (i = 0; i < camss->res->tpg_num; i++) { + ret = msm_tpg_register_entity(&camss->tpg[i], + &camss->v4l2_dev); + if (ret < 0) { + dev_err(camss->dev, + "Failed to register tpg%d entity: %d\n", + i, ret); + goto err_reg_tpg; + } + } + } + for (i = 0; i < camss->res->csid_num; i++) { ret = msm_csid_register_entity(&camss->csid[i], &camss->v4l2_dev); @@ -4739,6 +4782,13 @@ static int camss_register_entities(struct camss *camss) for (i--; i >= 0; i--) msm_csid_unregister_entity(&camss->csid[i]); + i = camss->res->tpg_num; +err_reg_tpg: + if (camss->tpg) { + for (i--; i >= 0; i--) + msm_tpg_unregister_entity(&camss->tpg[i]); + } + i = camss->res->csiphy_num; err_reg_csiphy: for (i--; i >= 0; i--) { @@ -4764,6 +4814,11 @@ static void camss_unregister_entities(struct camss *camss) msm_csiphy_unregister_entity(&camss->csiphy[i]); } + if (camss->tpg) { + for (i = 0; i < camss->res->tpg_num; i++) + msm_tpg_unregister_entity(&camss->tpg[i]); + } + for (i = 0; i < camss->res->csid_num; i++) msm_csid_unregister_entity(&camss->csid[i]); From 6fe7081e6c68615c6e52e27d6eab7b7cd2ebd07a Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Tue, 17 Mar 2026 18:05:47 +0800 Subject: [PATCH 34/49] FROMLIST: media: qcom: camss: tpg: Add TPG support for multiple targets Add support for TPG found on LeMans, Monaco, Hamoa. Link: https://lore.kernel.org/all/20260317-camss_tpg-v10-3-b4cfa85c2e1b@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Tested-by: Bryan O'Donoghue # Dell Inpsiron14p Signed-off-by: Wenmeng Liu --- drivers/media/platform/qcom/camss/Makefile | 1 + .../platform/qcom/camss/camss-csid-680.c | 14 +- .../platform/qcom/camss/camss-csid-gen3.c | 14 +- .../platform/qcom/camss/camss-tpg-gen1.c | 231 ++++++++++++++++++ drivers/media/platform/qcom/camss/camss.c | 117 ++++++++- 5 files changed, 371 insertions(+), 6 deletions(-) create mode 100644 drivers/media/platform/qcom/camss/camss-tpg-gen1.c diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index d747aa7db3c12..27898b3cc7d3c 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -16,6 +16,7 @@ qcom-camss-objs += \ camss-format.o \ camss-ispif.o \ camss-tpg.o \ + camss-tpg-gen1.o \ camss-vfe.o \ camss-vfe-4-1.o \ camss-vfe-4-7.o \ diff --git a/drivers/media/platform/qcom/camss/camss-csid-680.c b/drivers/media/platform/qcom/camss/camss-csid-680.c index 3ad3a174bcfb8..2e4547455d229 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-680.c +++ b/drivers/media/platform/qcom/camss/camss-csid-680.c @@ -103,6 +103,8 @@ #define CSI2_RX_CFG0_PHY_NUM_SEL 20 #define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 #define CSI2_RX_CFG0_PHY_TYPE_SEL 24 +#define CSI2_RX_CFG0_TPG_MUX_EN BIT(27) +#define CSI2_RX_CFG0_TPG_MUX_SEL GENMASK(29, 28) #define CSID_CSI2_RX_CFG1 0x204 #define CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN BIT(0) @@ -185,10 +187,20 @@ static void __csid_configure_rx(struct csid_device *csid, struct csid_phy_config *phy, int vc) { u32 val; + struct camss *camss; + camss = csid->camss; val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; - val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) << CSI2_RX_CFG0_PHY_NUM_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); diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen3.c b/drivers/media/platform/qcom/camss/camss-csid-gen3.c index bd059243790ed..222765fe7914d 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-gen3.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.c @@ -66,6 +66,8 @@ #define CSI2_RX_CFG0_VC_MODE 3 #define CSI2_RX_CFG0_DL0_INPUT_SEL 4 #define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSI2_RX_CFG0_TPG_MUX_EN BIT(27) +#define CSI2_RX_CFG0_TPG_MUX_SEL GENMASK(29, 28) #define CSID_CSI2_RX_CFG1 0x204 #define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) @@ -109,10 +111,20 @@ static void __csid_configure_rx(struct csid_device *csid, struct csid_phy_config *phy, int vc) { int val; + struct camss *camss; + camss = csid->camss; val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; - val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX) << CSI2_RX_CFG0_PHY_NUM_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); diff --git a/drivers/media/platform/qcom/camss/camss-tpg-gen1.c b/drivers/media/platform/qcom/camss/camss-tpg-gen1.c new file mode 100644 index 0000000000000..d29de5f93c18e --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-tpg-gen1.c @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * + * Qualcomm MSM Camera Subsystem - TPG (Test Pattern Generator) Module + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include + +#include "camss-tpg.h" +#include "camss.h" + +/* TPG global registers */ +#define TPG_HW_VERSION 0x0 +# define HW_VERSION_STEPPING GENMASK(15, 0) +# define HW_VERSION_REVISION GENMASK(27, 16) +# define HW_VERSION_GENERATION GENMASK(31, 28) + +#define TPG_HW_VER(gen, rev, step) \ + (((u32)(gen) << 28) | ((u32)(rev) << 16) | (u32)(step)) + +#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_STATUS 0x4 + +#define TPG_CTRL 0x64 +# define TPG_CTRL_TEST_EN BIT(0) +# define TPG_CTRL_PHY_SEL BIT(3) +# define TPG_CTRL_NUM_ACTIVE_LANES GENMASK(5, 4) +# define TPG_CTRL_VC_DT_PATTERN_ID GENMASK(8, 6) +# define TPG_CTRL_OVERLAP_SHDR_EN BIT(10) +# define TPG_CTRL_NUM_ACTIVE_VC GENMASK(31, 30) + +#define TPG_CLEAR 0x1F4 + +/* TPG VC-based registers */ +#define TPG_VC_n_GAIN_CFG(n) (0x60 + (n) * 0x60) + +#define TPG_VC_n_CFG0(n) (0x68 + (n) * 0x60) +# define TPG_VC_n_CFG0_VC_NUM GENMASK(4, 0) +# define TPG_VC_n_CFG0_NUM_ACTIVE_DT GENMASK(9, 8) +# define TPG_VC_n_CFG0_NUM_BATCH GENMASK(15, 12) +# define TPG_VC_n_CFG0_NUM_FRAMES GENMASK(31, 16) + +#define TPG_VC_n_LSFR_SEED(n) (0x6C + (n) * 0x60) +#define TPG_VC_n_HBI_CFG(n) (0x70 + (n) * 0x60) +#define TPG_VC_n_VBI_CFG(n) (0x74 + (n) * 0x60) + +#define TPG_VC_n_COLOR_BARS_CFG(n) (0x78 + (n) * 0x60) +# define TPG_VC_n_COLOR_BARS_CFG_PIX_PATTERN GENMASK(2, 0) +# define TPG_VC_n_COLOR_BARS_CFG_QCFA_EN BIT(3) +# define TPG_VC_n_COLOR_BARS_CFG_SPLIT_EN BIT(4) +# define TPG_VC_n_COLOR_BARS_CFG_NOISE_EN BIT(5) +# define TPG_VC_n_COLOR_BARS_CFG_ROTATE_PERIOD GENMASK(13, 8) +# define TPG_VC_n_COLOR_BARS_CFG_XCFA_EN BIT(16) +# define TPG_VC_n_COLOR_BARS_CFG_SIZE_X GENMASK(26, 24) +# define TPG_VC_n_COLOR_BARS_CFG_SIZE_Y GENMASK(30, 28) + +/* TPG DT-based registers */ +#define TPG_VC_m_DT_n_CFG_0(m, n) (0x7C + (m) * 0x60 + (n) * 0xC) +# define TPG_VC_m_DT_n_CFG_0_FRAME_HEIGHT GENMASK(15, 0) +# define TPG_VC_m_DT_n_CFG_0_FRAME_WIDTH GENMASK(31, 16) + +#define TPG_VC_m_DT_n_CFG_1(m, n) (0x80 + (m) * 0x60 + (n) * 0xC) +# define TPG_VC_m_DT_n_CFG_1_DATA_TYPE GENMASK(5, 0) +# define TPG_VC_m_DT_n_CFG_1_ECC_XOR_MASK GENMASK(13, 8) +# define TPG_VC_m_DT_n_CFG_1_CRC_XOR_MASK GENMASK(31, 16) + +#define TPG_VC_m_DT_n_CFG_2(m, n) (0x84 + (m) * 0x60 + (n) * 0xC) +# define TPG_VC_m_DT_n_CFG_2_PAYLOAD_MODE GENMASK(3, 0) +/* v2.0.0: USER[19:4], ENC[23:20] */ +# define TPG_V2_0_0_VC_m_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD GENMASK(19, 4) +# define TPG_V2_0_0_VC_m_DT_n_CFG_2_ENCODE_FORMAT GENMASK(23, 20) +/* v2.1.0: USER[27:4], ENC[31:28] */ +# define TPG_V2_1_0_VC_m_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD GENMASK(27, 4) +# define TPG_V2_1_0_VC_m_DT_n_CFG_2_ENCODE_FORMAT GENMASK(31, 28) + +#define TPG_HBI_PCT_DEFAULT 545 /* 545% */ +#define TPG_VBI_PCT_DEFAULT 10 /* 10% */ +#define PERCENT_BASE 100 + +/* Default user-specified payload for TPG test generator. + * Keep consistent with CSID TPG default: 0xBE. + */ +#define TPG_USER_SPECIFIED_PAYLOAD_DEFAULT 0xBE +#define TPG_LFSR_SEED_DEFAULT 0x12345678 +#define TPG_COLOR_BARS_CFG_STANDARD \ + FIELD_PREP(TPG_VC_n_COLOR_BARS_CFG_ROTATE_PERIOD, 0xA) + +static const char * const testgen_payload_modes[] = { + [TPG_PAYLOAD_MODE_DISABLED] = "Disabled", + [TPG_PAYLOAD_MODE_INCREMENTING] = "Incrementing", + [TPG_PAYLOAD_MODE_ALTERNATING_55_AA] = "Alternating 0x55/0xAA", + [TPG_PAYLOAD_MODE_RANDOM] = "Pseudo-random Data", + [TPG_PAYLOAD_MODE_USER_SPECIFIED] = "User Specified", + [TPG_PAYLOAD_MODE_COLOR_BARS] = "Color bars", +}; + +static int tpg_stream_on(struct tpg_device *tpg) +{ + struct tpg_testgen_config *tg = &tpg->testgen; + struct v4l2_mbus_framefmt *input_format; + const struct tpg_format_info *format; + u8 payload_mode = (tg->mode > TPG_PAYLOAD_MODE_DISABLED) ? + tg->mode - 1 : 0; + u8 lane_cnt = tpg->res->lane_cnt; + u8 vc, dt, last_vc = 0; + u32 val; + + for (vc = 0; vc <= MSM_TPG_ACTIVE_VC; vc++) { + last_vc = vc; + + input_format = &tpg->fmt; + format = tpg_get_fmt_entry(tpg->res->formats->formats, + tpg->res->formats->nformats, + input_format->code); + if (IS_ERR(format)) + return -EINVAL; + + /* VC configuration */ + val = FIELD_PREP(TPG_VC_n_CFG0_NUM_ACTIVE_DT, MSM_TPG_ACTIVE_DT) | + FIELD_PREP(TPG_VC_n_CFG0_NUM_FRAMES, 0); + writel(val, tpg->base + TPG_VC_n_CFG0(vc)); + + writel(TPG_LFSR_SEED_DEFAULT, tpg->base + TPG_VC_n_LSFR_SEED(vc)); + + val = DIV_ROUND_UP(input_format->width * format->bpp * TPG_HBI_PCT_DEFAULT, + BITS_PER_BYTE * lane_cnt * PERCENT_BASE); + writel(val, tpg->base + TPG_VC_n_HBI_CFG(vc)); + + val = input_format->height * TPG_VBI_PCT_DEFAULT / PERCENT_BASE; + writel(val, tpg->base + TPG_VC_n_VBI_CFG(vc)); + + writel(TPG_COLOR_BARS_CFG_STANDARD, tpg->base + TPG_VC_n_COLOR_BARS_CFG(vc)); + + /* DT configuration */ + for (dt = 0; dt <= MSM_TPG_ACTIVE_DT; dt++) { + val = FIELD_PREP(TPG_VC_m_DT_n_CFG_0_FRAME_HEIGHT, + input_format->height & 0xffff) | + FIELD_PREP(TPG_VC_m_DT_n_CFG_0_FRAME_WIDTH, + input_format->width & 0xffff); + writel(val, tpg->base + TPG_VC_m_DT_n_CFG_0(vc, dt)); + + val = FIELD_PREP(TPG_VC_m_DT_n_CFG_1_DATA_TYPE, format->data_type); + writel(val, tpg->base + TPG_VC_m_DT_n_CFG_1(vc, dt)); + + if (tpg->hw_version == TPG_HW_VER_2_0_0) { + val = FIELD_PREP(TPG_VC_m_DT_n_CFG_2_PAYLOAD_MODE, payload_mode) | + FIELD_PREP(TPG_V2_0_0_VC_m_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD, + TPG_USER_SPECIFIED_PAYLOAD_DEFAULT) | + FIELD_PREP(TPG_V2_0_0_VC_m_DT_n_CFG_2_ENCODE_FORMAT, + format->encode_format); + } else if (tpg->hw_version >= TPG_HW_VER_2_1_0) { + val = FIELD_PREP(TPG_VC_m_DT_n_CFG_2_PAYLOAD_MODE, payload_mode) | + FIELD_PREP(TPG_V2_1_0_VC_m_DT_n_CFG_2_USER_SPECIFIED_PAYLOAD, + TPG_USER_SPECIFIED_PAYLOAD_DEFAULT) | + FIELD_PREP(TPG_V2_1_0_VC_m_DT_n_CFG_2_ENCODE_FORMAT, + format->encode_format); + } + writel(val, tpg->base + TPG_VC_m_DT_n_CFG_2(vc, dt)); + } + } + + /* Global TPG control */ + val = FIELD_PREP(TPG_CTRL_TEST_EN, 1) | + FIELD_PREP(TPG_CTRL_NUM_ACTIVE_LANES, lane_cnt - 1) | + FIELD_PREP(TPG_CTRL_NUM_ACTIVE_VC, last_vc); + writel(val, tpg->base + TPG_CTRL); + + return 0; +} + +static int tpg_reset(struct tpg_device *tpg) +{ + writel(0, tpg->base + TPG_CTRL); + writel(1, tpg->base + TPG_CLEAR); + + return 0; +} + +static void tpg_stream_off(struct tpg_device *tpg) +{ + tpg_reset(tpg); +} + +static int tpg_configure_stream(struct tpg_device *tpg, u8 enable) +{ + if (enable) + return tpg_stream_on(tpg); + + tpg_stream_off(tpg); + + return 0; +} + +static int tpg_configure_testgen_pattern(struct tpg_device *tpg, s32 val) +{ + if (val >= 0 && val <= TPG_PAYLOAD_MODE_COLOR_BARS) + tpg->testgen.mode = val; + + return 0; +} + +static u32 tpg_hw_version(struct tpg_device *tpg) +{ + u32 hw_version = readl(tpg->base + TPG_HW_VERSION); + + tpg->hw_version = hw_version; + dev_dbg(tpg->camss->dev, "tpg HW Version = %u.%u.%u\n", + (u32)FIELD_GET(HW_VERSION_GENERATION, hw_version), + (u32)FIELD_GET(HW_VERSION_REVISION, hw_version), + (u32)FIELD_GET(HW_VERSION_STEPPING, hw_version)); + + return hw_version; +} + +static void tpg_subdev_init(struct tpg_device *tpg) +{ + tpg->testgen.modes = testgen_payload_modes; + tpg->testgen.nmodes = TPG_PAYLOAD_MODE_NUM_SUPPORTED_GEN1; +} + +const struct tpg_hw_ops tpg_ops_gen1 = { + .configure_stream = tpg_configure_stream, + .configure_testgen_pattern = tpg_configure_testgen_pattern, + .hw_version = tpg_hw_version, + .reset = tpg_reset, + .subdev_init = tpg_subdev_init, +}; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index ea04d48efe24f..bbd56b1b8b1c2 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -3560,6 +3560,54 @@ static const struct camss_subdev_resources csiphy_res_8775p[] = { }, }; +static const struct camss_subdev_resources tpg_res_8775p[] = { + /* TPG0 */ + { + .regulators = {}, + .clock = { "cpas_ahb", "csiphy_rx" }, + .clock_rate = { + { 0 }, + { 400000000 }, + }, + .reg = { "tpg0" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, + /* TPG1 */ + { + .regulators = {}, + .clock = { "cpas_ahb", "csiphy_rx" }, + .clock_rate = { + { 0 }, + { 400000000 }, + }, + .reg = { "tpg1" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, + /* TPG2 */ + { + .regulators = {}, + .clock = { "cpas_ahb", "csiphy_rx" }, + .clock_rate = { + { 0 }, + { 400000000 }, + }, + .reg = { "tpg2" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, +}; + static const struct camss_subdev_resources csid_res_8775p[] = { /* CSID0 */ { @@ -3928,6 +3976,54 @@ static const struct camss_subdev_resources csiphy_res_x1e80100[] = { }, }; +static const struct camss_subdev_resources tpg_res_x1e80100[] = { + /* TPG0 */ + { + .regulators = {}, + .clock = { "cpas_ahb", "csid_csiphy_rx" }, + .clock_rate = { + { 0 }, + { 400000000 }, + }, + .reg = { "csitpg0" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, + /* TPG1 */ + { + .regulators = {}, + .clock = { "cpas_ahb", "csid_csiphy_rx" }, + .clock_rate = { + { 0 }, + { 400000000 }, + }, + .reg = { "csitpg1" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, + /* TPG2 */ + { + .regulators = {}, + .clock = { "cpas_ahb", "csid_csiphy_rx" }, + .clock_rate = { + { 0 }, + { 400000000 }, + }, + .reg = { "csitpg2" }, + .tpg = { + .lane_cnt = 4, + .formats = &tpg_formats_gen1, + .hw_ops = &tpg_ops_gen1 + } + }, +}; + static const struct camss_subdev_resources csid_res_x1e80100[] = { /* CSID0 */ { @@ -4041,7 +4137,7 @@ static const struct camss_subdev_resources vfe_res_x1e80100[] = { .clock = {"camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", "cpas_fast_ahb", "cpas_vfe0", "vfe0_fast_ahb", "vfe0" }, - .clock_rate = { { 0 }, + .clock_rate = { { 400000000 }, { 0 }, { 0 }, { 0 }, @@ -4065,7 +4161,7 @@ static const struct camss_subdev_resources vfe_res_x1e80100[] = { .clock = { "camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", "cpas_fast_ahb", "cpas_vfe1", "vfe1_fast_ahb", "vfe1" }, - .clock_rate = { { 0 }, + .clock_rate = { { 400000000 }, { 0 }, { 0 }, { 0 }, @@ -4089,7 +4185,7 @@ static const struct camss_subdev_resources vfe_res_x1e80100[] = { .clock = { "camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", "vfe_lite_ahb", "cpas_vfe_lite", "vfe_lite", "vfe_lite_csid" }, - .clock_rate = { { 0 }, + .clock_rate = { { 400000000 }, { 0 }, { 0 }, { 0 }, @@ -4112,7 +4208,7 @@ static const struct camss_subdev_resources vfe_res_x1e80100[] = { .clock = { "camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", "vfe_lite_ahb", "cpas_vfe_lite", "vfe_lite", "vfe_lite_csid" }, - .clock_rate = { { 0 }, + .clock_rate = { { 400000000 }, { 0 }, { 0 }, { 0 }, @@ -5039,6 +5135,13 @@ static int camss_probe(struct platform_device *pdev) if (!camss->csiphy) return -ENOMEM; + if (camss->res->tpg_num > 0) { + camss->tpg = devm_kcalloc(dev, camss->res->tpg_num, + sizeof(*camss->tpg), GFP_KERNEL); + if (!camss->tpg) + return -ENOMEM; + } + camss->csid = devm_kcalloc(dev, camss->res->csid_num, sizeof(*camss->csid), GFP_KERNEL); if (!camss->csid) @@ -5234,11 +5337,13 @@ static const struct camss_resources qcs8300_resources = { .pd_name = "top", .legacy_phy = true, .csiphy_res = csiphy_res_8300, + .tpg_res = tpg_res_8775p, .csid_res = csid_res_8775p, .csid_wrapper_res = &csid_wrapper_res_sm8550, .vfe_res = vfe_res_8775p, .icc_res = icc_res_qcs8300, .csiphy_num = ARRAY_SIZE(csiphy_res_8300), + .tpg_num = ARRAY_SIZE(tpg_res_8775p), .csid_num = ARRAY_SIZE(csid_res_8775p), .vfe_num = ARRAY_SIZE(vfe_res_8775p), .icc_path_num = ARRAY_SIZE(icc_res_qcs8300), @@ -5249,11 +5354,13 @@ static const struct camss_resources sa8775p_resources = { .pd_name = "top", .legacy_phy = true, .csiphy_res = csiphy_res_8775p, + .tpg_res = tpg_res_8775p, .csid_res = csid_res_8775p, .csid_wrapper_res = &csid_wrapper_res_sm8550, .vfe_res = vfe_res_8775p, .icc_res = icc_res_sa8775p, .csiphy_num = ARRAY_SIZE(csiphy_res_8775p), + .tpg_num = ARRAY_SIZE(tpg_res_8775p), .csid_num = ARRAY_SIZE(csid_res_8775p), .vfe_num = ARRAY_SIZE(vfe_res_8775p), .icc_path_num = ARRAY_SIZE(icc_res_sa8775p), @@ -5385,12 +5492,14 @@ static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", .csiphy_res = csiphy_res_x1e80100, + .tpg_res = tpg_res_x1e80100, .csid_res = csid_res_x1e80100, .vfe_res = vfe_res_x1e80100, .csid_wrapper_res = &csid_wrapper_res_x1e80100, .icc_res = icc_res_x1e80100, .icc_path_num = ARRAY_SIZE(icc_res_x1e80100), .csiphy_num = ARRAY_SIZE(csiphy_res_x1e80100), + .tpg_num = ARRAY_SIZE(tpg_res_x1e80100), .csid_num = ARRAY_SIZE(csid_res_x1e80100), .vfe_num = ARRAY_SIZE(vfe_res_x1e80100), }; From 536013958d4159244d3c0ba48e67fbb7c0edb9bd Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:31 +0800 Subject: [PATCH 35/49] FROMLIST: dt-bindings: media: Add bindings for qcom,x1p42100-camss Add bindings for the Camera Subsystem for X1P42100. The X1P42100 platform provides: - 2 x CSIPHY - 3 x TPG - 3 x CSID - 2 x CSID Lite - 1 x IFE - 2 x IFE Lite Link: https://lore.kernel.org/all/20260410-purwa_camss-v1-1-eedcf6d9d8ee@oss.qualcomm.com/ Signed-off-by: Wenmeng Liu --- .../bindings/media/qcom,x1p42100-camss.yaml | 424 ++++++++++++++++++ 1 file changed, 424 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml b/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml new file mode 100644 index 0000000000000..8bfa7e616c3b6 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml @@ -0,0 +1,424 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,x1p42100-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm X1P42100 Camera Subsystem (CAMSS) + +maintainers: + - Wenmeng Liu + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,x1p42100-camss + + reg: + maxItems: 14 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csid_wrapper + - const: csiphy0 + - const: csiphy4 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe_lite0 + - const: vfe_lite1 + + '#address-cells': + const: 2 + + '#size-cells': + const: 2 + + ranges: true + + clocks: + maxItems: 22 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: core_ahb + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe_lite + - const: cphy_rx_clk_src + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy4 + - const: csiphy4_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + + interrupts: + maxItems: 10 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy4 + - const: vfe0 + - const: vfe_lite0 + - const: vfe_lite1 + + interconnects: + maxItems: 4 + + interconnect-names: + items: + - const: ahb + - const: hf_mnoc + - const: sf_mnoc + - const: sf_icp_mnoc + + iommus: + oneOf: + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected + - description: Legacy slot 0 - do not use + - description: Legacy slot 1 - do not use + - description: Legacy slot 2 - do not use + - items: + - description: S1 HLOS IFE and IFE_LITE non-protected read + - description: S1 HLOS IFE and IFE_LITE non-protected write + - description: S1 HLOS SFE non-protected read + - description: S1 HLOS SFE non-protected write + - description: S1 HLOS CDM IFE non-protected + + power-domains: + items: + - description: IFE0 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: top + + vdd-csiphy-0p8-supply: + description: + 0.8V supply to a PHY. + + vdd-csiphy-1p2-supply: + description: + 1.2V supply to a PHY. + + phys: + maxItems: 2 + + phy-names: + items: + - const: csiphy0 + - const: csiphy4 + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. Supports either standard single sensor mode or + Qualcomm's combo mode with one sensor in 2x1 + 1x1 data-lane, clock-lane mode. + + patternProperties: + "^port@[0-3]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + + description: + Input port for receiving CSI data. + + properties: + endpoint@0: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + description: + Endpoint for receiving a single sensor input (or first leg of combo). + + properties: + data-lanes: + minItems: 1 + maxItems: 4 # Base max allows 4 (for D-PHY) + + clock-lanes: + maxItems: 1 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + endpoint@1: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + description: + Endpoint for receiving the second leg of a combo sensor input. + + properties: + data-lanes: + maxItems: 1 + + clock-lanes: + maxItems: 1 + + bus-type: + const: 4 # Combo is D-PHY specific + + required: + - data-lanes + + allOf: + # Case 1: Combo Mode (endpoint@1 is present) + # If endpoint@1 exists, we restrict endpoint@0 to 2 lanes (D-PHY split) + - if: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 2 + maxItems: 2 + bus-type: + const: 4 + endpoint@1: + properties: + data-lanes: + minItems: 1 + maxItems: 1 + bus-type: + const: 4 + + # Case 2: Single Mode (endpoint@1 is missing) + # We explicitly allow up to 4 lanes here to cover the D-PHY use case. + - if: + not: + required: + - endpoint@1 + then: + properties: + endpoint@0: + properties: + data-lanes: + minItems: 1 + maxItems: 4 + +patternProperties: + "^phy@[0-9a-f]+$": + $ref: /schemas/phy/qcom,x1e80100-csi2-phy.yaml + unevaluatedProperties: false + + "^opp-table(-.*)?$": + type: object + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + - ports + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + camss: isp@acb7000 { + compatible = "qcom,x1p42100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0ace4000 0 0x1000>, + <0 0x0acec000 0 0x4000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0x4000>, + <0 0x0acc7000 0 0x2000>, + <0 0x0accb000 0 0x2000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csiphy0", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_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>; + + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe_lite", + "cphy_rx_clk_src", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy4", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc 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>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>, + <&apps_smmu 0x840 0x60>, + <&apps_smmu 0x860 0x60>, + <&apps_smmu 0x18a0 0x0>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + + power-domain-names = "ife0", + "top"; + + vdd-csiphy-0p8-supply = <&csiphy_0p8_supply>; + vdd-csiphy-1p2-supply = <&csiphy_1p2_supply>; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + csiphy_ep0: endpoint { + data-lanes = <0 1>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; From 1deb55fe2efb4ad1c3698e35a261a7da4f96c268 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:32 +0800 Subject: [PATCH 36/49] FROMLIST: media: qcom: camss: add support for X1P42100 camss The Purwa camera subsystem is a cut-down variant of the Hamoa CAMSS. Compared to Hamoa, Purwa provides only two CSIPHY instances and does not include the VFE1. Link: https://lore.kernel.org/all/20260410-purwa_camss-v1-2-eedcf6d9d8ee@oss.qualcomm.com/ Signed-off-by: Wenmeng Liu --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 2 + drivers/media/platform/qcom/camss/camss-vfe.c | 2 + drivers/media/platform/qcom/camss/camss.c | 109 ++++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 4 files changed, 114 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c index 4154832745525..d37f71de0f42c 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c @@ -1020,6 +1020,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_8650: case CAMSS_8775P: case CAMSS_X1E80100: + case CAMSS_X1P42100: ret = true; break; } @@ -1115,6 +1116,7 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_array_size = ARRAY_SIZE(lane_regs_sc8280xp); break; case CAMSS_X1E80100: + case CAMSS_X1P42100: regs->lane_regs = &lane_regs_x1e80100[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_x1e80100); regs->offset = 0x1000; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 5baf0e3d4bc46..b48dfad5a8a73 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_8650: case CAMSS_8775P: case CAMSS_X1E80100: + case CAMSS_X1P42100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: { @@ -2012,6 +2013,7 @@ static int vfe_bpl_align(struct vfe_device *vfe) case CAMSS_8650: case CAMSS_8775P: case CAMSS_X1E80100: + case CAMSS_X1P42100: ret = 16; break; default: diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index bbd56b1b8b1c2..cab82648134c5 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4254,6 +4254,98 @@ static const struct resources_wrapper csid_wrapper_res_x1e80100 = { .reg = "csid_wrapper", }; +static const struct camss_subdev_resources csiphy_res_x1p42100[] = { + /* CSIPHY0 */ + { + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, + /* CSIPHY4 */ + { + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + }, + }, +}; + +static const struct camss_subdev_resources vfe_res_x1p42100[] = { + /* IFE0 */ + { + .regulators = {}, + .clock = {"camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", + "cpas_fast_ahb", "cpas_vfe0", "vfe0_fast_ahb", + "vfe0" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 345600000, 432000000, 594000000, 675000000, + 727000000 }, }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 4, + .pd_name = "ife0", + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* IFE_LITE_0 */ + { + .regulators = {}, + .clock = { "camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", + "vfe_lite_ahb", "cpas_vfe_lite", "vfe_lite", + "vfe_lite_csid" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 266666667, 400000000, 480000000 }, }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, + /* IFE_LITE_1 */ + { + .regulators = {}, + .clock = { "camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb", + "vfe_lite_ahb", "cpas_vfe_lite", "vfe_lite", + "vfe_lite_csid" }, + .clock_rate = { { 400000000 }, + { 0 }, + { 0 }, + { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 266666667, 400000000, 480000000 }, }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .is_lite = true, + .line_num = 4, + .hw_ops = &vfe_ops_680, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + }, + }, +}; + /* * camss_add_clock_margin - Add margin to clock frequency rate * @rate: Clock frequency rate @@ -5504,6 +5596,22 @@ static const struct camss_resources x1e80100_resources = { .vfe_num = ARRAY_SIZE(vfe_res_x1e80100), }; +static const struct camss_resources x1p42100_resources = { + .version = CAMSS_X1P42100, + .pd_name = "top", + .csiphy_res = csiphy_res_x1p42100, + .tpg_res = tpg_res_x1e80100, + .csid_res = csid_res_x1e80100, + .vfe_res = vfe_res_x1p42100, + .csid_wrapper_res = &csid_wrapper_res_x1e80100, + .icc_res = icc_res_x1e80100, + .icc_path_num = ARRAY_SIZE(icc_res_x1e80100), + .csiphy_num = ARRAY_SIZE(csiphy_res_x1p42100), + .tpg_num = ARRAY_SIZE(tpg_res_x1e80100), + .csid_num = ARRAY_SIZE(csid_res_x1e80100), + .vfe_num = ARRAY_SIZE(vfe_res_x1p42100), +}; + static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, { .compatible = "qcom,msm8939-camss", .data = &msm8939_resources }, @@ -5522,6 +5630,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sm8550-camss", .data = &sm8550_resources }, { .compatible = "qcom,sm8650-camss", .data = &sm8650_resources }, { .compatible = "qcom,x1e80100-camss", .data = &x1e80100_resources }, + { .compatible = "qcom,x1p42100-camss", .data = &x1p42100_resources }, { } }; diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 315d4ee87bf22..541b5c8bf1926 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_8650, CAMSS_8775P, CAMSS_X1E80100, + CAMSS_X1P42100, }; enum icc_count { From b8036cf23909aeb3115c2accc50d0b631f2c0d67 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 28 Jan 2026 00:56:37 +0530 Subject: [PATCH 37/49] FROMLIST: arm64: dts: qcom: x1e80100: Add CAMCC block definition Add the CAMCC block for x1e80100. The x1e80100 CAMCC block is an iteration of previous CAMCC blocks with the exception of having two required power-domains not just one. Reviewed-by: Vladimir Zapolskiy Reviewed-by: Konrad Dybcio Signed-off-by: Bryan O'Donoghue Signed-off-by: Jagadeesh Kona Reviewed-by: Abel Vesa Link: https://lore.kernel.org/r/20260128-purwa-videocc-camcc-v1-6-b23de57df5ba@oss.qualcomm.com --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 81897f11a1fcd..b49870319521f 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -5543,6 +5544,22 @@ #power-domain-cells = <1>; }; + camcc: clock-controller@ade0000 { + compatible = "qcom,x1e80100-camcc"; + reg = <0 0x0ade0000 0 0x20000>; + clocks = <&gcc GCC_CAMERA_AHB_CLK>, + <&bi_tcxo_div2>, + <&bi_tcxo_ao_div2>, + <&sleep_clk>; + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + #clock-cells = <1>; + #reset-cells = <1>; + #power-domain-cells = <1>; + }; + mdss: display-subsystem@ae00000 { compatible = "qcom,x1e80100-mdss"; reg = <0 0x0ae00000 0 0x1000>; From 90fc8870f7f5bfeae18201885ff28da6b370e9a9 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:39 +0000 Subject: [PATCH 38/49] FROMLIST: arm64: dts: qcom: x1e80100: Add CCI definitions Add in two CCI buses. One bus has two CCI bus master pinouts: cci_i2c_sda0 = gpio101 cci_i2c_scl0 = gpio102 cci_i2c_sda1 = gpio103 cci_i2c_scl1 = gpio104 The second bus has two CCI bus master pinouts: cci_i2c_sda2 = gpio105 cci_i2c_scl2 = gpio106 aon_cci_i2c_sda3 = gpio235 aon_cci_i2c_scl3 = gpio236 Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-2-1d5a9306116a@linaro.org/ Reviewed-by: Konrad Dybcio Reviewed-by: Vladimir Zapolskiy Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 150 ++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index b49870319521f..80db3cf6b7528 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -5544,6 +5544,84 @@ #power-domain-cells = <1>; }; + cci0: cci@ac15000 { + compatible = "qcom,x1e80100-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac15000 0 0x1000>; + + interrupts = ; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_0_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + pinctrl-0 = <&cci0_default>; + pinctrl-1 = <&cci0_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci0_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci0_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + cci1: cci@ac16000 { + compatible = "qcom,x1e80100-cci", "qcom,msm8996-cci"; + reg = <0 0x0ac16000 0 0x1000>; + + interrupts = ; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CCI_1_CLK>; + clock-names = "camnoc_axi", + "cpas_ahb", + "cci"; + + power-domains = <&camcc CAM_CC_TITAN_TOP_GDSC>; + + pinctrl-0 = <&cci1_default>; + pinctrl-1 = <&cci1_sleep>; + pinctrl-names = "default", "sleep"; + + #address-cells = <1>; + #size-cells = <0>; + + status = "disabled"; + + cci1_i2c0: i2c-bus@0 { + reg = <0>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + + cci1_i2c1: i2c-bus@1 { + reg = <1>; + clock-frequency = <1000000>; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + camcc: clock-controller@ade0000 { compatible = "qcom,x1e80100-camcc"; reg = <0 0x0ade0000 0 0x20000>; @@ -6192,6 +6270,78 @@ gpio-ranges = <&tlmm 0 0 239>; wakeup-parent = <&pdc>; + cci0_default: cci0-default-state { + cci0_i2c0_default: cci0-i2c0-default-pins { + /* cci_i2c_sda0, cci_i2c_scl0 */ + pins = "gpio101", "gpio102"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + + cci0_i2c1_default: cci0-i2c1-default-pins { + /* cci_i2c_sda1, cci_i2c_scl1 */ + pins = "gpio103", "gpio104"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci0_sleep: cci0-sleep-state { + cci0_i2c0_sleep: cci0-i2c0-sleep-pins { + /* cci_i2c_sda0, cci_i2c_scl0 */ + pins = "gpio101", "gpio102"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + + cci0_i2c1_sleep: cci0-i2c1-sleep-pins { + /* cci_i2c_sda1, cci_i2c_scl1 */ + pins = "gpio103", "gpio104"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + cci1_default: cci1-default-state { + cci1_i2c0_default: cci1-i2c0-default-pins { + /* cci_i2c_sda2, cci_i2c_scl2 */ + pins = "gpio105", "gpio106"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-up; + }; + + cci1_i2c1_default: cci1-i2c1-default-pins { + /* aon_cci_i2c_sda3, aon_cci_i2c_scl3 */ + pins = "gpio235", "gpio236"; + function = "aon_cci"; + drive-strength = <2>; + bias-pull-up; + }; + }; + + cci1_sleep: cci1-sleep-state { + cci1_i2c0_sleep: cci1-i2c0-sleep-pins { + /* cci_i2c_sda2, cci_i2c_scl2 */ + pins = "gpio105", "gpio106"; + function = "cci_i2c"; + drive-strength = <2>; + bias-pull-down; + }; + + cci1_i2c1_sleep: cci1-i2c1-sleep-pins { + /* aon_cci_i2c_sda3, aon_cci_i2c_scl3 */ + pins = "gpio235", "gpio236"; + function = "aon_cci"; + drive-strength = <2>; + bias-pull-down; + }; + }; + edp0_hpd_default: edp0-hpd-default-state { pins = "gpio119"; function = "edp0_hot"; From 734747fec73f5827e518601fe435cecb4037ed20 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:40 +0000 Subject: [PATCH 39/49] FROMLIST: arm64: dts: qcom: x1e80100: Add CAMSS block definition Add dtsi to describe the xe180100 CAMSS block 4 x CSIPHY 3 x TPG 2 x CSID 2 x CSID Lite 2 x IFE 2 x IFE Lite Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-3-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/hamoa.dtsi | 347 ++++++++++++++++++++++++++++ 1 file changed, 347 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/hamoa.dtsi b/arch/arm64/boot/dts/qcom/hamoa.dtsi index 80db3cf6b7528..2ac0d3a614a66 100644 --- a/arch/arm64/boot/dts/qcom/hamoa.dtsi +++ b/arch/arm64/boot/dts/qcom/hamoa.dtsi @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -5622,6 +5623,352 @@ }; }; + camss: isp@acb7000 { + compatible = "qcom,x1e80100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0ace4000 0 0x1000>, + <0 0x0ace6000 0 0x1000>, + <0 0x0ace8000 0 0x1000>, + <0 0x0acec000 0 0x4000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0xf000>, + <0 0x0ac71000 0 0xf000>, + <0 0x0acc7000 0 0x2000>, + <0 0x0accb000 0 0x2000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_1_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_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_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_1_CLK>, + <&camcc CAM_CC_IFE_1_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>; + + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe_lite", + "cphy_rx_clk_src", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy4", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&gem_noc 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>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x820 0x60>, + <&apps_smmu 0x840 0x60>, + <&apps_smmu 0x860 0x60>, + <&apps_smmu 0x18a0 0x0>; + + #address-cells = <2>; + #size-cells = <2>; + ranges; + + phys = <&csiphy0 PHY_QCOM_CSI2_MODE_DPHY>, + <&csiphy1 PHY_QCOM_CSI2_MODE_DPHY>, + <&csiphy2 PHY_QCOM_CSI2_MODE_DPHY>, + <&csiphy4 PHY_QCOM_CSI2_MODE_DPHY>; + phy-names = "csiphy0", + "csiphy1", + "csiphy2", + "csiphy4"; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_IFE_1_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "top"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy0_inep0: endpoint@0 { + reg = <0>; + }; + }; + + port@1 { + reg = <1>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy1_inep0: endpoint@0 { + reg = <0>; + }; + }; + + port@2 { + reg = <2>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy2_inep0: endpoint@0 { + reg = <0>; + }; + }; + + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy4_inep0: endpoint@0 { + reg = <0>; + }; + }; + }; + + csiphy0: phy@ace4000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace4000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy1: phy@ace6000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace6000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY1_CLK>, + <&camcc CAM_CC_CSI1PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy2: phy@ace8000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0ace8000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY2_CLK>, + <&camcc CAM_CC_CSI2PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxc_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MXC>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy4: phy@acec000 { + compatible = "qcom,x1e80100-csi2-phy"; + reg = <0 0x0acec000 0 0x2000>; + + clocks = <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>; + clock-names = "core", + "timer"; + + operating-points-v2 = <&csiphy_mxa_opp_table>; + + interrupts = ; + + power-domains = <&rpmhpd RPMHPD_MX>, + <&rpmhpd RPMHPD_MMCX>; + power-domain-names = "mx", + "mmcx"; + + #phy-cells = <1>; + + status = "disabled"; + }; + + csiphy_mxc_opp_table: opp-table-mxc { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + + csiphy_mxa_opp_table: opp-table-mxa { + compatible = "operating-points-v2"; + + opp-300000000 { + opp-hz = /bits/ 64 <300000000>; + required-opps = <&rpmhpd_opp_low_svs_d1>, + <&rpmhpd_opp_low_svs_d1>; + }; + + opp-400000000 { + opp-hz = /bits/ 64 <400000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + + opp-480000000 { + opp-hz = /bits/ 64 <480000000>; + required-opps = <&rpmhpd_opp_low_svs>, + <&rpmhpd_opp_low_svs>; + }; + }; + }; + camcc: clock-controller@ade0000 { compatible = "qcom,x1e80100-camcc"; reg = <0 0x0ade0000 0 0x20000>; From 317aeb48fd0bcbd65b9e4286b17636c99c9b826a Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:41 +0000 Subject: [PATCH 40/49] FROMLIST: arm64: dts: qcom: x1e80100-crd: Add pm8010 CRD pmic,id=m regulators Add pmic,id = m rpmh to regulator definitions. This regulator set provides vreg_l3m_1p8 the regulator for the ov08x40 RGB sensor on the CRD. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-4-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1-crd.dtsi b/arch/arm64/boot/dts/qcom/x1-crd.dtsi index 5e324f35547a4..9ed3e6530062e 100644 --- a/arch/arm64/boot/dts/qcom/x1-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-crd.dtsi @@ -858,6 +858,36 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1808000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p9: ldo7 { + regulator-name = "vreg_l7m_2p9"; + regulator-min-microvolt = <2912000>; + regulator-max-microvolt = <2912000>; + regulator-initial-mode = ; + }; + }; }; &gpu { From 2045b9605d26f5cbc73d8e3ded5308d1cda14a00 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:42 +0000 Subject: [PATCH 41/49] FROMLIST: arm64: dts: qcom: x1e80100-crd: Add ov08x40 RGB sensor on CSIPHY4 Define ov08x40 on cci1_i2c1. The RGB sensor appears on the AON CCI pins connected to CSIPHY4 in four lane mode. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-5-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/x1-crd.dtsi | 76 ++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1-crd.dtsi b/arch/arm64/boot/dts/qcom/x1-crd.dtsi index 9ed3e6530062e..3751b21d09612 100644 --- a/arch/arm64/boot/dts/qcom/x1-crd.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-crd.dtsi @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -894,6 +895,65 @@ status = "okay"; }; +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1 2 3>; + remote-endpoint = <&ov08x40_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov08x40"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&cam_rgb_default>; + pinctrl-names = "default"; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7b_2p8>; + dovdd-supply = <&vreg_l3m_1p8>; + + port { + ov08x40_ep: endpoint { + data-lanes = <1 2 3 4>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + &i2c0 { clock-frequency = <400000>; @@ -1508,6 +1568,22 @@ <44 4>, /* SPI (TPM) */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; From 1d8dd82638ee88767653e644d3708c160ba38b6c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:43 +0000 Subject: [PATCH 42/49] FROMLIST: arm64: dts: qcom: x1e80100-t14s: Add pm8010 camera PMIC with voltage levels for IR and RGB camera Add the PM8010 PMIC providing the following voltage rails: vreg_l1m_r @ 1v2 IR sensor vreg_l2m_r @ 1v2 RGB sensor vreg_l3m_r @ 1v8 IR sensor vreg_l4m_r @ 1v8 RGB sensor vreg_l5m_r @ 2v8 IR sensor vreg_l7m_r @ 2v8 RGB sensor Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-6-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../qcom/x1e78100-lenovo-thinkpad-t14s.dtsi | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi index 261e59de654d3..81fd524e863af 100644 --- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi @@ -475,6 +475,13 @@ regulator-initial-mode = ; }; + vreg_l7b_2p8: ldo7 { + regulator-name = "vreg_l7b_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-initial-mode = ; + }; + vreg_l8b_3p0: ldo8 { regulator-name = "vreg_l8b_3p0"; regulator-min-microvolt = <3072000>; @@ -718,6 +725,58 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p2: ldo1 { + regulator-name = "vreg_l1m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p2: ldo2 { + regulator-name = "vreg_l2m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l5m_2p8: ldo5 { + regulator-name = "vreg_l5m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p8: ldo7 { + regulator-name = "vreg_l7m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + }; + }; &gpu { From 8aaaaa37239c35680748011467b1fe9d523e0d9a Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:44 +0000 Subject: [PATCH 43/49] FROMLIST: arm64: dts: qcom: x1e80100-t14s: Add on ov02c10 RGB sensor on CSIPHY4 Switch on the ov02c10 RGB sensor on CSIPHY4. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-7-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../qcom/x1e78100-lenovo-thinkpad-t14s.dtsi | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi index 81fd524e863af..24e3fbcfbb7bf 100644 --- a/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi +++ b/arch/arm64/boot/dts/qcom/x1e78100-lenovo-thinkpad-t14s.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -779,6 +780,66 @@ }; +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1>; + remote-endpoint = <&ov02c10_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov02c10"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7m_2p8>; + dvdd-supply = <&vreg_l2m_1p2>; + dovdd-supply = <&vreg_l4m_1p8>; + + port { + ov02c10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + &gpu { status = "okay"; @@ -1352,6 +1413,22 @@ <72 2>, /* Secure EC I2C connection (?) */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + ec_int_n_default: ec-int-n-state { pins = "gpio66"; function = "gpio"; From ba8582e76ab71f4b8d519939f018cdad01e1e76f Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:45 +0000 Subject: [PATCH 44/49] FROMLIST: arm64: dts: qcom: x1e80100-lenovo-yoga-slim7x: Add pm8010 camera PMIC with voltage levels for IR and RGB camera Add voltage regulators-8 for Camera on slim7x including: - vreg_l1m_1p2 - vreg_l3m_1p8 Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-8-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../dts/qcom/x1e80100-lenovo-yoga-slim7x.dts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index 4bacc33360aa5..c36457f1cb6d4 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -795,6 +795,57 @@ regulator-initial-mode = ; }; }; + + regulators-8 { + compatible = "qcom,pm8010-rpmh-regulators"; + qcom,pmic-id = "m"; + + vdd-l1-l2-supply = <&vreg_s5j_1p2>; + vdd-l3-l4-supply = <&vreg_s4c_1p8>; + vdd-l7-supply = <&vreg_bob1>; + + vreg_l1m_1p2: ldo1 { + regulator-name = "vreg_l1m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l2m_1p2: ldo2 { + regulator-name = "vreg_l2m_1p2"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1260000>; + regulator-initial-mode = ; + }; + + vreg_l3m_1p8: ldo3 { + regulator-name = "vreg_l3m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l4m_1p8: ldo4 { + regulator-name = "vreg_l4m_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1900000>; + regulator-initial-mode = ; + }; + + vreg_l5m_2p8: ldo5 { + regulator-name = "vreg_l5m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + + vreg_l7m_2p8: ldo7 { + regulator-name = "vreg_l7m_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <3072000>; + regulator-initial-mode = ; + }; + }; }; &gpu { From fe06f5708ffac43e59abba78a0ccd642198172b0 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:46 +0000 Subject: [PATCH 45/49] FROMLIST: arm64: dts: qcom: x1e80100-lenovo-yoga-slim7x: Add l7b_2p8 voltage regulator for RGB camera Some sleuthing work by Aleksandrs Vinarskis in the bowels of the ACPI tables for this part shows we need l7b_2p8 for the avdd supply. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-9-1d5a9306116a@linaro.org/ Suggested-by: Aleksandrs Vinarskis Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index c36457f1cb6d4..d23a80f2e03a1 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -552,6 +552,13 @@ regulator-initial-mode = ; }; + vreg_l7b_2p8: ldo7 { + regulator-name = "vreg_l7b_2p8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + regulator-initial-mode = ; + }; + vreg_l8b_3p0: ldo8 { regulator-name = "vreg_l8b_3p0"; regulator-min-microvolt = <3072000>; From d6c31a511f444719ba7be2daa8f3be06baa36bf7 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:47 +0000 Subject: [PATCH 46/49] FROMLIST: arm64: dts: qcom: x1e80100-lenovo-yoga-slim7x: Add ov02c10 RGB sensor on CSIPHY4 Add in the RGB sensor on CSIPHY4. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-10-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- .../dts/qcom/x1e80100-lenovo-yoga-slim7x.dts | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts index d23a80f2e03a1..45d99709dd34f 100644 --- a/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts +++ b/arch/arm64/boot/dts/qcom/x1e80100-lenovo-yoga-slim7x.dts @@ -7,6 +7,7 @@ #include #include +#include #include #include "hamoa.dtsi" @@ -863,6 +864,66 @@ }; }; +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1>; + remote-endpoint = <&ov02c10_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@36 { + compatible = "ovti,ov02c10"; + reg = <0x36>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7b_2p8>; + dvdd-supply = <&vreg_l1m_1p2>; + dovdd-supply = <&vreg_l3m_1p8>; + + port { + ov02c10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <400000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + &i2c0 { clock-frequency = <400000>; @@ -1410,6 +1471,22 @@ <44 4>, /* SPI (TPM) */ <238 1>; /* UFS Reset */ + cam_rgb_default: cam-rgb-default-state { + mclk-pins { + pins = "gpio100"; + function = "cam_aon"; + drive-strength = <16>; + bias-disable; + }; + + reset-n-pins { + pins = "gpio237"; + function = "gpio"; + drive-strength = <2>; + bias-disable; + }; + }; + edp_reg_en: edp-reg-en-state { pins = "gpio70"; function = "gpio"; From 93731c92aed1ca8af07a8e147b65ae0e37ce933c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 10:27:48 +0000 Subject: [PATCH 47/49] FROMLIST: arm64: dts: qcom: x1e80100-dell-inspiron14-7441: Switch on CAMSS RGB sensor Inspiron14 has a ov02e10 sensor on CSIPHY4. Enable the list of dependencies now. Link: https://lore.kernel.org/all/20260326-x1e-camss-csi2-phy-dtsi-v3-11-1d5a9306116a@linaro.org/ Signed-off-by: Bryan O'Donoghue --- arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi | 61 +++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi index bf04a12b16bc9..e31f69fa43854 100644 --- a/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi +++ b/arch/arm64/boot/dts/qcom/x1-dell-thena.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include #include #include "hamoa-pmics.dtsi" @@ -792,6 +793,66 @@ }; }; +&camss { + status = "okay"; + + ports { + /* + * port0 => csiphy0 + * port1 => csiphy1 + * port2 => csiphy2 + * port3 => csiphy4 + */ + port@3 { + camss_csiphy4_inep0: endpoint@0 { + clock-lanes = <7>; + data-lanes = <0 1>; + remote-endpoint = <&ov02e10_ep>; + }; + }; + }; +}; + +&cci1 { + status = "okay"; +}; + +&cci1_i2c1 { + camera@10 { + compatible = "ovti,ov02e10"; + reg = <0x10>; + + reset-gpios = <&tlmm 237 GPIO_ACTIVE_LOW>; + pinctrl-names = "default"; + pinctrl-0 = <&cam_rgb_default>; + + clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clocks = <&camcc CAM_CC_MCLK4_CLK>; + assigned-clock-rates = <19200000>; + + orientation = <0>; /* front facing */ + + avdd-supply = <&vreg_l7b_2p8>; + dvdd-supply = <&vreg_l7b_2p8>; + dovdd-supply = <&vreg_cam_1p8>; + + port { + ov02e10_ep: endpoint { + data-lanes = <1 2>; + link-frequencies = /bits/ 64 <360000000>; + remote-endpoint = <&camss_csiphy4_inep0>; + }; + }; + }; +}; + +&csiphy4 { + vdda-0p9-supply = <&vreg_l2c_0p8>; + vdda-1p2-supply = <&vreg_l1c_1p2>; + + status = "okay"; +}; + &i2c0 { clock-frequency = <400000>; From 1189d38a5034f05cdf5c7926fc3f9fc33c78f1c4 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:33 +0800 Subject: [PATCH 48/49] FROMLIST: arm64: dts: qcom: purwa: Add camss node Add node for the X1P42100 camera subsystem. Link: https://lore.kernel.org/all/20260410-purwa_camss-v1-3-eedcf6d9d8ee@oss.qualcomm.com/ Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/purwa.dtsi | 158 ++++++++++++++++++++++++++++ 1 file changed, 158 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa.dtsi b/arch/arm64/boot/dts/qcom/purwa.dtsi index 05e736a0f0935..7efefccf5547f 100644 --- a/arch/arm64/boot/dts/qcom/purwa.dtsi +++ b/arch/arm64/boot/dts/qcom/purwa.dtsi @@ -19,6 +19,8 @@ /delete-node/ &cpu_pd9; /delete-node/ &cpu_pd10; /delete-node/ &cpu_pd11; +/delete-node/ &csiphy1; +/delete-node/ &csiphy2; /delete-node/ &gpu_opp_table; /delete-node/ &gpu_speed_bin; /delete-node/ &pcie3_phy; @@ -36,6 +38,162 @@ /delete-node/ &cluster2_rep_2_3; /delete-node/ &apss_funnel_in2; +&camss { + compatible = "qcom,x1p42100-camss"; + + reg = <0 0x0acb7000 0 0x2000>, + <0 0x0acb9000 0 0x2000>, + <0 0x0acbb000 0 0x2000>, + <0 0x0acc6000 0 0x1000>, + <0 0x0acca000 0 0x1000>, + <0 0x0acb6000 0 0x1000>, + <0 0x0ace4000 0 0x1000>, + <0 0x0acec000 0 0x4000>, + <0 0x0acf6000 0 0x1000>, + <0 0x0acf7000 0 0x1000>, + <0 0x0acf8000 0 0x1000>, + <0 0x0ac62000 0 0x4000>, + <0 0x0acc7000 0 0x2000>, + <0 0x0accb000 0 0x2000>; + + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csid_wrapper", + "csiphy0", + "csiphy4", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + interrupts = , + , + , + , + , + , + , + , + , + ; + + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy4", + "vfe0", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_AXI_NRT_CLK>, + <&camcc CAM_CC_CAMNOC_AXI_RT_CLK>, + <&camcc CAM_CC_CORE_AHB_CLK>, + <&camcc CAM_CC_CPAS_AHB_CLK>, + <&camcc CAM_CC_CPAS_FAST_AHB_CLK>, + <&camcc CAM_CC_CPAS_IFE_0_CLK>, + <&camcc CAM_CC_CPAS_IFE_LITE_CLK>, + <&camcc CAM_CC_CPHY_RX_CLK_SRC>, + <&camcc CAM_CC_CSID_CLK>, + <&camcc CAM_CC_CSID_CSIPHY_RX_CLK>, + <&camcc CAM_CC_CSIPHY0_CLK>, + <&camcc CAM_CC_CSI0PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_IFE_0_CLK>, + <&camcc CAM_CC_IFE_0_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>; + + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "core_ahb", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe_lite", + "cphy_rx_clk_src", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy4", + "csiphy4_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid"; + + interconnects = <&gem_noc 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>, + <&mmss_noc MASTER_CAMNOC_SF QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>, + <&mmss_noc MASTER_CAMNOC_ICP QCOM_ICC_TAG_ALWAYS + &mc_virt SLAVE_EBI1 QCOM_ICC_TAG_ALWAYS>; + interconnect-names = "ahb", + "hf_mnoc", + "sf_mnoc", + "sf_icp_mnoc"; + + iommus = <&apps_smmu 0x800 0x60>, + <&apps_smmu 0x860 0x60>, + <&apps_smmu 0x1860 0x60>, + <&apps_smmu 0x18e0 0x00>, + <&apps_smmu 0x19a0 0x20>; + + power-domains = <&camcc CAM_CC_IFE_0_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "top"; + + phys = <&csiphy0 PHY_TYPE_DPHY>, + <&csiphy4 PHY_TYPE_DPHY>; + phy-names = "csiphy0", + "csiphy4"; + + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy0_inep0: endpoint@0 { + reg = <0>; + }; + }; + + port@3 { + reg = <3>; + #address-cells = <1>; + #size-cells = <0>; + camss_csiphy4_inep0: endpoint@0 { + reg = <0>; + }; + }; + }; +}; + &camcc { compatible = "qcom,x1p42100-camcc"; }; From b5f00413f08314319635e61373e68ad402e867aa Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:34 +0800 Subject: [PATCH 49/49] FROMLIST: arm64: dts: qcom: purwa-iot-evk: Add camss node enable camss node for purwa iot evk board camss tpg support. Link: https://lore.kernel.org/all/20260410-purwa_camss-v1-4-eedcf6d9d8ee@oss.qualcomm.com/ Signed-off-by: Wenmeng Liu --- arch/arm64/boot/dts/qcom/purwa-iot-evk.dts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts index f26f8b6487381..bbe74117bbd93 100644 --- a/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts +++ b/arch/arm64/boot/dts/qcom/purwa-iot-evk.dts @@ -734,6 +734,10 @@ }; }; +&camss { + status = "okay"; +}; + &i2c3 { clock-frequency = <400000>;