From a9e58d34187fc1b8d8486745005e464e246b6ca3 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:47:57 +0000 Subject: [PATCH 01/53] 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 2a79746a0304d3912a8c59ec397f95dd0f518dbf Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:47:58 +0000 Subject: [PATCH 02/53] 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 f77a66b1e127792e52caa371a2a621b598014e6a Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:47:59 +0000 Subject: [PATCH 03/53] 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 cc5e12608660465924ba15f11bd84e8dc4b7edab Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Wed, 25 Mar 2026 21:48:00 +0000 Subject: [PATCH 04/53] 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 41a3ff4bd3555ba8fd95e7114dc56af34dfcbd0c Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:04:43 +0000 Subject: [PATCH 05/53] 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 989460ec8af2ff7677105b08e91f28a44aec7a2a Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:04:44 +0000 Subject: [PATCH 06/53] 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 15011f5752a99..05bfd1649e445 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -22296,6 +22296,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 639b61ee67955902d20eb59722c5d7b29eac70d9 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:29 +0000 Subject: [PATCH 07/53] 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 2d1662ef522b7..c17b9757b2c86 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: 1.2V 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 771b168b10d2c4df8873924623975ecc73429327 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:30 +0000 Subject: [PATCH 08/53] 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 c17b9757b2c86..f44138f522bba 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 f3cb7b9e0b65b014e1ba492854cbc5622aed55b8 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:31 +0000 Subject: [PATCH 09/53] 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 f44138f522bba..d2763977a494d 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 2c33cb0ab5cb46fc98de60fb57c5eb86c731c465 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:32 +0000 Subject: [PATCH 10/53] 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 2123f6388e3d7..95e655a8b6aa0 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 @@ -5362,6 +5363,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 7666093618d42df4fef7f9e238685c5354ce5f20 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:33 +0000 Subject: [PATCH 11/53] 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 95e655a8b6aa0..e814a96953b1b 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5512,6 +5512,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, @@ -5523,6 +5524,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, @@ -5534,6 +5536,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, @@ -5547,6 +5550,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, @@ -5558,6 +5562,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, @@ -5571,6 +5576,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, .tpg_res = tpg_res_8775p, .csid_res = csid_res_8775p, @@ -5587,6 +5593,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, .tpg_res = tpg_res_8775p, .csid_res = csid_res_8775p, @@ -5602,6 +5609,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, @@ -5613,6 +5621,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, @@ -5624,6 +5633,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, @@ -5635,6 +5645,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, @@ -5661,6 +5672,7 @@ static const struct camss_resources sm6350_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, @@ -5674,6 +5686,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, @@ -5688,6 +5701,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, @@ -5701,6 +5715,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, @@ -5715,6 +5730,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, @@ -5729,6 +5745,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, .tpg_res = tpg_res_x1e80100, .csid_res = csid_res_x1e80100, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 93d691c8ac63b..698694d3064ea 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -107,6 +107,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 *tpg_res; const struct camss_subdev_resources *csid_res; From 8b37333bd4ea6ff1f1970b185ce036257d1876c6 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:34 +0000 Subject: [PATCH 12/53] 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 539ac4888b608..57bc0eda43a18 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 @@ -572,16 +662,16 @@ 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); @@ -709,6 +799,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 @@ -743,8 +887,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 = { @@ -758,8 +906,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, }; @@ -788,7 +941,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", @@ -828,6 +985,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 9d9657b82f748..1879826034aac 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 @@ -97,6 +98,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]; @@ -104,6 +106,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; @@ -118,6 +121,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 e814a96953b1b..bc268148b57db 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4794,14 +4794,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; @@ -4833,15 +4854,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); } } @@ -4931,6 +4963,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, @@ -5057,6 +5092,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) { @@ -5132,8 +5170,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; } @@ -5148,8 +5188,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]); + } if (camss->tpg) { for (i = 0; i < camss->res->tpg_num; i++) From 6f807b7424b0066d7a1b11f390c140ab441311d4 Mon Sep 17 00:00:00 2001 From: Bryan O'Donoghue Date: Thu, 26 Mar 2026 01:28:35 +0000 Subject: [PATCH 13/53] 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 bc268148b57db..36918e9c22eb1 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4191,15 +4191,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, @@ -4208,15 +4199,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, @@ -4225,15 +4207,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, @@ -4242,15 +4215,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, @@ -5787,7 +5751,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, .tpg_res = tpg_res_x1e80100, .csid_res = csid_res_x1e80100, From 39caf36fdd99c3d877bea225048477ed529f9c5a Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:13 -0700 Subject: [PATCH 14/53] FROMLIST: media: dt-bindings: Add CAMSS device for Kaanapali Add bindings for Camera Subsystem (CAMSS) on the Qualcomm Kaanapali platform. The Kaanapali platform provides: - 6 x CSIPHY (CSI Physical Layer) - 3 x TPG (Test Pattern Generator) - 3 x CSID (CSI Decoder) - 2 x CSID Lite - 3 x VFE (Video Front End), 5 RDI per VFE - 2 x VFE Lite, 4 RDI per VFE Lite Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-1-2541d8e55651@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Reviewed-by: Krzysztof Kozlowski Signed-off-by: Hangxiang Ma --- .../bindings/media/qcom,kaanapali-camss.yaml | 433 ++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml b/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml new file mode 100644 index 0000000000000..2f2bb682f32f4 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,kaanapali-camss.yaml @@ -0,0 +1,433 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,kaanapali-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Kaanapali Camera Subsystem (CAMSS) + +maintainers: + - Hangxiang Ma + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,kaanapali-camss + + reg: + maxItems: 19 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 35 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: cpas_vfe2 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy2 + - const: csiphy2_timer + - const: csiphy3 + - const: csiphy3_timer + - const: csiphy4 + - const: csiphy4_timer + - const: csiphy5 + - const: csiphy5_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe2 + - const: vfe2_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + - const: qdss_debug_xo + + interrupts: + maxItems: 16 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - 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: + maxItems: 1 + + power-domains: + items: + - description: + IFE0 GDSC - Global Distributed Switch Controller for IFE0. + - description: + IFE1 GDSC - Global Distributed Switch Controller for IFE1. + - description: + IFE2 GDSC - Global Distributed Switch Controller for IFE2. + - description: + Titan GDSC - Global Distributed Switch Controller for the entire camss. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: ife2 + - const: top + + vdd-csiphy0-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY0 core block. + + vdd-csiphy0-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY0 pll block. + + vdd-csiphy1-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY1 core block. + + vdd-csiphy1-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY1 pll block. + + vdd-csiphy2-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY2 core block. + + vdd-csiphy2-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY2 pll block. + + vdd-csiphy3-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY3 core block. + + vdd-csiphy3-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY3 pll block. + + vdd-csiphy4-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY4 core block. + + vdd-csiphy4-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY4 pll block. + + vdd-csiphy5-0p8-supply: + description: + Phandle to a 0.8V regulator supply to CSIPHY5 core block. + + vdd-csiphy5-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY5 pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-5]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input ports for receiving CSI data on CSIPHY 0-5. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@9253000 { + compatible = "qcom,kaanapali-camss"; + + reg = <0x0 0x09253000 0x0 0x5e80>, + <0x0 0x09263000 0x0 0x5e80>, + <0x0 0x09273000 0x0 0x5e80>, + <0x0 0x092d3000 0x0 0x3880>, + <0x0 0x092e7000 0x0 0x3880>, + <0x0 0x09523000 0x0 0x2000>, + <0x0 0x09525000 0x0 0x2000>, + <0x0 0x09527000 0x0 0x2000>, + <0x0 0x09529000 0x0 0x2000>, + <0x0 0x0952b000 0x0 0x2000>, + <0x0 0x0952d000 0x0 0x2000>, + <0x0 0x093fd000 0x0 0x400>, + <0x0 0x093fe000 0x0 0x400>, + <0x0 0x093ff000 0x0 0x400>, + <0x0 0x09151000 0x0 0x20000>, + <0x0 0x09171000 0x0 0x20000>, + <0x0 0x09191000 0x0 0x20000>, + <0x0 0x092dc000 0x0 0x9000>, + <0x0 0x092f0000 0x0 0x9000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&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_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "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_NRT_ICP_SF 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 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + vdd-csiphy0-0p8-supply = <&vreg_0p8_supply>; + vdd-csiphy0-1p2-supply = <&vreg_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 06cced3caf6ce2c8e4a58eef43e7ec1bf3145ee2 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:14 -0700 Subject: [PATCH 15/53] FROMLIST: media: qcom: camss: Add Kaanapali compatible camss driver Add support for Kaanapali in the camss driver. Add high level resource information along with the bus bandwidth votes. Module level detailed resource information will be enumerated in the following patches of the series. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-2-2541d8e55651@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Signed-off-by: Hangxiang Ma --- drivers/media/platform/qcom/camss/camss.c | 22 ++++++++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 23 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 36918e9c22eb1..c6754760dc45b 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -35,6 +35,20 @@ static const struct parent_dev_ops vfe_parent_dev_ops; +static const struct resources_icc icc_res_kaanapali[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + /* Based on 4096 x 3072 30 FPS 2496 Mbps mode */ + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 471860, + .icc_bw_tbl.peak = 925857, + }, +}; + static const struct camss_subdev_resources csiphy_res_8x16[] = { /* CSIPHY0 */ { @@ -5516,6 +5530,13 @@ static void camss_remove(struct platform_device *pdev) camss_genpd_cleanup(camss); } +static const struct camss_resources kaanapali_resources = { + .version = CAMSS_KAANAPALI, + .pd_name = "top", + .icc_res = icc_res_kaanapali, + .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), +}; + static const struct camss_resources msm8916_resources = { .version = CAMSS_8x16, .legacy_phy = true, @@ -5765,6 +5786,7 @@ static const struct camss_resources x1e80100_resources = { }; static const struct of_device_id camss_dt_match[] = { + { .compatible = "qcom,kaanapali-camss", .data = &kaanapali_resources }, { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, { .compatible = "qcom,msm8939-camss", .data = &msm8939_resources }, { .compatible = "qcom,msm8953-camss", .data = &msm8953_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 698694d3064ea..cea213dc36ebc 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -96,6 +96,7 @@ enum camss_version { CAMSS_8550, CAMSS_8650, CAMSS_8775P, + CAMSS_KAANAPALI, CAMSS_X1E80100, }; From 9fd32238b8766532a7d7223ad3054b7d57a32197 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:15 -0700 Subject: [PATCH 16/53] FROMLIST: media: qcom: camss: csiphy: Add support for v2.4.0 two-phase CSIPHY Add more detailed resource information for CSIPHY devices in the camss driver along with the support for v2.4.0 in the 2 phase CSIPHY driver that is responsible for the PHY lane register configuration, module reset and interrupt handling. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-3-2541d8e55651@oss.qualcomm.com/ Reviewed-by: Bryan O'Donoghue Signed-off-by: Hangxiang Ma --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 124 +++++++++++++++++ drivers/media/platform/qcom/camss/camss.c | 126 ++++++++++++++++++ 2 files changed, 250 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 dac8d2ecf7995..795b333185e54 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 @@ -804,6 +804,123 @@ csiphy_lane_regs lane_regs_sm8650[] = { {0x0c10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, }; +/* 3nm 2PH v 2.4.0 2p5Gbps 4 lane DPHY mode */ +static const struct +csiphy_lane_regs lane_regs_2_4_0[] = { + /* LN 0 */ + {0x0094, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x00A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0090, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0098, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0094, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0000, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x002C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0034, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x001C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0014, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0020, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0008, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0094, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x005C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0060, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 2 */ + {0x0494, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x04A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0490, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0498, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0494, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0400, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x042C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0434, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x041C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0414, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0404, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0420, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0408, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0494, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x045C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0460, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 4 */ + {0x0894, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x08A0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0890, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0898, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0894, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0830, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0800, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0838, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x082C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0834, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x081C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0814, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x083C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0804, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0820, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0808, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0894, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x085C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0860, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN 6 */ + {0x0C94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0CA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C90, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C94, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0C30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C00, 0x8C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C38, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C08, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0C94, 0xD7, 0x00, CSIPHY_SKEW_CAL}, + {0x0C5C, 0x54, 0x00, CSIPHY_SKEW_CAL}, + {0x0C60, 0xFD, 0x00, CSIPHY_SKEW_CAL}, + {0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL}, + + /* LN CLK */ + {0x0E94, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0EA0, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E90, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E98, 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E94, 0x07, 0xd1, CSIPHY_DEFAULT_PARAMS}, + {0x0E30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E28, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E00, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E0C, 0xFF, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E38, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E2C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E34, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E1C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E14, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E3C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E04, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E20, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x0E08, 0x19, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + /* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */ static const struct csiphy_lane_regs lane_regs_x1e80100[] = { @@ -1140,6 +1257,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_8550: case CAMSS_8650: case CAMSS_8775P: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: ret = true; break; @@ -1259,6 +1377,12 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sa8775p[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); break; + case CAMSS_KAANAPALI: + regs->lane_regs = &lane_regs_2_4_0[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_2_4_0); + regs->offset = 0x1000; + regs->common_status_offset = 0x138; + break; default: break; } diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index c6754760dc45b..3272364303ee2 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -35,6 +35,129 @@ static const struct parent_dev_ops vfe_parent_dev_ops; +static const struct camss_subdev_resources csiphy_res_kaanapali[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdd-csiphy0-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy0-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy0", "csiphy0_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdd-csiphy1-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy1-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy1", "csiphy1_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY2 */ + { + .regulators = { + { .supply = "vdd-csiphy2-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy2-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy2", "csiphy2_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY3 */ + { + .regulators = { + { .supply = "vdd-csiphy3-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy3-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy3", "csiphy3_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY4 */ + { + .regulators = { + { .supply = "vdd-csiphy4-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy4-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy4", "csiphy4_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY5 */ + { + .regulators = { + { .supply = "vdd-csiphy5-0p8", .init_load_uA = 151020 }, + { .supply = "vdd-csiphy5-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy5", "csiphy5_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy5" }, + .interrupt = { "csiphy5" }, + .csiphy = { + .id = 5, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, +}; + static const struct resources_icc icc_res_kaanapali[] = { { .name = "ahb", @@ -5533,8 +5656,11 @@ static void camss_remove(struct platform_device *pdev) static const struct camss_resources kaanapali_resources = { .version = CAMSS_KAANAPALI, .pd_name = "top", + .legacy_phy = true, + .csiphy_res = csiphy_res_kaanapali, .icc_res = icc_res_kaanapali, .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), + .csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali), }; static const struct camss_resources msm8916_resources = { From c0abf4c20b500db407f24718374e8df82ba1d671 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:16 -0700 Subject: [PATCH 17/53] FROMLIST: media: qcom: camss: csid: Add support for CSID gen4 Add more detailed resource information for CSID devices along with the driver for CSID gen4 that is responsible for CSID register configuration, module reset and IRQ handling for BUF_DONE events. And aggregate a common definition 'CSI2_RX_CFG0_PHY_SEL_BASE_IDX' into csid header file. In this CSID version, RUP and AUP update values are split into two registers along with a SET register. Accordingly, enhance the CSID interface to accommodate both the legacy combined reg_update and the split RUP and AUP updates. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-4-2541d8e55651@oss.qualcomm.com/ Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma --- drivers/media/platform/qcom/camss/Makefile | 1 + .../platform/qcom/camss/camss-csid-680.c | 1 - .../platform/qcom/camss/camss-csid-gen3.c | 1 - .../platform/qcom/camss/camss-csid-gen4.c | 376 ++++++++++++++++++ .../media/platform/qcom/camss/camss-csid.h | 11 +- drivers/media/platform/qcom/camss/camss.c | 75 ++++ 6 files changed, 462 insertions(+), 3 deletions(-) create mode 100644 drivers/media/platform/qcom/camss/camss-csid-gen4.c diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index 27898b3cc7d3c..cebfd947f28ef 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -10,6 +10,7 @@ qcom-camss-objs += \ camss-csid-680.o \ camss-csid-gen2.o \ camss-csid-gen3.o \ + camss-csid-gen4.o \ camss-csiphy.o \ camss-csiphy-2ph-1-0.o \ camss-csiphy-3ph-1-0.o \ diff --git a/drivers/media/platform/qcom/camss/camss-csid-680.c b/drivers/media/platform/qcom/camss/camss-csid-680.c index 345a67c8fb947..bf7164085ddb4 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-680.c +++ b/drivers/media/platform/qcom/camss/camss-csid-680.c @@ -101,7 +101,6 @@ #define CSI2_RX_CFG0_DL2_INPUT_SEL 12 #define CSI2_RX_CFG0_DL3_INPUT_SEL 16 #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) diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen3.c b/drivers/media/platform/qcom/camss/camss-csid-gen3.c index 0fdbf75fb27db..da9458cd178bd 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-gen3.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.c @@ -105,7 +105,6 @@ #define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi) (csid_is_lite(csid) && IS_CSID_690(csid) ?\ (0x34C + 0x100 * (rdi)) :\ (0x54C + 0x100 * (rdi))) -#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 static void __csid_configure_rx(struct csid_device *csid, struct csid_phy_config *phy, int vc) diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen4.c b/drivers/media/platform/qcom/camss/camss-csid-gen4.c new file mode 100644 index 0000000000000..41035352c4bb0 --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-gen4.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-csid-gen4.c + * + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include +#include +#include +#include + +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen3.h" + +/* Reset and Command Registers */ +#define CSID_RST_CFG 0x108 +#define RST_MODE BIT(0) +#define RST_LOCATION BIT(4) + +/* Reset and Command Registers */ +#define CSID_RST_CMD 0x10C +#define SELECT_HW_RST BIT(0) +#define SELECT_IRQ_RST BIT(2) +#define CSID_IRQ_CMD 0x110 +#define IRQ_CMD_CLEAR BIT(0) + +/* Register Update Commands, RUP/AUP */ +#define CSID_RUP_CMD 0x114 +#define CSID_AUP_CMD 0x118 +#define CSID_RUP_AUP_RDI(rdi) (BIT(8) << (rdi)) +#define CSID_RUP_AUP_CMD 0x11C +#define RUP_SET BIT(0) +#define MUP BIT(4) + +/* Top level interrupt registers */ +#define CSID_TOP_IRQ_STATUS 0x180 +#define CSID_TOP_IRQ_MASK 0x184 +#define CSID_TOP_IRQ_CLEAR 0x188 +#define INFO_RST_DONE BIT(0) +#define CSI2_RX_IRQ_STATUS BIT(2) +#define BUF_DONE_IRQ_STATUS BIT(3) + +/* Buffer done interrupt registers */ +#define CSID_BUF_DONE_IRQ_STATUS 0x1A0 +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET 16 +#define CSID_BUF_DONE_IRQ_MASK 0x1A4 +#define CSID_BUF_DONE_IRQ_CLEAR 0x1A8 +#define CSID_BUF_DONE_IRQ_SET 0x1AC + +/* CSI2 RX interrupt registers */ +#define CSID_CSI2_RX_IRQ_STATUS 0x1B0 +#define CSID_CSI2_RX_IRQ_MASK 0x1B4 +#define CSID_CSI2_RX_IRQ_CLEAR 0x1B8 +#define CSID_CSI2_RX_IRQ_SET 0x1BC + +/* CSI2 RX Configuration */ +#define CSID_CSI2_RX_CFG0 0x880 +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_DL0_INPUT_SEL 4 +#define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSID_CSI2_RX_CFG1 0x884 +#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_VC_MODE BIT(2) + +#define MSM_CSID_MAX_SRC_STREAMS_GEN4 (csid_is_lite(csid) ? 4 : 5) + +/* RDI Configuration */ +#define CSID_RDI_CFG0(rdi) \ + ((csid_is_lite(csid) ? 0x3080 : 0x5480) + 0x200 * (rdi)) +#define RDI_CFG0_RETIME_BS BIT(5) +#define RDI_CFG0_TIMESTAMP_EN BIT(6) +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) +#define RDI_CFG0_DECODE_FORMAT 12 +#define RDI_CFG0_DT 16 +#define RDI_CFG0_VC 22 +#define RDI_CFG0_EN BIT(31) + +/* RDI Control and Configuration */ +#define CSID_RDI_CTRL(rdi) \ + ((csid_is_lite(csid) ? 0x3088 : 0x5488) + 0x200 * (rdi)) +#define RDI_CTRL_START_CMD BIT(0) + +#define CSID_RDI_CFG1(rdi) \ + ((csid_is_lite(csid) ? 0x3094 : 0x5494) + 0x200 * (rdi)) +#define RDI_CFG1_DROP_H_EN BIT(5) +#define RDI_CFG1_DROP_V_EN BIT(6) +#define RDI_CFG1_CROP_H_EN BIT(7) +#define RDI_CFG1_CROP_V_EN BIT(8) +#define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) + +/* RDI Pixel Store Configuration */ +#define CSID_RDI_PIX_STORE_CFG0(rdi) (0x5498 + 0x200 * (rdi)) +#define RDI_PIX_STORE_CFG0_EN BIT(0) +#define RDI_PIX_STORE_CFG0_MIN_HBI 1 + +/* RDI IRQ Status in wrapper */ +#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) (0x224 + (0x10 * (rdi))) +#define CSID_CSI2_RDIN_IRQ_MASK(rdi) (0x228 + (0x10 * (rdi))) +#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) (0x22C + (0x10 * (rdi))) +#define INFO_RUP_DONE BIT(23) + +static void __csid_aup_rup_trigger(struct csid_device *csid) +{ + /* trigger SET in combined register */ + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD); +} + +static void __csid_aup_rup_clear(struct csid_device *csid, int port_id) +{ + /* Hardware clears the registers upon consuming the settings */ + csid->aup_update &= ~CSID_RUP_AUP_RDI(port_id); + csid->rup_update &= ~CSID_RUP_AUP_RDI(port_id); +} + +static void __csid_aup_update(struct csid_device *csid, int port_id) +{ + csid->aup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->aup_update, csid->base + CSID_AUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_reg_update(struct csid_device *csid, int port_id) +{ + csid->rup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->rup_update, csid->base + CSID_RUP_CMD); + + __csid_aup_rup_trigger(csid); +} + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy) +{ + int val; + + 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; + writel(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_ECC_CORRECTION_EN; + writel(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_configure_rx_vc(struct csid_device *csid, int vc) +{ + int val; + + if (vc > 3) { + val = readl(csid->base + CSID_CSI2_RX_CFG1); + val |= CSI2_RX_CFG1_VC_MODE; + writel(val, csid->base + CSID_CSI2_RX_CFG1); + } +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + int val = 0; + + if (enable) + val = RDI_CTRL_START_CMD; + + writel(val, csid->base + CSID_RDI_CTRL(rdi)); +} + +static void __csid_configure_rdi_pix_store(struct csid_device *csid, u8 rdi) +{ + u32 val; + + /* + * Configure pixel store to allow absorption of hblanking or idle time. + * This helps with horizontal crop and prevents line buffer conflicts. + * Reset state is 0x8 which has MIN_HBI=4, we keep the default MIN_HBI + * and just enable the pixel store functionality. + */ + val = (4 << RDI_PIX_STORE_CFG0_MIN_HBI) | RDI_PIX_STORE_CFG0_EN; + writel(val, csid->base + CSID_RDI_PIX_STORE_CFG0(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc) +{ + u32 val; + u8 lane_cnt = csid->phy.lane_cnt; + + /* Source pads matching RDI channels on hardware. + * E.g. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. + */ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + + if (!lane_cnt) + lane_cnt = 4; + + val = RDI_CFG0_TIMESTAMP_EN; + val |= RDI_CFG0_TIMESTAMP_STB_SEL; + val |= RDI_CFG0_RETIME_BS; + + /* note: for non-RDI path, this should be format->decode_format */ + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; + val |= vc << RDI_CFG0_VC; + val |= format->data_type << RDI_CFG0_DT; + writel(val, csid->base + CSID_RDI_CFG0(port)); + + val = RDI_CFG1_PACKING_FORMAT_MIPI; + writel(val, csid->base + CSID_RDI_CFG1(port)); + + /* Configure pixel store using dedicated register in gen4 */ + if (!csid_is_lite(csid)) + __csid_configure_rdi_pix_store(csid, port); + + val = 0; + writel(val, csid->base + CSID_RDI_CTRL(port)); + + val = readl(csid->base + CSID_RDI_CFG0(port)); + + if (enable) + val |= RDI_CFG0_EN; + + writel(val, csid->base + CSID_RDI_CFG0(port)); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + u8 i, k; + + __csid_configure_rx(csid, &csid->phy); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i, 0); + __csid_configure_rx_vc(csid, 0); + + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++) + __csid_aup_update(csid, i); + + __csid_reg_update(csid, i); + + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return 0; +} + +static void csid_subdev_reg_update(struct csid_device *csid, int port_id, + bool clear) +{ + if (clear) + __csid_aup_rup_clear(csid, port_id); + else + __csid_aup_update(csid, port_id); +} + +/** + * csid_isr - CSID module interrupt service routine + * @irq: Interrupt line + * @dev: CSID device + * + * Return IRQ_HANDLED on success + */ +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val, buf_done_val; + u8 reset_done; + int i; + + val = readl(csid->base + CSID_TOP_IRQ_STATUS); + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + + reset_done = val & INFO_RST_DONE; + + buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS); + writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); + writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); + + if (val & INFO_RUP_DONE) + csid_subdev_reg_update(csid, i, true); + + if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) + camss_buf_done(csid->camss, csid->id, i); + } + } + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + if (reset_done) + complete(&csid->reset_complete); + + return IRQ_HANDLED; +} + +/** + * csid_reset - Trigger reset on CSID module and wait to complete + * @csid: CSID device + * + * Return 0 on success or a negative error code otherwise + */ +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + u32 val; + int i; + + reinit_completion(&csid->reset_complete); + + val = INFO_RST_DONE | BUF_DONE_IRQ_STATUS; + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + writel(val, csid->base + CSID_TOP_IRQ_MASK); + + val = 0; + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_GEN4; i++) { + if (csid->phy.en_vc & BIT(i)) { + /* + * Only need to clear buf done IRQ status here, + * RUP done IRQ status will be cleared once isr + * strobe generated by CSID_RST_CMD + */ + val |= BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i); + } + } + writel(val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + writel(val, csid->base + CSID_BUF_DONE_IRQ_MASK); + + /* Clear all IRQ status with CLEAR bits set */ + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + val = RST_LOCATION | RST_MODE; + writel(val, csid->base + CSID_RST_CFG); + + val = SELECT_HW_RST | SELECT_IRQ_RST; + writel(val, csid->base + CSID_RST_CMD); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + + if (!time) { + dev_err(csid->camss->dev, "CSID reset timeout\n"); + return -EIO; + } + + return 0; +} + +static void csid_subdev_init(struct csid_device *csid) +{ + csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; +} + +const struct csid_hw_ops csid_ops_gen4 = { + .configure_stream = csid_configure_stream, + .configure_testgen_pattern = csid_configure_testgen_pattern, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, + .reg_update = csid_subdev_reg_update, +}; diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index 5296b10f6bac8..e6590b2bd8be5 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -27,6 +27,8 @@ /* CSID hardware can demultiplex up to 4 outputs */ #define MSM_CSID_MAX_SRC_STREAMS 4 +/* CSIPHY to hardware PHY selector mapping */ +#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1 #define CSID_RESET_TIMEOUT_MS 500 enum csid_testgen_mode { @@ -154,7 +156,13 @@ struct csid_device { void __iomem *base; u32 irq; char irq_name[30]; - u32 reg_update; + union { + u32 reg_update; + struct { + u32 rup_update; + u32 aup_update; + }; + }; struct camss_clock *clock; int nclocks; struct regulator_bulk_data *supplies; @@ -218,6 +226,7 @@ extern const struct csid_hw_ops csid_ops_340; extern const struct csid_hw_ops csid_ops_680; extern const struct csid_hw_ops csid_ops_gen2; extern const struct csid_hw_ops csid_ops_gen3; +extern const struct csid_hw_ops csid_ops_gen4; /* * csid_is_lite - Check if CSID is CSID lite. diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 3272364303ee2..8d4b9c6eddb2a 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -158,6 +158,79 @@ static const struct camss_subdev_resources csiphy_res_kaanapali[] = { }, }; +static const struct camss_subdev_resources csid_res_kaanapali[] = { + /* CSID0 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE1 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_gen4, + .formats = &csid_formats_gen2 + } + } +}; + static const struct resources_icc icc_res_kaanapali[] = { { .name = "ahb", @@ -5658,9 +5731,11 @@ static const struct camss_resources kaanapali_resources = { .pd_name = "top", .legacy_phy = true, .csiphy_res = csiphy_res_kaanapali, + .csid_res = csid_res_kaanapali, .icc_res = icc_res_kaanapali, .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), .csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali), + .csid_num = ARRAY_SIZE(csid_res_kaanapali), }; static const struct camss_resources msm8916_resources = { From 6bdeba58251db3782651b6b2fb4a5061eb2b56b8 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 01:05:17 -0700 Subject: [PATCH 18/53] FROMLIST: media: qcom: camss: vfe: Add support for VFE gen4 Add Video Front End (VFE) version gen4 as found on the Kaanapali SoC. The FULL front end modules in Kaanapali camera subsystem are called TFEs (Thin Front End), however, retaining the name VFE at places to maintain consistency and avoid unnecessary code changes. This change limits the VFE output lines to 3 for now as constrained by the CAMSS driver framework. Kaanapali architecture requires for the REG_UPDATE and AUP_UPDATE to be issued after all of the CSID configuration has been done. Additionally, the number of AUP_UPDATEs should match the number of buffers enqueued to the write master while it's being enabled. Although the real time data from TFE goes through the RT_CAMNOC, we are required to enable both the camnoc_rt_axi and camnoc_nrt_axi clocks for the PDX_NOC, that follows both the RT and NRT NOCs in this architecture, to ensure that both of the latter are idle after reset. Link: https://lore.kernel.org/all/20260508-kaanapali-camss-v13-5-2541d8e55651@oss.qualcomm.com/ Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma --- drivers/media/platform/qcom/camss/Makefile | 1 + .../platform/qcom/camss/camss-vfe-gen4.c | 197 ++++++++++++++++++ drivers/media/platform/qcom/camss/camss-vfe.c | 9 +- drivers/media/platform/qcom/camss/camss-vfe.h | 2 + drivers/media/platform/qcom/camss/camss.c | 138 ++++++++++++ 5 files changed, 345 insertions(+), 2 deletions(-) create mode 100644 drivers/media/platform/qcom/camss/camss-vfe-gen4.c diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index cebfd947f28ef..b114ca37e36e2 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -28,6 +28,7 @@ qcom-camss-objs += \ camss-vfe-680.o \ camss-vfe-gen1.o \ camss-vfe-gen3.o \ + camss-vfe-gen4.o \ camss-vfe-vbif.o \ camss-video.o diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c new file mode 100644 index 0000000000000..d73d70898710a --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-vfe-gen4.c + * + * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module gen4 + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include + +#include "camss.h" +#include "camss-vfe.h" + +/* VFE-gen4 Bus Register Base Addresses */ +#define BUS_REG_BASE (vfe_is_lite(vfe) ? 0x800 : 0x1000) + +#define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) +#define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) + +#define VFE_BUS_WM_TEST_BUS_CTRL (BUS_REG_BASE + 0x128) + +#define VFE_BUS_WM_CFG(n) (BUS_REG_BASE + 0x500 + (n) * 0x100) +#define WM_CFG_EN BIT(0) +#define WM_VIR_FRM_EN BIT(1) +#define WM_CFG_MODE BIT(16) +#define VFE_BUS_WM_IMAGE_ADDR(n) (BUS_REG_BASE + 0x504 + (n) * 0x100) +#define VFE_BUS_WM_FRAME_INCR(n) (BUS_REG_BASE + 0x508 + (n) * 0x100) +#define VFE_BUS_WM_IMAGE_CFG_0(n) (BUS_REG_BASE + 0x50C + (n) * 0x100) +#define WM_IMAGE_CFG_0_DEFAULT_WIDTH (0xFFFF) +#define VFE_BUS_WM_IMAGE_CFG_2(n) (BUS_REG_BASE + 0x514 + (n) * 0x100) +#define WM_IMAGE_CFG_2_DEFAULT_STRIDE (0xFFFF) +#define VFE_BUS_WM_PACKER_CFG(n) (BUS_REG_BASE + 0x518 + (n) * 0x100) + +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(n) (BUS_REG_BASE + 0x530 + (n) * 0x100) +#define VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(n) (BUS_REG_BASE + 0x534 + (n) * 0x100) + +/* VFE lite has no such registers */ +#define VFE_BUS_WM_FRAMEDROP_PERIOD(n) (BUS_REG_BASE + 0x538 + (n) * 0x100) +#define VFE_BUS_WM_FRAMEDROP_PATTERN(n) (BUS_REG_BASE + 0x53C + (n) * 0x100) + +#define VFE_BUS_WM_MMU_PREFETCH_CFG(n) (BUS_REG_BASE + 0x560 + (n) * 0x100) +#define VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(n) (BUS_REG_BASE + 0x564 + (n) * 0x100) + +/* + * IFE write master client IDs + * + * VIDEO_FULL 0 + * VIDEO_DC4_Y 1 + * VIDEO_DC4_C 2 + * VIDEO_DC16_Y 3 + * VIDEO_DC16_C 4 + * DISPLAY_DS2_Y 5 + * DISPLAY_DS2_C 6 + * FD_Y 7 + * FD_C 8 + * PIXEL_RAW 9 + * STATS_AEC_BG 10 + * STATS_AEC_BHIST 11 + * STATS_TINTLESS_BG 12 + * STATS_AWB_BG 13 + * STATS_AWB_BFW 14 + * STATS_AF_BHIST 15 + * STATS_ALSC_BG 16 + * STATS_FLICKER_BAYERRS 17 + * STATS_TMC_BHIST 18 + * PDAF_0 19 + * PDAF_1 20 + * PDAF_2 21 + * PDAF_3 22 + * RDI0 23 + * RDI1 24 + * RDI2 25 + * RDI3 26 + * RDI4 27 + * + * IFE Lite write master client IDs + * + * RDI0 0 + * RDI1 1 + * RDI2 2 + * RDI3 3 + * GAMMA 4 + * STATES_BE 5 + */ +#define RDI_WM(n) ((vfe_is_lite(vfe) ? 0x0 : 0x17) + (n)) + +static void vfe_wm_start(struct vfe_device *vfe, u8 wm, struct vfe_line *line) +{ + struct v4l2_pix_format_mplane *pix = + &line->video_out.active_fmt.fmt.pix_mp; + + wm = RDI_WM(wm); + + /* no clock gating at bus input */ + writel(WM_CGC_OVERRIDE_ALL, vfe->base + VFE_BUS_WM_CGC_OVERRIDE); + + writel(0x0, vfe->base + VFE_BUS_WM_TEST_BUS_CTRL); + + writel(ALIGN(pix->plane_fmt[0].bytesperline, 16) * pix->height >> 8, + vfe->base + VFE_BUS_WM_FRAME_INCR(wm)); + writel((WM_IMAGE_CFG_0_DEFAULT_WIDTH & 0xFFFF), + vfe->base + VFE_BUS_WM_IMAGE_CFG_0(wm)); + writel(WM_IMAGE_CFG_2_DEFAULT_STRIDE, + vfe->base + VFE_BUS_WM_IMAGE_CFG_2(wm)); + writel(0, vfe->base + VFE_BUS_WM_PACKER_CFG(wm)); + + /* no dropped frames, one irq per frame */ + if (!vfe_is_lite(vfe)) { + writel(0, vfe->base + VFE_BUS_WM_FRAMEDROP_PERIOD(wm)); + writel(1, vfe->base + VFE_BUS_WM_FRAMEDROP_PATTERN(wm)); + } + + writel(0, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PERIOD(wm)); + writel(1, vfe->base + VFE_BUS_WM_IRQ_SUBSAMPLE_PATTERN(wm)); + + writel(1, vfe->base + VFE_BUS_WM_MMU_PREFETCH_CFG(wm)); + writel(0xFFFFFFFF, vfe->base + VFE_BUS_WM_MMU_PREFETCH_MAX_OFFSET(wm)); + + writel(WM_CFG_EN | WM_CFG_MODE, vfe->base + VFE_BUS_WM_CFG(wm)); +} + +static void vfe_wm_stop(struct vfe_device *vfe, u8 wm) +{ + wm = RDI_WM(wm); + writel(0, vfe->base + VFE_BUS_WM_CFG(wm)); +} + +static void vfe_wm_update(struct vfe_device *vfe, u8 wm, u32 addr, + struct vfe_line *line) +{ + wm = RDI_WM(wm); + writel(addr >> 8, vfe->base + VFE_BUS_WM_IMAGE_ADDR(wm)); + + dev_dbg(vfe->camss->dev, "wm:%d, image buf addr:0x%x\n", wm, addr); +} + +static void vfe_reg_update(struct vfe_device *vfe, enum vfe_line_id line_id) +{ + int port_id = line_id; + + camss_reg_update(vfe->camss, vfe->id, port_id, false); +} + +static inline void vfe_reg_update_clear(struct vfe_device *vfe, + enum vfe_line_id line_id) +{ + int port_id = line_id; + + camss_reg_update(vfe->camss, vfe->id, port_id, true); +} + +static const struct camss_video_ops vfe_video_ops_gen4 = { + .queue_buffer = vfe_queue_buffer_v2, + .flush_buffers = vfe_flush_buffers, +}; + +static void vfe_subdev_init(struct device *dev, struct vfe_device *vfe) +{ + vfe->video_ops = vfe_video_ops_gen4; +} + +static void vfe_global_reset(struct vfe_device *vfe) +{ + vfe_isr_reset_ack(vfe); +} + +static irqreturn_t vfe_isr(int irq, void *dev) +{ + /* nop */ + return IRQ_HANDLED; +} + +static int vfe_halt(struct vfe_device *vfe) +{ + /* rely on vfe_disable_output() to stop the VFE */ + return 0; +} + +const struct vfe_hw_ops vfe_ops_gen4 = { + .global_reset = vfe_global_reset, + .hw_version = vfe_hw_version, + .isr = vfe_isr, + .pm_domain_off = vfe_pm_domain_off, + .pm_domain_on = vfe_pm_domain_on, + .reg_update = vfe_reg_update, + .reg_update_clear = vfe_reg_update_clear, + .subdev_init = vfe_subdev_init, + .vfe_disable = vfe_disable, + .vfe_enable = vfe_enable_v2, + .vfe_halt = vfe_halt, + .vfe_wm_start = vfe_wm_start, + .vfe_wm_stop = vfe_wm_stop, + .vfe_buf_done = vfe_buf_done, + .vfe_wm_update = vfe_wm_update, +}; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 319d191589884..826ab85a44a14 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -353,6 +353,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_8550: case CAMSS_8650: case CAMSS_8775P: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: @@ -525,7 +526,8 @@ int vfe_enable_output_v2(struct vfe_line *line) spin_lock_irqsave(&vfe->output_lock, flags); - ops->reg_update_clear(vfe, line->id); + if (ops->reg_update_clear) + ops->reg_update_clear(vfe, line->id); if (output->state > VFE_OUTPUT_RESERVED) { dev_err(vfe->camss->dev, @@ -552,7 +554,9 @@ int vfe_enable_output_v2(struct vfe_line *line) output->gen2.active_num++; ops->vfe_wm_update(vfe, output->wm_idx[0], output->buf[i]->addr[0], line); - ops->reg_update(vfe, line->id); + + if (!vfe->res->reg_update_after_csid_config) + ops->reg_update(vfe, line->id); } spin_unlock_irqrestore(&vfe->output_lock, flags); @@ -2013,6 +2017,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_8550: case CAMSS_8650: case CAMSS_8775P: + case CAMSS_KAANAPALI: case CAMSS_X1E80100: ret = 16; break; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h index ae9dad353a378..c402ef170c81b 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.h +++ b/drivers/media/platform/qcom/camss/camss-vfe.h @@ -133,6 +133,7 @@ struct vfe_isr_ops { struct vfe_subdev_resources { bool is_lite; + bool reg_update_after_csid_config; u8 line_num; bool has_pd; char *pd_name; @@ -249,6 +250,7 @@ extern const struct vfe_hw_ops vfe_ops_340; extern const struct vfe_hw_ops vfe_ops_480; extern const struct vfe_hw_ops vfe_ops_680; extern const struct vfe_hw_ops vfe_ops_gen3; +extern const struct vfe_hw_ops vfe_ops_gen4; int vfe_get(struct vfe_device *vfe); void vfe_put(struct vfe_device *vfe); diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 8d4b9c6eddb2a..c514256de4804 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -231,6 +231,142 @@ static const struct camss_subdev_resources csid_res_kaanapali[] = { } }; +/* In Kaanapali, CAMNOC requires all CPAS_TFEX clocks + * to operate on any TFE Full. + */ +static const struct camss_subdev_resources vfe_res_kaanapali[] = { + /* VFE0 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe0_fast_ahb", "vfe0", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe1_fast_ahb", "vfe1", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe2_fast_ahb", "vfe2", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE3 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE4 - IFE Lite */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, +}; + static const struct resources_icc icc_res_kaanapali[] = { { .name = "ahb", @@ -5732,10 +5868,12 @@ static const struct camss_resources kaanapali_resources = { .legacy_phy = true, .csiphy_res = csiphy_res_kaanapali, .csid_res = csid_res_kaanapali, + .vfe_res = vfe_res_kaanapali, .icc_res = icc_res_kaanapali, .icc_path_num = ARRAY_SIZE(icc_res_kaanapali), .csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali), .csid_num = ARRAY_SIZE(csid_res_kaanapali), + .vfe_num = ARRAY_SIZE(vfe_res_kaanapali), }; static const struct camss_resources msm8916_resources = { From 2c06f1f8c80404a40a96e283559935b1042d5799 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:31 +0800 Subject: [PATCH 19/53] 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 ca32238f45c5674c83a93fe19c1dbe58f9a6bad9 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:32 +0800 Subject: [PATCH 20/53] 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 795b333185e54..4badd4c64e1ef 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 @@ -1259,6 +1259,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: + case CAMSS_X1P42100: ret = true; break; } @@ -1358,6 +1359,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 826ab85a44a14..dbe5a9af452bf 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -355,6 +355,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: + case CAMSS_X1P42100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: { @@ -2019,6 +2020,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_8775P: case CAMSS_KAANAPALI: 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 c514256de4804..49f125b549b6c 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4847,6 +4847,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 @@ -6124,6 +6216,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,kaanapali-camss", .data = &kaanapali_resources }, { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, @@ -6144,6 +6252,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 cea213dc36ebc..6695c26fa8885 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -98,6 +98,7 @@ enum camss_version { CAMSS_8775P, CAMSS_KAANAPALI, CAMSS_X1E80100, + CAMSS_X1P42100, }; enum icc_count { From b5f70cf8643dcd1aa38f30fcec313e476fb9ee95 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:03 -0700 Subject: [PATCH 21/53] FROMLIST: media: dt-bindings: Add CAMSS device for SM8750 Add bindings for Camera Subsystem (CAMSS) on the Qualcomm SM8750 platform. The SM8750 platform provides: - 6 x CSIPHY (CSI Physical Layer) - 3 x TPG (Test Pattern Generator) - 3 x CSID (CSI Decoder) - 2 x CSID Lite - 3 x VFE (Video Front End), 5 RDI per VFE - 2 x VFE Lite, 4 RDI per VFE Lite Reviewed-by: Bryan O'Donoghue Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-1-fc6861a65c67@oss.qualcomm.com/ --- .../bindings/media/qcom,sm8750-camss.yaml | 433 ++++++++++++++++++ 1 file changed, 433 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml b/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml new file mode 100644 index 0000000000000..fc0550899c074 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,sm8750-camss.yaml @@ -0,0 +1,433 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,sm8750-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm SM8750 Camera Subsystem (CAMSS) + +maintainers: + - Hangxiang Ma + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,sm8750-camss + + reg: + maxItems: 19 + + reg-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 35 + + clock-names: + items: + - const: camnoc_nrt_axi + - const: camnoc_rt_axi + - const: cpas_ahb + - const: cpas_fast_ahb + - const: cpas_vfe0 + - const: cpas_vfe1 + - const: cpas_vfe2 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy2 + - const: csiphy2_timer + - const: csiphy3 + - const: csiphy3_timer + - const: csiphy4 + - const: csiphy4_timer + - const: csiphy5 + - const: csiphy5_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe2 + - const: vfe2_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + - const: qdss_debug_xo + + interrupts: + maxItems: 16 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy2 + - const: csiphy3 + - const: csiphy4 + - const: csiphy5 + - const: vfe0 + - const: vfe1 + - const: vfe2 + - 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: + maxItems: 1 + + power-domains: + items: + - description: + IFE0 GDSC - Global Distributed Switch Controller for IFE0. + - description: + IFE1 GDSC - Global Distributed Switch Controller for IFE1. + - description: + IFE2 GDSC - Global Distributed Switch Controller for IFE2. + - description: + Titan GDSC - Global Distributed Switch Controller for the entire camss. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: ife2 + - const: top + + vdd-csiphy0-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY0 core block. + + vdd-csiphy0-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY0 pll block. + + vdd-csiphy1-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY1 core block. + + vdd-csiphy1-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY1 pll block. + + vdd-csiphy2-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY2 core block. + + vdd-csiphy2-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY2 pll block. + + vdd-csiphy3-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY3 core block. + + vdd-csiphy3-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY3 pll block. + + vdd-csiphy4-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY4 core block. + + vdd-csiphy4-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY4 pll block. + + vdd-csiphy5-0p9-supply: + description: + Phandle to a 0.9V regulator supply to CSIPHY5 core block. + + vdd-csiphy5-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSIPHY5 pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-5]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + description: + Input ports for receiving CSI data on CSIPHY 0-5. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + isp@ad27000 { + compatible = "qcom,sm8750-camss"; + + reg = <0x0 0x0ad27000 0x0 0x2b00>, + <0x0 0x0ad2a000 0x0 0x2b00>, + <0x0 0x0ad2d000 0x0 0x2b00>, + <0x0 0x0ad6d000 0x0 0xa00>, + <0x0 0x0ad72000 0x0 0xa00>, + <0x0 0x0ada9000 0x0 0x2000>, + <0x0 0x0adab000 0x0 0x2000>, + <0x0 0x0adad000 0x0 0x2000>, + <0x0 0x0adaf000 0x0 0x2000>, + <0x0 0x0adb1000 0x0 0x2000>, + <0x0 0x0adb3000 0x0 0x2000>, + <0x0 0x0ad8b000 0x0 0x400>, + <0x0 0x0ad8c000 0x0 0x400>, + <0x0 0x0ad8d000 0x0 0x400>, + <0x0 0x0ac86000 0x0 0x10000>, + <0x0 0x0ac96000 0x0 0x10000>, + <0x0 0x0aca6000 0x0 0x10000>, + <0x0 0x0ad6e000 0x0 0x3000>, + <0x0 0x0ad73000 0x0 0x3000>; + reg-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "csitpg0", + "csitpg1", + "csitpg2", + "vfe0", + "vfe1", + "vfe2", + "vfe_lite0", + "vfe_lite1"; + + clocks = <&camcc CAM_CC_CAMNOC_NRT_AXI_CLK>, + <&camcc CAM_CC_CAMNOC_RT_AXI_CLK>, + <&camcc CAM_CC_CAM_TOP_AHB_CLK>, + <&camcc CAM_CC_CAM_TOP_FAST_AHB_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_CAMNOC_RT_IFE_LITE_CLK>, + <&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_CSIPHY3_CLK>, + <&camcc CAM_CC_CSI3PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY4_CLK>, + <&camcc CAM_CC_CSI4PHYTIMER_CLK>, + <&camcc CAM_CC_CSIPHY5_CLK>, + <&camcc CAM_CC_CSI5PHYTIMER_CLK>, + <&gcc GCC_CAMERA_HF_AXI_CLK>, + <&gcc GCC_CAMERA_SF_AXI_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_CLK>, + <&camcc CAM_CC_TFE_0_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_CLK>, + <&camcc CAM_CC_TFE_1_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_CLK>, + <&camcc CAM_CC_TFE_2_MAIN_FAST_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CLK>, + <&camcc CAM_CC_IFE_LITE_AHB_CLK>, + <&camcc CAM_CC_IFE_LITE_CPHY_RX_CLK>, + <&camcc CAM_CC_IFE_LITE_CSID_CLK>, + <&camcc CAM_CC_QDSS_DEBUG_XO_CLK>; + clock-names = "camnoc_nrt_axi", + "camnoc_rt_axi", + "cpas_ahb", + "cpas_fast_ahb", + "cpas_vfe0", + "cpas_vfe1", + "cpas_vfe2", + "cpas_vfe_lite", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_timer", + "csiphy2", + "csiphy2_timer", + "csiphy3", + "csiphy3_timer", + "csiphy4", + "csiphy4_timer", + "csiphy5", + "csiphy5_timer", + "gcc_axi_hf", + "gcc_axi_sf", + "vfe0", + "vfe0_fast_ahb", + "vfe1", + "vfe1_fast_ahb", + "vfe2", + "vfe2_fast_ahb", + "vfe_lite", + "vfe_lite_ahb", + "vfe_lite_cphy_rx", + "vfe_lite_csid", + "qdss_debug_xo"; + + interrupts = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + interrupt-names = "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "csiphy2", + "csiphy3", + "csiphy4", + "csiphy5", + "vfe0", + "vfe1", + "vfe2", + "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_NRT_ICP_SF 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 0x1c00 0x00>; + + power-domains = <&camcc CAM_CC_TFE_0_GDSC>, + <&camcc CAM_CC_TFE_1_GDSC>, + <&camcc CAM_CC_TFE_2_GDSC>, + <&camcc CAM_CC_TITAN_TOP_GDSC>; + power-domain-names = "ife0", + "ife1", + "ife2", + "top"; + + vdd-csiphy0-0p9-supply = <&vreg_0p9_supply>; + vdd-csiphy0-1p2-supply = <&vreg_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 955f0b723c3eea27293b9d6316d0d721f906ca69 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Tue, 12 May 2026 21:49:27 -0700 Subject: [PATCH 22/53] FROMLIST: media: qcom: camss: Add SM8750 compatible camss driver Add SM8750 platform support to the CAMSS driver with ICC bandwidth resources and device tree match entry. Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-2-fc6861a65c67@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/camss.c | 22 ++++++++++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 23 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 49f125b549b6c..4441cb84167ea 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4534,6 +4534,20 @@ static const struct resources_icc icc_res_sa8775p[] = { }, }; +static const struct resources_icc icc_res_sm8750[] = { + { + .name = "ahb", + .icc_bw_tbl.avg = 150000, + .icc_bw_tbl.peak = 300000, + }, + /* Based on 4096 x 3072 30 FPS 2496 Mbps mode */ + { + .name = "hf_mnoc", + .icc_bw_tbl.avg = 471860, + .icc_bw_tbl.peak = 925857, + }, +}; + static const struct camss_subdev_resources csiphy_res_x1e80100[] = { /* CSIPHY0 */ { @@ -6200,6 +6214,13 @@ static const struct camss_resources sm8650_resources = { .vfe_num = ARRAY_SIZE(vfe_res_sm8650), }; +static const struct camss_resources sm8750_resources = { + .version = CAMSS_8750, + .pd_name = "top", + .icc_res = icc_res_sm8750, + .icc_path_num = ARRAY_SIZE(icc_res_sm8750), +}; + static const struct camss_resources x1e80100_resources = { .version = CAMSS_X1E80100, .pd_name = "top", @@ -6251,6 +6272,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sm8250-camss", .data = &sm8250_resources }, { .compatible = "qcom,sm8550-camss", .data = &sm8550_resources }, { .compatible = "qcom,sm8650-camss", .data = &sm8650_resources }, + { .compatible = "qcom,sm8750-camss", .data = &sm8750_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 6695c26fa8885..d0f60931cd1fe 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -95,6 +95,7 @@ enum camss_version { CAMSS_845, CAMSS_8550, CAMSS_8650, + CAMSS_8750, CAMSS_8775P, CAMSS_KAANAPALI, CAMSS_X1E80100, From 3740aaddc7aca6a1810239fbc9b17ae342eb6fec Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:05 -0700 Subject: [PATCH 23/53] FROMLIST: media: qcom: camss: csiphy: Add support for v2.3.0 two-phase CSIPHY Add more detailed resource information for CSIPHY devices in the camss driver along with the support for v2.3.0 in the 2 phase CSIPHY driver that is responsible for the PHY lane register configuration, module reset and interrupt handling. Additionally, generalize the struct name for the lane configuration that had been added for Kaanapali and use it for SM8750 as well as they share the settings. Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-3-fc6861a65c67@oss.qualcomm.com/ --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 5 +- drivers/media/platform/qcom/camss/camss.c | 126 ++++++++++++++++++ 2 files changed, 130 insertions(+), 1 deletion(-) 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 4badd4c64e1ef..4c9e2d86e1a90 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 @@ -804,7 +804,7 @@ csiphy_lane_regs lane_regs_sm8650[] = { {0x0c10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS}, }; -/* 3nm 2PH v 2.4.0 2p5Gbps 4 lane DPHY mode */ +/* 3nm 2PH v 2.3.0/2.4.0 2p5Gbps 4 lane DPHY mode */ static const struct csiphy_lane_regs lane_regs_2_4_0[] = { /* LN 0 */ @@ -1256,6 +1256,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: @@ -1379,7 +1380,9 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sa8775p[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); break; + case CAMSS_8750: case CAMSS_KAANAPALI: + /* CSPHY v2.4.0 is backward compatible with v2.3.0 settings */ regs->lane_regs = &lane_regs_2_4_0[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_2_4_0); regs->offset = 0x1000; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 4441cb84167ea..b554c84513a7f 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4534,6 +4534,129 @@ static const struct resources_icc icc_res_sa8775p[] = { }, }; +static const struct camss_subdev_resources csiphy_res_8750[] = { + /* CSIPHY0 */ + { + .regulators = { + { .supply = "vdd-csiphy0-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy0-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy0", "csiphy0_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy0" }, + .interrupt = { "csiphy0" }, + .csiphy = { + .id = 0, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY1 */ + { + .regulators = { + { .supply = "vdd-csiphy1-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy1-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy1", "csiphy1_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy1" }, + .interrupt = { "csiphy1" }, + .csiphy = { + .id = 1, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY2 */ + { + .regulators = { + { .supply = "vdd-csiphy2-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy2-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy2", "csiphy2_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy2" }, + .interrupt = { "csiphy2" }, + .csiphy = { + .id = 2, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY3 */ + { + .regulators = { + { .supply = "vdd-csiphy3-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy3-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy3", "csiphy3_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy3" }, + .interrupt = { "csiphy3" }, + .csiphy = { + .id = 3, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY4 */ + { + .regulators = { + { .supply = "vdd-csiphy4-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy4-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy4", "csiphy4_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy4" }, + .interrupt = { "csiphy4" }, + .csiphy = { + .id = 4, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, + /* CSIPHY5 */ + { + .regulators = { + { .supply = "vdd-csiphy5-0p9", .init_load_uA = 148000 }, + { .supply = "vdd-csiphy5-1p2", .init_load_uA = 14660 } + }, + .clock = { "csiphy5", "csiphy5_timer", + "cpas_ahb", "cpas_fast_ahb" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000 }, + { 0 }, + { 0 } }, + .reg = { "csiphy5" }, + .interrupt = { "csiphy5" }, + .csiphy = { + .id = 5, + .hw_ops = &csiphy_ops_3ph_1_0, + .formats = &csiphy_formats_sdm845 + } + }, +}; + static const struct resources_icc icc_res_sm8750[] = { { .name = "ahb", @@ -6217,7 +6340,10 @@ static const struct camss_resources sm8650_resources = { static const struct camss_resources sm8750_resources = { .version = CAMSS_8750, .pd_name = "top", + .legacy_phy = true, + .csiphy_res = csiphy_res_8750, .icc_res = icc_res_sm8750, + .csiphy_num = ARRAY_SIZE(csiphy_res_8750), .icc_path_num = ARRAY_SIZE(icc_res_sm8750), }; From 461b099fc85fa31332003392beafde521bde0fad Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:06 -0700 Subject: [PATCH 24/53] FROMLIST: media: qcom: camss: csid: Add support for CSID 980 Add more detailed resource information for CSID devices along with the driver for CSID 980 that is responsible for CSID register configuration, module reset and IRQ handling for BUF_DONE events. In SM8750, RUP and AUP updates for the CSID Full modules are split into two registers along with a SET register. However, CSID Lite modules still use a single register to update RUP and AUP without the additional SET register. Handled such differences in the driver. Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-4-fc6861a65c67@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/Makefile | 1 + .../platform/qcom/camss/camss-csid-980.c | 442 ++++++++++++++++++ .../media/platform/qcom/camss/camss-csid.h | 1 + drivers/media/platform/qcom/camss/camss.c | 75 +++ 4 files changed, 519 insertions(+) create mode 100644 drivers/media/platform/qcom/camss/camss-csid-980.c diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile index b114ca37e36e2..c19d3183882a9 100644 --- a/drivers/media/platform/qcom/camss/Makefile +++ b/drivers/media/platform/qcom/camss/Makefile @@ -8,6 +8,7 @@ qcom-camss-objs += \ camss-csid-4-7.o \ camss-csid-340.o \ camss-csid-680.o \ + camss-csid-980.o \ camss-csid-gen2.o \ camss-csid-gen3.o \ camss-csid-gen4.o \ diff --git a/drivers/media/platform/qcom/camss/camss-csid-980.c b/drivers/media/platform/qcom/camss/camss-csid-980.c new file mode 100644 index 0000000000000..79eb063000b8d --- /dev/null +++ b/drivers/media/platform/qcom/camss/camss-csid-980.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * camss-csid-980.c + * + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + */ +#include +#include +#include +#include +#include +#include +#include "camss.h" +#include "camss-csid.h" +#include "camss-csid-gen3.h" + +/* Reset and Command Registers */ +#define CSID_RST_CFG 0xC +#define RST_MODE BIT(0) +#define RST_LOCATION BIT(4) + +/* Reset and Command Registers */ +#define CSID_RST_CMD 0x10 +#define SELECT_HW_RST BIT(0) +#define SELECT_IRQ_RST BIT(2) +#define CSID_IRQ_CMD 0x14 +#define IRQ_CMD_CLEAR BIT(0) + +/* Register Update Commands, RUP/AUP */ +#define CSID_RUP_CMD 0x18 +#define CSID_AUP_CMD 0x1C +#define CSID_RUP_AUP_RDI(rdi) (BIT(8) << (rdi)) +#define CSID_RUP_AUP_CMD 0x20 +#define RUP_SET BIT(0) +#define MUP BIT(4) + +#define CSID_LITE_RUP_AUP_CMD 0x18 +#define CSID_LITE_RUP_RDI(rdi) (BIT(4) << (rdi)) +#define CSID_LITE_AUP_RDI(rdi) (BIT(20) << (rdi)) + +/* Top level interrupt registers */ +#define CSID_TOP_IRQ_STATUS (csid_is_lite(csid) ? 0x7C : 0x84) +#define CSID_TOP_IRQ_MASK (csid_is_lite(csid) ? 0x80 : 0x88) +#define CSID_TOP_IRQ_CLEAR (csid_is_lite(csid) ? 0x84 : 0x8C) +#define CSID_TOP_IRQ_SET (csid_is_lite(csid) ? 0x88 : 0x90) +#define INFO_RST_DONE BIT(0) +#define CSI2_RX_IRQ_STATUS BIT(2) +#define BUF_DONE_IRQ_STATUS BIT(csid_is_lite(csid) ? 13 : 3) + +/* Buffer done interrupt registers */ +#define CSID_BUF_DONE_IRQ_STATUS (csid_is_lite(csid) ? 0x8C : 0xA4) +#define BUF_DONE_IRQ_STATUS_RDI_OFFSET (csid_is_lite(csid) ? 1 : 16) +#define CSID_BUF_DONE_IRQ_MASK (csid_is_lite(csid) ? 0x90 : 0xA8) +#define CSID_BUF_DONE_IRQ_CLEAR (csid_is_lite(csid) ? 0x94 : 0xAC) +#define CSID_BUF_DONE_IRQ_SET (csid_is_lite(csid) ? 0x98 : 0xB0) + +/* CSI2 RX interrupt registers */ +#define CSID_CSI2_RX_IRQ_STATUS (csid_is_lite(csid) ? 0x9C : 0xB4) +#define CSID_CSI2_RX_IRQ_MASK (csid_is_lite(csid) ? 0xA0 : 0xB8) +#define CSID_CSI2_RX_IRQ_CLEAR (csid_is_lite(csid) ? 0xA4 : 0xBC) +#define CSID_CSI2_RX_IRQ_SET (csid_is_lite(csid) ? 0xA8 : 0xC0) + +/* CSI2 RX Configuration */ +#define CSID_CSI2_RX_CFG0 (csid_is_lite(csid) ? 0x200 : 0x400) +#define CSI2_RX_CFG0_NUM_ACTIVE_LANES 0 +#define CSI2_RX_CFG0_DL0_INPUT_SEL 4 +#define CSI2_RX_CFG0_PHY_NUM_SEL 20 +#define CSID_CSI2_RX_CFG1 (csid_is_lite(csid) ? 0x204 : 0x404) +#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0) +#define CSI2_RX_CFG1_VC_MODE BIT(2) + +#define MSM_CSID_MAX_SRC_STREAMS_980 (csid_is_lite(csid) ? 4 : 5) + +#define CSID_RDI_CFG0(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x500 + 0x100 * _rdi : \ + 0xE00 + 0x200 * _rdi; \ + }) +#define RDI_CFG0_RETIME_BS BIT(5) +#define RDI_CFG0_TIMESTAMP_EN BIT(6) +#define RDI_CFG0_TIMESTAMP_STB_SEL BIT(8) +#define RDI_CFG0_DECODE_FORMAT 12 +#define RDI_CFG0_DT 16 +#define RDI_CFG0_VC 22 +#define RDI_CFG0_DT_ID 27 +#define RDI_CFG0_EN BIT(31) + +/* RDI Control and Configuration */ +#define CSID_RDI_CTRL(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x504 + 0x100 * _rdi : \ + 0xE04 + 0x200 * _rdi; \ + }) +#define RDI_CTRL_START_CMD BIT(0) + +#define CSID_RDI_CFG1(rdi) \ + ({ \ + __typeof__(rdi) _rdi = (rdi); \ + csid_is_lite(csid) ? 0x510 + 0x100 * _rdi : \ + 0xE10 + 0x200 * _rdi; \ + }) +#define RDI_CFG1_DROP_H_EN BIT(5) +#define RDI_CFG1_DROP_V_EN BIT(6) +#define RDI_CFG1_CROP_H_EN BIT(7) +#define RDI_CFG1_CROP_V_EN BIT(8) +#define RDI_CFG1_PACKING_FORMAT_MIPI BIT(15) + +/* RDI Pixel Store Configuration */ +#define CSID_RDI_PIX_STORE_CFG0(rdi) (0xE14 + 0x200 * (rdi)) +#define RDI_PIX_STORE_CFG0_EN BIT(0) +#define RDI_PIX_STORE_CFG0_MIN_HBI 1 + +/* RDI IRQ Status in wrapper */ +#define CSID_CSI2_RDIN_IRQ_STATUS(rdi) \ + (csid_is_lite(csid) ? 0xEC : 0x114 + 0x10 * (rdi)) +#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi) \ + (csid_is_lite(csid) ? 0xF4 : 0x11C + 0x10 * (rdi)) +#define INFO_RUP_DONE BIT(23) + +static void __csid_full_aup_rup_trigger(struct csid_device *csid) +{ + /* trigger SET in combined register */ + writel(RUP_SET, csid->base + CSID_RUP_AUP_CMD); +} + +static void __csid_aup_update(struct csid_device *csid, int port_id) +{ + if (csid_is_lite(csid)) { + /* CSID Lites in v980 follow the legacy way of a combined RUP + * and AUP commands without an explicit SET register. + */ + csid->reg_update |= CSID_LITE_AUP_RDI(port_id); + writel(csid->reg_update, csid->base + CSID_LITE_RUP_AUP_CMD); + } else { + csid->aup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->aup_update, csid->base + CSID_AUP_CMD); + + /* CSID Fulls in v980 split AUP and RUP commands, which requires + * additional SET operation to make registers modification take + * effect. + */ + __csid_full_aup_rup_trigger(csid); + } +} + +static void __csid_rup_update(struct csid_device *csid, int port_id) +{ + if (csid_is_lite(csid)) { + /* CSID Lites in v980 follow the legacy way of a combined RUP + * and AUP commands without an explicit SET register. + */ + csid->reg_update |= CSID_LITE_RUP_RDI(port_id); + writel(csid->reg_update, csid->base + CSID_LITE_RUP_AUP_CMD); + } else { + csid->rup_update |= CSID_RUP_AUP_RDI(port_id); + writel(csid->rup_update, csid->base + CSID_RUP_CMD); + + /* CSID Fulls in v980 split AUP and RUP commands, which requires + * additional SET operation to make registers modification take + * effect. + */ + __csid_full_aup_rup_trigger(csid); + } +} + +static void __csid_aup_rup_clear(struct csid_device *csid, int port_id) +{ + /* Hardware clears the registers upon consuming the settings */ + if (csid_is_lite(csid)) { + csid->reg_update &= ~CSID_LITE_RUP_RDI(port_id); + csid->reg_update &= ~CSID_LITE_AUP_RDI(port_id); + } else { + csid->aup_update &= ~CSID_RUP_AUP_RDI(port_id); + csid->rup_update &= ~CSID_RUP_AUP_RDI(port_id); + } +} + +static void __csid_configure_rx(struct csid_device *csid, + struct csid_phy_config *phy) +{ + int val; + + 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; + writel(val, csid->base + CSID_CSI2_RX_CFG0); + + val = CSI2_RX_CFG1_ECC_CORRECTION_EN; + writel(val, csid->base + CSID_CSI2_RX_CFG1); +} + +static void __csid_configure_rx_vc(struct csid_device *csid, int vc) +{ + int val; + + if (vc > 3) { + val = readl(csid->base + CSID_CSI2_RX_CFG1); + val |= CSI2_RX_CFG1_VC_MODE; + writel(val, csid->base + CSID_CSI2_RX_CFG1); + } +} + +static void __csid_ctrl_rdi(struct csid_device *csid, int enable, u8 rdi) +{ + int val = 0; + u32 rdi_ctrl_offset = CSID_RDI_CTRL(rdi); + + if (enable) + val = RDI_CTRL_START_CMD; + + writel(val, csid->base + rdi_ctrl_offset); +} + +static void __csid_configure_rdi_pix_store(struct csid_device *csid, u8 rdi) +{ + u32 val; + + /* + * Configure pixel store to allow absorption of hblanking or idle time. + * This helps with horizontal crop and prevents line buffer conflicts. + * Reset state is 0x8 which has MIN_HBI=4, we keep the default MIN_HBI + * and just enable the pixel store functionality. + */ + val = (4 << RDI_PIX_STORE_CFG0_MIN_HBI) | RDI_PIX_STORE_CFG0_EN; + writel(val, csid->base + CSID_RDI_PIX_STORE_CFG0(rdi)); +} + +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 port, u8 vc) +{ + u32 val; + u8 lane_cnt = csid->phy.lane_cnt; + + /* Source pads matching RDI channels on hardware. + * E.g. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. + */ + struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + port]; + const struct csid_format_info *format = csid_get_fmt_entry(csid->res->formats->formats, + csid->res->formats->nformats, + input_format->code); + + if (!lane_cnt) + lane_cnt = 4; + + /* + * DT_ID is a two bit bitfield that is concatenated with + * the four least significant bits of the five bit VC + * bitfield to generate an internal CID value. + * + * CSID_RDI_CFG0(vc) + * DT_ID : 28:27 + * VC : 26:22 + * DT : 21:16 + * + * CID : VC 3:0 << 2 | DT_ID 1:0 + */ + u8 dt_id = vc & 0x03; + u32 rdi_cfg0_offset = CSID_RDI_CFG0(port); + u32 rdi_cfg1_offset = CSID_RDI_CFG1(port); + u32 rdi_ctrl_offset = CSID_RDI_CTRL(port); + + val = RDI_CFG0_TIMESTAMP_EN; + val |= RDI_CFG0_TIMESTAMP_STB_SEL; + val |= RDI_CFG0_RETIME_BS; + + /* note: for non-RDI path, this should be format->decode_format */ + val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT; + val |= vc << RDI_CFG0_VC; + val |= format->data_type << RDI_CFG0_DT; + val |= dt_id << RDI_CFG0_DT_ID; + writel(val, csid->base + rdi_cfg0_offset); + + val = RDI_CFG1_PACKING_FORMAT_MIPI; + writel(val, csid->base + rdi_cfg1_offset); + + /* Configure pixel store using dedicated register in 980 */ + if (!csid_is_lite(csid)) + __csid_configure_rdi_pix_store(csid, port); + + val = 0; + writel(val, csid->base + rdi_ctrl_offset); + + val = readl(csid->base + rdi_cfg0_offset); + + if (enable) + val |= RDI_CFG0_EN; + + writel(val, csid->base + rdi_cfg0_offset); +} + +static void csid_configure_stream(struct csid_device *csid, u8 enable) +{ + u8 i, k; + + __csid_configure_rx(csid, &csid->phy); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + __csid_configure_rdi_stream(csid, enable, i, 0); + __csid_configure_rx_vc(csid, 0); + + for (k = 0; k < CAMSS_INIT_BUF_COUNT; k++) { + __csid_aup_update(csid, i); + __csid_rup_update(csid, i); + } + + __csid_ctrl_rdi(csid, enable, i); + } + } +} + +static int csid_configure_testgen_pattern(struct csid_device *csid, s32 val) +{ + return 0; +} + +static void csid_subdev_reg_update(struct csid_device *csid, int port_id, + bool clear) +{ + if (clear) + __csid_aup_rup_clear(csid, port_id); + else + __csid_aup_update(csid, port_id); +} + +/** + * csid_isr - CSID module interrupt service routine + * @irq: Interrupt line + * @dev: CSID device + * + * Return IRQ_HANDLED on success + */ +static irqreturn_t csid_isr(int irq, void *dev) +{ + struct csid_device *csid = dev; + u32 val, buf_done_val; + u8 reset_done; + int i; + + val = readl(csid->base + CSID_TOP_IRQ_STATUS); + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + + reset_done = val & INFO_RST_DONE; + + buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS); + writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i)); + writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i)); + + if (val & INFO_RUP_DONE) + csid_subdev_reg_update(csid, i, true); + + if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i)) + camss_buf_done(csid->camss, csid->id, i); + } + } + + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + if (reset_done) + complete(&csid->reset_complete); + + return IRQ_HANDLED; +} + +/** + * csid_reset - Trigger reset on CSID module and wait to complete + * @csid: CSID device + * + * Return 0 on success or a negative error code otherwise + */ +static int csid_reset(struct csid_device *csid) +{ + unsigned long time; + u32 val; + int i; + + reinit_completion(&csid->reset_complete); + + val = INFO_RST_DONE | BUF_DONE_IRQ_STATUS; + writel(val, csid->base + CSID_TOP_IRQ_CLEAR); + writel(val, csid->base + CSID_TOP_IRQ_MASK); + + val = 0; + for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS_980; i++) { + if (csid->phy.en_vc & BIT(i)) { + /* + * Only need to clear buf done IRQ status here, + * RUP done IRQ status will be cleared once isr + * strobe generated by CSID_RST_CMD + */ + val |= BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i); + } + } + writel(val, csid->base + CSID_BUF_DONE_IRQ_CLEAR); + writel(val, csid->base + CSID_BUF_DONE_IRQ_MASK); + + /* Clear all IRQ status with CLEAR bits set */ + val = IRQ_CMD_CLEAR; + writel(val, csid->base + CSID_IRQ_CMD); + + val = RST_LOCATION | RST_MODE; + writel(val, csid->base + CSID_RST_CFG); + + val = SELECT_HW_RST | SELECT_IRQ_RST; + writel(val, csid->base + CSID_RST_CMD); + + time = wait_for_completion_timeout(&csid->reset_complete, + msecs_to_jiffies(CSID_RESET_TIMEOUT_MS)); + + if (!time) { + dev_err(csid->camss->dev, "CSID reset timeout\n"); + return -ETIMEDOUT; + } + + return 0; +} + +static void csid_subdev_init(struct csid_device *csid) +{ + csid->testgen.nmodes = CSID_PAYLOAD_MODE_DISABLED; +} + +const struct csid_hw_ops csid_ops_980 = { + .configure_stream = csid_configure_stream, + .configure_testgen_pattern = csid_configure_testgen_pattern, + .hw_version = csid_hw_version, + .isr = csid_isr, + .reset = csid_reset, + .src_pad_code = csid_src_pad_code, + .subdev_init = csid_subdev_init, + .reg_update = csid_subdev_reg_update, +}; + diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index e6590b2bd8be5..dd9c0868e9c73 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -224,6 +224,7 @@ extern const struct csid_hw_ops csid_ops_4_1; extern const struct csid_hw_ops csid_ops_4_7; extern const struct csid_hw_ops csid_ops_340; extern const struct csid_hw_ops csid_ops_680; +extern const struct csid_hw_ops csid_ops_980; extern const struct csid_hw_ops csid_ops_gen2; extern const struct csid_hw_ops csid_ops_gen3; extern const struct csid_hw_ops csid_ops_gen4; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index b554c84513a7f..d93f89d33b8c2 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4657,6 +4657,79 @@ static const struct camss_subdev_resources csiphy_res_8750[] = { }, }; +static const struct camss_subdev_resources csid_res_8750[] = { + /* CSID0 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid0" }, + .interrupt = { "csid0" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID1 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid1" }, + .interrupt = { "csid1" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID2 */ + { + .clock = { "csid", "csid_csiphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid2" }, + .interrupt = { "csid2" }, + .csid = { + .is_lite = false, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE0 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite0" }, + .interrupt = { "csid_lite0" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + }, + /* CSID_LITE1 */ + { + .clock = { "vfe_lite_csid", "vfe_lite_cphy_rx" }, + .clock_rate = { { 400000000, 480000000 }, + { 400000000, 480000000 } }, + .reg = { "csid_lite1" }, + .interrupt = { "csid_lite1" }, + .csid = { + .is_lite = true, + .parent_dev_ops = &vfe_parent_dev_ops, + .hw_ops = &csid_ops_980, + .formats = &csid_formats_gen2 + } + } +}; + static const struct resources_icc icc_res_sm8750[] = { { .name = "ahb", @@ -6342,8 +6415,10 @@ static const struct camss_resources sm8750_resources = { .pd_name = "top", .legacy_phy = true, .csiphy_res = csiphy_res_8750, + .csid_res = csid_res_8750, .icc_res = icc_res_sm8750, .csiphy_num = ARRAY_SIZE(csiphy_res_8750), + .csid_num = ARRAY_SIZE(csid_res_8750), .icc_path_num = ARRAY_SIZE(icc_res_sm8750), }; From e6d1bb2b4b7b34bd91793f1ba9ef82b69a6021a6 Mon Sep 17 00:00:00 2001 From: Hangxiang Ma Date: Fri, 8 May 2026 02:51:07 -0700 Subject: [PATCH 25/53] FROMLIST: media: qcom: camss: vfe: Add support for VFE 980 Add support for Video Front End (VFE) that is on the SM8750 SoCs. VFE gen4 has support for VFE 980. This change limits SM8750 VFE output lines to 3 for now as constrained by the CAMSS driver framework. Reviewed-by: Bryan O'Donoghue Co-developed-by: Atiya Kailany Signed-off-by: Atiya Kailany Signed-off-by: Hangxiang Ma Link: https://lore.kernel.org/all/20260508-add-support-for-camss-on-sm8750-v3-5-fc6861a65c67@oss.qualcomm.com/ --- .../platform/qcom/camss/camss-vfe-gen4.c | 10 +- drivers/media/platform/qcom/camss/camss-vfe.c | 2 + drivers/media/platform/qcom/camss/camss.c | 135 ++++++++++++++++++ 3 files changed, 144 insertions(+), 3 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c index d73d70898710a..46d8e61b9bac0 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe-gen4.c +++ b/drivers/media/platform/qcom/camss/camss-vfe-gen4.c @@ -13,8 +13,12 @@ #include "camss.h" #include "camss-vfe.h" -/* VFE-gen4 Bus Register Base Addresses */ -#define BUS_REG_BASE (vfe_is_lite(vfe) ? 0x800 : 0x1000) +#define IS_VFE_980(vfe) ((vfe)->camss->res->version == CAMSS_8750) + +#define BUS_REG_BASE_980 (vfe_is_lite(vfe) ? 0x200 : 0x800) +#define BUS_REG_BASE_1080 (vfe_is_lite(vfe) ? 0x800 : 0x1000) +#define BUS_REG_BASE \ + (IS_VFE_980(vfe) ? BUS_REG_BASE_980 : BUS_REG_BASE_1080) #define VFE_BUS_WM_CGC_OVERRIDE (BUS_REG_BASE + 0x08) #define WM_CGC_OVERRIDE_ALL (0x7FFFFFF) @@ -55,7 +59,7 @@ * DISPLAY_DS2_C 6 * FD_Y 7 * FD_C 8 - * PIXEL_RAW 9 + * RAW_OUT(1080)/IR_OUT(980) 9 * STATS_AEC_BG 10 * STATS_AEC_BHIST 11 * STATS_TINTLESS_BG 12 diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index dbe5a9af452bf..57c5be461c3b4 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -352,6 +352,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: @@ -2017,6 +2018,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_845: case CAMSS_8550: case CAMSS_8650: + case CAMSS_8750: case CAMSS_8775P: case CAMSS_KAANAPALI: case CAMSS_X1E80100: diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index d93f89d33b8c2..212bd3736d368 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4730,6 +4730,139 @@ static const struct camss_subdev_resources csid_res_8750[] = { } }; +static const struct camss_subdev_resources vfe_res_8750[] = { + /* VFE0 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe0_fast_ahb", "vfe0", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe0" }, + .interrupt = { "vfe0" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife0", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE1 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe1_fast_ahb", "vfe1", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe1" }, + .interrupt = { "vfe1" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife1", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE2 - TFE Full */ + { + .clock = { "gcc_axi_hf", "vfe2_fast_ahb", "vfe2", + "cpas_vfe0", "cpas_vfe1", "cpas_vfe2", + "camnoc_rt_axi", "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 360280000, 480000000, 630000000, 716000000, + 833000000 }, + { 0 }, + { 0 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe2" }, + .interrupt = { "vfe2" }, + .vfe = { + .line_num = 3, + .is_lite = false, + .reg_update_after_csid_config = true, + .has_pd = true, + .pd_name = "ife2", + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE0 */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite0" }, + .interrupt = { "vfe_lite0" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + }, + /* VFE_LITE1 */ + { + .clock = { "gcc_axi_hf", "vfe_lite_ahb", "vfe_lite", + "cpas_vfe_lite", "camnoc_rt_axi", + "camnoc_nrt_axi", "qdss_debug_xo" }, + .clock_rate = { { 0 }, + { 0 }, + { 266666667, 400000000, 480000000 }, + { 0 }, + { 200000000, 300000000, 400000000, 480000000 }, + { 0 }, + { 0 } }, + .reg = { "vfe_lite1" }, + .interrupt = { "vfe_lite1" }, + .vfe = { + .line_num = 4, + .is_lite = true, + .reg_update_after_csid_config = true, + .hw_ops = &vfe_ops_gen4, + .formats_rdi = &vfe_formats_rdi_845, + .formats_pix = &vfe_formats_pix_845 + } + } +}; + static const struct resources_icc icc_res_sm8750[] = { { .name = "ahb", @@ -6416,9 +6549,11 @@ static const struct camss_resources sm8750_resources = { .legacy_phy = true, .csiphy_res = csiphy_res_8750, .csid_res = csid_res_8750, + .vfe_res = vfe_res_8750, .icc_res = icc_res_sm8750, .csiphy_num = ARRAY_SIZE(csiphy_res_8750), .csid_num = ARRAY_SIZE(csid_res_8750), + .vfe_num = ARRAY_SIZE(vfe_res_8750), .icc_path_num = ARRAY_SIZE(icc_res_sm8750), }; From a60e1a0ceb11b292ea9f688cc8f84aafce50304b Mon Sep 17 00:00:00 2001 From: Nihal Kumar Gupta Date: Tue, 19 May 2026 14:29:37 +0530 Subject: [PATCH 26/53] FROMLIST: dt-bindings: media: Add bindings for qcom,glymur-camss Add device tree bindings for the Camera Subsystem (CAMSS) on the Qualcomm Glymur platform. The Glymur platform provides: - 3 x CSIPHY (CSI Physical Layer) - 3 x CSID (CSI Decoder), 2 x CSID Lite - 3 x TPG (Test Pattern Generator) - 2 x VFE (Video Front End), 2 x VFE Lite Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260529-glymur_camss-v1-1-bee535396d22@oss.qualcomm.com/ --- .../bindings/media/qcom,glymur-camss.yaml | 343 ++++++++++++++++++ 1 file changed, 343 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/qcom,glymur-camss.yaml diff --git a/Documentation/devicetree/bindings/media/qcom,glymur-camss.yaml b/Documentation/devicetree/bindings/media/qcom,glymur-camss.yaml new file mode 100644 index 0000000000000..5596f3fb99003 --- /dev/null +++ b/Documentation/devicetree/bindings/media/qcom,glymur-camss.yaml @@ -0,0 +1,343 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/qcom,glymur-camss.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Qualcomm Glymur Camera Subsystem (CAMSS) + +maintainers: + - Nihal Kumar Gupta + +description: + The CAMSS IP is a CSI decoder and ISP present on Qualcomm platforms. + +properties: + compatible: + const: qcom,glymur-camss + + reg: + maxItems: 16 + + reg-names: + items: + - const: csid_wrapper + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy4 + - const: csitpg0 + - const: csitpg1 + - const: csitpg2 + - const: vfe0 + - const: vfe1 + - const: vfe_lite0 + - const: vfe_lite1 + + clocks: + maxItems: 26 + + 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_vfe1 + - const: cpas_vfe_lite + - const: csid + - const: csid_csiphy_rx + - const: csiphy0 + - const: csiphy0_timer + - const: csiphy1 + - const: csiphy1_timer + - const: csiphy4 + - const: csiphy4_timer + - const: gcc_axi_hf + - const: gcc_axi_sf + - const: vfe0 + - const: vfe0_fast_ahb + - const: vfe1 + - const: vfe1_fast_ahb + - const: vfe_lite + - const: vfe_lite_ahb + - const: vfe_lite_cphy_rx + - const: vfe_lite_csid + + interrupts: + maxItems: 12 + + interrupt-names: + items: + - const: csid0 + - const: csid1 + - const: csid2 + - const: csid_lite0 + - const: csid_lite1 + - const: csiphy0 + - const: csiphy1 + - const: csiphy4 + - const: vfe0 + - const: vfe1 + - 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: + maxItems: 1 + + power-domains: + items: + - description: IFE0 GDSC - Image Front End, Global Distributed Switch Controller. + - description: IFE1 GDSC - Image Front End, Global Distributed Switch Controller. + - description: Titan Top GDSC - Titan ISP Block, Global Distributed Switch Controller. + + power-domain-names: + items: + - const: ife0 + - const: ife1 + - const: top + + vdd-csiphy-0p8-supply: + description: + Phandle to 0.8V regulator supply to CSI PHYs. + + vdd-csiphy-1p2-supply: + description: + Phandle to a 1.2V regulator supply to CSI PHYs pll block. + + ports: + $ref: /schemas/graph.yaml#/properties/ports + + description: + CSI input ports. + + patternProperties: + "^port@[0-2]$": + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false + + description: + Input port for receiving CSI data. + + properties: + endpoint: + $ref: video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + minItems: 1 + maxItems: 4 + + bus-type: + enum: + - 1 # MEDIA_BUS_TYPE_CSI2_CPHY + - 4 # MEDIA_BUS_TYPE_CSI2_DPHY + + required: + - data-lanes + +required: + - compatible + - reg + - reg-names + - clocks + - clock-names + - interrupts + - interrupt-names + - interconnects + - interconnect-names + - iommus + - power-domains + - power-domain-names + - ports + +additionalProperties: false + +examples: + - | + #include + #include + #include + #include + #include + #include + + soc { + #address-cells = <2>; + #size-cells = <2>; + + camss: isp@acb6000 { + compatible = "qcom,glymur-camss"; + + reg = <0x0 0x0acb6000 0x0 0x1000>, + <0x0 0x0acb7000 0x0 0x2000>, + <0x0 0x0acb9000 0x0 0x2000>, + <0x0 0x0acbb000 0x0 0x2000>, + <0x0 0x0acc6000 0x0 0x1000>, + <0x0 0x0acca000 0x0 0x1000>, + <0x0 0x0ace4000 0x0 0x2000>, + <0x0 0x0ace6000 0x0 0x2000>, + <0x0 0x0acec000 0x0 0x2000>, + <0x0 0x0acf6000 0x0 0x1000>, + <0x0 0x0acf7000 0x0 0x1000>, + <0x0 0x0acf8000 0x0 0x1000>, + <0x0 0x0ac62000 0x0 0xf000>, + <0x0 0x0ac71000 0x0 0xf000>, + <0x0 0x0acc7000 0x0 0x2000>, + <0x0 0x0accb000 0x0 0x2000>; + + reg-names = "csid_wrapper", + "csid0", + "csid1", + "csid2", + "csid_lite0", + "csid_lite1", + "csiphy0", + "csiphy1", + "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_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_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", + "csid", + "csid_csiphy_rx", + "csiphy0", + "csiphy0_timer", + "csiphy1", + "csiphy1_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", + "csiphy4", + "vfe0", + "vfe1", + "vfe_lite0", + "vfe_lite1"; + + interconnects = <&hsc_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 0x00>; + + 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"; + + 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 2 3>; + remote-endpoint = <&sensor_ep>; + }; + }; + }; + }; + }; From 4795a43b68c52948a7dde8a135680960f2925709 Mon Sep 17 00:00:00 2001 From: Prashant Shrotriya Date: Mon, 25 May 2026 10:44:33 +0530 Subject: [PATCH 27/53] FROMLIST: media: qcom: camss: Add Glymur compatible Add CAMSS_GLYMUR enum, Glymur compatible and Glymur camss driver private data, the private data just include some basic information for now, later changes will enumerate with csiphy, tpg, csid and vfe resources. Signed-off-by: Prashant Shrotriya Link: https://lore.kernel.org/all/20260529-glymur_camss-v1-3-bee535396d22@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/camss.c | 7 +++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 212bd3736d368..40a7187cae061 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -6589,7 +6589,14 @@ static const struct camss_resources x1p42100_resources = { .vfe_num = ARRAY_SIZE(vfe_res_x1p42100), }; +static const struct camss_resources glymur_resources = { + .version = CAMSS_GLYMUR, + .pd_name = "top", + .legacy_phy = true, +}; + static const struct of_device_id camss_dt_match[] = { + { .compatible = "qcom,glymur-camss", .data = &glymur_resources }, { .compatible = "qcom,kaanapali-camss", .data = &kaanapali_resources }, { .compatible = "qcom,msm8916-camss", .data = &msm8916_resources }, { .compatible = "qcom,msm8939-camss", .data = &msm8939_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index d0f60931cd1fe..7cd35c838d74a 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -97,6 +97,7 @@ enum camss_version { CAMSS_8650, CAMSS_8750, CAMSS_8775P, + CAMSS_GLYMUR, CAMSS_KAANAPALI, CAMSS_X1E80100, CAMSS_X1P42100, From b0f09b1cdaad5e25f8aeee9ca4ca10730483df97 Mon Sep 17 00:00:00 2001 From: Prashant Shrotriya Date: Mon, 25 May 2026 10:57:02 +0530 Subject: [PATCH 28/53] FROMLIST: media: qcom: camss: Add CSIPHY support for Glymur Glymur uses the same CSIPHY hardware version as x1e80100. The only difference between the two platforms is the number of CSIPHY instances. x1e80100 has four, while Glymur has three. Signed-off-by: Prashant Shrotriya Link: https://lore.kernel.org/all/20260529-glymur_camss-v1-4-bee535396d22@oss.qualcomm.com/ --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 2 + drivers/media/platform/qcom/camss/camss.c | 54 +++++++++++++++++++ 2 files changed, 56 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 4c9e2d86e1a90..6de38deb63b97 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 @@ -1258,6 +1258,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_8650: case CAMSS_8750: case CAMSS_8775P: + case CAMSS_GLYMUR: case CAMSS_KAANAPALI: case CAMSS_X1E80100: case CAMSS_X1P42100: @@ -1359,6 +1360,7 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_regs = &lane_regs_sc8280xp[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sc8280xp); break; + case CAMSS_GLYMUR: case CAMSS_X1E80100: case CAMSS_X1P42100: regs->lane_regs = &lane_regs_x1e80100[0]; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 40a7187cae061..630ca2a625c03 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5282,6 +5282,60 @@ static const struct camss_subdev_resources vfe_res_x1p42100[] = { }, }; +static const struct camss_subdev_resources csiphy_res_glymur[] = { + /* 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, + .formats = &csiphy_formats_sdm845 + }, + }, + /* 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, + .formats = &csiphy_formats_sdm845 + }, + }, + /* 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, + .formats = &csiphy_formats_sdm845 + }, + }, +}; + /* * camss_add_clock_margin - Add margin to clock frequency rate * @rate: Clock frequency rate From 345791f64da4738f15fe018222b63d38d4a81982 Mon Sep 17 00:00:00 2001 From: Prashant Shrotriya Date: Mon, 25 May 2026 11:03:09 +0530 Subject: [PATCH 29/53] FROMLIST: media: qcom: camss: enable vfe for Glymur Extend vfe_src_pad_code() and vfe_bpl_align() for Glymur. Signed-off-by: Prashant Shrotriya Link: https://lore.kernel.org/all/20260529-glymur_camss-v1-5-bee535396d22@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/camss-vfe.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 57c5be461c3b4..36e39d55a4a8c 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -354,6 +354,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_8650: case CAMSS_8750: case CAMSS_8775P: + case CAMSS_GLYMUR: case CAMSS_KAANAPALI: case CAMSS_X1E80100: case CAMSS_X1P42100: @@ -2020,6 +2021,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_8650: case CAMSS_8750: case CAMSS_8775P: + case CAMSS_GLYMUR: case CAMSS_KAANAPALI: case CAMSS_X1E80100: case CAMSS_X1P42100: From cb3f2b342ae4d1c995463e4621f23c2dfdccb531 Mon Sep 17 00:00:00 2001 From: Prashant Shrotriya Date: Mon, 25 May 2026 11:07:06 +0530 Subject: [PATCH 30/53] FROMLIST: media: qcom: camss: Enumerate resources for Glymur Enumerate csiphy, csid and vfe resources for Glymur. Signed-off-by: Prashant Shrotriya Link: https://lore.kernel.org/all/20260529-glymur_camss-v1-6-bee535396d22@oss.qualcomm.com/ --- drivers/media/platform/qcom/camss/camss.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 630ca2a625c03..b9940a95e33bf 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -6647,6 +6647,17 @@ static const struct camss_resources glymur_resources = { .version = CAMSS_GLYMUR, .pd_name = "top", .legacy_phy = true, + .csiphy_res = csiphy_res_glymur, + .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_glymur), + .tpg_num = ARRAY_SIZE(tpg_res_x1e80100), + .csid_num = ARRAY_SIZE(csid_res_x1e80100), + .vfe_num = ARRAY_SIZE(vfe_res_x1e80100), }; static const struct of_device_id camss_dt_match[] = { From a43e45b784089276cc763358a2be21b0508322c3 Mon Sep 17 00:00:00 2001 From: Prashant Shrotriya Date: Fri, 15 May 2026 19:16:22 +0530 Subject: [PATCH 31/53] FROMLIST: media: qcom: camss: add support for QCM2390 camss Add CAMSS driver support for Shikra SoC. Add high level resource definitions for 2 CSIPHY, 2 CSID and 2 VFE instances along with the interconnect bandwidth votes for AHB, HF and SF MNOC paths. Signed-off-by: Prashant Shrotriya Signed-off-by: Nihal Kumar Gupta Link: https://lore.kernel.org/all/20260526-shikra-camss-review-v1-3-645d2c8c75a7@qti.qualcomm.com/ --- .../platform/qcom/camss/camss-csiphy-3ph-1-0.c | 2 ++ drivers/media/platform/qcom/camss/camss-vfe.c | 1 + drivers/media/platform/qcom/camss/camss.c | 14 ++++++++++++++ drivers/media/platform/qcom/camss/camss.h | 1 + 4 files changed, 18 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 6de38deb63b97..75c0aef3725e2 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 @@ -1247,6 +1247,7 @@ static bool csiphy_is_gen2(u32 version) switch (version) { case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: case CAMSS_6350: case CAMSS_7280: @@ -1343,6 +1344,7 @@ static int csiphy_init(struct csiphy_device *csiphy) regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); break; case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: regs->lane_regs = &lane_regs_qcm2290[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_qcm2290); diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index 36e39d55a4a8c..c12814085b077 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -342,6 +342,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, break; case CAMSS_660: case CAMSS_2290: + case CAMSS_2390: case CAMSS_6150: case CAMSS_6350: case CAMSS_7280: diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index b9940a95e33bf..234fb6741ea29 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -6428,6 +6428,19 @@ static const struct camss_resources qcm2290_resources = { .vfe_num = ARRAY_SIZE(vfe_res_2290), }; +static const struct camss_resources qcm2390_resources = { + .version = CAMSS_2390, + .legacy_phy = true, + .csiphy_res = csiphy_res_2290, + .csid_res = csid_res_2290, + .vfe_res = vfe_res_2290, + .icc_res = icc_res_2290, + .icc_path_num = ARRAY_SIZE(icc_res_2290), + .csiphy_num = ARRAY_SIZE(csiphy_res_2290), + .csid_num = ARRAY_SIZE(csid_res_2290), + .vfe_num = ARRAY_SIZE(vfe_res_2290), +}; + static const struct camss_resources qcs8300_resources = { .version = CAMSS_8300, .pd_name = "top", @@ -6675,6 +6688,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sdm660-camss", .data = &sdm660_resources }, { .compatible = "qcom,sdm670-camss", .data = &sdm670_resources }, { .compatible = "qcom,sdm845-camss", .data = &sdm845_resources }, + { .compatible = "qcom,shikra-camss", .data = &qcm2390_resources }, { .compatible = "qcom,sm6150-camss", .data = &sm6150_resources }, { .compatible = "qcom,sm6350-camss", .data = &sm6350_resources }, { .compatible = "qcom,sm8250-camss", .data = &sm8250_resources }, diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 7cd35c838d74a..91438769419e5 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -82,6 +82,7 @@ enum pm_domain { enum camss_version { CAMSS_660, CAMSS_2290, + CAMSS_2390, CAMSS_6150, CAMSS_6350, CAMSS_7280, From 00e274f0f861e4be22538636040e58bb67549eef Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Thu, 25 Jun 2026 17:42:45 +0800 Subject: [PATCH 32/53] FROMLIST: i2c: qcom-cci: drop custom suspend/resume and rely on runtime PM helpers cci_resume() unconditionally calls cci_resume_runtime() regardless of the runtime PM state. If the device is already runtime-suspended before system suspend, the clock is re-enabled while runtime_status remains RPM_SUSPENDED. As a result, pm_request_autosuspend() does not arm the timer, leaving the clock permanently enabled. Fixes: e517526195de ("i2c: Add Qualcomm CCI I2C driver") Cc: stable@vger.kernel.org Reviewed-by: Vladimir Zapolskiy Reviewed-by: Konrad Dybcio Reviewed-by: Loic Poulain Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/all/20260625-cci-v1-1-a100cda673ce@oss.qualcomm.com/ --- drivers/i2c/busses/i2c-qcom-cci.c | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/drivers/i2c/busses/i2c-qcom-cci.c b/drivers/i2c/busses/i2c-qcom-cci.c index 4d64895a9e9e4..bdeda3979c481 100644 --- a/drivers/i2c/busses/i2c-qcom-cci.c +++ b/drivers/i2c/busses/i2c-qcom-cci.c @@ -492,24 +492,8 @@ static int __maybe_unused cci_resume_runtime(struct device *dev) return 0; } -static int __maybe_unused cci_suspend(struct device *dev) -{ - if (!pm_runtime_suspended(dev)) - return cci_suspend_runtime(dev); - - return 0; -} - -static int __maybe_unused cci_resume(struct device *dev) -{ - cci_resume_runtime(dev); - pm_request_autosuspend(dev); - - return 0; -} - static const struct dev_pm_ops qcom_cci_pm = { - SET_SYSTEM_SLEEP_PM_OPS(cci_suspend, cci_resume) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) SET_RUNTIME_PM_OPS(cci_suspend_runtime, cci_resume_runtime, NULL) }; From 06c38ef8bbccc480f37f123833211f2a8fb63d1c Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:19 +0200 Subject: [PATCH 33/53] FROMLIST: media: qcom: camss: csiphy-3ph: Fix lane mask calculation The lane mask must be multiplied by 2, but this was accidentally omitted. Link: https://lore.kernel.org/r/20260617-qcom-cphy-v9-1-83da8a8e4e44@ixit.cz Reviewed-by: Vladimir Zapolskiy Suggested-by: Nihal Kumar Gupta Signed-off-by: David Heidelberg Signed-off-by: Anusha Arun Nandi --- drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 75c0aef3725e2..4d99d334dad4c 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 @@ -1236,7 +1236,7 @@ static u8 csiphy_get_lane_mask(struct csiphy_lanes_cfg *lane_cfg) lane_mask = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; for (i = 0; i < lane_cfg->num_data; i++) - lane_mask |= 1 << lane_cfg->data[i].pos; + lane_mask |= BIT(lane_cfg->data[i].pos * 2); return lane_mask; } From 85295a8dffc048efddc2146f51e6f05657ff3f63 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:20 +0200 Subject: [PATCH 34/53] FROMLIST: media: qcom: camss: csiphy: Introduce PHY configuration Read PHY configuration from the device-tree bus-type and save it into the csiphy structure for later use. For C-PHY, skip clock line configuration, as there is none. Link: https://lore.kernel.org/r/20260617-qcom-cphy-v9-2-83da8a8e4e44@ixit.cz Acked-by: Cory Keitz Reviewed-by: Bryan O'Donoghue Reviewed-by: Frank Li Signed-off-by: David Heidelberg Signed-off-by: Anusha Arun Nandi --- drivers/media/platform/qcom/camss/camss-csiphy.h | 2 ++ drivers/media/platform/qcom/camss/camss.c | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h index 1879826034aac..e8a7445f146db 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.h +++ b/drivers/media/platform/qcom/camss/camss-csiphy.h @@ -31,11 +31,13 @@ struct csiphy_lane { /** * struct csiphy_lanes_cfg - CSIPHY lanes configuration + * @phy_cfg: interface selection (C-PHY or D-PHY) * @num_data: number of data lanes * @data: data lanes configuration * @clk: clock lane configuration (only for D-PHY) */ struct csiphy_lanes_cfg { + enum v4l2_mbus_type phy_cfg; int num_data; struct csiphy_lane *data; struct csiphy_lane clk; diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 234fb6741ea29..696263abefff2 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5566,9 +5566,13 @@ static int camss_parse_endpoint_node(struct device *dev, csd->interface.csiphy_id = vep.base.port; mipi_csi2 = &vep.bus.mipi_csi2; - lncfg->clk.pos = mipi_csi2->clock_lane; - lncfg->clk.pol = mipi_csi2->lane_polarities[0]; lncfg->num_data = mipi_csi2->num_data_lanes; + lncfg->phy_cfg = vep.bus_type; + + if (lncfg->phy_cfg != V4L2_MBUS_CSI2_CPHY) { + lncfg->clk.pos = mipi_csi2->clock_lane; + lncfg->clk.pol = mipi_csi2->lane_polarities[0]; + } lncfg->data = devm_kcalloc(dev, lncfg->num_data, sizeof(*lncfg->data), From bed32de90b18e15ca76fd7d701f89fee4f754ae4 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:21 +0200 Subject: [PATCH 35/53] FROMLIST: media: qcom: camss: csiphy-3ph: Use odd bits for configuring C-PHY lanes So far, only D-PHY mode was supported, which uses even bits when enabling or masking lanes. For C-PHY configuration, the hardware instead requires using the odd bits. Since there can be unrecognized configuration allow returning failure. Link: https://lore.kernel.org/r/20260617-qcom-cphy-v9-3-83da8a8e4e44@ixit.cz Acked-by: Cory Keitz Reviewed-by: Bryan O'Donoghue Signed-off-by: David Heidelberg Signed-off-by: Anusha Arun Nandi --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) 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 4d99d334dad4c..639d320b313b9 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 @@ -14,6 +14,7 @@ #include #include #include +#include #define CSIPHY_3PH_LNn_CFG1(n) (0x000 + 0x100 * (n)) #define CSIPHY_3PH_LNn_CFG1_SWI_REC_DLY_PRG (BIT(7) | BIT(6)) @@ -1230,13 +1231,22 @@ static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy, static u8 csiphy_get_lane_mask(struct csiphy_lanes_cfg *lane_cfg) { - u8 lane_mask; - int i; + u8 lane_mask = 0; + u8 offset = 0; - lane_mask = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; + switch (lane_cfg->phy_cfg) { + case V4L2_MBUS_CSI2_CPHY: + offset = 1; + break; + case V4L2_MBUS_CSI2_DPHY: + lane_mask = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; + break; + default: + break; + } - for (i = 0; i < lane_cfg->num_data; i++) - lane_mask |= BIT(lane_cfg->data[i].pos * 2); + for (int i = 0; i < lane_cfg->num_data; i++) + lane_mask |= BIT((lane_cfg->data[i].pos * 2) + offset); return lane_mask; } @@ -1282,10 +1292,7 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, settle_cnt = csiphy_settle_cnt_calc(link_freq, csiphy->timer_clk_rate); - val = CSIPHY_3PH_CMN_CSI_COMMON_CTRL5_CLK_ENABLE; - for (i = 0; i < c->num_data; i++) - val |= BIT(c->data[i].pos * 2); - + val = csiphy_get_lane_mask(c); writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 5)); From e30e629e87c0638c151a457a79ba00c08ea772e0 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:22 +0200 Subject: [PATCH 36/53] FROMLIST: media: qcom: camss: Prepare CSID for C-PHY support Inherit C-PHY information from CSIPHY, so we can configure CSID properly. CSI2_RX_CFG0_PHY_TYPE_SEL must be set to 1, when C-PHY mode is used. Link: https://lore.kernel.org/r/20260617-qcom-cphy-v9-4-83da8a8e4e44@ixit.cz Reviewed-by: Bryan O'Donoghue Acked-by: Cory Keitz Reviewed-by: Frank Li Signed-off-by: David Heidelberg Signed-off-by: Anusha Arun Nandi --- drivers/media/platform/qcom/camss/camss-csid-gen2.c | 1 + drivers/media/platform/qcom/camss/camss-csid.c | 5 +++++ drivers/media/platform/qcom/camss/camss-csid.h | 6 ++++++ 3 files changed, 12 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen2.c b/drivers/media/platform/qcom/camss/camss-csid-gen2.c index eadcb2f7e3aaa..a5b406cc8ead3 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-gen2.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen2.c @@ -183,6 +183,7 @@ static void __csid_configure_rx(struct csid_device *csid, val = (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_NUM_SEL; + val |= csid->phy.phy_sel << CSI2_RX_CFG0_PHY_TYPE_SEL; writel_relaxed(val, csid->base + CSID_CSI2_RX_CFG0); val = 1 << CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN; diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c index 48459b46a981b..bcc34ac9dd212 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.c +++ b/drivers/media/platform/qcom/camss/camss-csid.c @@ -1291,6 +1291,11 @@ static int csid_link_setup(struct media_entity *entity, lane_cfg = &csiphy->cfg.csi2->lane_cfg; csid->phy.lane_cnt = lane_cfg->num_data; + if (lane_cfg->phy_cfg == V4L2_MBUS_CSI2_CPHY) + csid->phy.phy_sel = CSID_PHY_SEL_CPHY; + else + csid->phy.phy_sel = CSID_PHY_SEL_DPHY; + csid->phy.lane_assign = csid_get_lane_assign(lane_cfg, lane_cfg->num_data); csid->tpg_linked = false; } diff --git a/drivers/media/platform/qcom/camss/camss-csid.h b/drivers/media/platform/qcom/camss/camss-csid.h index dd9c0868e9c73..2b2094c5e9e16 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -46,6 +46,11 @@ enum csid_testgen_mode { CSID_PAYLOAD_MODE_NUM_SUPPORTED_GEN2 = 9, /* excluding disabled */ }; +enum csid_phy_sel { + CSID_PHY_SEL_DPHY = 0, + CSID_PHY_SEL_CPHY = 1 +}; + struct csid_format_info { u32 code; u8 data_type; @@ -72,6 +77,7 @@ struct csid_phy_config { u32 lane_assign; u32 en_vc; u8 need_vc_update; + enum csid_phy_sel phy_sel; }; struct csid_device; From 3b333935130690e97b2d7ee963284defbf0ddaa8 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:23 +0200 Subject: [PATCH 37/53] FROMLIST: media: qcom: camss: Initialize lanes after lane configuration is available The lanes must not be initialized before the driver has access to the lane configuration, as it depends on whether D-PHY or C-PHY mode is in use. Move the lane initialization to csiphy_lanes_enable which is called when the configuration structures are available. Link: https://lore.kernel.org/r/20260617-qcom-cphy-v9-5-83da8a8e4e44@ixit.cz Co-developed-by: Petr Hodina Signed-off-by: Petr Hodina Reviewed-by: Bryan O'Donoghue Acked-by: Cory Keitz Reviewed-by: Frank Li Signed-off-by: David Heidelberg Signed-off-by: Anusha Arun Nandi --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 147 +++++++++++++----- 1 file changed, 106 insertions(+), 41 deletions(-) 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 639d320b313b9..b205d16d4bcab 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 @@ -1290,6 +1290,111 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, u8 val; int i; + switch (csiphy->camss->res->version) { + case CAMSS_845: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sdm845[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_2290: + case CAMSS_2390: + case CAMSS_6150: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_qcm2290[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_qcm2290); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_6350: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sm6350[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sm6350); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_7280: + case CAMSS_8250: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sm8250[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8250); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_8280XP: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sc8280xp[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sc8280xp); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_GLYMUR: + case CAMSS_X1E80100: + case CAMSS_X1P42100: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_x1e80100[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_x1e80100); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_8550: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sm8550[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8550); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_8650: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sm8650[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8650); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_8300: + case CAMSS_8775P: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_sa8775p[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + case CAMSS_8750: + case CAMSS_KAANAPALI: + if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { + regs->lane_regs = &lane_regs_2_4_0[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_2_4_0); + } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = NULL; + regs->lane_array_size = 0; + } + break; + default: + break; + } + + if (!regs->lane_regs) + WARN_ONCE(1, "Missing lane_regs definition!\n"); + settle_cnt = csiphy_settle_cnt_calc(link_freq, csiphy->timer_clk_rate); val = csiphy_get_lane_mask(c); @@ -1342,64 +1447,24 @@ static int csiphy_init(struct csiphy_device *csiphy) return -ENOMEM; csiphy->regs = regs; - regs->offset = 0x800; regs->common_status_offset = 0xb0; switch (csiphy->camss->res->version) { - case CAMSS_845: - regs->lane_regs = &lane_regs_sdm845[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); - break; - case CAMSS_2290: - case CAMSS_2390: - case CAMSS_6150: - regs->lane_regs = &lane_regs_qcm2290[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_qcm2290); - break; - case CAMSS_6350: - regs->lane_regs = &lane_regs_sm6350[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sm6350); - break; - case CAMSS_7280: - case CAMSS_8250: - regs->lane_regs = &lane_regs_sm8250[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8250); - break; - case CAMSS_8280XP: - regs->lane_regs = &lane_regs_sc8280xp[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sc8280xp); - break; case CAMSS_GLYMUR: 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; - break; case CAMSS_8550: - regs->lane_regs = &lane_regs_sm8550[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8550); - regs->offset = 0x1000; - break; case CAMSS_8650: - regs->lane_regs = &lane_regs_sm8650[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8650); regs->offset = 0x1000; break; - case CAMSS_8300: - case CAMSS_8775P: - regs->lane_regs = &lane_regs_sa8775p[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); - break; case CAMSS_8750: case CAMSS_KAANAPALI: /* CSPHY v2.4.0 is backward compatible with v2.3.0 settings */ - regs->lane_regs = &lane_regs_2_4_0[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_2_4_0); regs->offset = 0x1000; regs->common_status_offset = 0x138; break; default: + regs->offset = 0x800; break; } From 3d8b4a176dc60081ab462723cde88dcfe698386a Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:24 +0200 Subject: [PATCH 38/53] FROMLIST: media: qcom: camss: csiphy-3ph: Add Gen2 v1.1 MIPI CSI-2 C-PHY init Add a PHY configuration sequence for the sdm845 which uses a Qualcomm Gen 2 version 1.1 CSI-2 PHY. The PHY can be configured as two phase or three phase in C-PHY or D-PHY mode. This configuration supports three-phase C-PHY mode. Link: https://lore.kernel.org/r/20260617-qcom-cphy-v9-6-83da8a8e4e44@ixit.cz Acked-by: Cory Keitz Signed-off-by: David Heidelberg Signed-off-by: Anusha Arun Nandi --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 78 ++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) 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 b205d16d4bcab..01bae2d37dc67 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 @@ -50,6 +50,13 @@ #define CSIPHY_3PH_CMN_CSI_COMMON_STATUSn(offset, common_status_offset, n) \ ((offset) + (common_status_offset) + 0x4 * (n)) +#define CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(n) \ + (0x0100 + ((n) * 0x4)) +#define CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(n) \ + (0x0300 + ((n) * 0x4)) +#define CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(n) \ + (0x0500 + ((n) * 0x4)) + #define CSIPHY_DEFAULT_PARAMS 0 #define CSIPHY_LANE_ENABLE 1 #define CSIPHY_SETTLE_CNT_LOWER_BYTE 2 @@ -146,6 +153,7 @@ csiphy_lane_regs lane_regs_sa8775p[] = { }; /* GEN2 1.0 2PH */ +/* 5 entries: clock + 4 lanes */ static const struct csiphy_lane_regs lane_regs_sdm845[] = { {0x0004, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -220,6 +228,72 @@ csiphy_lane_regs lane_regs_sdm845[] = { {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, }; +/* GEN2 1.0 3PH */ +/* 3 entries: 3 lanes (C-PHY) */ +static const struct +csiphy_lane_regs lane_regs_sdm845_3ph[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x43, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0xa0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(5), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(20), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(6), 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(8), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(9), 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(10), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(17), 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(24), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(25), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(55), 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x43, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0xa0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(5), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(20), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(6), 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(8), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(9), 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(10), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(17), 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(24), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(25), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(55), 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, + + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x43, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0xa0, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(5), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(20), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(6), 0x3e, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(8), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(9), 0x7f, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(10), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(17), 0x12, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(24), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(25), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(55), 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, + +}; + /* GEN2 1.1 2PH */ static const struct csiphy_lane_regs lane_regs_sc8280xp[] = { @@ -1296,8 +1370,8 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, regs->lane_regs = &lane_regs_sdm845[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845); } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { - regs->lane_regs = NULL; - regs->lane_array_size = 0; + regs->lane_regs = &lane_regs_sdm845_3ph[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845_3ph); } break; case CAMSS_2290: From 7f0a42393f049080e2eb18c6e31552ac462532a7 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:25 +0200 Subject: [PATCH 39/53] FROMLIST: media: qcom: camss: csiphy-3ph: Update Gen2 v1.1 MIPI CSI-2 C-PHY init These values should improve C-PHY behaviour. Should match most recent Qualcomm code. Link: https://lore.kernel.org/r/20260617-qcom-cphy-v9-7-83da8a8e4e44@ixit.cz Acked-by: Cory Keitz Suggested-by: Konrad Dybcio Signed-off-by: David Heidelberg Signed-off-by: Anusha Arun Nandi --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) 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 01bae2d37dc67..8e01b23d297a4 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 @@ -232,9 +232,9 @@ csiphy_lane_regs lane_regs_sdm845[] = { /* 3 entries: 3 lanes (C-PHY) */ static const struct csiphy_lane_regs lane_regs_sdm845_3ph[] = { - {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x43, 0x00, CSIPHY_DEFAULT_PARAMS}, - {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0xa0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0xac, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0xa5, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, @@ -252,9 +252,9 @@ csiphy_lane_regs lane_regs_sdm845_3ph[] = { {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(25), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(55), 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, - {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x43, 0x00, CSIPHY_DEFAULT_PARAMS}, - {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0xa0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0xac, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0xa5, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, @@ -272,9 +272,9 @@ csiphy_lane_regs lane_regs_sdm845_3ph[] = { {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(25), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(55), 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, - {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x43, 0x00, CSIPHY_DEFAULT_PARAMS}, - {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0xa0, 0x00, CSIPHY_DEFAULT_PARAMS}, - {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x63, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0xac, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0xa5, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, @@ -291,7 +291,6 @@ csiphy_lane_regs lane_regs_sdm845_3ph[] = { {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(25), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(55), 0x51, 0x00, CSIPHY_DEFAULT_PARAMS}, - }; /* GEN2 1.1 2PH */ From caf6e29c8388aacffa36a0b6e570a75d1e9ecc07 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:26 +0200 Subject: [PATCH 40/53] FROMLIST: media: qcom: camss: Account for C-PHY when calculating link frequency Ensure that the link frequency divider correctly accounts for C-PHY operation. The divider differs between D-PHY and C-PHY, as described in the MIPI CSI-2 specification. For more details, see: https://docs.kernel.org/driver-api/media/tx-rx.html#pixel-rate Link: https://lore.kernel.org/r/20260617-qcom-cphy-v9-8-83da8a8e4e44@ixit.cz Suggested-by: Sakari Ailus Link: https://docs.kernel.org/driver-api/media/tx-rx.html#pixel-rate Signed-off-by: David Heidelberg Signed-off-by: Anusha Arun Nandi --- drivers/media/platform/qcom/camss/camss-csid.c | 6 ++++-- drivers/media/platform/qcom/camss/camss-csiphy.c | 9 ++++++--- drivers/media/platform/qcom/camss/camss.c | 15 +++++++++++++-- drivers/media/platform/qcom/camss/camss.h | 2 +- 4 files changed, 24 insertions(+), 8 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss-csid.c b/drivers/media/platform/qcom/camss/camss-csid.c index bcc34ac9dd212..c8cb6f1a3d3bc 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.c +++ b/drivers/media/platform/qcom/camss/camss-csid.c @@ -540,14 +540,16 @@ static int csid_set_clock_rates(struct csid_device *csid) { struct device *dev = csid->camss->dev; const struct csid_format_info *fmt; + const bool cphy = (csid->phy.phy_sel == CSID_PHY_SEL_CPHY); + s64 link_freq; int i, j; int ret; fmt = csid_get_fmt_entry(csid->res->formats->formats, csid->res->formats->nformats, csid->fmt[MSM_CSIPHY_PAD_SINK].code); - link_freq = camss_get_link_freq(&csid->subdev.entity, fmt->bpp, - csid->phy.lane_cnt); + + link_freq = camss_get_link_freq(&csid->subdev.entity, fmt->bpp, csid->phy.lane_cnt, cphy); if (link_freq < 0) link_freq = 0; diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c index 57bc0eda43a18..7904076f48843 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.c +++ b/drivers/media/platform/qcom/camss/camss-csiphy.c @@ -146,8 +146,9 @@ static int csiphy_set_clock_rates_legacy(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; + const bool cphy = (csiphy->cfg.csi2->lane_cfg.phy_cfg == V4L2_MBUS_CSI2_CPHY); - link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes); + link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes, cphy); if (link_freq < 0) link_freq = 0; @@ -272,9 +273,10 @@ static int csiphy_stream_on_legacy(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; + const bool cphy = (csiphy->cfg.csi2->lane_cfg.phy_cfg == V4L2_MBUS_CSI2_CPHY); u8 val; - link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes); + link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes, cphy); if (link_freq < 0) { dev_err(csiphy->camss->dev, @@ -331,13 +333,14 @@ static int csiphy_stream_on(struct csiphy_device *csiphy) union phy_configure_opts dphy_opts = { 0 }; struct device *dev = csiphy->camss->dev; u8 num_lanes = lncfg->num_data; + const bool cphy = (lncfg->phy_cfg == V4L2_MBUS_CSI2_CPHY); 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); + link_freq = camss_get_link_freq(&csiphy->subdev.entity, bpp, num_lanes, cphy); if (link_freq < 0) { dev_err(dev, diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 696263abefff2..e013d4d655385 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -33,6 +33,14 @@ #define CAMSS_CLOCK_MARGIN_NUMERATOR 105 #define CAMSS_CLOCK_MARGIN_DENOMINATOR 100 +/* + * C-PHY encodes data by 16/7 ~ 2.28 bits/symbol + * D-PHY doesn't encode data, thus 16/16 = 1 b/s + */ +#define CAMSS_COMMON_PHY_DIVIDENT 16 +#define CAMSS_CPHY_DIVISOR 7 +#define CAMSS_DPHY_DIVISOR 16 + static const struct parent_dev_ops vfe_parent_dev_ops; static const struct camss_subdev_resources csiphy_res_kaanapali[] = { @@ -5424,19 +5432,22 @@ struct media_pad *camss_find_sensor_pad(struct media_entity *entity) * @entity: Media entity in the current pipeline * @bpp: Number of bits per pixel for the current format * @lanes: Number of lanes in the link to the sensor + * @cphy: If C-PHY encoding is used. * * Return link frequency on success or a negative error code otherwise */ s64 camss_get_link_freq(struct media_entity *entity, unsigned int bpp, - unsigned int lanes) + unsigned int lanes, const bool cphy) { struct media_pad *sensor_pad; + unsigned int div = lanes * 2 * (cphy ? CAMSS_CPHY_DIVISOR : + CAMSS_DPHY_DIVISOR); sensor_pad = camss_find_sensor_pad(entity); if (!sensor_pad) return -ENODEV; - return v4l2_get_link_freq(sensor_pad, bpp, 2 * lanes); + return v4l2_get_link_freq(sensor_pad, CAMSS_COMMON_PHY_DIVIDENT * bpp, div); } /* diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h index 91438769419e5..b447815b353f3 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -175,7 +175,7 @@ int camss_enable_clocks(int nclocks, struct camss_clock *clock, void camss_disable_clocks(int nclocks, struct camss_clock *clock); struct media_pad *camss_find_sensor_pad(struct media_entity *entity); s64 camss_get_link_freq(struct media_entity *entity, unsigned int bpp, - unsigned int lanes); + unsigned int lanes, const bool cphy); int camss_get_pixel_clock(struct media_entity *entity, u64 *pixel_clock); int camss_pm_domain_on(struct camss *camss, int id); void camss_pm_domain_off(struct camss *camss, int id); From 9256d200acf3a00529a356bfa7343afa346adc52 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:27 +0200 Subject: [PATCH 41/53] FROMLIST: media: qcom: camss: Enable C-PHY where available After all the changes done we can now safely enable C-PHY for a SoC where it's available. Link: https://lore.kernel.org/r/20260617-qcom-cphy-v9-9-83da8a8e4e44@ixit.cz Acked-by: Cory Keitz Reviewed-by: Bryan O'Donoghue Reviewed-by: Frank Li Signed-off-by: David Heidelberg Signed-off-by: Anusha Arun Nandi --- drivers/media/platform/qcom/camss/camss.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index e013d4d655385..3b1bc57c6f946 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5565,11 +5565,11 @@ static int camss_parse_endpoint_node(struct device *dev, if (ret) return ret; - /* - * Most SoCs support both D-PHY and C-PHY standards, but currently only - * D-PHY is supported in the driver. - */ - if (vep.bus_type != V4L2_MBUS_CSI2_DPHY) { + switch (vep.bus_type) { + case V4L2_MBUS_CSI2_CPHY: + case V4L2_MBUS_CSI2_DPHY: + break; + default: dev_err(dev, "Unsupported bus type %d\n", vep.bus_type); return -EINVAL; } From 86e29f1a17e065d03490aa3a721890dcf896eee4 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 17 Jul 2026 16:13:26 -0700 Subject: [PATCH 42/53] FROMLIST: media: qcom: camss: Program CSIPHY common control registers Program the CSIPHY common-control registers during lane enable so SA8775P uses the required 3-phase 1.5 Gsps reset-release values for both C-PHY and D-PHY. Keep the existing reset-release value for the other CAMSS variants. Link: https://lore.kernel.org/r/20260717231331.1229693-2-anusha.nandi@oss.qualcomm.com Co-developed-by: Anusha Arun Nandi Signed-off-by: Anusha Arun Nandi Signed-off-by: Jigarkumar Zala --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) 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 8e01b23d297a4..899d3fd052dbb 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 @@ -1148,8 +1148,6 @@ static void csiphy_reset(struct csiphy_device *csiphy) writel_relaxed(0x1, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 0)); usleep_range(5000, 8000); - writel_relaxed(0x0, csiphy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 0)); } static irqreturn_t csiphy_isr(int irq, void *dev) @@ -1478,9 +1476,37 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, writel_relaxed(val, csiphy->base + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 6)); - val = 0x02; - writel_relaxed(val, csiphy->base + - CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 7)); + switch (csiphy->camss->res->version) { + case CAMSS_8300: + case CAMSS_8775P: + if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + val = 0x5A; + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 7)); + val = 0xE; + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 0)); + } else { + val = 0x02; + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 7)); + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 0)); + } + break; + case CAMSS_7280: + case CAMSS_8250: + case CAMSS_8280XP: + case CAMSS_845: + default: + val = 0x02; + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 7)); + val = 0x0; + writel_relaxed(val, csiphy->base + + CSIPHY_3PH_CMN_CSI_COMMON_CTRLn(regs->offset, 0)); + break; + } val = 0x00; writel_relaxed(val, csiphy->base + From acfb700c56fea0c9053ef4da7d0825a7e58dca04 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 17 Jul 2026 16:13:27 -0700 Subject: [PATCH 43/53] FROMLIST: media: qcom: camss: Prepare CSID for C-PHY support in gen3 Program the gen3 CSID CSI2 RX PHY type field from the configured PHY type. The RX path needs this value to distinguish C-PHY from D-PHY input, so leaving it at the default makes C-PHY configuration incomplete. Link: https://lore.kernel.org/r/20260717231331.1229693-3-anusha.nandi@oss.qualcomm.com Co-developed-by: Anusha Arun Nandi Signed-off-by: Anusha Arun Nandi Signed-off-by: Jigarkumar Zala --- drivers/media/platform/qcom/camss/camss-csid-gen3.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/platform/qcom/camss/camss-csid-gen3.c b/drivers/media/platform/qcom/camss/camss-csid-gen3.c index da9458cd178bd..b8be2da78aba7 100644 --- a/drivers/media/platform/qcom/camss/camss-csid-gen3.c +++ b/drivers/media/platform/qcom/camss/camss-csid-gen3.c @@ -66,6 +66,7 @@ #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_PHY_TYPE_SEL 24 #define CSI2_RX_CFG0_TPG_MUX_EN BIT(27) #define CSI2_RX_CFG0_TPG_MUX_SEL GENMASK(29, 28) @@ -114,6 +115,7 @@ static void __csid_configure_rx(struct csid_device *csid, camss = csid->camss; val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES; + val |= phy->phy_sel << CSI2_RX_CFG0_PHY_TYPE_SEL; val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL; if (camss->tpg && csid->tpg_linked && From b8b8bb9128f15e893f9d4fa7ea5954c016c0ead6 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 17 Jul 2026 16:13:28 -0700 Subject: [PATCH 44/53] FROMLIST: media: qcom: camss: Add sa8775p C-PHY 3ph lane config Add the lane_regs_sa8775p_3ph[] register table for the sa8775p Gen3 CSIPHY at 1.5 Gsps, and select it in csiphy_lanes_enable() for CAMSS_8775P when the endpoint is configured for C-PHY, falling back to the existing sa8775p D-PHY table otherwise. Link: https://lore.kernel.org/r/20260717231331.1229693-4-anusha.nandi@oss.qualcomm.com Co-developed-by: Anusha Arun Nandi Signed-off-by: Anusha Arun Nandi Signed-off-by: Jigarkumar Zala --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 111 +++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) 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 899d3fd052dbb..f717862db6c12 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 @@ -56,6 +56,12 @@ (0x0300 + ((n) * 0x4)) #define CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(n) \ (0x0500 + ((n) * 0x4)) +#define CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(n) \ + (0x0900 + ((n) * 0x4)) +#define CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(n) \ + (0x0A00 + ((n) * 0x4)) +#define CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(n) \ + (0x0B00 + ((n) * 0x4)) #define CSIPHY_DEFAULT_PARAMS 0 #define CSIPHY_LANE_ENABLE 1 @@ -152,6 +158,101 @@ csiphy_lane_regs lane_regs_sa8775p[] = { {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, }; +/* GEN3 3PH sa8775p 1.5Gsps */ +/* 3 entries: 3 lanes (C-PHY) */ +static const struct +csiphy_lane_regs lane_regs_sa8775p_3ph[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(34), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(35), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(36), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(6), 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(9), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(17), 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(25), 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(55), 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(5), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(20), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(34), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(35), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(36), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(6), 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(8), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(9), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(10), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(17), 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(24), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(25), 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(55), 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(1), 0x06, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(2), 0x00, 0x00, CSIPHY_SETTLE_CNT_HIGHER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(5), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(20), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(34), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(35), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(36), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(6), 0x3E, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(7), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(8), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(9), 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(10), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(11), 0x00, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(17), 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(24), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(51), 0x41, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(25), 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(55), 0x50, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(33), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(32), 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(44), 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(33), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(32), 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(44), 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(33), 0x20, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(32), 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(44), 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x24, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x24, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x24, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + /* GEN2 1.0 2PH */ /* 5 entries: clock + 4 lanes */ static const struct @@ -1440,7 +1541,6 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, } break; case CAMSS_8300: - case CAMSS_8775P: if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { regs->lane_regs = &lane_regs_sa8775p[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); @@ -1459,6 +1559,15 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, regs->lane_array_size = 0; } break; + case CAMSS_8775P: + if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { + regs->lane_regs = &lane_regs_sa8775p_3ph[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p_3ph); + } else { + regs->lane_regs = &lane_regs_sa8775p[0]; + regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); + } + break; default: break; } From caf6d8be087ee9b4e230ed0959d7d782dfb91840 Mon Sep 17 00:00:00 2001 From: Anusha Arun Nandi Date: Fri, 17 Jul 2026 16:13:29 -0700 Subject: [PATCH 45/53] FROMLIST: media: qcom: camss: Add sa8300 C-PHY 3ph lane config Share the C-PHY/D-PHY lane_regs selection for CAMSS_8300 so the sa8300 platform uses the same 3ph handling as CAMSS_8775P. Also drop CAMSS_8300 from the missing-C-PHY-table guard now that a C-PHY table is provided. Link: https://lore.kernel.org/r/20260717231331.1229693-5-anusha.nandi@oss.qualcomm.com Co-developed-by: Jigarkumar Zala Signed-off-by: Jigarkumar Zala Signed-off-by: Anusha Arun Nandi --- .../media/platform/qcom/camss/camss-csiphy-3ph-1-0.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) 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 f717862db6c12..bee15b3b81b1b 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 @@ -1540,15 +1540,6 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, regs->lane_array_size = 0; } break; - case CAMSS_8300: - if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { - regs->lane_regs = &lane_regs_sa8775p[0]; - regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); - } else if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { - regs->lane_regs = NULL; - regs->lane_array_size = 0; - } - break; case CAMSS_8750: case CAMSS_KAANAPALI: if (c->phy_cfg == V4L2_MBUS_CSI2_DPHY) { @@ -1559,6 +1550,7 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, regs->lane_array_size = 0; } break; + case CAMSS_8300: case CAMSS_8775P: if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { regs->lane_regs = &lane_regs_sa8775p_3ph[0]; From 25ff538a07f36f81484a6111d1d48bfd6bd6966a Mon Sep 17 00:00:00 2001 From: Anusha Arun Nandi Date: Fri, 17 Jul 2026 16:13:30 -0700 Subject: [PATCH 46/53] FROMLIST: media: qcom: camss: Dynamic data-rate specific C-PHY register settings The C-PHY PHY register configuration needs to vary with the link (symbol) data rate. Until now only a single base lane_regs table was applied per platform, regardless of the negotiated rate. Introduce a data-rate selection mechanism for C-PHY: - Add struct data_rate_reg_info describing a per-bandwidth register override table. - Add csiphy_cphy_data_rate_config(), which selects the first table entry whose bandwidth satisfies the required PHY data rate (derived from the resolved link frequency) and writes those overrides on top of the base lane_regs configuration. The settle-count parameter types are handled specially. When the link frequency cannot be resolved, it falls back to the lowest supported rate. - Add per-data-rate register tables and data_rate_settings tables for sa8775p and 8300(1.5/1.7/2.5/3.5/4.5 GSpS) and sm8250 (2.5/3.5/4.5 GSpS). - Select the appropriate data-rate settings table in csiphy_lanes_enable() for both platforms when the endpoint is configured for C-PHY. Link: https://lore.kernel.org/r/20260717231331.1229693-6-anusha.nandi@oss.qualcomm.com Co-developed-by: Jigarkumar Zala Signed-off-by: Jigarkumar Zala Signed-off-by: Anusha Arun Nandi --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 249 ++++++++++++++++++ .../media/platform/qcom/camss/camss-csiphy.h | 6 + 2 files changed, 255 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 bee15b3b81b1b..82aaeffffbfab 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 @@ -72,6 +72,8 @@ #define CSIPHY_3PH_REGS 6 #define CSIPHY_SKEW_CAL 7 +#define CSIPHY_CPHY_DATA_RATE_DEFAULT_IDX 0 + struct csiphy_lane_regs { s32 reg_addr; s32 reg_data; @@ -236,6 +238,9 @@ csiphy_lane_regs lane_regs_sa8775p_3ph[] = { {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(32), 0x61, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(44), 0x01, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sa8775p_3ph_1p5Gsps[] = { {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, @@ -253,6 +258,183 @@ csiphy_lane_regs lane_regs_sa8775p_3ph[] = { {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, }; +struct csiphy_lane_regs datarate_sa8775p_3ph_1p7Gsps[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x56, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0xAE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x65, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x56, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0xAE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x65, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x56, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0xAE, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x65, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x12, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sa8775p_3ph_2p5Gsps[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0xC8, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x08, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sa8775p_3ph_3p5Gsps[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sa8775p_3ph_4p5Gsps[] = { + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN1_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN3_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(26), 0x80, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(23), 0x46, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(27), 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN5_CSI_3PH_CTRLn_ADDR(3), 0x08, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(45), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN9_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(45), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN10_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(45), 0x02, 0x00, CSIPHY_DEFAULT_PARAMS}, + {CSIPHY_LN11_CSI_3PH_CTRLn_ADDR(34), 0x05, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +static struct data_rate_reg_info data_rate_settings_sa8775p_3ph[] = { + { + /* 1.5 GSpS */ + .bandwidth = 1500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sa8775p_3ph_1p5Gsps), + .data_rate_reg_array = datarate_sa8775p_3ph_1p5Gsps, + }, + { + /* 1.7 GSpS */ + .bandwidth = 1700000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sa8775p_3ph_1p7Gsps), + .data_rate_reg_array = datarate_sa8775p_3ph_1p7Gsps, + }, + { + /* 2.5 GSpS */ + .bandwidth = 2500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sa8775p_3ph_2p5Gsps), + .data_rate_reg_array = datarate_sa8775p_3ph_2p5Gsps, + }, + { + /* 3.5 GSpS */ + .bandwidth = 3500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sa8775p_3ph_3p5Gsps), + .data_rate_reg_array = datarate_sa8775p_3ph_3p5Gsps, + }, + { + /* 4.5 GSpS */ + .bandwidth = 4500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sa8775p_3ph_4p5Gsps), + .data_rate_reg_array = datarate_sa8775p_3ph_4p5Gsps, + }, +}; + +struct csiphy_lane_regs datarate_sm8250_3ph_2p5Gsps[] = { + {0x144, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0x32, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x0B, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sm8250_3ph_3p5Gsps[] = { + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x1D, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x03, 0x01, CSIPHY_DEFAULT_PARAMS}, +}; + +struct csiphy_lane_regs datarate_sm8250_3ph_4p5Gsps[] = { + {0x144, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x164, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x16C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x9B4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x344, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x364, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x36C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xAB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, + {0x544, 0xB2, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x564, 0x33, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0x56C, 0x25, 0x00, CSIPHY_DEFAULT_PARAMS}, + {0xBB4, 0x02, 0x01, CSIPHY_DEFAULT_PARAMS}, +}; + +static struct data_rate_reg_info data_rate_settings_sm8250_3ph[] = { + { + /* 2.5 GSpS */ + .bandwidth = 2500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sm8250_3ph_2p5Gsps), + .data_rate_reg_array = datarate_sm8250_3ph_2p5Gsps, + }, + { + /* 3.5 GSpS */ + .bandwidth = 3500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sm8250_3ph_3p5Gsps), + .data_rate_reg_array = datarate_sm8250_3ph_3p5Gsps, + }, + { + /* 4.5 GSpS */ + .bandwidth = 4500000000, + .data_rate_reg_array_size = ARRAY_SIZE(datarate_sm8250_3ph_4p5Gsps), + .data_rate_reg_array = datarate_sm8250_3ph_4p5Gsps, + }, +}; + /* GEN2 1.0 2PH */ /* 5 entries: clock + 4 lanes */ static const struct @@ -1374,6 +1556,60 @@ static void csiphy_gen1_config_lanes(struct csiphy_device *csiphy, writel_relaxed(val, csiphy->base + CSIPHY_3PH_LNn_MISC1(l)); } +/* + * csiphy_cphy_data_rate_config - Apply data-rate specific C-PHY overrides + * + * Applied on top of the base lane_regs. Selects the first table entry whose + * bandwidth >= the data rate derived from @link_freq (highest entry if none + * qualifies, default entry if @link_freq is unknown) and writes its overrides. + */ +static void csiphy_cphy_data_rate_config(struct csiphy_device *csiphy, + struct data_rate_reg_info *settings, + size_t num_settings, + s64 link_freq, u8 settle_cnt) +{ + struct device *dev = csiphy->camss->dev; + const struct csiphy_lane_regs *r; + size_t idx, i; + u32 val; + + if (!settings || !num_settings) + return; + + if (!link_freq) { + /* Link frequency unknown; use the default (lowest) entry. */ + idx = CSIPHY_CPHY_DATA_RATE_DEFAULT_IDX; + } else { + /* First entry that satisfies the rate, else the highest. */ + for (idx = 0; idx < num_settings; idx++) { + if (settings[idx].bandwidth >= link_freq) + break; + } + } + + dev_dbg(dev, + "CSIPHY using specific bandwidth %llu bits/s (entry %zu) for link_freq %lld\n", + settings[idx].bandwidth, idx, link_freq); + + r = settings[idx].data_rate_reg_array; + for (i = 0; i < settings[idx].data_rate_reg_array_size; i++, r++) { + switch (r->csiphy_param_type) { + case CSIPHY_SETTLE_CNT_LOWER_BYTE: + val = settle_cnt & 0xff; + break; + case CSIPHY_SETTLE_CNT_HIGHER_BYTE: + val = (settle_cnt >> 8) & 0xff; + break; + default: + val = r->reg_data; + break; + } + writel_relaxed(val, csiphy->base + r->reg_addr); + if (r->delay_us) + udelay(r->delay_us); + } +} + static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy, u8 settle_cnt) { @@ -1458,6 +1694,8 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, { struct csiphy_lanes_cfg *c = &cfg->csi2->lane_cfg; struct csiphy_device_regs *regs = csiphy->regs; + struct data_rate_reg_info *data_rate_settings = NULL; + size_t num_data_rate_settings = 0; u8 settle_cnt; u8 val; int i; @@ -1555,6 +1793,8 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { regs->lane_regs = &lane_regs_sa8775p_3ph[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p_3ph); + data_rate_settings = data_rate_settings_sa8775p_3ph; + num_data_rate_settings = ARRAY_SIZE(data_rate_settings_sa8775p_3ph); } else { regs->lane_regs = &lane_regs_sa8775p[0]; regs->lane_array_size = ARRAY_SIZE(lane_regs_sa8775p); @@ -1618,6 +1858,15 @@ static void csiphy_lanes_enable(struct csiphy_device *csiphy, else csiphy_gen1_config_lanes(csiphy, cfg, settle_cnt); + /* + * For C-PHY platforms with a data-rate settings table, apply the + * data-rate specific overrides on top of the base lane_regs config. + */ + if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY && data_rate_settings) + csiphy_cphy_data_rate_config(csiphy, data_rate_settings, + num_data_rate_settings, + link_freq, settle_cnt); + /* IRQ_MASK registers - disable all interrupts */ for (i = 11; i < 22; i++) { writel_relaxed(0, csiphy->base + diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h index e8a7445f146db..805f040290f62 100644 --- a/drivers/media/platform/qcom/camss/camss-csiphy.h +++ b/drivers/media/platform/qcom/camss/camss-csiphy.h @@ -63,6 +63,12 @@ struct csiphy_formats { const struct csiphy_format_info *formats; }; +struct data_rate_reg_info { + u64 bandwidth; + ssize_t data_rate_reg_array_size; + struct csiphy_lane_regs *data_rate_reg_array; +}; + struct csiphy_device; struct csiphy_hw_ops { From 4355d77c2681dd199d2b531c2b21646b889ec442 Mon Sep 17 00:00:00 2001 From: Anusha Arun Nandi Date: Fri, 17 Jul 2026 16:13:31 -0700 Subject: [PATCH 47/53] FROMLIST: media: qcom: camss: validate local/remote endpoint bus-type A link is invalid if the local CSIPHY endpoint and the remote sensor endpoint describe different bus types. Such a mismatch can otherwise go undetected until later probe or streaming failures. Parse the remote endpoint in camss_parse_endpoint_node() and compare its bus-type with the local endpoint. Reject the link with -EINVAL if the two ends disagree, so C-PHY/D-PHY mismatches are caught early during probe. Link: https://lore.kernel.org/r/20260717231331.1229693-7-anusha.nandi@oss.qualcomm.com Co-developed-by: Jigarkumar Zala Signed-off-by: Jigarkumar Zala Signed-off-by: Anusha Arun Nandi --- drivers/media/platform/qcom/camss/camss.c | 28 ++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 3b1bc57c6f946..10631c7360d27 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5557,7 +5557,9 @@ static int camss_parse_endpoint_node(struct device *dev, { struct csiphy_lanes_cfg *lncfg = &csd->interface.csi2.lane_cfg; struct v4l2_mbus_config_mipi_csi2 *mipi_csi2; - struct v4l2_fwnode_endpoint vep = { { 0 } }; + struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_UNKNOWN }; + struct v4l2_fwnode_endpoint remote_vep = { .bus_type = V4L2_MBUS_UNKNOWN }; + struct fwnode_handle *remote_ep; unsigned int i; int ret; @@ -5574,6 +5576,30 @@ static int camss_parse_endpoint_node(struct device *dev, return -EINVAL; } + /* Get the remote (sensor) endpoint handle, e.g. imx686_ep1 */ + remote_ep = fwnode_graph_get_remote_endpoint(ep); + if (!remote_ep) { + dev_dbg(dev, "No remote endpoint found for %pfw\n", ep); + return -ENODEV; + } + + /* Parse the remote bus type and release the handle */ + ret = v4l2_fwnode_endpoint_parse(remote_ep, &remote_vep); + fwnode_handle_put(remote_ep); + if (ret) { + dev_dbg(dev, "Failed to parse remote endpoint\n"); + return ret; + } + + /* The local (CSIPHY) and remote (sensor) ends must agree */ + if (vep.bus_type != remote_vep.bus_type) { + dev_dbg(dev, "Bus type mismatch! Local (CSI-PHY): %u, Remote (Sensor): %u\n", + vep.bus_type, remote_vep.bus_type); + return -EINVAL; + } + + dev_dbg(dev, "Verified link: both ends use bus-type %u\n", vep.bus_type); + csd->interface.csiphy_id = vep.base.port; mipi_csi2 = &vep.bus.mipi_csi2; From 73eb18e782bb1a7332d70e25fe51f5d841a72cb7 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 24 Jul 2026 17:50:37 +0800 Subject: [PATCH 48/53] FROMLIST: dt-bindings: media: i2c: Add Samsung S5KJN5 image sensor Add device tree bindings for the Samsung S5KJN5, a 50 MP GBRG 10-bit RAW MIPI CSI-2 image sensor controlled over CCI. Reviewed-by: Krzysztof Kozlowski Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/all/20260724-sk5jn5-v2-1-871d3b9a2e47@oss.qualcomm.com/ --- .../bindings/media/i2c/samsung,s5kjn5.yaml | 113 ++++++++++++++++++ MAINTAINERS | 6 + 2 files changed, 119 insertions(+) create mode 100644 Documentation/devicetree/bindings/media/i2c/samsung,s5kjn5.yaml diff --git a/Documentation/devicetree/bindings/media/i2c/samsung,s5kjn5.yaml b/Documentation/devicetree/bindings/media/i2c/samsung,s5kjn5.yaml new file mode 100644 index 0000000000000..9526d2bc5f5be --- /dev/null +++ b/Documentation/devicetree/bindings/media/i2c/samsung,s5kjn5.yaml @@ -0,0 +1,113 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/media/i2c/samsung,s5kjn5.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Samsung S5KJN5 Image Sensor + +description: + Samsung S5KJN5 is a 50MP GBRG 10-bit RAW MIPI CSI-2 image sensor. + The sensor is controlled over I2C. The full resolution pixel array is + 8192x6144, data output format is RAW10 transferred over 4-lane MIPI + D-PHY interface. + +maintainers: + - Wenmeng Liu + +allOf: + - $ref: /schemas/media/video-interface-devices.yaml# + +properties: + compatible: + const: samsung,s5kjn5 + + reg: + maxItems: 1 + + clocks: + description: MCLK/XVCLK input clock. + maxItems: 1 + + reset-gpios: + description: Active low GPIO connected to RESET pad of the sensor. + maxItems: 1 + + vddio-supply: + description: + 1.8 volt I/O voltage supply (VDD18). Required for both 1.8 and 1.2 volt + I/O operation. + + vddd-supply: + description: Digital core voltage supply, 1.0 volts. + + vdda-supply: + description: Analogue voltage supply, 2.2 volts. + + vddio1p2-supply: + description: + 1.2 volt I/O voltage supply (VDDIO12). Required only for 1.2 volt I/O + operation. + + afvdd-supply: + description: Autofocus actuator voltage supply, 2.8-3.0 volts. + + port: + $ref: /schemas/graph.yaml#/$defs/port-base + additionalProperties: false + + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + items: + - const: 1 + - const: 2 + - const: 3 + - const: 4 + + required: + - link-frequencies + +required: + - compatible + - reg + - clocks + - port + +unevaluatedProperties: false + +examples: + - | + #include + + i2c { + #address-cells = <1>; + #size-cells = <0>; + + camera@10 { + compatible = "samsung,s5kjn5"; + reg = <0x10>; + clocks = <&camera_mclk 0>; + assigned-clocks = <&camera_mclk 0>; + assigned-clock-rates = <19200000>; + reset-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; + vddio-supply = <&vreg_1p8>; + vddd-supply = <&vreg_1p0>; + vdda-supply = <&vreg_2p2>; + vddio1p2-supply = <&vreg_1p2>; + afvdd-supply = <&vreg_2p8>; + + port { + endpoint { + link-frequencies = /bits/ 64 <1248000000>; + data-lanes = <1 2 3 4>; + remote-endpoint = <&mipi_csi2_ep>; + }; + }; + }; + }; +... diff --git a/MAINTAINERS b/MAINTAINERS index 05bfd1649e445..e03dcc1e9f093 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -24121,6 +24121,12 @@ T: git git://linuxtv.org/media_tree.git F: Documentation/devicetree/bindings/media/i2c/samsung,s5kjn1.yaml F: drivers/media/i2c/s5kjn1.c +SAMSUNG S5KJN5 CAMERA DRIVER +M: Wenmeng Liu +L: linux-media@vger.kernel.org +S: Supported +F: Documentation/devicetree/bindings/media/i2c/samsung,s5kjn5.yaml + SAMSUNG S5P Security SubSystem (SSS) DRIVER M: Krzysztof Kozlowski M: Vladimir Zapolskiy From dffc6e97f95f9c17ef21a558a29f96e54944017c Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 24 Jul 2026 17:50:38 +0800 Subject: [PATCH 49/53] FROMLIST: media: i2c: Add Samsung S5KJN5 image sensor driver Add a V4L2 sub-device driver for the Samsung S5KJN5, a 50 MP GBRG 10-bit RAW MIPI CSI-2 image sensor. The driver supports the 4096x3072 mode and exposes the standard controls (exposure, gain, vblank/hblank, test pattern). Signed-off-by: Wenmeng Liu Link: https://lore.kernel.org/all/20260724-sk5jn5-v2-1-871d3b9a2e47@oss.qualcomm.com/ --- MAINTAINERS | 1 + drivers/media/i2c/Kconfig | 11 + drivers/media/i2c/Makefile | 1 + drivers/media/i2c/s5kjn5.c | 2835 ++++++++++++++++++++++++++++++++++++ 4 files changed, 2848 insertions(+) create mode 100644 drivers/media/i2c/s5kjn5.c diff --git a/MAINTAINERS b/MAINTAINERS index e03dcc1e9f093..976ffc237936f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -24126,6 +24126,7 @@ M: Wenmeng Liu L: linux-media@vger.kernel.org S: Supported F: Documentation/devicetree/bindings/media/i2c/samsung,s5kjn5.yaml +F: drivers/media/i2c/s5kjn5.c SAMSUNG S5P Security SubSystem (SSS) DRIVER M: Krzysztof Kozlowski diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig index 5d173e0ecf424..c7ea4f7b4345c 100644 --- a/drivers/media/i2c/Kconfig +++ b/drivers/media/i2c/Kconfig @@ -803,6 +803,17 @@ config VIDEO_S5KJN1 To compile this driver as a module, choose M here: the module will be called s5kjn1. +config VIDEO_S5KJN5 + tristate "Samsung S5KJN5 sensor support" + depends on GPIOLIB + select V4L2_CCI_I2C + help + This is a V4L2 sensor driver for Samsung S5KJN5 50MP GBRG + 10-bit RAW MIPI CSI-2 camera sensor. + + To compile this driver as a module, choose M here: the + module will be called s5kjn5. + config VIDEO_T4KA3 tristate "Toshiba T4KA3 sensor support" depends on ACPI || COMPILE_TEST diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile index e45359efe0e41..f32aa42e0ac74 100644 --- a/drivers/media/i2c/Makefile +++ b/drivers/media/i2c/Makefile @@ -131,6 +131,7 @@ obj-$(CONFIG_VIDEO_S5K3M5) += s5k3m5.o obj-$(CONFIG_VIDEO_S5K5BAF) += s5k5baf.o obj-$(CONFIG_VIDEO_S5K6A3) += s5k6a3.o obj-$(CONFIG_VIDEO_S5KJN1) += s5kjn1.o +obj-$(CONFIG_VIDEO_S5KJN5) += s5kjn5.o obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o diff --git a/drivers/media/i2c/s5kjn5.c b/drivers/media/i2c/s5kjn5.c new file mode 100644 index 0000000000000..865db808aabcf --- /dev/null +++ b/drivers/media/i2c/s5kjn5.c @@ -0,0 +1,2835 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Samsung S5KJN5 50 MP GBRG 10-bit RAW MIPI CSI-2 sensor driver + * + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define S5KJN5_REG_CHIP_ID CCI_REG16(0x0000) +#define S5KJN5_CHIP_ID 0x38e5 + +#define S5KJN5_REG_STREAMING CCI_REG8(0x0100) +#define S5KJN5_STREAMING_ON 0x01 +#define S5KJN5_STREAMING_OFF 0x00 + +#define S5KJN5_REG_FRAME_COUNT CCI_REG8(0x0005) +#define S5KJN5_FRAME_COUNT_STANDBY 0xff +#define S5KJN5_STANDBY_POLL_ITERS 20 + +#define S5KJN5_REG_VTS CCI_REG16(0x0340) +#define S5KJN5_VTS_MAX 65535 + +#define S5KJN5_REG_EXPOSURE CCI_REG16(0x0202) + +/* Analogue gain: linear, reg = real * 32 */ +#define S5KJN5_REG_AGAIN CCI_REG16(0x0204) +#define S5KJN5_AGAIN_MIN 0x0020 /* 1x */ +#define S5KJN5_AGAIN_MAX 0x0a00 /* 80x */ +#define S5KJN5_AGAIN_DEFAULT S5KJN5_AGAIN_MIN +#define S5KJN5_AGAIN_STEP 1 + +/* Digital gain: reg = real * 256 */ +#define S5KJN5_REG_DGAIN CCI_REG16(0x020e) +#define S5KJN5_DGAIN_MIN 0x0100 /* 1x */ +#define S5KJN5_DGAIN_MAX 0x1000 /* 16x */ +#define S5KJN5_DGAIN_DEFAULT S5KJN5_DGAIN_MIN +#define S5KJN5_DGAIN_STEP 1 + +#define S5KJN5_REG_TEST_PATTERN CCI_REG16(0x0600) + +#define S5KJN5_EXPOSURE_MIN 4 +#define S5KJN5_EXPOSURE_DEFAULT 0x0100 + +#define S5KJN5_XVCLK_RATE 19200000 + +#define S5KJN5_DATA_LANES 4 + +static const s64 s5kjn5_link_freqs[] = { + 1248000000LL, +}; + +static const char * const s5kjn5_supply_names[] = { + "vddio", + "vddd", + "vdda", + "vddio1p2", + "afvdd", +}; + +#define S5KJN5_NUM_SUPPLIES ARRAY_SIZE(s5kjn5_supply_names) + +struct s5kjn5_mode { + u32 width; + u32 height; + u32 hts; + u32 vts_min; + u64 pixel_rate; + u32 exposure_margin; + const struct cci_reg_sequence *regs; + u32 num_regs; +}; + +/* + * Large blocks of contiguous registers, written as I2C bursts as + * directed by the vendor initialisation sequence. + */ +static const u8 s5kjn5_data_a614[] = { + 0x82, 0x80, 0x01, 0x00, 0x17, 0x53, 0x02, 0xfc, 0xe7, 0x02, 0x83, 0xea, + 0xb7, 0xe7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x87, 0x83, 0xa4, 0x87, 0x0d, + 0x03, 0xa4, 0xc7, 0x0d, 0x01, 0x46, 0xa6, 0x85, 0x22, 0x85, 0x97, 0x40, + 0x01, 0xfc, 0xe7, 0x80, 0xe0, 0x40, 0x97, 0xb0, 0xfe, 0xfb, 0xe7, 0x80, + 0x60, 0xdc, 0x05, 0x46, 0xa6, 0x85, 0x22, 0x85, 0x97, 0x40, 0x01, 0xfc, + 0xe7, 0x80, 0x80, 0x3f, 0x37, 0xa7, 0x02, 0x24, 0x93, 0x07, 0x87, 0x54, + 0x03, 0xc6, 0xc7, 0x02, 0x85, 0x46, 0x63, 0x01, 0xd6, 0x02, 0x83, 0xc6, + 0x07, 0x00, 0x09, 0x47, 0x63, 0x84, 0xe6, 0x08, 0xb7, 0xc7, 0x02, 0x24, + 0x83, 0xa7, 0x07, 0xb7, 0x05, 0x45, 0x82, 0x97, 0x17, 0x53, 0x02, 0xfc, + 0x67, 0x00, 0x83, 0xe6, 0x03, 0xd5, 0x47, 0x05, 0x05, 0xc9, 0x83, 0xd8, + 0x27, 0x05, 0xb7, 0xe6, 0x01, 0x24, 0x83, 0xd5, 0x66, 0x5f, 0x13, 0x07, + 0x87, 0x54, 0x81, 0x46, 0x25, 0x48, 0x03, 0x56, 0xe7, 0x02, 0x09, 0x07, + 0x63, 0xe0, 0xc5, 0x0e, 0x85, 0x06, 0xe3, 0x9a, 0x06, 0xff, 0x37, 0x07, + 0x00, 0x40, 0x3a, 0x95, 0x23, 0x10, 0x15, 0x01, 0x03, 0xd5, 0x67, 0x05, + 0x4d, 0xd5, 0x83, 0xd8, 0x27, 0x05, 0x37, 0xe7, 0x01, 0x24, 0x83, 0x55, + 0x67, 0x5f, 0xbe, 0x86, 0x01, 0x47, 0x25, 0x48, 0x03, 0xd6, 0xe6, 0x02, + 0x89, 0x06, 0x63, 0xee, 0xc5, 0x0a, 0x05, 0x07, 0xe3, 0x1a, 0x07, 0xff, + 0x37, 0x07, 0x00, 0x40, 0x3a, 0x95, 0x23, 0x10, 0x15, 0x01, 0x83, 0xc6, + 0x07, 0x00, 0x09, 0x47, 0xe3, 0x90, 0xe6, 0xf8, 0x03, 0xd5, 0x87, 0x02, + 0x1d, 0xc5, 0x83, 0xd8, 0x67, 0x02, 0x37, 0xf7, 0x01, 0x24, 0x83, 0x55, + 0xa7, 0x81, 0xbe, 0x86, 0x01, 0x47, 0x25, 0x48, 0x03, 0xd6, 0x26, 0x00, + 0x89, 0x06, 0x63, 0xe3, 0xc5, 0x06, 0x05, 0x07, 0xe3, 0x1a, 0x07, 0xff, + 0x37, 0x07, 0x00, 0x40, 0x3a, 0x95, 0x23, 0x10, 0x15, 0x01, 0x03, 0xd5, + 0xa7, 0x02, 0x39, 0xd1, 0x83, 0xd8, 0x67, 0x02, 0x37, 0xf7, 0x01, 0x24, + 0x83, 0x55, 0xa7, 0x81, 0xbe, 0x86, 0x01, 0x47, 0x25, 0x48, 0x03, 0xd6, + 0x26, 0x00, 0x89, 0x06, 0x63, 0xe4, 0xc5, 0x02, 0x05, 0x07, 0xe3, 0x1a, + 0x07, 0xff, 0xb7, 0x07, 0x00, 0x40, 0x3e, 0x95, 0xb7, 0xc7, 0x02, 0x24, + 0x83, 0xa7, 0x07, 0xb7, 0x23, 0x10, 0x15, 0x01, 0x05, 0x45, 0x82, 0x97, + 0x17, 0x53, 0x02, 0xfc, 0x67, 0x00, 0x03, 0xd8, 0x21, 0x07, 0x06, 0x07, + 0xba, 0x97, 0x83, 0xd8, 0x47, 0x00, 0xe1, 0xbf, 0x21, 0x07, 0x06, 0x07, + 0x3e, 0x97, 0x83, 0x58, 0x47, 0x00, 0x69, 0xbf, 0x13, 0x87, 0x06, 0x02, + 0x06, 0x07, 0x3e, 0x97, 0x83, 0x58, 0x07, 0x00, 0x39, 0xbf, 0x13, 0x07, + 0x07, 0x02, 0x06, 0x07, 0x3e, 0x97, 0x83, 0x58, 0x07, 0x00, 0x89, 0xb7, + 0x17, 0x53, 0x02, 0xfc, 0xe7, 0x02, 0x83, 0xcf, 0x32, 0x84, 0xb7, 0xe7, + 0x01, 0x24, 0x03, 0x2b, 0x46, 0x00, 0x83, 0x2a, 0x46, 0x09, 0x03, 0x2a, + 0xc6, 0x04, 0x03, 0x48, 0x86, 0x00, 0x93, 0x87, 0x07, 0x87, 0x03, 0x46, + 0x86, 0x09, 0x03, 0x47, 0x04, 0x05, 0x83, 0xab, 0x07, 0x0e, 0x03, 0xac, + 0x47, 0x0e, 0x33, 0x18, 0x0b, 0x01, 0x33, 0x17, 0xea, 0x00, 0x33, 0x96, + 0xca, 0x00, 0x23, 0x22, 0x04, 0x01, 0x78, 0xc4, 0xaa, 0x84, 0x2e, 0x89, + 0x23, 0x2a, 0xc4, 0x08, 0xde, 0x85, 0x62, 0x85, 0x01, 0x46, 0xb6, 0x89, + 0x97, 0x40, 0x01, 0xfc, 0xe7, 0x80, 0x00, 0x25, 0xce, 0x86, 0x22, 0x86, + 0xca, 0x85, 0x26, 0x85, 0x97, 0xb0, 0xfd, 0xfb, 0xe7, 0x80, 0x00, 0xb0, + 0x62, 0x85, 0x05, 0x46, 0xde, 0x85, 0x97, 0x40, 0x01, 0xfc, 0xe7, 0x80, + 0x20, 0x23, 0xb7, 0xc7, 0x02, 0x24, 0x83, 0xa7, 0x07, 0xb7, 0x23, 0x22, + 0x64, 0x01, 0x23, 0x2a, 0x54, 0x09, 0x23, 0x26, 0x44, 0x05, 0x01, 0x45, + 0x82, 0x97, 0x17, 0x53, 0x02, 0xfc, 0x67, 0x00, 0xe3, 0xc9, 0x01, 0x00, + 0x17, 0x53, 0x02, 0xfc, 0xe7, 0x02, 0x43, 0xc8, 0x2a, 0x84, 0xef, 0xe0, + 0xef, 0xa9, 0xa1, 0x47, 0x63, 0x06, 0xf4, 0x00, 0x17, 0x53, 0x02, 0xfc, + 0x67, 0x00, 0x43, 0xc9, 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0x00, 0x0c, + 0x39, 0xc5, 0xb7, 0x37, 0x01, 0x24, 0x83, 0xc7, 0x27, 0x1a, 0xfd, 0xd3, + 0x37, 0x84, 0x00, 0x40, 0x83, 0x55, 0xe4, 0xf3, 0x0d, 0x45, 0x93, 0xe5, + 0x05, 0x24, 0x97, 0xd0, 0xff, 0xfb, 0xe7, 0x80, 0xa0, 0x0a, 0x83, 0x55, + 0x24, 0xf7, 0xb7, 0xa7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x53, 0x03, 0xd7, + 0x47, 0xb6, 0xc2, 0x05, 0xc1, 0x81, 0x13, 0x77, 0xf7, 0xdb, 0x93, 0xf5, + 0xf5, 0xdb, 0x41, 0x45, 0x23, 0x92, 0xe7, 0xb6, 0x97, 0xd0, 0xff, 0xfb, + 0xe7, 0x80, 0x00, 0x08, 0x55, 0xb7, 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, + 0xa0, 0x03, 0x55, 0xd5, 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0x80, 0x7d, + 0x19, 0xc9, 0xb7, 0x97, 0x01, 0x24, 0x93, 0x87, 0x07, 0xd7, 0x03, 0xc7, + 0x87, 0x03, 0x83, 0xc7, 0x27, 0x06, 0x63, 0x06, 0xf7, 0x06, 0x97, 0x70, + 0xff, 0xfb, 0xe7, 0x80, 0xa0, 0x7b, 0x51, 0xd1, 0xb7, 0x97, 0x01, 0x24, + 0x93, 0x87, 0x07, 0xd7, 0x03, 0xc7, 0xc7, 0x01, 0x83, 0xc7, 0x27, 0x06, + 0xe3, 0x19, 0xf7, 0xf6, 0xb7, 0x27, 0x02, 0x24, 0x05, 0x64, 0x93, 0x87, + 0x07, 0x6b, 0xa2, 0x97, 0x03, 0xc7, 0xf7, 0x80, 0x85, 0x47, 0x63, 0x17, + 0xf7, 0x00, 0xb7, 0x37, 0x01, 0x24, 0x83, 0xc7, 0x57, 0xa5, 0xb1, 0xc3, + 0xb7, 0x87, 0x00, 0x40, 0x83, 0xd5, 0xe7, 0xf3, 0x0d, 0x45, 0x93, 0xe5, + 0x05, 0x01, 0x97, 0xd0, 0xff, 0xfb, 0xe7, 0x80, 0x20, 0x00, 0xb7, 0xa7, + 0x01, 0x24, 0x93, 0x87, 0x07, 0x53, 0x03, 0xd7, 0x47, 0xb6, 0x3d, 0x9b, + 0x23, 0x92, 0xe7, 0xb6, 0x1d, 0xb7, 0xb7, 0x27, 0x02, 0x24, 0x05, 0x64, + 0x93, 0x87, 0x07, 0x6b, 0xa2, 0x97, 0x03, 0xc7, 0xf7, 0x80, 0x91, 0x47, + 0xe3, 0x0d, 0xf7, 0xfa, 0xc1, 0xb7, 0xb7, 0x87, 0x00, 0x40, 0x83, 0xd5, + 0xe7, 0xf3, 0x0d, 0x45, 0x93, 0xe5, 0x05, 0x04, 0x97, 0xd0, 0xff, 0xfb, + 0xe7, 0x80, 0x00, 0xfc, 0xb7, 0x97, 0x01, 0x24, 0x93, 0x87, 0x07, 0x53, + 0xa2, 0x97, 0x03, 0xd7, 0x47, 0xb6, 0x13, 0x77, 0xf7, 0xfb, 0x23, 0x92, + 0xe7, 0xb6, 0xc5, 0xb5, 0x35, 0x71, 0x22, 0xcf, 0x26, 0xcd, 0x73, 0x24, + 0x20, 0x34, 0xf3, 0x24, 0x10, 0x34, 0x73, 0x60, 0x04, 0x30, 0x06, 0xcb, + 0x16, 0xc9, 0x1a, 0xc7, 0x1e, 0xc5, 0x2a, 0xc3, 0x2e, 0xc1, 0xb2, 0xde, + 0xb6, 0xdc, 0xba, 0xda, 0xbe, 0xd8, 0xc2, 0xd6, 0xc6, 0xd4, 0xf2, 0xd2, + 0xf6, 0xd0, 0xfa, 0xce, 0xfe, 0xcc, 0x82, 0xe2, 0x86, 0xe0, 0x0a, 0xfe, + 0x0e, 0xfc, 0x12, 0xfa, 0x16, 0xf8, 0x1a, 0xf6, 0x1e, 0xf4, 0x2a, 0xf2, + 0x2e, 0xf0, 0x32, 0xee, 0x36, 0xec, 0x3a, 0xea, 0x3e, 0xe8, 0x42, 0xe6, + 0x46, 0xe4, 0x72, 0xe2, 0x76, 0xe0, 0x27, 0x2e, 0xe1, 0xff, 0x27, 0x2c, + 0xf1, 0xff, 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0x60, 0xf3, 0x19, 0xc5, + 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0xc0, 0xef, 0x63, 0x1c, 0x05, 0x12, + 0x93, 0x05, 0x00, 0x24, 0x41, 0x45, 0x97, 0xd0, 0xff, 0xfb, 0xe7, 0x80, + 0x60, 0xf9, 0x81, 0x45, 0x93, 0x77, 0x15, 0x00, 0x85, 0xc7, 0x37, 0xd7, + 0x01, 0x24, 0xb7, 0xa7, 0x01, 0x24, 0x13, 0x07, 0x07, 0xc4, 0x93, 0x87, + 0x07, 0x53, 0x03, 0x56, 0x47, 0x07, 0x83, 0xd6, 0xa7, 0xb6, 0x05, 0x06, + 0x93, 0xe6, 0x16, 0x00, 0x23, 0x1a, 0xc7, 0x06, 0x23, 0x95, 0xd7, 0xb6, + 0x93, 0x77, 0x25, 0x00, 0x85, 0xc7, 0x37, 0xd7, 0x01, 0x24, 0xb7, 0xa7, + 0x01, 0x24, 0x13, 0x07, 0x07, 0xc4, 0x93, 0x87, 0x07, 0x53, 0x03, 0x56, + 0xc7, 0x0c, 0x83, 0xd6, 0xa7, 0xb6, 0x05, 0x06, 0x93, 0xe6, 0x26, 0x00, + 0x23, 0x16, 0xc7, 0x0c, 0x23, 0x95, 0xd7, 0xb6, 0x93, 0x77, 0x05, 0x20, + 0x13, 0x75, 0x05, 0x04, 0xc5, 0xc3, 0xb7, 0xd7, 0x01, 0x24, 0x93, 0x87, + 0x07, 0xc4, 0x03, 0xd7, 0x67, 0x08, 0x05, 0x07, 0x23, 0x93, 0xe7, 0x08, + 0xd1, 0xc5, 0x37, 0xa7, 0x01, 0x24, 0x13, 0x07, 0x07, 0x53, 0x83, 0x56, + 0xa7, 0xb6, 0x93, 0xe6, 0x06, 0x20, 0x23, 0x15, 0xd7, 0xb6, 0x11, 0xc9, + 0x03, 0xd6, 0xa7, 0x08, 0x05, 0x06, 0x23, 0x95, 0xc7, 0x08, 0x93, 0xe6, + 0x06, 0x04, 0x23, 0x15, 0xd7, 0xb6, 0xda, 0x40, 0xca, 0x42, 0x3a, 0x43, + 0xaa, 0x43, 0x1a, 0x45, 0x8a, 0x45, 0x76, 0x56, 0xe6, 0x56, 0x56, 0x57, + 0xc6, 0x57, 0x36, 0x58, 0xa6, 0x58, 0x16, 0x5e, 0x86, 0x5e, 0x76, 0x4f, + 0xe6, 0x4f, 0x16, 0x60, 0x86, 0x60, 0x72, 0x71, 0xe2, 0x71, 0x52, 0x72, + 0xc2, 0x72, 0x32, 0x73, 0xa2, 0x73, 0x12, 0x75, 0x82, 0x75, 0x72, 0x66, + 0xe2, 0x66, 0x52, 0x67, 0xc2, 0x67, 0x32, 0x68, 0xa2, 0x68, 0x12, 0x6e, + 0x82, 0x6e, 0x07, 0x2f, 0xc1, 0xff, 0x87, 0x2f, 0x81, 0xff, 0x73, 0x70, + 0x04, 0x30, 0x73, 0x90, 0x14, 0x34, 0x73, 0x10, 0x24, 0x34, 0x7a, 0x44, + 0xea, 0x44, 0x0d, 0x61, 0x73, 0x00, 0x20, 0x30, 0x59, 0xdd, 0xb7, 0xd7, + 0x01, 0x24, 0x93, 0x87, 0x07, 0xc4, 0x03, 0xd7, 0xa7, 0x08, 0x05, 0x07, + 0x23, 0x95, 0xe7, 0x08, 0xc9, 0xd5, 0x37, 0xa7, 0x01, 0x24, 0x13, 0x07, + 0x07, 0x53, 0x83, 0x56, 0xa7, 0xb6, 0x95, 0xbf, 0xb7, 0xa7, 0x01, 0x24, + 0x83, 0xd5, 0x87, 0x09, 0x41, 0x45, 0x97, 0xd0, 0xff, 0xfb, 0xe7, 0x80, + 0xe0, 0xe5, 0x85, 0x45, 0xe1, 0xb5, 0x01, 0x00, 0x82, 0x80, 0x01, 0x00, + 0x17, 0x53, 0x02, 0xfc, 0xe7, 0x02, 0x83, 0x97, 0x37, 0xe4, 0x01, 0x24, + 0x13, 0x04, 0x04, 0x4c, 0x83, 0x44, 0xe4, 0x0a, 0x85, 0x47, 0x23, 0x07, + 0xf4, 0x0a, 0x97, 0xa0, 0xfd, 0xfb, 0xe7, 0x80, 0x20, 0xe3, 0x23, 0x07, + 0x94, 0x0a, 0x17, 0x53, 0x02, 0xfc, 0x67, 0x00, 0x63, 0x97, 0x01, 0x00, + 0xb7, 0xa7, 0x02, 0x24, 0x83, 0xc7, 0x07, 0x5a, 0x05, 0x47, 0x63, 0x83, + 0xe7, 0x00, 0x82, 0x80, 0x17, 0x53, 0x02, 0xfc, 0xe7, 0x02, 0xe3, 0x91, + 0x37, 0x94, 0x01, 0x24, 0x13, 0x04, 0x04, 0x53, 0x03, 0x47, 0x04, 0x1b, + 0x41, 0x11, 0x63, 0x07, 0xf7, 0x00, 0x41, 0x01, 0x17, 0x53, 0x02, 0xfc, + 0x67, 0x00, 0x63, 0x93, 0x89, 0x47, 0xe3, 0x1a, 0xf5, 0xfe, 0x83, 0x47, + 0x34, 0x41, 0xad, 0xc3, 0x83, 0xa9, 0x05, 0x00, 0x2e, 0xc6, 0x97, 0xc0, + 0x01, 0xfc, 0xe7, 0x80, 0x20, 0xb8, 0xaa, 0x84, 0x97, 0x80, 0x01, 0xfc, + 0xe7, 0x80, 0x80, 0xc7, 0xb2, 0x45, 0x2a, 0x89, 0x9c, 0x41, 0x63, 0xf3, + 0x97, 0x00, 0xa6, 0x87, 0x88, 0x51, 0x9c, 0xc1, 0x2e, 0xc6, 0x4a, 0x95, + 0x97, 0xb0, 0x00, 0xfc, 0xe7, 0x80, 0x00, 0xc5, 0xb2, 0x45, 0xaa, 0x84, + 0xe8, 0xc9, 0x33, 0x85, 0x29, 0x01, 0x97, 0xb0, 0x00, 0xfc, 0xe7, 0x80, + 0xe0, 0xc3, 0x85, 0x67, 0x3e, 0x94, 0x83, 0x27, 0xc4, 0x83, 0x26, 0x95, + 0xb2, 0x45, 0x63, 0xf3, 0xa7, 0x00, 0xaa, 0x87, 0x23, 0x22, 0xf4, 0x98, + 0xe8, 0xc5, 0x71, 0xb7, 0x01, 0x45, 0x2e, 0xc6, 0x97, 0xb0, 0x01, 0xfc, + 0xe7, 0x80, 0x80, 0x35, 0xb2, 0x45, 0xaa, 0x89, 0x51, 0xbf, 0x01, 0x00, + 0x17, 0x53, 0x02, 0xfc, 0xe7, 0x02, 0x43, 0x89, 0x2a, 0x84, 0xef, 0xe0, + 0xaf, 0xfc, 0x01, 0xe8, 0xb7, 0xd7, 0x01, 0x24, 0x03, 0xa7, 0x87, 0xc1, + 0x91, 0x47, 0x63, 0x06, 0xf7, 0x00, 0x17, 0x53, 0x02, 0xfc, 0x67, 0x00, + 0xa3, 0x89, 0xb7, 0xd7, 0x01, 0x24, 0x83, 0xc7, 0x07, 0xfa, 0xe5, 0xdb, + 0xb7, 0x47, 0x01, 0x24, 0x83, 0xc7, 0x27, 0xc4, 0xfd, 0xf3, 0x97, 0xe0, + 0x00, 0xfc, 0xe7, 0x80, 0xa0, 0x97, 0xb7, 0x87, 0x02, 0x24, 0x05, 0x47, + 0xa3, 0x80, 0xe7, 0x4e, 0xc9, 0xbf, 0x01, 0x00, 0x17, 0x53, 0x02, 0xfc, + 0xe7, 0x02, 0x43, 0x84, 0x37, 0x84, 0x02, 0x24, 0x13, 0x04, 0xc4, 0x49, + 0x83, 0x47, 0x54, 0x04, 0x99, 0xe7, 0xef, 0xe0, 0x7f, 0x82, 0x17, 0x53, + 0x02, 0xfc, 0x67, 0x00, 0xe3, 0x84, 0x97, 0xe0, 0x00, 0xfc, 0xe7, 0x80, + 0x20, 0xaf, 0xa3, 0x02, 0x04, 0x04, 0xef, 0xe0, 0xff, 0x80, 0x17, 0x53, + 0x02, 0xfc, 0x67, 0x00, 0x63, 0x83, 0x01, 0x00, 0x17, 0x53, 0x02, 0xfc, + 0xe7, 0x02, 0x83, 0x80, 0xb7, 0xe7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x87, + 0x03, 0xa9, 0x87, 0x0e, 0x83, 0xa4, 0xc7, 0x0e, 0x01, 0x46, 0xca, 0x85, + 0x2a, 0x84, 0x26, 0x85, 0x97, 0x40, 0x01, 0xfc, 0xe7, 0x80, 0xc0, 0xd6, + 0x22, 0x85, 0x97, 0xa0, 0xff, 0xfb, 0xe7, 0x80, 0x60, 0x3e, 0x05, 0x46, + 0xca, 0x85, 0x26, 0x85, 0x97, 0x40, 0x01, 0xfc, 0xe7, 0x80, 0x40, 0xd5, + 0x85, 0x47, 0x63, 0x0f, 0xf4, 0x00, 0x91, 0x47, 0x63, 0x0c, 0xf4, 0x00, + 0xb7, 0xc7, 0x02, 0x24, 0x83, 0xa7, 0x07, 0xb7, 0x09, 0x45, 0x82, 0x97, + 0x17, 0x43, 0x02, 0xfc, 0x67, 0x00, 0x43, 0x7d, 0x97, 0x70, 0xff, 0xfb, + 0xe7, 0x80, 0x00, 0xc0, 0x75, 0xf1, 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, + 0x60, 0xbc, 0x69, 0xdd, 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0x40, 0x36, + 0x19, 0xc9, 0xb7, 0x97, 0x01, 0x24, 0x93, 0x87, 0x07, 0xd7, 0x03, 0xc7, + 0x87, 0x03, 0x83, 0xc7, 0x27, 0x06, 0x63, 0x06, 0xf7, 0x06, 0x97, 0x70, + 0xff, 0xfb, 0xe7, 0x80, 0x60, 0x34, 0x4d, 0xd9, 0xb7, 0x97, 0x01, 0x24, + 0x93, 0x87, 0x07, 0xd7, 0x03, 0xc7, 0xc7, 0x01, 0x83, 0xc7, 0x27, 0x06, + 0xe3, 0x10, 0xf7, 0xfa, 0xb7, 0xc7, 0x02, 0x24, 0x83, 0xa7, 0x47, 0xb7, + 0xb7, 0x06, 0x00, 0x40, 0x13, 0x86, 0x46, 0x06, 0x89, 0x65, 0x3e, 0x96, + 0x13, 0x87, 0x06, 0x1f, 0x93, 0x85, 0xf5, 0xf1, 0x23, 0x10, 0xb6, 0x00, + 0x3e, 0x97, 0x7d, 0x56, 0x23, 0x10, 0xc7, 0x00, 0x37, 0xd6, 0x01, 0x24, + 0x13, 0x06, 0x06, 0xe7, 0x03, 0x57, 0xc6, 0x05, 0x03, 0x56, 0x66, 0x06, + 0x93, 0x86, 0x86, 0x1d, 0x32, 0x97, 0x42, 0x07, 0xb6, 0x97, 0x41, 0x83, + 0x23, 0x90, 0xe7, 0x00, 0x91, 0xbf, 0xb7, 0xc7, 0x02, 0x24, 0x83, 0xa7, + 0x47, 0xb7, 0xb7, 0x06, 0x00, 0x40, 0x13, 0x86, 0x46, 0x06, 0x89, 0x65, + 0x3e, 0x96, 0x13, 0x87, 0x06, 0x1f, 0x93, 0x85, 0xf5, 0xf1, 0x23, 0x10, + 0xb6, 0x00, 0x3e, 0x97, 0x7d, 0x56, 0x23, 0x10, 0xc7, 0x00, 0x37, 0xd6, + 0x01, 0x24, 0x13, 0x06, 0x06, 0xe7, 0x03, 0x57, 0x06, 0x06, 0x93, 0x86, + 0xa6, 0x1d, 0x03, 0x56, 0x66, 0x06, 0x5d, 0xbf, 0x17, 0x43, 0x02, 0xfc, + 0xe7, 0x02, 0x03, 0x6d, 0xb7, 0xd7, 0x00, 0x24, 0x83, 0xc7, 0x47, 0x6d, + 0x85, 0x44, 0x63, 0x80, 0x97, 0x14, 0xb7, 0xe7, 0x00, 0x24, 0x03, 0xc4, + 0xc7, 0x84, 0xb7, 0xa7, 0x01, 0x24, 0x83, 0xc7, 0x67, 0x92, 0x33, 0x34, + 0x80, 0x00, 0x33, 0x04, 0x80, 0x40, 0x79, 0x98, 0x13, 0x04, 0x64, 0x02, + 0xed, 0xe7, 0xb7, 0x67, 0x00, 0x24, 0x93, 0x87, 0x07, 0x33, 0x03, 0xd7, + 0xe7, 0x5b, 0x19, 0xc7, 0x13, 0x47, 0xf7, 0xff, 0x61, 0x8f, 0x13, 0x14, + 0x07, 0x01, 0x41, 0x80, 0x83, 0xd7, 0x07, 0x5c, 0x0d, 0x45, 0x5d, 0x8c, + 0x42, 0x04, 0x41, 0x80, 0xa2, 0x85, 0x97, 0xd0, 0xff, 0xfb, 0xe7, 0x80, + 0xa0, 0xbb, 0x93, 0x15, 0x05, 0x01, 0xc1, 0x81, 0xaa, 0x84, 0x63, 0x09, + 0xb4, 0x00, 0x05, 0x65, 0xa1, 0x8d, 0x2d, 0x05, 0x97, 0xa0, 0xff, 0xfb, + 0xe7, 0x80, 0x80, 0x46, 0x13, 0x95, 0x04, 0x01, 0x93, 0xf7, 0x14, 0x00, + 0x41, 0x81, 0x91, 0xcb, 0xb7, 0xd7, 0x01, 0x24, 0x93, 0x87, 0x07, 0xc4, + 0x03, 0xd7, 0x47, 0x07, 0x05, 0x07, 0x23, 0x9a, 0xe7, 0x06, 0x93, 0x77, + 0x25, 0x00, 0x91, 0xcb, 0xb7, 0xd7, 0x01, 0x24, 0x93, 0x87, 0x07, 0xc4, + 0x03, 0xd7, 0xc7, 0x0c, 0x05, 0x07, 0x23, 0x96, 0xe7, 0x0c, 0x93, 0x77, + 0x45, 0x00, 0x91, 0xcb, 0xb7, 0xd7, 0x01, 0x24, 0x93, 0x87, 0x07, 0xc4, + 0x03, 0xd7, 0xe7, 0x0c, 0x05, 0x07, 0x23, 0x97, 0xe7, 0x0c, 0x93, 0x77, + 0x05, 0x02, 0x91, 0xcb, 0xb7, 0xd7, 0x01, 0x24, 0x93, 0x87, 0x07, 0xc4, + 0x03, 0xd7, 0x07, 0x0f, 0x05, 0x07, 0x23, 0x98, 0xe7, 0x0e, 0x93, 0x77, + 0x05, 0x20, 0x91, 0xcb, 0xb7, 0xd7, 0x01, 0x24, 0x93, 0x87, 0x07, 0xc4, + 0x03, 0xd7, 0x67, 0x08, 0x05, 0x07, 0x23, 0x93, 0xe7, 0x08, 0x13, 0x75, + 0x05, 0x04, 0x11, 0xc9, 0xb7, 0xd7, 0x01, 0x24, 0x93, 0x87, 0x07, 0xc4, + 0x03, 0xd7, 0xa7, 0x08, 0x05, 0x07, 0x23, 0x95, 0xe7, 0x08, 0x17, 0x43, + 0x02, 0xfc, 0x67, 0x00, 0xe3, 0x5d, 0xb7, 0xd7, 0x01, 0x24, 0x83, 0xd7, + 0xa7, 0xe7, 0x81, 0xdb, 0x97, 0x60, 0xfe, 0xfb, 0xe7, 0x80, 0x80, 0x68, + 0x63, 0x11, 0x95, 0x06, 0xb7, 0x97, 0x01, 0x24, 0x93, 0x87, 0x07, 0xd7, + 0x03, 0xc7, 0xc7, 0x01, 0x83, 0xc7, 0x27, 0x06, 0x63, 0x07, 0xf7, 0x04, + 0x13, 0x64, 0x04, 0x24, 0x42, 0x04, 0x41, 0x80, 0x11, 0xa0, 0x01, 0x44, + 0xb7, 0x67, 0x00, 0x24, 0x93, 0x87, 0x07, 0x33, 0x03, 0xc7, 0x27, 0x3b, + 0xe3, 0x0f, 0x07, 0xec, 0x37, 0xa7, 0x01, 0x24, 0x03, 0x47, 0x67, 0x92, + 0xe3, 0x09, 0x07, 0xec, 0x37, 0xd7, 0x01, 0x24, 0x03, 0x57, 0xa7, 0xe7, + 0xe3, 0x03, 0x07, 0xec, 0x37, 0x97, 0x01, 0x24, 0x03, 0x47, 0x17, 0x00, + 0xe3, 0x0d, 0x07, 0xea, 0x13, 0x74, 0xf4, 0xdf, 0x42, 0x04, 0x41, 0x80, + 0x7d, 0xb5, 0x97, 0x60, 0xfe, 0xfb, 0xe7, 0x80, 0xe0, 0x61, 0x85, 0x47, + 0xe3, 0x1c, 0xf5, 0xfa, 0xb7, 0x97, 0x01, 0x24, 0x93, 0x87, 0x07, 0xd7, + 0x03, 0xc7, 0xc7, 0x01, 0x83, 0xc7, 0x27, 0x06, 0xe3, 0x12, 0xf7, 0xfa, + 0x13, 0x64, 0x04, 0x20, 0x42, 0x04, 0x41, 0x80, 0x61, 0xbf, 0x01, 0x00, + 0x71, 0x71, 0x22, 0xd7, 0x26, 0xd5, 0x73, 0x24, 0x20, 0x34, 0xf3, 0x24, + 0x10, 0x34, 0x73, 0x60, 0x04, 0x30, 0x2e, 0xc5, 0xa5, 0x65, 0xbe, 0xdc, + 0x06, 0xd3, 0x16, 0xd1, 0x1a, 0xcf, 0x1e, 0xcd, 0x22, 0xcb, 0x2a, 0xc7, + 0x32, 0xc3, 0x36, 0xc1, 0xba, 0xde, 0xc2, 0xda, 0xc6, 0xd8, 0xf2, 0xd0, + 0xf6, 0xce, 0xfa, 0xcc, 0xfe, 0xca, 0x82, 0xe2, 0x86, 0xe0, 0x0a, 0xfe, + 0x0e, 0xfc, 0x12, 0xfa, 0x16, 0xf8, 0x1a, 0xf6, 0x1e, 0xf4, 0x2a, 0xf2, + 0x2e, 0xf0, 0x32, 0xee, 0x26, 0xc9, 0xca, 0xd6, 0xce, 0xd4, 0xd2, 0xd2, + 0x93, 0x85, 0x05, 0x40, 0x05, 0x45, 0x36, 0xec, 0x3a, 0xea, 0x3e, 0xe8, + 0x42, 0xe6, 0x46, 0xe4, 0x72, 0xe2, 0x76, 0xe0, 0x27, 0x2e, 0xe1, 0xff, + 0x27, 0x2c, 0xf1, 0xff, 0x97, 0xd0, 0xff, 0xfb, 0xe7, 0x80, 0x40, 0x97, + 0xa1, 0x67, 0xe9, 0x8f, 0x2a, 0x84, 0x63, 0x94, 0x07, 0x18, 0xb7, 0x64, + 0x01, 0x24, 0x93, 0x84, 0x04, 0x40, 0x85, 0x67, 0xe1, 0x8f, 0xcd, 0xcf, + 0x37, 0xd7, 0x01, 0x24, 0x37, 0x89, 0x02, 0x24, 0x13, 0x07, 0x07, 0xc4, + 0x13, 0x09, 0xc9, 0x49, 0x83, 0x56, 0x67, 0x0e, 0x83, 0x27, 0x09, 0x05, + 0x85, 0x06, 0x85, 0x07, 0x23, 0x28, 0xf9, 0x04, 0x23, 0x13, 0xd7, 0x0e, + 0x85, 0x8b, 0x63, 0x9f, 0x07, 0x1a, 0x85, 0x47, 0xa3, 0x0a, 0xf9, 0x04, + 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0x00, 0xff, 0x19, 0xc5, 0x03, 0x57, + 0x49, 0x05, 0x93, 0x07, 0x10, 0x10, 0x63, 0x06, 0xf7, 0x24, 0xdc, 0x50, + 0x09, 0x45, 0x82, 0x97, 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0xc0, 0x85, + 0x11, 0xc5, 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0x20, 0x88, 0x55, 0xc5, + 0x97, 0x60, 0x00, 0xfc, 0xe7, 0x80, 0x40, 0x5a, 0xb7, 0x87, 0x00, 0x24, + 0x83, 0xc7, 0x07, 0x8c, 0xaa, 0x89, 0x63, 0x92, 0x07, 0x1c, 0xb7, 0xd7, + 0x01, 0x24, 0x93, 0x87, 0x07, 0xe7, 0xbc, 0x5f, 0x63, 0x9a, 0x07, 0x16, + 0x37, 0x99, 0x01, 0x24, 0x13, 0x09, 0x09, 0x53, 0xb7, 0x27, 0x00, 0x24, + 0x83, 0xc7, 0x77, 0x52, 0x63, 0x96, 0x07, 0x1e, 0x03, 0x45, 0xc9, 0x18, + 0x63, 0x1d, 0x05, 0x1c, 0xdc, 0x50, 0x0d, 0x45, 0x82, 0x97, 0x4e, 0x85, + 0x97, 0x60, 0x00, 0xfc, 0xe7, 0x80, 0x00, 0x5a, 0x85, 0x67, 0x3e, 0x99, + 0x23, 0x20, 0xa9, 0xa2, 0x13, 0x74, 0x04, 0x40, 0x21, 0xc4, 0xb7, 0xd7, + 0x01, 0x24, 0x93, 0x87, 0x07, 0xc4, 0x37, 0xa7, 0x01, 0x24, 0x83, 0xd6, + 0x67, 0x0e, 0x13, 0x07, 0x07, 0x53, 0x03, 0x47, 0x17, 0x9b, 0x85, 0x06, + 0x37, 0x84, 0x02, 0x24, 0x13, 0x04, 0xc4, 0x49, 0x13, 0x37, 0x17, 0x00, + 0x23, 0x93, 0xd7, 0x0e, 0x23, 0x0a, 0xe4, 0x04, 0x97, 0x70, 0xff, 0xfb, + 0xe7, 0x80, 0x40, 0xf3, 0x63, 0x06, 0x05, 0x10, 0x03, 0x57, 0x44, 0x05, + 0x93, 0x07, 0x10, 0x10, 0x63, 0x00, 0xf7, 0x10, 0xdc, 0x50, 0x1d, 0x45, + 0x82, 0x97, 0x9a, 0x50, 0x8a, 0x52, 0x7a, 0x43, 0xea, 0x43, 0x5a, 0x44, + 0xca, 0x44, 0x3a, 0x45, 0xaa, 0x45, 0x1a, 0x46, 0x8a, 0x46, 0x76, 0x57, + 0xe6, 0x57, 0x56, 0x58, 0xc6, 0x58, 0x36, 0x59, 0xa6, 0x59, 0x16, 0x5a, + 0x06, 0x5e, 0xf6, 0x4e, 0x66, 0x4f, 0xd6, 0x4f, 0x16, 0x60, 0x86, 0x60, + 0x72, 0x71, 0xe2, 0x71, 0x52, 0x72, 0xc2, 0x72, 0x32, 0x73, 0xa2, 0x73, + 0x12, 0x75, 0x82, 0x75, 0x72, 0x66, 0xe2, 0x66, 0x52, 0x67, 0xc2, 0x67, + 0x32, 0x68, 0xa2, 0x68, 0x12, 0x6e, 0x82, 0x6e, 0x07, 0x2f, 0xc1, 0xff, + 0x87, 0x2f, 0x81, 0xff, 0x73, 0x70, 0x04, 0x30, 0x73, 0x90, 0x14, 0x34, + 0x73, 0x10, 0x24, 0x34, 0x3a, 0x54, 0xaa, 0x54, 0x4d, 0x61, 0x73, 0x00, + 0x20, 0x30, 0x37, 0xd9, 0x01, 0x24, 0x13, 0x09, 0x09, 0xc4, 0x83, 0x57, + 0x49, 0x0e, 0xb7, 0x64, 0x01, 0x24, 0x93, 0x84, 0x04, 0x40, 0xd8, 0x50, + 0x85, 0x07, 0x01, 0x45, 0x23, 0x12, 0xf9, 0x0e, 0x02, 0x97, 0x97, 0x60, + 0xff, 0xfb, 0xe7, 0x80, 0x20, 0x71, 0x25, 0xe5, 0xb7, 0x29, 0x00, 0x24, + 0x37, 0x99, 0x01, 0x24, 0x93, 0x89, 0x09, 0x33, 0x13, 0x09, 0x09, 0x53, + 0x05, 0x6a, 0x83, 0xc7, 0x79, 0x1f, 0x4a, 0x9a, 0x23, 0x20, 0x0a, 0xa2, + 0xb9, 0xef, 0x03, 0x45, 0xc9, 0x18, 0x2d, 0xe5, 0x83, 0xc7, 0x09, 0x20, + 0x89, 0xc7, 0x03, 0x27, 0x4a, 0xb3, 0x63, 0x0a, 0xf7, 0x00, 0x97, 0xe0, + 0x00, 0xfc, 0xe7, 0x80, 0xe0, 0xd2, 0xdc, 0x50, 0x05, 0x45, 0x82, 0x97, + 0x29, 0xbd, 0x01, 0xa0, 0x85, 0x47, 0x23, 0x0a, 0x09, 0x04, 0xa3, 0x0a, + 0x09, 0x04, 0x23, 0x28, 0xf9, 0x04, 0x3d, 0xbd, 0x7d, 0x55, 0x97, 0x70, + 0x01, 0xfc, 0xe7, 0x80, 0xa0, 0x04, 0x59, 0xb5, 0xef, 0xe0, 0x5f, 0xd9, + 0x01, 0xb7, 0x97, 0x60, 0xff, 0xfb, 0xe7, 0x80, 0x20, 0x6d, 0x49, 0xf9, + 0x83, 0x57, 0x49, 0x0e, 0x85, 0x8b, 0xc9, 0xf7, 0xcd, 0xbd, 0x97, 0x70, + 0x01, 0xfc, 0xe7, 0x80, 0x20, 0x03, 0x23, 0x11, 0xa9, 0x4e, 0x03, 0x45, + 0xc9, 0x18, 0x49, 0xdd, 0x97, 0xc0, 0xff, 0xfb, 0xe7, 0x80, 0x40, 0xb4, + 0x41, 0xbf, 0x97, 0x70, 0x01, 0xfc, 0xe7, 0x80, 0x60, 0x01, 0x37, 0x99, + 0x01, 0x24, 0x13, 0x09, 0x09, 0x53, 0x8d, 0x67, 0xca, 0x97, 0x03, 0xc7, + 0xd7, 0x6f, 0x23, 0x2e, 0xa9, 0x4e, 0x85, 0x47, 0x63, 0x06, 0xf7, 0x00, + 0x83, 0x27, 0x09, 0x4f, 0xe3, 0x77, 0xf5, 0xea, 0x97, 0x60, 0x00, 0xfc, + 0xe7, 0x80, 0x80, 0xfc, 0x97, 0x70, 0x01, 0xfc, 0xe7, 0x80, 0x40, 0xfe, + 0x23, 0x20, 0xa9, 0x50, 0x21, 0xbd, 0x97, 0xc0, 0xff, 0xfb, 0xe7, 0x80, + 0xa0, 0xb2, 0x0d, 0xb5, 0x97, 0x70, 0x01, 0xfc, 0xe7, 0x80, 0xc0, 0xfc, + 0x23, 0x12, 0xa9, 0x4e, 0x31, 0xb5, 0xef, 0xe0, 0x7f, 0xd0, 0x55, 0xbb, + 0x17, 0x43, 0x02, 0xfc, 0xe7, 0x02, 0xc3, 0x1e, 0x2a, 0x84, 0xef, 0xd0, + 0xbf, 0xa7, 0x89, 0x47, 0x63, 0x06, 0xf4, 0x00, 0x17, 0x43, 0x02, 0xfc, + 0x67, 0x00, 0xc3, 0x1f, 0xb7, 0xe7, 0x00, 0x24, 0x03, 0xd7, 0xc7, 0xc8, + 0x85, 0x64, 0x93, 0x87, 0xf4, 0xb3, 0xe3, 0x15, 0xf7, 0xfe, 0x37, 0xa9, + 0x02, 0x24, 0x13, 0x09, 0x89, 0x54, 0x83, 0x47, 0x19, 0x0c, 0xe9, 0xff, + 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0x00, 0xe3, 0x61, 0xf9, 0x97, 0x70, + 0xff, 0xfb, 0xe7, 0x80, 0xa0, 0xe3, 0x79, 0xf1, 0x37, 0x25, 0x02, 0x24, + 0x13, 0x05, 0x05, 0xed, 0x97, 0x00, 0xff, 0xfb, 0xe7, 0x80, 0x80, 0xfa, + 0xb7, 0x97, 0x01, 0x24, 0x37, 0x67, 0x01, 0x24, 0x03, 0x27, 0x07, 0x40, + 0x93, 0x87, 0x07, 0x53, 0xa6, 0x97, 0x85, 0x44, 0x1d, 0x45, 0x23, 0x8d, + 0x97, 0xce, 0x02, 0x97, 0xa3, 0x00, 0x99, 0x0c, 0x97, 0x80, 0x01, 0xfc, + 0xe7, 0x80, 0x00, 0x83, 0x51, 0xf5, 0xb7, 0x27, 0x01, 0x24, 0x23, 0x80, + 0x87, 0x54, 0x97, 0xb0, 0xfe, 0xfb, 0xe7, 0x80, 0x60, 0x02, 0x23, 0x01, + 0x99, 0x0c, 0x9d, 0xbf, 0x17, 0x43, 0x02, 0xfc, 0xe7, 0x02, 0xc3, 0x14, + 0x37, 0xa4, 0x02, 0x24, 0x13, 0x04, 0x84, 0x54, 0x03, 0x47, 0x24, 0x0c, + 0x85, 0x47, 0x63, 0x0a, 0xf7, 0x00, 0x97, 0xb0, 0xfe, 0xfb, 0xe7, 0x80, + 0xe0, 0x69, 0x17, 0x43, 0x02, 0xfc, 0x67, 0x00, 0xe3, 0x14, 0x97, 0x70, + 0x01, 0xfc, 0xe7, 0x80, 0x60, 0x7e, 0x65, 0xf5, 0x97, 0xb0, 0xfe, 0xfb, + 0xe7, 0x80, 0x80, 0x0f, 0x23, 0x01, 0x04, 0x0c, 0xe9, 0xbf, 0x01, 0x00, + 0x17, 0x43, 0x02, 0xfc, 0xe7, 0x02, 0x83, 0x10, 0x9d, 0x47, 0x63, 0x1f, + 0xf5, 0x00, 0x37, 0x94, 0x01, 0x24, 0x13, 0x04, 0x04, 0x53, 0x85, 0x67, + 0xa2, 0x97, 0x83, 0xc7, 0xa7, 0xcf, 0x9d, 0xe7, 0x17, 0x43, 0x02, 0xfc, + 0x67, 0x00, 0xc3, 0x10, 0x2a, 0x84, 0xef, 0xd0, 0x7f, 0xdd, 0x85, 0x47, + 0xe3, 0x18, 0xf4, 0xfe, 0xb7, 0xe7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x4c, + 0x23, 0xae, 0x07, 0x10, 0x23, 0xa4, 0x07, 0x7e, 0x17, 0x43, 0x02, 0xfc, + 0x67, 0x00, 0x83, 0x0e, 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0xc0, 0xd3, + 0x71, 0xf5, 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0x60, 0xd4, 0x69, 0xf1, + 0x8d, 0x67, 0x3e, 0x94, 0x83, 0x27, 0x84, 0x6d, 0xb7, 0x24, 0x01, 0x24, + 0x93, 0x84, 0x04, 0x5f, 0x91, 0xef, 0x83, 0xa7, 0x44, 0x0e, 0x99, 0xcb, + 0xb7, 0xd7, 0x01, 0x24, 0x83, 0xc7, 0x07, 0xfa, 0xc5, 0xd3, 0x97, 0x00, + 0xff, 0xfb, 0xe7, 0x80, 0x20, 0xe3, 0x59, 0xbf, 0x83, 0xa7, 0xc4, 0x0a, + 0xc1, 0xdb, 0x05, 0x45, 0x97, 0x30, 0xfe, 0xfb, 0xe7, 0x80, 0x80, 0x51, + 0xb7, 0x35, 0x20, 0x2d, 0x75, 0x78, 0x37, 0xf5, 0x20, 0x2d, 0x93, 0x85, + 0x05, 0x60, 0x13, 0x08, 0x08, 0xa0, 0x91, 0x68, 0x13, 0x05, 0x05, 0x60, + 0xb3, 0x87, 0x05, 0x01, 0x03, 0xc7, 0x07, 0x00, 0x93, 0x06, 0xf0, 0x0f, + 0x13, 0x16, 0x87, 0x01, 0x61, 0x86, 0x06, 0x07, 0x63, 0x44, 0x06, 0x00, + 0x93, 0x76, 0xf7, 0x0f, 0x23, 0x80, 0xd7, 0x00, 0x85, 0x07, 0xe3, 0x91, + 0xb7, 0xfe, 0xb3, 0x85, 0x17, 0x01, 0xe3, 0x9b, 0xa5, 0xfc, 0xb7, 0xa7, + 0x02, 0x24, 0x05, 0x47, 0x01, 0x45, 0xa3, 0x84, 0xe7, 0x60, 0x97, 0x30, + 0xfe, 0xfb, 0xe7, 0x80, 0xe0, 0x4b, 0xb7, 0xd7, 0x01, 0x24, 0x83, 0xc7, + 0x07, 0xfa, 0x8d, 0xd3, 0x83, 0x27, 0x84, 0x6d, 0x91, 0xff, 0x83, 0xa7, + 0x44, 0x0e, 0x99, 0xdb, 0x9d, 0xbf, 0x01, 0x00, 0x17, 0x43, 0x02, 0xfc, + 0xe7, 0x02, 0x83, 0xff, 0xb7, 0xd7, 0x01, 0x24, 0x93, 0x87, 0x07, 0xf4, + 0x03, 0xc7, 0x17, 0x05, 0x2a, 0x84, 0x11, 0xc7, 0x03, 0xc7, 0x17, 0x00, + 0x89, 0x47, 0x63, 0x07, 0xf7, 0x04, 0xb7, 0xe7, 0x01, 0x24, 0x93, 0x87, + 0x07, 0x87, 0x83, 0xa4, 0x87, 0x0f, 0x03, 0xa9, 0xc7, 0x0f, 0x01, 0x46, + 0xa6, 0x85, 0x4a, 0x85, 0x97, 0x30, 0x01, 0xfc, 0xe7, 0x80, 0x40, 0x54, + 0x22, 0x85, 0x97, 0xd0, 0xfe, 0xfb, 0xe7, 0x80, 0x20, 0xd7, 0x4a, 0x85, + 0x05, 0x46, 0xa6, 0x85, 0x97, 0x30, 0x01, 0xfc, 0xe7, 0x80, 0xc0, 0x52, + 0xb7, 0xc7, 0x02, 0x24, 0x83, 0xa7, 0x07, 0xb7, 0x11, 0x45, 0x82, 0x97, + 0x17, 0x43, 0x02, 0xfc, 0x67, 0x00, 0x83, 0xfb, 0xb7, 0xe7, 0x00, 0x24, + 0x83, 0xd6, 0xc7, 0xc8, 0x85, 0x67, 0x13, 0x87, 0xf7, 0xb3, 0xe3, 0x94, + 0xe6, 0xfa, 0x37, 0x97, 0x01, 0x24, 0x13, 0x07, 0x07, 0x53, 0xba, 0x97, + 0x03, 0xa5, 0x07, 0xb2, 0x81, 0x45, 0x33, 0x25, 0xa0, 0x00, 0x97, 0xd0, + 0x00, 0xfc, 0xe7, 0x80, 0x60, 0xbb, 0x61, 0xb7, 0x17, 0x43, 0x02, 0xfc, + 0xe7, 0x02, 0xc3, 0xf5, 0x97, 0x60, 0xff, 0xfb, 0xe7, 0x80, 0xc0, 0x37, + 0x11, 0xc5, 0xb7, 0xe7, 0x00, 0x24, 0x83, 0xc7, 0xc7, 0x84, 0xbd, 0xef, + 0x13, 0x84, 0x81, 0xe7, 0x03, 0x47, 0x84, 0x00, 0x85, 0x47, 0x63, 0x03, + 0xf7, 0x06, 0x03, 0x57, 0x24, 0x03, 0xb7, 0x67, 0x00, 0x40, 0x23, 0x98, + 0xe7, 0x18, 0x83, 0x57, 0x44, 0x03, 0x37, 0x67, 0x00, 0x40, 0x23, 0x14, + 0xf7, 0x20, 0x97, 0x60, 0xff, 0xfb, 0xe7, 0x80, 0x20, 0x34, 0x19, 0xc5, + 0xb7, 0xe7, 0x00, 0x24, 0x03, 0xc7, 0xc7, 0x84, 0x81, 0x47, 0x09, 0xeb, + 0x83, 0x46, 0x84, 0x00, 0x05, 0x47, 0x81, 0x47, 0x63, 0x84, 0xe6, 0x00, + 0x83, 0x57, 0xc4, 0x05, 0x37, 0xa7, 0x00, 0x40, 0x23, 0x12, 0xf7, 0x10, + 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0xc0, 0xb6, 0x35, 0xc1, 0x97, 0x70, + 0xff, 0xfb, 0xe7, 0x80, 0x60, 0xb7, 0x05, 0xc9, 0x17, 0x43, 0x02, 0xfc, + 0x67, 0x00, 0xc3, 0xef, 0xb7, 0x67, 0x00, 0x40, 0x23, 0x98, 0x07, 0x18, + 0x81, 0x47, 0x55, 0xb7, 0xb7, 0x67, 0x00, 0x40, 0x23, 0x98, 0x07, 0x18, + 0x13, 0x84, 0x81, 0xe7, 0x83, 0x46, 0x84, 0x00, 0x05, 0x47, 0x81, 0x47, + 0xe3, 0x95, 0xe6, 0xf8, 0x69, 0xb7, 0x97, 0x60, 0xff, 0xfb, 0xe7, 0x80, + 0x20, 0x2d, 0x31, 0xed, 0x83, 0x46, 0x84, 0x00, 0x05, 0x47, 0x81, 0x47, + 0x63, 0x84, 0xe6, 0x00, 0x83, 0x57, 0x44, 0x08, 0x37, 0x87, 0x00, 0x40, + 0x23, 0x14, 0xf7, 0x10, 0x17, 0x43, 0x02, 0xfc, 0x67, 0x00, 0xc3, 0xea, + 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0x40, 0xb1, 0x59, 0xf9, 0x97, 0x60, + 0xff, 0xfb, 0xe7, 0x80, 0xe0, 0x29, 0x19, 0xc5, 0xb7, 0xe7, 0x00, 0x24, + 0x03, 0xc7, 0xc7, 0x84, 0x81, 0x47, 0x09, 0xeb, 0x83, 0x46, 0x84, 0x00, + 0x05, 0x47, 0x81, 0x47, 0x63, 0x84, 0xe6, 0x00, 0x83, 0x57, 0x64, 0x07, + 0x37, 0x07, 0x01, 0x40, 0x23, 0x14, 0xf7, 0x10, 0x9d, 0xb7, 0xb7, 0xe7, + 0x00, 0x24, 0x03, 0xc7, 0xc7, 0x84, 0x81, 0x47, 0x55, 0xf7, 0x69, 0xbf, + 0x17, 0x43, 0x02, 0xfc, 0xe7, 0x02, 0x03, 0xe1, 0x41, 0x11, 0x3a, 0x84, + 0x22, 0xe6, 0x26, 0xe4, 0x4a, 0xe2, 0x4e, 0xe0, 0xaa, 0x84, 0x36, 0x89, + 0x97, 0xa0, 0xfe, 0xfb, 0xe7, 0x80, 0x80, 0x66, 0xb7, 0x27, 0x02, 0x24, + 0x93, 0x87, 0x07, 0x6b, 0xa2, 0x97, 0x05, 0x67, 0xba, 0x97, 0x83, 0xc7, + 0x07, 0x8d, 0x63, 0x9d, 0x07, 0x18, 0x83, 0xc7, 0x04, 0x00, 0x63, 0x99, + 0x07, 0x18, 0xb7, 0xa7, 0x02, 0x24, 0x93, 0x89, 0x87, 0x54, 0x03, 0xc7, + 0x99, 0x05, 0x63, 0x01, 0x07, 0x18, 0x03, 0xca, 0xa9, 0x05, 0x03, 0xd6, + 0xa9, 0x0b, 0x37, 0xe7, 0x01, 0x24, 0x03, 0x55, 0x67, 0x5f, 0x93, 0x87, + 0x87, 0x54, 0x01, 0x47, 0xa1, 0x45, 0x63, 0x69, 0xa6, 0x22, 0x83, 0xd6, + 0xc7, 0x0a, 0x89, 0x07, 0x63, 0xf1, 0xa6, 0x26, 0x05, 0x07, 0xe3, 0x18, + 0xb7, 0xfe, 0x37, 0xcb, 0x02, 0x24, 0x53, 0x09, 0x00, 0xf0, 0x87, 0x27, + 0x8b, 0xb7, 0x9d, 0x46, 0x43, 0x79, 0xf9, 0x90, 0x13, 0x07, 0x07, 0x05, + 0x06, 0x07, 0x4e, 0x97, 0x83, 0x57, 0xc7, 0x00, 0x11, 0x8d, 0x53, 0x77, + 0x05, 0xd0, 0x91, 0x8f, 0xd3, 0xf7, 0x07, 0xd0, 0x93, 0x17, 0x3a, 0x00, + 0xb6, 0x97, 0x53, 0x77, 0xf7, 0x18, 0x93, 0x87, 0x87, 0x02, 0x86, 0x07, + 0xce, 0x97, 0x83, 0xd7, 0xc7, 0x00, 0x07, 0x26, 0x8b, 0xb7, 0x13, 0xf7, + 0xf7, 0x0f, 0xa1, 0x83, 0xd3, 0x77, 0x07, 0xd0, 0xd3, 0xf6, 0x07, 0xd0, + 0xc3, 0xf7, 0xc7, 0x68, 0x53, 0x79, 0xf9, 0x08, 0x43, 0x79, 0xe9, 0x78, + 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0xc0, 0x8a, 0xaa, 0x8a, 0x93, 0xda, + 0x8a, 0x40, 0x97, 0x70, 0xff, 0xfb, 0xe7, 0x80, 0xe0, 0x89, 0xc2, 0x0a, + 0x93, 0x07, 0x8a, 0x04, 0x13, 0x75, 0xf5, 0x0f, 0x93, 0xda, 0x0a, 0x41, + 0xd3, 0xf7, 0x0a, 0xd0, 0xd3, 0x74, 0x05, 0xd0, 0x07, 0x27, 0x8b, 0xb7, + 0x86, 0x07, 0xce, 0x97, 0x03, 0xdc, 0xc7, 0x00, 0xc3, 0xf4, 0xe4, 0x78, + 0xdc, 0x4c, 0x53, 0x74, 0x0c, 0xd0, 0xd3, 0x07, 0x00, 0xf0, 0x83, 0xd4, + 0xc7, 0x00, 0x53, 0xf4, 0x84, 0x08, 0x13, 0x0a, 0x0a, 0x05, 0x06, 0x0a, + 0x4e, 0x9a, 0x03, 0x5a, 0x4a, 0x00, 0xd3, 0x17, 0xf4, 0xa0, 0x99, 0xc3, + 0x53, 0x14, 0x84, 0x20, 0xb7, 0xcb, 0x02, 0x24, 0x83, 0xa7, 0x0b, 0xb7, + 0x0d, 0x45, 0x82, 0x97, 0xd3, 0x97, 0x14, 0xc0, 0xc2, 0x07, 0xc1, 0x83, + 0x63, 0x95, 0x87, 0x0b, 0xb7, 0x47, 0x01, 0x24, 0x93, 0x87, 0x07, 0x27, + 0x03, 0xd7, 0x67, 0x12, 0x83, 0xd6, 0xe7, 0x10, 0x89, 0x47, 0x7d, 0x17, + 0xb3, 0x97, 0xe7, 0x00, 0xd3, 0xf7, 0x07, 0xd0, 0x53, 0xf7, 0x16, 0xd0, + 0x53, 0x04, 0x00, 0xf0, 0xd3, 0xf7, 0x27, 0x11, 0x37, 0xca, 0x02, 0x24, + 0xd3, 0xf7, 0xe7, 0x18, 0xb7, 0xc7, 0x02, 0x24, 0x07, 0xa7, 0xc7, 0xb7, + 0x83, 0xa7, 0x0b, 0xb7, 0x25, 0x45, 0xd3, 0xf7, 0xe7, 0x00, 0xd3, 0x9a, + 0x17, 0xc0, 0x82, 0x97, 0x87, 0x27, 0x0a, 0xb8, 0xc2, 0x0a, 0x93, 0xda, + 0x0a, 0x01, 0x53, 0x74, 0xf4, 0x10, 0xd6, 0x94, 0xc2, 0x04, 0x23, 0x93, + 0x59, 0x0d, 0xc1, 0x80, 0xd3, 0x17, 0x14, 0xc0, 0x23, 0x92, 0xf9, 0x0c, + 0xb7, 0x07, 0x00, 0x40, 0x19, 0xec, 0x93, 0x87, 0xe7, 0x03, 0xca, 0x97, + 0x23, 0x90, 0x97, 0x00, 0x32, 0x64, 0xa2, 0x64, 0x12, 0x69, 0x82, 0x69, + 0x41, 0x01, 0x17, 0x43, 0x02, 0xfc, 0x67, 0x00, 0x23, 0xc7, 0x93, 0x87, + 0x07, 0x04, 0x32, 0x64, 0xa2, 0x64, 0x12, 0x69, 0x82, 0x69, 0xca, 0x97, + 0x23, 0x90, 0x97, 0x00, 0x41, 0x01, 0x17, 0x43, 0x02, 0xfc, 0x67, 0x00, + 0x63, 0xc5, 0x93, 0x77, 0xfa, 0x0f, 0x13, 0x5a, 0x8a, 0x00, 0x87, 0x29, + 0x8b, 0xb7, 0xd3, 0xf7, 0x07, 0xd0, 0xd3, 0x76, 0x0a, 0xd0, 0x37, 0xca, + 0x02, 0x24, 0x07, 0x27, 0x0a, 0xb8, 0xc3, 0xf7, 0x37, 0x69, 0x53, 0x74, + 0xf4, 0x18, 0x53, 0x74, 0xe4, 0x10, 0x53, 0x1b, 0x14, 0xc0, 0x42, 0x0b, + 0x13, 0x5b, 0x0b, 0x01, 0x5a, 0x85, 0x97, 0x60, 0x00, 0xfc, 0xe7, 0x80, + 0xa0, 0x1a, 0xaa, 0x8a, 0x5a, 0x85, 0x97, 0x60, 0x00, 0xfc, 0xe7, 0x80, + 0xe0, 0x19, 0x93, 0xda, 0x8a, 0x00, 0xd3, 0x97, 0x04, 0xc0, 0xc2, 0x0a, + 0x13, 0x75, 0xf5, 0x0f, 0x93, 0xda, 0x0a, 0x01, 0x53, 0x74, 0x05, 0xd0, + 0xd3, 0xf7, 0x0a, 0xd0, 0xc2, 0x07, 0xc1, 0x87, 0x43, 0x74, 0x34, 0x79, + 0x63, 0xd7, 0x87, 0x03, 0x53, 0x74, 0x89, 0x18, 0xb7, 0x47, 0x01, 0x24, + 0x93, 0x87, 0x07, 0x27, 0x03, 0xd7, 0x67, 0x12, 0x83, 0xd6, 0xe7, 0x10, + 0x89, 0x47, 0x7d, 0x17, 0xb3, 0x97, 0xe7, 0x00, 0xd3, 0xf7, 0x07, 0xd0, + 0x53, 0xf7, 0x16, 0xd0, 0xd3, 0xf7, 0x87, 0x10, 0xc5, 0xbd, 0x53, 0x74, + 0x89, 0x10, 0xd9, 0xbf, 0x93, 0x17, 0x4a, 0x00, 0xce, 0x97, 0x83, 0xd7, + 0xa7, 0x06, 0x93, 0xf6, 0xf7, 0x0f, 0x37, 0xcb, 0x02, 0x24, 0xa1, 0x83, + 0x53, 0xf9, 0x06, 0xd0, 0xd3, 0xf7, 0x07, 0xd0, 0x07, 0x27, 0x8b, 0xb7, + 0x43, 0x79, 0xe9, 0x78, 0xe3, 0x0e, 0x07, 0xe0, 0x93, 0x07, 0xf7, 0x04, + 0x86, 0x07, 0xce, 0x97, 0x03, 0xd6, 0xc7, 0x00, 0x93, 0x06, 0xf7, 0xff, + 0x75, 0xbb, 0x93, 0x17, 0x3a, 0x00, 0xba, 0x97, 0x93, 0x87, 0x87, 0x02, + 0x86, 0x07, 0xce, 0x97, 0x83, 0xd7, 0xc7, 0x00, 0x7d, 0xbf, 0x01, 0x00, + 0x17, 0x43, 0x02, 0xfc, 0xe7, 0x02, 0x63, 0xb3, 0xb7, 0x47, 0x01, 0x24, + 0x03, 0xd7, 0xc7, 0xe1, 0x89, 0x47, 0x2a, 0x84, 0xae, 0x84, 0x63, 0x19, + 0xf7, 0x00, 0xb7, 0xa7, 0x01, 0x24, 0x03, 0xa7, 0x47, 0x06, 0xfd, 0x57, + 0x63, 0x04, 0xf7, 0x04, 0xb7, 0xe7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x87, + 0x03, 0xa9, 0x87, 0x10, 0x83, 0xa9, 0xc7, 0x10, 0x01, 0x46, 0xca, 0x85, + 0x4e, 0x85, 0x97, 0x30, 0x01, 0xfc, 0xe7, 0x80, 0x60, 0x09, 0xa6, 0x85, + 0x22, 0x85, 0x97, 0xc0, 0x00, 0xfc, 0xe7, 0x80, 0x60, 0x75, 0x4e, 0x85, + 0x05, 0x46, 0xca, 0x85, 0x97, 0x30, 0x01, 0xfc, 0xe7, 0x80, 0xc0, 0x07, + 0xb7, 0xc7, 0x02, 0x24, 0x83, 0xa7, 0x07, 0xb7, 0x15, 0x45, 0x82, 0x97, + 0x17, 0x43, 0x02, 0xfc, 0x67, 0x00, 0xe3, 0xaf, 0xb7, 0xc7, 0x02, 0x24, + 0x03, 0xa6, 0x47, 0xb7, 0xb7, 0x07, 0x00, 0x40, 0x93, 0x87, 0x07, 0x06, + 0x3e, 0x96, 0x09, 0x67, 0x13, 0x08, 0x05, 0x02, 0xaa, 0x87, 0x09, 0x8e, + 0x13, 0x07, 0xf7, 0xf1, 0x23, 0x90, 0xe7, 0x00, 0xb3, 0x06, 0xf6, 0x00, + 0x23, 0x90, 0xe6, 0x00, 0x89, 0x07, 0xe3, 0x99, 0x07, 0xff, 0x83, 0xc7, + 0xc5, 0x00, 0xb1, 0xcb, 0x83, 0xaf, 0x05, 0x00, 0x09, 0x63, 0x13, 0x88, + 0xe5, 0x00, 0x81, 0x47, 0x0d, 0x4f, 0x85, 0x4e, 0x09, 0x4e, 0x13, 0x03, + 0x03, 0xf0, 0x33, 0x17, 0xff, 0x00, 0x33, 0x77, 0xf7, 0x01, 0x33, 0x96, + 0xfe, 0x00, 0xb3, 0x16, 0xfe, 0x00, 0x79, 0x8e, 0xb3, 0x08, 0xf5, 0x00, + 0xf9, 0x8e, 0x89, 0x07, 0x7d, 0x47, 0x19, 0xc2, 0x03, 0x47, 0x08, 0x00, + 0x1a, 0x86, 0x81, 0xc6, 0x03, 0x46, 0x18, 0x00, 0x22, 0x06, 0x51, 0x8f, + 0x23, 0x90, 0xe8, 0x00, 0x03, 0xc7, 0xc5, 0x00, 0x09, 0x08, 0xe3, 0xc4, + 0xe7, 0xfc, 0xb7, 0xc7, 0x02, 0x24, 0x83, 0xa7, 0x07, 0xb7, 0x1d, 0x45, + 0x82, 0x87, 0x01, 0x00, 0x17, 0x43, 0x02, 0xfc, 0xe7, 0x02, 0x43, 0xa4, + 0xb7, 0xa7, 0x02, 0x24, 0x03, 0xc7, 0x67, 0x60, 0x85, 0x47, 0x63, 0x0c, + 0xf7, 0x00, 0xb7, 0xc7, 0x02, 0x24, 0x83, 0xa7, 0x07, 0xb7, 0x21, 0x45, + 0x82, 0x97, 0x17, 0x43, 0x02, 0xfc, 0x67, 0x00, 0x63, 0xa4, 0x97, 0x60, + 0xff, 0xfb, 0xe7, 0x80, 0xe0, 0xe8, 0x75, 0xd1, 0xb7, 0xe7, 0x00, 0x24, + 0x83, 0xc7, 0xb7, 0xad, 0xe9, 0xff, 0xb7, 0xb7, 0x00, 0x24, 0x03, 0xd7, + 0x47, 0x33, 0xb7, 0x07, 0x01, 0x40, 0x23, 0x99, 0xe7, 0xdc, 0xe1, 0xb7, + 0x17, 0x43, 0x02, 0xfc, 0xe7, 0x02, 0x43, 0x9f, 0xb7, 0xb7, 0x02, 0x24, + 0x93, 0x87, 0x87, 0xb4, 0x23, 0xae, 0xf1, 0x94, 0x37, 0x64, 0x01, 0x24, + 0x9d, 0x66, 0xb7, 0xb5, 0x02, 0x24, 0xb7, 0xb7, 0x02, 0x24, 0x13, 0x04, + 0x04, 0x40, 0x93, 0x87, 0xc7, 0x83, 0x93, 0x86, 0xf6, 0xbf, 0x11, 0x46, + 0x93, 0x85, 0x05, 0xfb, 0x05, 0x45, 0x5c, 0xc4, 0x97, 0xe0, 0xff, 0xfb, + 0xe7, 0x80, 0xc0, 0xe8, 0xc1, 0x66, 0xb7, 0xb5, 0x02, 0x24, 0xfd, 0x16, + 0x31, 0x46, 0x93, 0x85, 0x45, 0x98, 0x41, 0x45, 0x97, 0xe0, 0xff, 0xfb, + 0xe7, 0x80, 0x40, 0xe7, 0x37, 0xb7, 0x02, 0x24, 0x13, 0x07, 0x87, 0xb7, + 0xb7, 0xa7, 0x02, 0x24, 0x93, 0x87, 0x87, 0x54, 0x78, 0xc8, 0x37, 0xb7, + 0x02, 0x24, 0xa3, 0x80, 0x07, 0x0c, 0x23, 0x81, 0x07, 0x0c, 0x13, 0x07, + 0xc7, 0xc2, 0xb7, 0xb7, 0x02, 0x24, 0x18, 0xd4, 0x93, 0x87, 0x47, 0x2d, + 0x37, 0xb7, 0x02, 0x24, 0x7c, 0xc4, 0x13, 0x07, 0x87, 0x3b, 0xb7, 0xb7, + 0x02, 0x24, 0x18, 0xc0, 0x93, 0x87, 0x47, 0x37, 0x23, 0xaa, 0xf1, 0xa4, + 0x17, 0x43, 0x02, 0xfc, 0x67, 0x00, 0xc3, 0x97, 0x14, 0xa6, 0x02, 0x24, + 0x00, 0x8d, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3b, 0x00, 0x00, 0x00, 0x3f, + 0x00, 0x00, 0x80, 0x43, +}; + +static const u8 s5kjn5_data_bc98[] = { + 0x17, 0x43, 0x02, 0xfc, 0xe7, 0x02, 0x83, 0x82, 0x2a, 0x84, 0xef, 0xe0, + 0xbf, 0xb9, 0xa1, 0x47, 0x63, 0x06, 0xf4, 0x00, 0x17, 0x43, 0x02, 0xfc, + 0x67, 0x00, 0x83, 0x83, 0xb7, 0xc7, 0x02, 0x24, 0x83, 0xc7, 0x87, 0xb8, + 0xe5, 0xdb, 0xb7, 0x97, 0x01, 0x24, 0x93, 0x87, 0x07, 0x53, 0x05, 0x67, + 0x3e, 0x97, 0x83, 0x46, 0x07, 0xb9, 0xf9, 0xde, 0x83, 0xc7, 0x67, 0x3f, + 0xe1, 0xdf, 0x83, 0x57, 0x47, 0xb6, 0x93, 0xe7, 0x07, 0x20, 0x23, 0x12, + 0xf7, 0xb6, 0xe9, 0xb7, 0x17, 0x33, 0x02, 0xfc, 0xe7, 0x02, 0x43, 0x7b, + 0x37, 0xc8, 0x02, 0x24, 0x13, 0x08, 0x48, 0xb8, 0x83, 0x48, 0x48, 0x00, + 0x2a, 0x8b, 0xae, 0x8b, 0x32, 0x84, 0xb6, 0x84, 0x3a, 0x89, 0xbe, 0x89, + 0x63, 0x80, 0x08, 0x02, 0xb7, 0xa7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x53, + 0x03, 0xc7, 0x07, 0xb9, 0x83, 0xc7, 0xb7, 0x92, 0x11, 0xc7, 0x03, 0x47, + 0x58, 0x00, 0xbd, 0x8b, 0x63, 0x06, 0xf7, 0x04, 0x37, 0xe8, 0x01, 0x24, + 0x13, 0x08, 0x08, 0x87, 0x83, 0x2a, 0x08, 0x12, 0x03, 0x2a, 0x48, 0x12, + 0x01, 0x46, 0xd6, 0x85, 0x52, 0x85, 0x97, 0x30, 0x01, 0xfc, 0xe7, 0x80, + 0xa0, 0xd0, 0xce, 0x87, 0x4a, 0x87, 0xa6, 0x86, 0x22, 0x86, 0xde, 0x85, + 0x5a, 0x85, 0x97, 0x40, 0x00, 0xfc, 0xe7, 0x80, 0xa0, 0x66, 0x05, 0x46, + 0xd6, 0x85, 0x52, 0x85, 0x97, 0x30, 0x01, 0xfc, 0xe7, 0x80, 0x80, 0xce, + 0x17, 0x33, 0x02, 0xfc, 0x67, 0x00, 0xc3, 0x76, 0x23, 0x15, 0x06, 0x00, + 0x97, 0x60, 0xff, 0xfb, 0xe7, 0x80, 0x80, 0xba, 0x01, 0xcd, 0xb7, 0x97, + 0x01, 0x24, 0x93, 0x87, 0x07, 0xd7, 0x03, 0xc7, 0xc7, 0x00, 0x59, 0xdf, + 0x7d, 0x17, 0x23, 0x86, 0xe7, 0x00, 0x59, 0xbf, 0x97, 0x60, 0xff, 0xfb, + 0xe7, 0x80, 0x80, 0xb5, 0x6d, 0xd1, 0xb7, 0x97, 0x01, 0x24, 0x93, 0x87, + 0x07, 0xd7, 0x03, 0xc7, 0xd7, 0x00, 0x3d, 0xdf, 0x7d, 0x17, 0xa3, 0x86, + 0xe7, 0x00, 0x9d, 0xbf, 0x17, 0x33, 0x02, 0xfc, 0xe7, 0x02, 0x63, 0x6f, + 0xb7, 0xe7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x87, 0x03, 0xaa, 0x87, 0x12, + 0x83, 0xa9, 0xc7, 0x12, 0xae, 0x84, 0x2a, 0x84, 0x32, 0x89, 0xd2, 0x85, + 0x01, 0x46, 0x4e, 0x85, 0x97, 0x30, 0x01, 0xfc, 0xe7, 0x80, 0x00, 0xc7, + 0xa6, 0x85, 0x4a, 0x86, 0x22, 0x85, 0x97, 0x60, 0xff, 0xfb, 0xe7, 0x80, + 0x20, 0x6a, 0xaa, 0x84, 0x05, 0x46, 0xd2, 0x85, 0x4e, 0x85, 0x97, 0x30, + 0x01, 0xfc, 0xe7, 0x80, 0x20, 0xc5, 0xb7, 0xc7, 0x02, 0x24, 0x93, 0x87, + 0x47, 0xb8, 0x03, 0xc7, 0xe7, 0x10, 0x15, 0xc3, 0x37, 0xa7, 0x01, 0x24, + 0x13, 0x07, 0x07, 0x53, 0x03, 0x46, 0x37, 0xb9, 0x89, 0x46, 0x63, 0x1a, + 0xd6, 0x00, 0x83, 0x56, 0x87, 0xba, 0xe1, 0x8e, 0x89, 0xc6, 0x93, 0x06, + 0x00, 0x40, 0x63, 0x07, 0xd4, 0x00, 0x26, 0x85, 0x17, 0x33, 0x02, 0xfc, + 0x67, 0x00, 0xe3, 0x6a, 0x83, 0x26, 0x47, 0xb3, 0x7d, 0x57, 0xe3, 0x88, + 0xe6, 0xfe, 0x03, 0xd7, 0x27, 0x11, 0x93, 0x96, 0x04, 0x01, 0xc1, 0x82, + 0x11, 0xe3, 0x36, 0x87, 0xba, 0x84, 0x23, 0x99, 0xd7, 0x10, 0xe1, 0xbf, + 0x17, 0x33, 0x02, 0xfc, 0xe7, 0x02, 0x23, 0x65, 0x37, 0x29, 0x00, 0x24, + 0xb7, 0xa4, 0x01, 0x24, 0x13, 0x09, 0x09, 0x33, 0x93, 0x84, 0x04, 0x53, + 0x83, 0x47, 0x49, 0x1a, 0x03, 0xc7, 0x24, 0xb7, 0x2a, 0x84, 0xd9, 0x8f, + 0x63, 0x82, 0x07, 0x14, 0x83, 0x47, 0xe4, 0x00, 0x05, 0x47, 0x23, 0x05, + 0xe4, 0x00, 0x99, 0xe7, 0x83, 0x47, 0xc4, 0x00, 0xd1, 0xcf, 0x83, 0xc7, + 0x24, 0xb7, 0xc5, 0xcb, 0xb7, 0x6a, 0x01, 0x24, 0x13, 0x0a, 0x04, 0x03, + 0x03, 0x47, 0x04, 0x00, 0xa1, 0x69, 0xfd, 0x19, 0xa3, 0x01, 0xe4, 0x00, + 0x83, 0xa7, 0x0a, 0x4b, 0x23, 0x02, 0xe4, 0x00, 0x05, 0x67, 0xba, 0x97, + 0x83, 0xd7, 0x47, 0xe0, 0x23, 0x03, 0x04, 0x00, 0xb3, 0xf7, 0x37, 0x01, + 0x23, 0x1c, 0xf4, 0x00, 0x97, 0x40, 0xfd, 0xfb, 0xe7, 0x80, 0x00, 0x67, + 0x03, 0x58, 0x84, 0x01, 0xa3, 0x08, 0xa4, 0x00, 0x63, 0x01, 0x08, 0x06, + 0x37, 0x36, 0x05, 0x20, 0x13, 0x06, 0x06, 0xc8, 0x81, 0x46, 0x81, 0x47, + 0x41, 0x45, 0xb3, 0x05, 0xf4, 0x00, 0x33, 0x57, 0xf8, 0x40, 0x23, 0x80, + 0xd5, 0x02, 0x05, 0x8b, 0x85, 0x07, 0x11, 0xc7, 0x03, 0x47, 0x06, 0x00, + 0xba, 0x96, 0x93, 0xf6, 0xf6, 0x0f, 0x05, 0x06, 0xe3, 0x91, 0xa7, 0xfe, + 0x23, 0x08, 0xd4, 0x00, 0x83, 0x47, 0x49, 0x1a, 0x03, 0xc7, 0x24, 0xb7, + 0xd9, 0x8f, 0xc9, 0xc3, 0x23, 0x07, 0x04, 0x00, 0x23, 0x2e, 0x44, 0x01, + 0x17, 0x33, 0x02, 0xfc, 0x67, 0x00, 0xa3, 0x5b, 0x83, 0x47, 0xb4, 0x00, + 0xa5, 0xd7, 0x83, 0xc7, 0x24, 0xb7, 0xad, 0xf3, 0x39, 0xa0, 0x01, 0x48, + 0x45, 0xf1, 0x23, 0x1c, 0x34, 0x01, 0x4e, 0x88, 0x61, 0xbf, 0xb7, 0x6a, + 0x01, 0x24, 0x83, 0xa5, 0x0a, 0x4b, 0x85, 0x67, 0x13, 0x0a, 0x04, 0x03, + 0x93, 0x87, 0x07, 0xe1, 0x13, 0x06, 0x80, 0x07, 0xbe, 0x95, 0x52, 0x85, + 0x97, 0x60, 0x00, 0xfc, 0xe7, 0x80, 0x40, 0x0a, 0x21, 0xc9, 0x23, 0x05, + 0x04, 0x00, 0x03, 0x47, 0x24, 0x01, 0x83, 0x47, 0x64, 0x00, 0x83, 0x56, + 0x44, 0x01, 0xa3, 0x08, 0xe4, 0x00, 0x05, 0x47, 0x23, 0x1c, 0xd4, 0x00, + 0x23, 0x07, 0xe4, 0x00, 0xa3, 0x01, 0xf4, 0x00, 0x23, 0x03, 0x04, 0x00, + 0x23, 0x2e, 0x44, 0x01, 0x17, 0x33, 0x02, 0xfc, 0x67, 0x00, 0xa3, 0x54, + 0x83, 0xa5, 0x0a, 0x4b, 0x85, 0x67, 0x93, 0x87, 0x07, 0xe1, 0x13, 0x06, + 0x00, 0x0f, 0xbe, 0x95, 0x52, 0x85, 0x97, 0x60, 0x00, 0xfc, 0xe7, 0x80, + 0x20, 0x05, 0x9d, 0xb7, 0x83, 0x47, 0xa4, 0x00, 0xcd, 0xdb, 0xcd, 0xb5, + 0x37, 0xa5, 0x01, 0x24, 0x13, 0x05, 0x05, 0x0c, 0x97, 0x60, 0xff, 0xfb, + 0xe7, 0x80, 0x80, 0x43, 0x45, 0xbd, 0x01, 0x00, 0x17, 0x33, 0x02, 0xfc, + 0xe7, 0x02, 0x03, 0x4f, 0x83, 0x47, 0x15, 0x01, 0xa3, 0x04, 0x05, 0x00, + 0x2a, 0x84, 0x91, 0xef, 0x83, 0x57, 0x85, 0x01, 0x99, 0xeb, 0x83, 0x47, + 0xf5, 0x00, 0xa3, 0x07, 0x05, 0x00, 0xa3, 0x04, 0xf5, 0x00, 0x17, 0x33, + 0x02, 0xfc, 0x67, 0x00, 0xe3, 0x4e, 0x22, 0x85, 0x97, 0x90, 0xff, 0xfb, + 0xe7, 0x80, 0xc0, 0xc4, 0x83, 0x47, 0x34, 0x00, 0x03, 0x47, 0x64, 0x00, + 0x83, 0x46, 0x74, 0x00, 0xfd, 0x17, 0x05, 0x07, 0x93, 0xf7, 0xf7, 0x0f, + 0x23, 0x03, 0xe4, 0x00, 0xa3, 0x01, 0xf4, 0x00, 0x99, 0xc2, 0xa3, 0x03, + 0x04, 0x00, 0xb1, 0xef, 0x03, 0x47, 0x14, 0x01, 0x83, 0x56, 0x84, 0x01, + 0x83, 0x47, 0x54, 0x00, 0x23, 0x09, 0xe4, 0x00, 0x05, 0x47, 0x23, 0x1a, + 0xd4, 0x00, 0x23, 0x04, 0xe4, 0x00, 0x23, 0x1c, 0x04, 0x00, 0xa3, 0x08, + 0x04, 0x00, 0xc5, 0xe3, 0x83, 0x47, 0x14, 0x00, 0x13, 0xf7, 0x27, 0x00, + 0x19, 0xc7, 0x03, 0x47, 0x04, 0x00, 0x01, 0xc7, 0x03, 0x47, 0x24, 0x00, + 0x4d, 0xc3, 0x85, 0x8b, 0xa5, 0xcf, 0xb7, 0x27, 0x00, 0x24, 0x83, 0xc7, + 0x27, 0x4d, 0xd1, 0xd3, 0xb7, 0x67, 0x01, 0x24, 0x83, 0xa7, 0x07, 0x4b, + 0x05, 0x67, 0xba, 0x97, 0x23, 0x80, 0x07, 0xe0, 0x8d, 0xbf, 0x03, 0x47, + 0x04, 0x01, 0x5c, 0x4c, 0x93, 0x16, 0x17, 0x00, 0xb6, 0x97, 0x5c, 0xcc, + 0xb7, 0x27, 0x00, 0x24, 0x93, 0x87, 0x07, 0x33, 0x83, 0xc6, 0x37, 0x1a, + 0x89, 0xea, 0x83, 0x46, 0x64, 0x01, 0xa1, 0xda, 0xb7, 0xa6, 0x01, 0x24, + 0x83, 0xc6, 0x26, 0x0a, 0xb9, 0xf2, 0x83, 0xc7, 0x47, 0x1a, 0xa1, 0xf3, + 0x03, 0x46, 0x04, 0x00, 0xb7, 0x67, 0x01, 0x24, 0x83, 0xa5, 0x07, 0x4b, + 0x33, 0x06, 0xe6, 0x02, 0x85, 0x67, 0x93, 0x87, 0x07, 0xe1, 0xbe, 0x95, + 0x13, 0x05, 0x04, 0x03, 0x06, 0x06, 0x97, 0x60, 0x00, 0xfc, 0xe7, 0x80, + 0x60, 0xf2, 0x21, 0xbf, 0x85, 0x47, 0xa3, 0x04, 0xf4, 0x00, 0x17, 0x33, + 0x02, 0xfc, 0x67, 0x00, 0xe3, 0x3f, 0xfd, 0x17, 0xa3, 0x02, 0xf4, 0x00, + 0x22, 0x85, 0x97, 0x60, 0xff, 0xfb, 0xe7, 0x80, 0x60, 0x11, 0x17, 0x33, + 0x02, 0xfc, 0x67, 0x00, 0x63, 0x3e, 0x22, 0x85, 0x97, 0x60, 0xff, 0xfb, + 0xe7, 0x80, 0x40, 0x10, 0xdd, 0xb5, 0x01, 0x00, 0x89, 0x47, 0x63, 0x03, + 0xf5, 0x00, 0x82, 0x80, 0x17, 0x33, 0x02, 0xfc, 0xe7, 0x02, 0xa3, 0x38, + 0xb7, 0x84, 0x01, 0x24, 0x93, 0x84, 0x04, 0xaa, 0x87, 0xa7, 0x04, 0x0a, + 0x41, 0x11, 0x37, 0xc5, 0x02, 0x24, 0x53, 0x96, 0x17, 0xc0, 0x74, 0x00, + 0x91, 0x45, 0x13, 0x05, 0xa5, 0xb8, 0x97, 0x50, 0xff, 0xfb, 0xe7, 0x80, + 0x60, 0xc3, 0x37, 0x19, 0x01, 0x40, 0x42, 0x05, 0x41, 0x81, 0x13, 0x0a, + 0x49, 0x24, 0xb7, 0x89, 0x01, 0x24, 0x37, 0xc4, 0x02, 0x24, 0xb7, 0xca, + 0x02, 0x24, 0x23, 0x17, 0xa1, 0x00, 0x93, 0x89, 0x89, 0xb1, 0x13, 0x04, + 0x24, 0xb9, 0x93, 0x8a, 0xaa, 0xbb, 0x33, 0x0a, 0x9a, 0x40, 0x06, 0x05, + 0x22, 0x95, 0x83, 0x55, 0x25, 0x00, 0x03, 0x56, 0xc1, 0x00, 0x03, 0x55, + 0x05, 0x00, 0x21, 0x04, 0x97, 0x60, 0x00, 0xfc, 0xe7, 0x80, 0x80, 0x82, + 0x42, 0x05, 0x41, 0x81, 0x23, 0x90, 0xa9, 0x00, 0xb3, 0x87, 0x49, 0x01, + 0x23, 0x90, 0xa7, 0x00, 0x89, 0x09, 0x63, 0x05, 0x54, 0x01, 0x03, 0x55, + 0xe1, 0x00, 0xf1, 0xb7, 0xb7, 0x89, 0x01, 0x24, 0x37, 0xca, 0x02, 0x24, + 0x13, 0x09, 0x09, 0x26, 0x93, 0x89, 0xa9, 0xaf, 0x13, 0x0a, 0x2a, 0xc3, + 0x83, 0x57, 0xe1, 0x00, 0x03, 0x56, 0xc1, 0x00, 0x85, 0x09, 0x86, 0x07, + 0xa2, 0x97, 0x83, 0xd5, 0x27, 0x00, 0x03, 0xd5, 0x07, 0x00, 0x09, 0x09, + 0x21, 0x04, 0x97, 0x50, 0x00, 0xfc, 0xe7, 0x80, 0x60, 0x7d, 0x13, 0x75, + 0xf5, 0x0f, 0xa3, 0x8f, 0xa9, 0xfe, 0x42, 0x05, 0x41, 0x81, 0x23, 0x1f, + 0xa9, 0xfe, 0xe3, 0x17, 0x44, 0xfd, 0xb7, 0x19, 0x01, 0x40, 0x37, 0x89, + 0x01, 0x24, 0x37, 0xca, 0x02, 0x24, 0x93, 0x89, 0x29, 0x1f, 0x13, 0x09, + 0xc9, 0xb2, 0x13, 0x0a, 0x2a, 0xc6, 0xb3, 0x89, 0x99, 0x40, 0x83, 0x57, + 0xe1, 0x00, 0x03, 0x56, 0xc1, 0x00, 0x86, 0x07, 0xa2, 0x97, 0x83, 0xd5, + 0x27, 0x00, 0x03, 0xd5, 0x07, 0x00, 0x21, 0x04, 0x97, 0x50, 0x00, 0xfc, + 0xe7, 0x80, 0x80, 0x78, 0x42, 0x05, 0x41, 0x81, 0x23, 0x10, 0xa9, 0x00, + 0xb3, 0x07, 0x39, 0x01, 0x23, 0x90, 0xa7, 0x00, 0x09, 0x09, 0xe3, 0x18, + 0x44, 0xfd, 0xb7, 0x17, 0x01, 0x40, 0x37, 0x89, 0x01, 0x24, 0xb7, 0xc9, + 0x02, 0x24, 0x93, 0x87, 0xa7, 0x20, 0x13, 0x09, 0x69, 0xb4, 0x93, 0x89, + 0x29, 0xc9, 0xb3, 0x84, 0x97, 0x40, 0x83, 0x57, 0xe1, 0x00, 0x03, 0x56, + 0xc1, 0x00, 0x86, 0x07, 0xa2, 0x97, 0x83, 0xd5, 0x27, 0x00, 0x03, 0xd5, + 0x07, 0x00, 0x21, 0x04, 0x97, 0x50, 0x00, 0xfc, 0xe7, 0x80, 0x80, 0x73, + 0x42, 0x05, 0x41, 0x81, 0x23, 0x10, 0xa9, 0x00, 0xb3, 0x07, 0x99, 0x00, + 0x23, 0x90, 0xa7, 0x00, 0x09, 0x09, 0xe3, 0x18, 0x34, 0xfd, 0x41, 0x01, + 0x17, 0x33, 0x02, 0xfc, 0x67, 0x00, 0x23, 0x24, 0x17, 0x33, 0x02, 0xfc, + 0xe7, 0x02, 0x03, 0x22, 0x2a, 0x84, 0xef, 0xe0, 0x3f, 0x98, 0x1d, 0xe0, + 0xb7, 0x97, 0x01, 0x24, 0x93, 0x87, 0x07, 0x53, 0x0d, 0x67, 0x3e, 0x97, + 0x03, 0x27, 0x87, 0x6e, 0x05, 0x8b, 0x09, 0xcb, 0x37, 0x87, 0x00, 0x40, + 0x03, 0x57, 0x87, 0xf4, 0xa1, 0x46, 0x61, 0x8b, 0x63, 0x06, 0xd7, 0x00, + 0x17, 0x33, 0x02, 0xfc, 0x67, 0x00, 0x03, 0x21, 0x05, 0x67, 0xba, 0x97, + 0x23, 0x89, 0x07, 0xb6, 0xc5, 0xbf, 0x01, 0x00, 0x91, 0x47, 0x63, 0x03, + 0xf5, 0x00, 0x82, 0x80, 0x17, 0x33, 0x02, 0xfc, 0xe7, 0x02, 0x03, 0x1d, + 0x97, 0x50, 0xff, 0xfb, 0xe7, 0x80, 0xc0, 0x63, 0x09, 0xc5, 0x17, 0x33, + 0x02, 0xfc, 0x67, 0x00, 0x23, 0x1e, 0x97, 0x50, 0xff, 0xfb, 0xe7, 0x80, + 0xe0, 0x5d, 0x65, 0xf9, 0xb7, 0xc7, 0x02, 0x24, 0x03, 0xd7, 0x67, 0xb8, + 0xb7, 0xf7, 0x00, 0x40, 0x23, 0x90, 0xe7, 0x3e, 0xf9, 0xbf, 0x01, 0x00, + 0x37, 0xc7, 0x02, 0x24, 0x13, 0x07, 0x47, 0xb8, 0x83, 0x45, 0x07, 0x00, + 0xb7, 0xa7, 0x02, 0x24, 0xb7, 0xd6, 0x01, 0x24, 0x03, 0xd6, 0x47, 0x60, + 0x23, 0xa8, 0xb6, 0xda, 0xb7, 0x67, 0x01, 0x24, 0xb7, 0xc6, 0x02, 0x24, + 0x93, 0x87, 0x07, 0x40, 0x93, 0x86, 0x86, 0xc9, 0xd4, 0xc7, 0x09, 0xca, + 0xb7, 0xb6, 0x02, 0x24, 0x37, 0x26, 0x00, 0x24, 0x93, 0x86, 0x86, 0x68, + 0x23, 0x20, 0xd6, 0xce, 0x23, 0x19, 0x07, 0x10, 0x37, 0xc7, 0x02, 0x24, + 0x13, 0x07, 0x07, 0x2a, 0xb7, 0xc6, 0x02, 0x24, 0x98, 0xd7, 0x37, 0xc7, + 0x02, 0x24, 0x93, 0x86, 0x46, 0x11, 0x13, 0x07, 0x87, 0x2e, 0x23, 0xa4, + 0xd1, 0xa4, 0xd8, 0xc3, 0x82, 0x80, 0x00, 0x00, +}; + +static const u8 s5kjn5_data_c398[] = { + 0x29, 0xe1, 0x17, 0x33, 0x02, 0xfc, 0xe7, 0x02, 0x63, 0x12, 0xb7, 0x97, + 0x01, 0x24, 0x93, 0x87, 0x07, 0x53, 0x85, 0x64, 0xbe, 0x94, 0x03, 0xc7, + 0xe4, 0xb6, 0x8d, 0x66, 0x33, 0x84, 0xd7, 0x00, 0x83, 0x27, 0x84, 0x6e, + 0x05, 0xc3, 0x85, 0x8b, 0x89, 0xcb, 0xb7, 0x87, 0x00, 0x40, 0x83, 0xd7, + 0x87, 0xf4, 0x21, 0x47, 0xe1, 0x8b, 0x63, 0x8b, 0xe7, 0x02, 0x17, 0x33, + 0x02, 0xfc, 0x67, 0x00, 0x23, 0x11, 0x82, 0x80, 0x11, 0x47, 0xe3, 0x90, + 0xe7, 0xfe, 0xb7, 0xd7, 0x01, 0x24, 0x83, 0xc7, 0x07, 0xfa, 0xe5, 0xd7, + 0x97, 0xc0, 0x00, 0xfc, 0xe7, 0x80, 0x40, 0x1f, 0x37, 0x87, 0x02, 0x24, + 0x85, 0x46, 0x83, 0x27, 0x84, 0x6e, 0xa3, 0x00, 0xd7, 0x4e, 0x75, 0xbf, + 0x23, 0x89, 0x04, 0xb6, 0xe9, 0xb7, 0x01, 0x00, 0x09, 0xe5, 0xb7, 0xa7, + 0x01, 0x24, 0xa3, 0x83, 0x07, 0x0c, 0x49, 0xb0, 0x17, 0x33, 0x02, 0xfc, + 0xe7, 0x02, 0xe3, 0x08, 0x2a, 0x84, 0x2e, 0x8a, 0x97, 0x50, 0xff, 0xfb, + 0xe7, 0x80, 0x40, 0x4c, 0x1d, 0xc5, 0xb7, 0x97, 0x01, 0x24, 0x93, 0x87, + 0x07, 0x53, 0x05, 0x67, 0x3e, 0x97, 0x83, 0x46, 0x37, 0xb7, 0x05, 0x47, + 0x63, 0x85, 0xe6, 0x00, 0x83, 0xc7, 0x27, 0x41, 0x89, 0xcb, 0xb7, 0x87, + 0x02, 0x24, 0x03, 0xc7, 0xb7, 0x4a, 0x85, 0x47, 0xa2, 0x84, 0x63, 0x0f, + 0xf7, 0x02, 0xb7, 0xe7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x87, 0x83, 0xa9, + 0x87, 0x0a, 0x03, 0xa9, 0xc7, 0x0a, 0x01, 0x46, 0xce, 0x85, 0x4a, 0x85, + 0x97, 0x20, 0x01, 0xfc, 0xe7, 0x80, 0x40, 0x5d, 0xd2, 0x85, 0x22, 0x85, + 0x97, 0x80, 0x01, 0xfc, 0xe7, 0x80, 0x40, 0x1a, 0xaa, 0x84, 0x05, 0x46, + 0xce, 0x85, 0x4a, 0x85, 0x97, 0x20, 0x01, 0xfc, 0xe7, 0x80, 0x80, 0x5b, + 0x26, 0x85, 0x17, 0x33, 0x02, 0xfc, 0x67, 0x00, 0x43, 0x04, 0x01, 0x00, + 0x17, 0x33, 0x02, 0xfc, 0xe7, 0x02, 0x03, 0x02, 0x97, 0x50, 0xff, 0xfb, + 0xe7, 0x80, 0x00, 0x44, 0x09, 0xcd, 0x97, 0x50, 0xff, 0xfb, 0xe7, 0x80, + 0x60, 0x46, 0x01, 0xe9, 0xb7, 0xa7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x53, + 0x83, 0xa7, 0x47, 0xb2, 0x95, 0xef, 0x97, 0x50, 0xff, 0xfb, 0xe7, 0x80, + 0xe0, 0x41, 0x0d, 0xed, 0xb7, 0xe7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x87, + 0x84, 0x57, 0xc0, 0x57, 0x01, 0x46, 0xa6, 0x85, 0x22, 0x85, 0x97, 0x20, + 0x01, 0xfc, 0xe7, 0x80, 0xe0, 0x55, 0x97, 0x50, 0x00, 0xfc, 0xe7, 0x80, + 0xa0, 0xd7, 0x05, 0x46, 0xa6, 0x85, 0x22, 0x85, 0x97, 0x20, 0x01, 0xfc, + 0xe7, 0x80, 0x80, 0x54, 0x17, 0x33, 0x02, 0xfc, 0x67, 0x00, 0x03, 0xfe, + 0x97, 0x50, 0xff, 0xfb, 0xe7, 0x80, 0xc0, 0x40, 0x61, 0xf1, 0x97, 0x60, + 0x01, 0xfc, 0xe7, 0x80, 0x60, 0xd7, 0xb7, 0xd7, 0x01, 0x24, 0x03, 0xd4, + 0x07, 0xed, 0xaa, 0x84, 0x97, 0xc0, 0x01, 0xfc, 0xe7, 0x80, 0x00, 0x51, + 0x33, 0x14, 0xa4, 0x00, 0x97, 0xc0, 0x01, 0xfc, 0xe7, 0x80, 0x00, 0x52, + 0x33, 0x54, 0xa4, 0x40, 0xe3, 0xfa, 0x84, 0xf8, 0xc1, 0xb7, 0x01, 0x00, + 0x17, 0x33, 0x02, 0xfc, 0xe7, 0x02, 0xe3, 0xf5, 0x37, 0x84, 0x02, 0x24, + 0x13, 0x04, 0xc4, 0x49, 0x83, 0x57, 0x04, 0x00, 0xaa, 0x84, 0x2e, 0x89, + 0x91, 0xcf, 0x19, 0xe9, 0xb7, 0xa9, 0x01, 0x24, 0x93, 0x89, 0x09, 0x53, + 0x03, 0xc7, 0x09, 0xd0, 0x83, 0xc7, 0x19, 0xd0, 0x63, 0x08, 0xf7, 0x06, + 0xef, 0xc0, 0x9f, 0xaf, 0xb7, 0xe7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x87, + 0x03, 0xaa, 0x07, 0x02, 0x83, 0xa9, 0x47, 0x02, 0x01, 0x46, 0xd2, 0x85, + 0x4e, 0x85, 0x97, 0x20, 0x01, 0xfc, 0xe7, 0x80, 0x20, 0x4b, 0xca, 0x85, + 0x26, 0x85, 0x97, 0xb0, 0x00, 0xfc, 0xe7, 0x80, 0xa0, 0x1a, 0x2a, 0x89, + 0x05, 0x46, 0xd2, 0x85, 0x4e, 0x85, 0x97, 0x20, 0x01, 0xfc, 0xe7, 0x80, + 0x60, 0x49, 0x83, 0x57, 0x04, 0x00, 0x85, 0xc3, 0x99, 0xe8, 0xb7, 0xa9, + 0x01, 0x24, 0x93, 0x89, 0x09, 0x53, 0x03, 0xc7, 0x09, 0xd0, 0x83, 0xc7, + 0x19, 0xd0, 0x63, 0x06, 0xf7, 0x00, 0x97, 0x70, 0x01, 0xfc, 0xe7, 0x80, + 0xe0, 0xda, 0x4a, 0x85, 0x17, 0x33, 0x02, 0xfc, 0x67, 0x00, 0xe3, 0xef, + 0xb7, 0xe7, 0x01, 0x24, 0x93, 0x87, 0x07, 0x87, 0x03, 0xaa, 0x07, 0x02, + 0xc4, 0x53, 0x01, 0x46, 0xd2, 0x85, 0x26, 0x85, 0x97, 0x20, 0x01, 0xfc, + 0xe7, 0x80, 0xc0, 0x44, 0xca, 0x85, 0x01, 0x45, 0x97, 0xb0, 0x00, 0xfc, + 0xe7, 0x80, 0x40, 0x14, 0x2a, 0x89, 0x05, 0x46, 0xd2, 0x85, 0x26, 0x85, + 0x97, 0x20, 0x01, 0xfc, 0xe7, 0x80, 0x00, 0x43, 0x83, 0x57, 0x04, 0x00, + 0xcd, 0xdf, 0x55, 0xb7, 0xb7, 0xc7, 0x02, 0x24, 0x83, 0xc6, 0x07, 0x39, + 0x37, 0xd7, 0x01, 0x24, 0xb7, 0x67, 0x01, 0x24, 0x23, 0x28, 0xd7, 0xda, + 0x37, 0xc7, 0x02, 0x24, 0x93, 0x87, 0x07, 0x40, 0x13, 0x07, 0x87, 0x39, + 0x98, 0xd7, 0x37, 0xc7, 0x02, 0x24, 0x13, 0x07, 0xc7, 0x40, 0xd8, 0xc7, + 0x82, 0x80, 0x01, 0x00, 0x17, 0x33, 0x02, 0xfc, 0xe7, 0x02, 0xc3, 0xe6, + 0xb7, 0xc6, 0x02, 0x24, 0xb7, 0x87, 0x03, 0x24, 0x93, 0x86, 0x06, 0x6b, + 0x37, 0xa7, 0x01, 0x24, 0x93, 0x87, 0x07, 0xff, 0x13, 0x07, 0x07, 0x53, + 0x95, 0x8f, 0x23, 0x2c, 0xd7, 0xb4, 0x23, 0x2e, 0xf7, 0xb4, 0x97, 0x20, + 0x01, 0xfc, 0xe7, 0x80, 0x20, 0xe0, 0x19, 0xc5, 0xef, 0xd0, 0xdf, 0xd3, + 0xef, 0xf0, 0x0f, 0xc4, 0x61, 0x39, 0x49, 0x3f, 0x17, 0x33, 0x02, 0xfc, + 0x67, 0x00, 0x03, 0xe5, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x10, 0xe5, 0x38, + 0x00, 0x00, 0x00, 0x00, 0xbe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static const u8 s5kjn5_data_a548[] = { + 0x00, 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xb0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0f, + 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, +}; + +static const u8 s5kjn5_data_bb84[] = { + 0x00, 0xab, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x10, 0x00, + 0x20, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x96, 0x00, + 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x93, 0x00, 0x93, 0x00, 0x93, 0x00, + 0x93, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x8d, 0x00, + 0x8d, 0x00, 0x8d, 0x00, 0x8d, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, + 0x3f, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, + 0x3f, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x34, 0x00, 0x34, 0x00, 0x34, 0x00, + 0x34, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x10, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x1c, 0x00, 0x06, 0x00, + 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x2a, 0x00, 0x2a, 0x00, 0x2a, 0x00, + 0x2a, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x10, 0x00, + 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, + 0x0e, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x28, 0x00, 0x18, 0x00, + 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, + 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 0x00, 0x4d, +}; + +static const u8 s5kjn5_data_5634[] = { + 0x04, 0x1d, 0x04, 0x20, 0x3c, 0x85, 0x02, 0x24, 0x3c, 0xe6, 0x03, 0x20, + 0xd8, 0x85, 0x02, 0x24, 0xd0, 0x6e, 0x03, 0x20, 0xc4, 0x8d, 0x02, 0x24, + 0x48, 0x77, 0x03, 0x20, 0x48, 0xc5, 0x02, 0x24, 0x68, 0x12, 0x03, 0x20, + 0xa0, 0xc4, 0x02, 0x24, 0xe8, 0xfe, 0x02, 0x20, 0x54, 0x91, 0x02, 0x24, + 0xa4, 0x62, 0x03, 0x20, 0x9c, 0x95, 0x02, 0x24, 0x90, 0x1b, 0x00, 0x20, + 0x28, 0x96, 0x02, 0x24, 0xc4, 0x46, 0x03, 0x20, 0xe8, 0x96, 0x02, 0x24, + 0x14, 0x27, 0x03, 0x20, 0xc4, 0x98, 0x02, 0x24, 0x30, 0x4c, 0x02, 0x20, + 0x74, 0x9b, 0x02, 0x24, 0xc8, 0x2c, 0x02, 0x20, 0xd0, 0x9b, 0x02, 0x24, + 0x48, 0x4f, 0x02, 0x20, 0x28, 0x9c, 0x02, 0x24, 0xb0, 0x41, 0x02, 0x20, + 0x3c, 0x9a, 0x02, 0x24, 0xc8, 0x1d, 0x04, 0x20, 0xfc, 0x9a, 0x02, 0x24, + 0xac, 0x7f, 0x04, 0x20, 0x8c, 0x86, 0x02, 0x24, 0x7c, 0x80, 0x04, 0x20, + 0x10, 0x86, 0x02, 0x24, 0xf8, 0x87, 0x03, 0x20, 0x7c, 0xac, 0x02, 0x24, + 0x10, 0x07, 0x03, 0x20, 0xe0, 0x8e, 0x02, 0x24, 0x14, 0x09, 0x00, 0x20, + 0x24, 0x95, 0x02, 0x24, 0x20, 0x46, 0x04, 0x20, 0x18, 0xc4, 0x02, 0x24, + 0xb0, 0x5b, 0x04, 0x20, 0x40, 0x88, 0x02, 0x24, 0x50, 0x5c, 0x03, 0x20, + 0x44, 0x8a, 0x02, 0x24, 0xa4, 0x5b, 0x03, 0x20, 0x50, 0x89, 0x02, 0x24, + 0x30, 0x6a, 0x04, 0x20, 0x14, 0x85, 0x02, 0x24, 0x90, 0xf8, 0x02, 0x20, + 0x44, 0xa1, 0x02, 0x24, 0x04, 0x54, 0x01, 0x20, 0x18, 0xa6, 0x02, 0x24, + 0x04, 0x53, 0x00, 0x20, 0xa0, 0xa7, 0x02, 0x24, 0xc8, 0x50, 0x02, 0x20, + 0xb8, 0xac, 0x02, 0x24, 0x2c, 0x88, 0x02, 0x20, 0xf0, 0xad, 0x02, 0x24, + 0x7c, 0x82, 0x01, 0x20, 0xc8, 0xb4, 0x02, 0x24, 0xac, 0xf3, 0x03, 0x20, + 0x64, 0xb5, 0x02, 0x24, 0x10, 0x81, 0x03, 0x20, 0x70, 0xb9, 0x02, 0x24, + 0xbc, 0xfd, 0x02, 0x20, 0xe4, 0xb9, 0x02, 0x24, 0xbc, 0xa5, 0x04, 0x20, + 0x7c, 0xba, 0x02, 0x24, 0xb8, 0x03, 0x03, 0x20, 0xe4, 0xbc, 0x02, 0x24, + 0x84, 0x24, 0x02, 0x20, 0xb0, 0xbd, 0x02, 0x24, 0x9c, 0x4c, 0x02, 0x20, + 0xd0, 0xbf, 0x02, 0x24, 0x0c, 0x22, 0x02, 0x20, 0x54, 0xbe, 0x02, 0x24, +}; + +static const u8 s5kjn5_data_bb8a[] = { + 0x01, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0xc8, 0x00, 0xc8, 0x00, + 0xc8, 0x00, 0xc8, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0xc4, 0x00, 0xc4, 0x00, + 0xc2, 0x00, 0xc2, 0x00, 0xc2, 0x00, 0xc2, 0x00, 0xbe, 0x00, 0xbe, 0x00, + 0xbe, 0x00, 0xbe, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x16, 0x00, 0x16, 0x00, + 0x16, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x14, 0x00, 0x14, 0x00, 0x2a, 0x00, 0x2a, 0x00, 0x2a, 0x00, 0x2a, 0x00, + 0x2a, 0x00, 0x2a, 0x00, 0x2a, 0x00, 0x2a, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, + 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x19, 0x00, 0x19, 0x00, + 0x19, 0x00, 0x19, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, 0x14, 0x00, + 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x3a, 0x00, 0x0a, 0x00, 0x0a, 0x00, + 0x0a, 0x00, 0x0a, 0x00, 0x4b, 0x00, 0x4b, 0x00, 0x4b, 0x00, 0x4b, 0x00, + 0x02, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x2a, 0x00, 0x25, 0x00, + 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x23, 0x00, 0x23, 0x00, + 0x3f, 0x00, 0x31, 0x00, 0x21, 0x00, 0x21, 0x00, 0x0a, 0x00, 0x1b, 0x00, + 0x30, 0x00, 0x30, 0x00, 0x19, 0x00, 0x15, 0x00, 0x11, 0x00, 0x11, 0x00, + 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x19, 0x00, 0x19, 0x00, + 0x19, 0x00, 0x19, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x0a, 0x00, + 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x0b, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, +}; + +struct s5kjn5_init_op { + u32 reg; + u64 val; + const u8 *burst; + u16 burst_addr; + u16 burst_len; + u16 delay_us; +}; + +static const struct s5kjn5_init_op s5kjn5_init_ops[] = { + { .reg = CCI_REG16(0xfcfc), .val = 0x4000 }, + { .reg = CCI_REG16(0x0000), .val = 0x000e }, + { .reg = CCI_REG16(0x0000), .val = 0x38e5 }, + { .reg = CCI_REG16(0x6018), .val = 0x0001 }, + { .reg = CCI_REG16(0x7002), .val = 0x0408 }, + { .reg = CCI_REG16(0x6014), .val = 0x0001 }, + { .reg = CCI_REG16(0xfcfc), .val = 0x2002 }, + { .reg = CCI_REG16(0x1e92), .val = 0x8000 }, + { .reg = CCI_REG8(0x1e84), .val = 0x28 }, + { .reg = CCI_REG8(0x1e85), .val = 0x2b }, + { .reg = CCI_REG8(0x1e86), .val = 0x03 }, + { .reg = CCI_REG8(0x1e87), .val = 0x20 }, + { .reg = CCI_REG16(0xfcfc), .val = 0x4000 }, + { .reg = CCI_REG16(0x7002), .val = 0x0008 }, + { .delay_us = 5000 }, + { .reg = CCI_REG16(0xfcfc), .val = 0x2000 }, + { .reg = CCI_REG16(0xdcf0), .val = 0x0000 }, + { .reg = CCI_REG16(0xfcfc), .val = 0x2001 }, + { .reg = CCI_REG16(0x3c60), .val = 0x0000 }, + { .reg = CCI_REG16(0xfcfc), .val = 0x2002 }, + { .burst = s5kjn5_data_a614, .burst_addr = 0xa614, + .burst_len = ARRAY_SIZE(s5kjn5_data_a614) }, + { .burst = s5kjn5_data_bc98, .burst_addr = 0xbc98, + .burst_len = ARRAY_SIZE(s5kjn5_data_bc98) }, + { .burst = s5kjn5_data_c398, .burst_addr = 0xc398, + .burst_len = ARRAY_SIZE(s5kjn5_data_c398) }, + { .reg = CCI_REG8(0x849c), .val = 0x01 }, + { .reg = CCI_REG8(0x849d), .val = 0x00 }, + { .reg = CCI_REG8(0x849e), .val = 0x00 }, + { .reg = CCI_REG8(0x849f), .val = 0x00 }, + { .reg = CCI_REG8(0x84a0), .val = 0x00 }, + { .reg = CCI_REG8(0x84a1), .val = 0x00 }, + { .reg = CCI_REG8(0x84a2), .val = 0x00 }, + { .reg = CCI_REG8(0x84a3), .val = 0x05 }, + { .reg = CCI_REG8(0x84a4), .val = 0x00 }, + { .reg = CCI_REG8(0x84a5), .val = 0x00 }, + { .reg = CCI_REG8(0x84a6), .val = 0x00 }, + { .reg = CCI_REG8(0x84a7), .val = 0x00 }, + { .reg = CCI_REG8(0x84a8), .val = 0x00 }, + { .reg = CCI_REG8(0x84a9), .val = 0x00 }, + { .reg = CCI_REG8(0x84aa), .val = 0x00 }, + { .reg = CCI_REG8(0x84ab), .val = 0x01 }, + { .reg = CCI_REG8(0x84ac), .val = 0x01 }, + { .reg = CCI_REG8(0x84ad), .val = 0xff }, + { .reg = CCI_REG8(0x84b0), .val = 0x80 }, + { .reg = CCI_REG8(0x84b1), .val = 0x89 }, + { .reg = CCI_REG8(0x84b2), .val = 0x00 }, + { .reg = CCI_REG8(0x84b3), .val = 0x00 }, + { .reg = CCI_REG8(0x84b4), .val = 0x88 }, + { .reg = CCI_REG8(0x84b5), .val = 0x89 }, + { .reg = CCI_REG8(0x84b6), .val = 0x00 }, + { .reg = CCI_REG8(0x84b7), .val = 0x00 }, + { .reg = CCI_REG8(0x84b8), .val = 0xc0 }, + { .reg = CCI_REG8(0x84b9), .val = 0x97 }, + { .reg = CCI_REG8(0x84ba), .val = 0x00 }, + { .reg = CCI_REG8(0x84bb), .val = 0x00 }, + { .reg = CCI_REG8(0x84bc), .val = 0xa6 }, + { .reg = CCI_REG8(0x84bd), .val = 0x0e }, + { .reg = CCI_REG8(0x84be), .val = 0x00 }, + { .reg = CCI_REG8(0x84bf), .val = 0x00 }, + { .reg = CCI_REG8(0x84c0), .val = 0x22 }, + { .reg = CCI_REG8(0x84c1), .val = 0x06 }, + { .reg = CCI_REG8(0x84c2), .val = 0x00 }, + { .reg = CCI_REG8(0x84c3), .val = 0x00 }, + { .reg = CCI_REG8(0x84c4), .val = 0x00 }, + { .reg = CCI_REG8(0x84c5), .val = 0x2d }, + { .reg = CCI_REG8(0x84c8), .val = 0x54 }, + { .reg = CCI_REG8(0x84c9), .val = 0xc6 }, + { .reg = CCI_REG8(0x84ca), .val = 0x02 }, + { .reg = CCI_REG8(0x84cb), .val = 0x24 }, + { .reg = CCI_REG8(0x84cc), .val = 0x44 }, + { .reg = CCI_REG8(0x84cd), .val = 0xab }, + { .reg = CCI_REG8(0x84ce), .val = 0x02 }, + { .reg = CCI_REG8(0x84cf), .val = 0x24 }, + { .reg = CCI_REG8(0x84d0), .val = 0x44 }, + { .reg = CCI_REG8(0x84d1), .val = 0xab }, + { .reg = CCI_REG8(0x84d2), .val = 0x02 }, + { .reg = CCI_REG8(0x84d3), .val = 0x24 }, + { .reg = CCI_REG8(0x84d4), .val = 0x44 }, + { .reg = CCI_REG8(0x84d5), .val = 0xab }, + { .reg = CCI_REG8(0x84d6), .val = 0x02 }, + { .reg = CCI_REG8(0x84d7), .val = 0x24 }, + { .reg = CCI_REG8(0x84d8), .val = 0x44 }, + { .reg = CCI_REG8(0x84d9), .val = 0xab }, + { .reg = CCI_REG8(0x84da), .val = 0x02 }, + { .reg = CCI_REG8(0x84db), .val = 0x24 }, + { .reg = CCI_REG8(0x84dc), .val = 0x44 }, + { .reg = CCI_REG8(0x84dd), .val = 0xab }, + { .reg = CCI_REG8(0x84de), .val = 0x02 }, + { .reg = CCI_REG8(0x84df), .val = 0x24 }, + { .burst = s5kjn5_data_a548, .burst_addr = 0xa548, + .burst_len = ARRAY_SIZE(s5kjn5_data_a548) }, + { .burst = s5kjn5_data_bb84, .burst_addr = 0xbb84, + .burst_len = ARRAY_SIZE(s5kjn5_data_bb84) }, + { .reg = CCI_REG16(0xfcfc), .val = 0x2001 }, + { .burst = s5kjn5_data_5634, .burst_addr = 0x5634, + .burst_len = ARRAY_SIZE(s5kjn5_data_5634) }, + { .reg = CCI_REG16(0xfcfc), .val = 0x2000 }, + { .reg = CCI_REG8(0x2366), .val = 0x00 }, + { .reg = CCI_REG8(0x2367), .val = 0x1c }, + { .reg = CCI_REG8(0x2368), .val = 0x00 }, + { .reg = CCI_REG8(0x2369), .val = 0x1c }, + { .reg = CCI_REG16(0x238e), .val = 0x3f28 }, + { .reg = CCI_REG16(0x2398), .val = 0x5037 }, + { .reg = CCI_REG16(0x24b8), .val = 0x0101 }, + { .reg = CCI_REG8(0x66e4), .val = 0x1e }, + { .reg = CCI_REG8(0x66e5), .val = 0x8d }, + { .reg = CCI_REG8(0x66e6), .val = 0x00 }, + { .reg = CCI_REG8(0x66e7), .val = 0x00 }, + { .reg = CCI_REG8(0x6874), .val = 0x00 }, + { .reg = CCI_REG8(0x6875), .val = 0x00 }, + { .reg = CCI_REG8(0x6876), .val = 0x00 }, + { .reg = CCI_REG8(0x6877), .val = 0x00 }, + { .reg = CCI_REG8(0x6878), .val = 0x00 }, + { .reg = CCI_REG8(0x6879), .val = 0x00 }, + { .reg = CCI_REG8(0x687a), .val = 0x00 }, + { .reg = CCI_REG8(0x687b), .val = 0x00 }, + { .reg = CCI_REG8(0x6884), .val = 0x01 }, + { .reg = CCI_REG8(0x6885), .val = 0x00 }, + { .reg = CCI_REG8(0x6886), .val = 0x01 }, + { .reg = CCI_REG8(0x6887), .val = 0x00 }, + { .reg = CCI_REG8(0x6888), .val = 0x01 }, + { .reg = CCI_REG8(0x6889), .val = 0x00 }, + { .reg = CCI_REG8(0x688a), .val = 0x01 }, + { .reg = CCI_REG8(0x688b), .val = 0x00 }, + { .reg = CCI_REG16(0x77d2), .val = 0x0000 }, + { .reg = CCI_REG16(0x780a), .val = 0x0000 }, + { .reg = CCI_REG8(0x793e), .val = 0x01 }, + { .reg = CCI_REG8(0x793f), .val = 0x00 }, + { .reg = CCI_REG8(0x7940), .val = 0x70 }, + { .reg = CCI_REG8(0x7941), .val = 0x17 }, + { .reg = CCI_REG8(0x795c), .val = 0x04 }, + { .reg = CCI_REG8(0x795d), .val = 0x00 }, + { .reg = CCI_REG8(0x795e), .val = 0x04 }, + { .reg = CCI_REG8(0x795f), .val = 0x00 }, + { .reg = CCI_REG8(0x7960), .val = 0x08 }, + { .reg = CCI_REG8(0x7961), .val = 0x00 }, + { .reg = CCI_REG8(0x7962), .val = 0x10 }, + { .reg = CCI_REG8(0x7963), .val = 0x00 }, + { .reg = CCI_REG8(0x7964), .val = 0x08 }, + { .reg = CCI_REG8(0x7965), .val = 0x00 }, + { .reg = CCI_REG8(0x7966), .val = 0x10 }, + { .reg = CCI_REG8(0x7967), .val = 0x00 }, + { .reg = CCI_REG8(0x7968), .val = 0x08 }, + { .reg = CCI_REG8(0x7969), .val = 0x00 }, + { .reg = CCI_REG8(0x796a), .val = 0x08 }, + { .reg = CCI_REG8(0x796b), .val = 0x00 }, + { .reg = CCI_REG8(0x796c), .val = 0x08 }, + { .reg = CCI_REG8(0x796d), .val = 0x00 }, + { .reg = CCI_REG8(0x796e), .val = 0x08 }, + { .reg = CCI_REG8(0x796f), .val = 0x00 }, + { .reg = CCI_REG8(0x7972), .val = 0x04 }, + { .reg = CCI_REG8(0x7973), .val = 0x00 }, + { .reg = CCI_REG8(0x7974), .val = 0x04 }, + { .reg = CCI_REG8(0x7975), .val = 0x00 }, + { .reg = CCI_REG8(0x7976), .val = 0x08 }, + { .reg = CCI_REG8(0x7977), .val = 0x00 }, + { .reg = CCI_REG8(0x7978), .val = 0x10 }, + { .reg = CCI_REG8(0x7979), .val = 0x00 }, + { .reg = CCI_REG8(0x797a), .val = 0x08 }, + { .reg = CCI_REG8(0x797b), .val = 0x00 }, + { .reg = CCI_REG8(0x797c), .val = 0x10 }, + { .reg = CCI_REG8(0x797d), .val = 0x00 }, + { .reg = CCI_REG8(0x797e), .val = 0x08 }, + { .reg = CCI_REG8(0x797f), .val = 0x00 }, + { .reg = CCI_REG8(0x7980), .val = 0x08 }, + { .reg = CCI_REG8(0x7981), .val = 0x00 }, + { .reg = CCI_REG8(0x7982), .val = 0x08 }, + { .reg = CCI_REG8(0x7983), .val = 0x00 }, + { .reg = CCI_REG8(0x7984), .val = 0x08 }, + { .reg = CCI_REG8(0x7985), .val = 0x00 }, + { .reg = CCI_REG16(0xb3ac), .val = 0x4000 }, + { .reg = CCI_REG16(0xb3b4), .val = 0x2000 }, + { .reg = CCI_REG16(0xb3b8), .val = 0x1000 }, + { .reg = CCI_REG16(0xb3f8), .val = 0x8000 }, + { .reg = CCI_REG16(0xb400), .val = 0x4000 }, + { .reg = CCI_REG16(0xb404), .val = 0x2000 }, + { .reg = CCI_REG16(0xbf70), .val = 0x3a46 }, + { .reg = CCI_REG16(0xbf7c), .val = 0x0800 }, + { .reg = CCI_REG16(0xc4a8), .val = 0x0000 }, + { .reg = CCI_REG8(0xc4f8), .val = 0x00 }, + { .reg = CCI_REG8(0xc4f9), .val = 0xa8 }, + { .reg = CCI_REG8(0xc4fa), .val = 0x00 }, + { .reg = CCI_REG8(0xc4fb), .val = 0x00 }, + { .reg = CCI_REG16(0xd3da), .val = 0x0d00 }, + { .reg = CCI_REG8(0xd3e0), .val = 0x0d }, + { .reg = CCI_REG8(0xd3e1), .val = 0x00 }, + { .reg = CCI_REG8(0xd3e2), .val = 0x0d }, + { .reg = CCI_REG8(0xd3e3), .val = 0x00 }, + { .reg = CCI_REG8(0xd3e4), .val = 0x0d }, + { .reg = CCI_REG8(0xd3e5), .val = 0x00 }, + { .reg = CCI_REG8(0xd3e6), .val = 0x0d }, + { .reg = CCI_REG8(0xd3e7), .val = 0x00 }, + { .reg = CCI_REG16(0xd3ea), .val = 0x0d00 }, + { .reg = CCI_REG16(0xd3f4), .val = 0x301c }, + { .reg = CCI_REG16(0xd3f8), .val = 0x301c }, + { .reg = CCI_REG8(0xdd6c), .val = 0xb4 }, + { .reg = CCI_REG8(0xdd6d), .val = 0x7e }, + { .reg = CCI_REG8(0xdd6e), .val = 0xb6 }, + { .reg = CCI_REG8(0xdd6f), .val = 0x7e }, + { .reg = CCI_REG8(0xde34), .val = 0x00 }, + { .reg = CCI_REG8(0xde35), .val = 0x00 }, + { .reg = CCI_REG8(0xde36), .val = 0x92 }, + { .reg = CCI_REG8(0xde37), .val = 0x31 }, + { .reg = CCI_REG8(0xec42), .val = 0x01 }, + { .reg = CCI_REG8(0xec43), .val = 0x00 }, + { .reg = CCI_REG8(0xec44), .val = 0x01 }, + { .reg = CCI_REG8(0xec45), .val = 0x00 }, + { .reg = CCI_REG16(0xfcfc), .val = 0x2001 }, + { .reg = CCI_REG8(0x2542), .val = 0x20 }, + { .reg = CCI_REG8(0x2543), .val = 0x20 }, + { .reg = CCI_REG8(0x2544), .val = 0x20 }, + { .reg = CCI_REG8(0x2545), .val = 0x18 }, + { .reg = CCI_REG8(0x2554), .val = 0x00 }, + { .reg = CCI_REG8(0x2555), .val = 0x00 }, + { .reg = CCI_REG8(0x2556), .val = 0x00 }, + { .reg = CCI_REG8(0x2557), .val = 0x00 }, + { .reg = CCI_REG16(0x256e), .val = 0x0000 }, + { .reg = CCI_REG16(0x25d2), .val = 0x0102 }, + { .reg = CCI_REG16(0x2936), .val = 0x4400 }, + { .reg = CCI_REG8(0x2a14), .val = 0x00 }, + { .reg = CCI_REG8(0x2a15), .val = 0x02 }, + { .reg = CCI_REG8(0x2a16), .val = 0xdf }, + { .reg = CCI_REG8(0x2a17), .val = 0x03 }, + { .reg = CCI_REG8(0x2a18), .val = 0x00 }, + { .reg = CCI_REG8(0x2a19), .val = 0x02 }, + { .reg = CCI_REG8(0x2a1a), .val = 0x00 }, + { .reg = CCI_REG8(0x2a1b), .val = 0x02 }, + { .reg = CCI_REG8(0x3252), .val = 0x8c }, + { .reg = CCI_REG8(0x3253), .val = 0x00 }, + { .reg = CCI_REG8(0x3254), .val = 0x8c }, + { .reg = CCI_REG8(0x3255), .val = 0x00 }, + { .reg = CCI_REG8(0x3256), .val = 0x8c }, + { .reg = CCI_REG8(0x3257), .val = 0x00 }, + { .reg = CCI_REG8(0x3258), .val = 0x87 }, + { .reg = CCI_REG8(0x3259), .val = 0x00 }, + { .reg = CCI_REG8(0x325a), .val = 0x82 }, + { .reg = CCI_REG8(0x325b), .val = 0x00 }, + { .reg = CCI_REG8(0x3e1c), .val = 0x02 }, + { .reg = CCI_REG8(0x3e1d), .val = 0x00 }, + { .reg = CCI_REG8(0x3e1e), .val = 0x20 }, + { .reg = CCI_REG8(0x3e1f), .val = 0x00 }, + { .reg = CCI_REG16(0x5acc), .val = 0x6505 }, + { .reg = CCI_REG16(0xfcfc), .val = 0x4000 }, + { .reg = CCI_REG16(0x1858), .val = 0x123f }, + { .reg = CCI_REG16(0xfcfc), .val = 0x2001 }, + { .reg = CCI_REG16(0x3eb8), .val = 0x00ff }, + { .reg = CCI_REG16(0x3ecc), .val = 0xfe03 }, + { .reg = CCI_REG16(0x3f12), .val = 0x9001 }, + { .reg = CCI_REG8(0x33e0), .val = 0x1e }, + { .reg = CCI_REG8(0x33e1), .val = 0x00 }, + { .reg = CCI_REG8(0x33e2), .val = 0x1e }, + { .reg = CCI_REG8(0x33e3), .val = 0x00 }, + { .reg = CCI_REG8(0x33e4), .val = 0x1e }, + { .reg = CCI_REG8(0x33e5), .val = 0x00 }, + { .reg = CCI_REG8(0x33e6), .val = 0x1e }, + { .reg = CCI_REG8(0x33e7), .val = 0x00 }, + { .reg = CCI_REG8(0x33e8), .val = 0x1e }, + { .reg = CCI_REG8(0x33e9), .val = 0x00 }, + { .reg = CCI_REG8(0x33ea), .val = 0x1e }, + { .reg = CCI_REG8(0x33eb), .val = 0x00 }, + { .reg = CCI_REG8(0x3440), .val = 0x05 }, + { .reg = CCI_REG8(0x3441), .val = 0x00 }, + { .reg = CCI_REG8(0x3442), .val = 0x05 }, + { .reg = CCI_REG8(0x3443), .val = 0x00 }, + { .reg = CCI_REG8(0x3444), .val = 0x05 }, + { .reg = CCI_REG8(0x3445), .val = 0x00 }, + { .reg = CCI_REG8(0x3446), .val = 0x05 }, + { .reg = CCI_REG8(0x3447), .val = 0x00 }, + { .reg = CCI_REG8(0x3448), .val = 0x05 }, + { .reg = CCI_REG8(0x3449), .val = 0x00 }, + { .reg = CCI_REG8(0x344a), .val = 0x05 }, + { .reg = CCI_REG8(0x344b), .val = 0x00 }, + { .reg = CCI_REG8(0x3450), .val = 0x0a }, + { .reg = CCI_REG8(0x3451), .val = 0x00 }, + { .reg = CCI_REG8(0x3452), .val = 0x0a }, + { .reg = CCI_REG8(0x3453), .val = 0x00 }, + { .reg = CCI_REG8(0x3454), .val = 0x0a }, + { .reg = CCI_REG8(0x3455), .val = 0x00 }, + { .reg = CCI_REG8(0x3456), .val = 0x0a }, + { .reg = CCI_REG8(0x3457), .val = 0x00 }, + { .reg = CCI_REG8(0x3458), .val = 0x0a }, + { .reg = CCI_REG8(0x3459), .val = 0x00 }, + { .reg = CCI_REG8(0x345a), .val = 0x0a }, + { .reg = CCI_REG8(0x345b), .val = 0x00 }, + { .reg = CCI_REG8(0x34e0), .val = 0x14 }, + { .reg = CCI_REG8(0x34e1), .val = 0x00 }, + { .reg = CCI_REG8(0x34e2), .val = 0x14 }, + { .reg = CCI_REG8(0x34e3), .val = 0x00 }, + { .reg = CCI_REG8(0x34e4), .val = 0x14 }, + { .reg = CCI_REG8(0x34e5), .val = 0x00 }, + { .reg = CCI_REG8(0x34e6), .val = 0x14 }, + { .reg = CCI_REG8(0x34e7), .val = 0x00 }, + { .reg = CCI_REG8(0x34e8), .val = 0x14 }, + { .reg = CCI_REG8(0x34e9), .val = 0x00 }, + { .reg = CCI_REG8(0x34ea), .val = 0x14 }, + { .reg = CCI_REG8(0x34eb), .val = 0x00 }, + { .reg = CCI_REG8(0x3500), .val = 0x14 }, + { .reg = CCI_REG8(0x3501), .val = 0x00 }, + { .reg = CCI_REG8(0x3502), .val = 0x14 }, + { .reg = CCI_REG8(0x3503), .val = 0x00 }, + { .reg = CCI_REG8(0x3504), .val = 0x14 }, + { .reg = CCI_REG8(0x3505), .val = 0x00 }, + { .reg = CCI_REG8(0x3506), .val = 0x14 }, + { .reg = CCI_REG8(0x3507), .val = 0x00 }, + { .reg = CCI_REG8(0x3508), .val = 0x14 }, + { .reg = CCI_REG8(0x3509), .val = 0x00 }, + { .reg = CCI_REG8(0x350a), .val = 0x14 }, + { .reg = CCI_REG8(0x350b), .val = 0x00 }, + { .reg = CCI_REG8(0x3520), .val = 0x14 }, + { .reg = CCI_REG8(0x3521), .val = 0x00 }, + { .reg = CCI_REG8(0x3522), .val = 0x14 }, + { .reg = CCI_REG8(0x3523), .val = 0x00 }, + { .reg = CCI_REG8(0x3524), .val = 0x14 }, + { .reg = CCI_REG8(0x3525), .val = 0x00 }, + { .reg = CCI_REG8(0x3526), .val = 0x14 }, + { .reg = CCI_REG8(0x3527), .val = 0x00 }, + { .reg = CCI_REG8(0x3528), .val = 0x14 }, + { .reg = CCI_REG8(0x3529), .val = 0x00 }, + { .reg = CCI_REG8(0x352a), .val = 0x14 }, + { .reg = CCI_REG8(0x352b), .val = 0x00 }, + { .reg = CCI_REG8(0x3580), .val = 0x23 }, + { .reg = CCI_REG8(0x3581), .val = 0x00 }, + { .reg = CCI_REG8(0x3582), .val = 0x23 }, + { .reg = CCI_REG8(0x3583), .val = 0x00 }, + { .reg = CCI_REG8(0x3584), .val = 0x23 }, + { .reg = CCI_REG8(0x3585), .val = 0x00 }, + { .reg = CCI_REG8(0x3586), .val = 0x23 }, + { .reg = CCI_REG8(0x3587), .val = 0x00 }, + { .reg = CCI_REG8(0x3588), .val = 0x23 }, + { .reg = CCI_REG8(0x3589), .val = 0x00 }, + { .reg = CCI_REG8(0x358a), .val = 0x23 }, + { .reg = CCI_REG8(0x358b), .val = 0x00 }, + { .reg = CCI_REG8(0x35a0), .val = 0x19 }, + { .reg = CCI_REG8(0x35a1), .val = 0x00 }, + { .reg = CCI_REG8(0x35a2), .val = 0x19 }, + { .reg = CCI_REG8(0x35a3), .val = 0x00 }, + { .reg = CCI_REG8(0x35a4), .val = 0x19 }, + { .reg = CCI_REG8(0x35a5), .val = 0x00 }, + { .reg = CCI_REG8(0x35a6), .val = 0x19 }, + { .reg = CCI_REG8(0x35a7), .val = 0x00 }, + { .reg = CCI_REG8(0x35a8), .val = 0x19 }, + { .reg = CCI_REG8(0x35a9), .val = 0x00 }, + { .reg = CCI_REG8(0x35aa), .val = 0x19 }, + { .reg = CCI_REG8(0x35ab), .val = 0x00 }, + { .reg = CCI_REG8(0x35d0), .val = 0x1e }, + { .reg = CCI_REG8(0x35d1), .val = 0x00 }, + { .reg = CCI_REG8(0x35d2), .val = 0x1e }, + { .reg = CCI_REG8(0x35d3), .val = 0x00 }, + { .reg = CCI_REG8(0x35d4), .val = 0x1e }, + { .reg = CCI_REG8(0x35d5), .val = 0x00 }, + { .reg = CCI_REG8(0x35d6), .val = 0x1e }, + { .reg = CCI_REG8(0x35d7), .val = 0x00 }, + { .reg = CCI_REG8(0x35d8), .val = 0x1e }, + { .reg = CCI_REG8(0x35d9), .val = 0x00 }, + { .reg = CCI_REG8(0x35da), .val = 0x1e }, + { .reg = CCI_REG8(0x35db), .val = 0x00 }, + { .reg = CCI_REG8(0x35e0), .val = 0x1e }, + { .reg = CCI_REG8(0x35e1), .val = 0x00 }, + { .reg = CCI_REG8(0x35e2), .val = 0x1e }, + { .reg = CCI_REG8(0x35e3), .val = 0x00 }, + { .reg = CCI_REG8(0x35e4), .val = 0x1e }, + { .reg = CCI_REG8(0x35e5), .val = 0x00 }, + { .reg = CCI_REG8(0x35e6), .val = 0x1e }, + { .reg = CCI_REG8(0x35e7), .val = 0x00 }, + { .reg = CCI_REG8(0x35e8), .val = 0x1e }, + { .reg = CCI_REG8(0x35e9), .val = 0x00 }, + { .reg = CCI_REG8(0x35ea), .val = 0x1e }, + { .reg = CCI_REG8(0x35eb), .val = 0x00 }, + { .reg = CCI_REG8(0x35f0), .val = 0x1e }, + { .reg = CCI_REG8(0x35f1), .val = 0x00 }, + { .reg = CCI_REG8(0x35f2), .val = 0x1e }, + { .reg = CCI_REG8(0x35f3), .val = 0x00 }, + { .reg = CCI_REG8(0x35f4), .val = 0x1e }, + { .reg = CCI_REG8(0x35f5), .val = 0x00 }, + { .reg = CCI_REG8(0x35f6), .val = 0x1e }, + { .reg = CCI_REG8(0x35f7), .val = 0x00 }, + { .reg = CCI_REG8(0x35f8), .val = 0x1e }, + { .reg = CCI_REG8(0x35f9), .val = 0x00 }, + { .reg = CCI_REG8(0x35fa), .val = 0x1e }, + { .reg = CCI_REG8(0x35fb), .val = 0x00 }, + { .reg = CCI_REG8(0x3600), .val = 0x1e }, + { .reg = CCI_REG8(0x3601), .val = 0x00 }, + { .reg = CCI_REG8(0x3602), .val = 0x1e }, + { .reg = CCI_REG8(0x3603), .val = 0x00 }, + { .reg = CCI_REG8(0x3604), .val = 0x1e }, + { .reg = CCI_REG8(0x3605), .val = 0x00 }, + { .reg = CCI_REG8(0x3606), .val = 0x1e }, + { .reg = CCI_REG8(0x3607), .val = 0x00 }, + { .reg = CCI_REG8(0x3608), .val = 0x1e }, + { .reg = CCI_REG8(0x3609), .val = 0x00 }, + { .reg = CCI_REG8(0x360a), .val = 0x1e }, + { .reg = CCI_REG8(0x360b), .val = 0x00 }, + { .reg = CCI_REG8(0x3610), .val = 0x1e }, + { .reg = CCI_REG8(0x3611), .val = 0x00 }, + { .reg = CCI_REG8(0x3612), .val = 0x1e }, + { .reg = CCI_REG8(0x3613), .val = 0x00 }, + { .reg = CCI_REG8(0x3614), .val = 0x1e }, + { .reg = CCI_REG8(0x3615), .val = 0x00 }, + { .reg = CCI_REG8(0x3616), .val = 0x1e }, + { .reg = CCI_REG8(0x3617), .val = 0x00 }, + { .reg = CCI_REG8(0x3618), .val = 0x1e }, + { .reg = CCI_REG8(0x3619), .val = 0x00 }, + { .reg = CCI_REG8(0x361a), .val = 0x1e }, + { .reg = CCI_REG8(0x361b), .val = 0x00 }, + { .reg = CCI_REG8(0x3620), .val = 0x00 }, + { .reg = CCI_REG8(0x3621), .val = 0x00 }, + { .reg = CCI_REG8(0x3622), .val = 0x00 }, + { .reg = CCI_REG8(0x3623), .val = 0x00 }, + { .reg = CCI_REG8(0x3624), .val = 0x00 }, + { .reg = CCI_REG8(0x3625), .val = 0x00 }, + { .reg = CCI_REG8(0x3626), .val = 0x00 }, + { .reg = CCI_REG8(0x3627), .val = 0x00 }, + { .reg = CCI_REG8(0x3628), .val = 0x00 }, + { .reg = CCI_REG8(0x3629), .val = 0x00 }, + { .reg = CCI_REG8(0x362a), .val = 0x00 }, + { .reg = CCI_REG8(0x362b), .val = 0x00 }, + { .reg = CCI_REG8(0x3630), .val = 0x0a }, + { .reg = CCI_REG8(0x3631), .val = 0x00 }, + { .reg = CCI_REG8(0x3632), .val = 0x0a }, + { .reg = CCI_REG8(0x3633), .val = 0x00 }, + { .reg = CCI_REG8(0x3634), .val = 0x0a }, + { .reg = CCI_REG8(0x3635), .val = 0x00 }, + { .reg = CCI_REG8(0x3636), .val = 0x0a }, + { .reg = CCI_REG8(0x3637), .val = 0x00 }, + { .reg = CCI_REG8(0x3638), .val = 0x0a }, + { .reg = CCI_REG8(0x3639), .val = 0x00 }, + { .reg = CCI_REG8(0x363a), .val = 0x0a }, + { .reg = CCI_REG8(0x363b), .val = 0x00 }, + { .reg = CCI_REG8(0x3650), .val = 0x1e }, + { .reg = CCI_REG8(0x3651), .val = 0x00 }, + { .reg = CCI_REG8(0x3652), .val = 0x1e }, + { .reg = CCI_REG8(0x3653), .val = 0x00 }, + { .reg = CCI_REG8(0x3654), .val = 0x1e }, + { .reg = CCI_REG8(0x3655), .val = 0x00 }, + { .reg = CCI_REG8(0x3656), .val = 0x1e }, + { .reg = CCI_REG8(0x3657), .val = 0x00 }, + { .reg = CCI_REG8(0x3658), .val = 0x1e }, + { .reg = CCI_REG8(0x3659), .val = 0x00 }, + { .reg = CCI_REG8(0x365a), .val = 0x1e }, + { .reg = CCI_REG8(0x365b), .val = 0x00 }, + { .reg = CCI_REG8(0x3660), .val = 0x1e }, + { .reg = CCI_REG8(0x3661), .val = 0x00 }, + { .reg = CCI_REG8(0x3662), .val = 0x1e }, + { .reg = CCI_REG8(0x3663), .val = 0x00 }, + { .reg = CCI_REG8(0x3664), .val = 0x1e }, + { .reg = CCI_REG8(0x3665), .val = 0x00 }, + { .reg = CCI_REG8(0x3666), .val = 0x1e }, + { .reg = CCI_REG8(0x3667), .val = 0x00 }, + { .reg = CCI_REG8(0x3668), .val = 0x1e }, + { .reg = CCI_REG8(0x3669), .val = 0x00 }, + { .reg = CCI_REG8(0x366a), .val = 0x1e }, + { .reg = CCI_REG8(0x366b), .val = 0x00 }, + { .reg = CCI_REG8(0x36a0), .val = 0x64 }, + { .reg = CCI_REG8(0x36a1), .val = 0x00 }, + { .reg = CCI_REG8(0x36a2), .val = 0x64 }, + { .reg = CCI_REG8(0x36a3), .val = 0x00 }, + { .reg = CCI_REG8(0x36a4), .val = 0x64 }, + { .reg = CCI_REG8(0x36a5), .val = 0x00 }, + { .reg = CCI_REG8(0x36a6), .val = 0x64 }, + { .reg = CCI_REG8(0x36a7), .val = 0x00 }, + { .reg = CCI_REG8(0x36a8), .val = 0x64 }, + { .reg = CCI_REG8(0x36a9), .val = 0x00 }, + { .reg = CCI_REG8(0x36aa), .val = 0x64 }, + { .reg = CCI_REG8(0x36ab), .val = 0x00 }, + { .reg = CCI_REG8(0x36c0), .val = 0x8c }, + { .reg = CCI_REG8(0x36c1), .val = 0x00 }, + { .reg = CCI_REG8(0x36c2), .val = 0x8c }, + { .reg = CCI_REG8(0x36c3), .val = 0x00 }, + { .reg = CCI_REG8(0x36c4), .val = 0x8c }, + { .reg = CCI_REG8(0x36c5), .val = 0x00 }, + { .reg = CCI_REG8(0x36c6), .val = 0x8c }, + { .reg = CCI_REG8(0x36c7), .val = 0x00 }, + { .reg = CCI_REG8(0x36c8), .val = 0x8c }, + { .reg = CCI_REG8(0x36c9), .val = 0x00 }, + { .reg = CCI_REG8(0x36ca), .val = 0x8c }, + { .reg = CCI_REG8(0x36cb), .val = 0x00 }, + { .reg = CCI_REG8(0x36e0), .val = 0x64 }, + { .reg = CCI_REG8(0x36e1), .val = 0x00 }, + { .reg = CCI_REG8(0x36e2), .val = 0x64 }, + { .reg = CCI_REG8(0x36e3), .val = 0x00 }, + { .reg = CCI_REG8(0x36e4), .val = 0x64 }, + { .reg = CCI_REG8(0x36e5), .val = 0x00 }, + { .reg = CCI_REG8(0x36e6), .val = 0x64 }, + { .reg = CCI_REG8(0x36e7), .val = 0x00 }, + { .reg = CCI_REG8(0x36e8), .val = 0x64 }, + { .reg = CCI_REG8(0x36e9), .val = 0x00 }, + { .reg = CCI_REG8(0x36ea), .val = 0x64 }, + { .reg = CCI_REG8(0x36eb), .val = 0x00 }, + { .reg = CCI_REG8(0x36f0), .val = 0x32 }, + { .reg = CCI_REG8(0x36f1), .val = 0x00 }, + { .reg = CCI_REG8(0x36f2), .val = 0x32 }, + { .reg = CCI_REG8(0x36f3), .val = 0x00 }, + { .reg = CCI_REG8(0x36f4), .val = 0x32 }, + { .reg = CCI_REG8(0x36f5), .val = 0x00 }, + { .reg = CCI_REG8(0x36f6), .val = 0x32 }, + { .reg = CCI_REG8(0x36f7), .val = 0x00 }, + { .reg = CCI_REG8(0x36f8), .val = 0x32 }, + { .reg = CCI_REG8(0x36f9), .val = 0x00 }, + { .reg = CCI_REG8(0x36fa), .val = 0x32 }, + { .reg = CCI_REG8(0x36fb), .val = 0x00 }, + { .reg = CCI_REG8(0x3700), .val = 0x32 }, + { .reg = CCI_REG8(0x3701), .val = 0x00 }, + { .reg = CCI_REG8(0x3702), .val = 0x32 }, + { .reg = CCI_REG8(0x3703), .val = 0x00 }, + { .reg = CCI_REG8(0x3704), .val = 0x32 }, + { .reg = CCI_REG8(0x3705), .val = 0x00 }, + { .reg = CCI_REG8(0x3706), .val = 0x32 }, + { .reg = CCI_REG8(0x3707), .val = 0x00 }, + { .reg = CCI_REG8(0x3708), .val = 0x32 }, + { .reg = CCI_REG8(0x3709), .val = 0x00 }, + { .reg = CCI_REG8(0x370a), .val = 0x32 }, + { .reg = CCI_REG8(0x370b), .val = 0x00 }, + { .reg = CCI_REG8(0x3720), .val = 0x32 }, + { .reg = CCI_REG8(0x3721), .val = 0x00 }, + { .reg = CCI_REG8(0x3722), .val = 0x32 }, + { .reg = CCI_REG8(0x3723), .val = 0x00 }, + { .reg = CCI_REG8(0x3724), .val = 0x32 }, + { .reg = CCI_REG8(0x3725), .val = 0x00 }, + { .reg = CCI_REG8(0x3726), .val = 0x32 }, + { .reg = CCI_REG8(0x3727), .val = 0x00 }, + { .reg = CCI_REG8(0x3728), .val = 0x32 }, + { .reg = CCI_REG8(0x3729), .val = 0x00 }, + { .reg = CCI_REG8(0x372a), .val = 0x32 }, + { .reg = CCI_REG8(0x372b), .val = 0x00 }, + { .reg = CCI_REG8(0x3730), .val = 0x32 }, + { .reg = CCI_REG8(0x3731), .val = 0x00 }, + { .reg = CCI_REG8(0x3732), .val = 0x32 }, + { .reg = CCI_REG8(0x3733), .val = 0x00 }, + { .reg = CCI_REG8(0x3734), .val = 0x32 }, + { .reg = CCI_REG8(0x3735), .val = 0x00 }, + { .reg = CCI_REG8(0x3736), .val = 0x32 }, + { .reg = CCI_REG8(0x3737), .val = 0x00 }, + { .reg = CCI_REG8(0x3738), .val = 0x32 }, + { .reg = CCI_REG8(0x3739), .val = 0x00 }, + { .reg = CCI_REG8(0x373a), .val = 0x32 }, + { .reg = CCI_REG8(0x373b), .val = 0x00 }, + { .reg = CCI_REG8(0x3790), .val = 0x32 }, + { .reg = CCI_REG8(0x3791), .val = 0x00 }, + { .reg = CCI_REG8(0x3792), .val = 0x32 }, + { .reg = CCI_REG8(0x3793), .val = 0x00 }, + { .reg = CCI_REG8(0x3794), .val = 0x32 }, + { .reg = CCI_REG8(0x3795), .val = 0x00 }, + { .reg = CCI_REG8(0x3796), .val = 0x32 }, + { .reg = CCI_REG8(0x3797), .val = 0x00 }, + { .reg = CCI_REG8(0x3798), .val = 0x32 }, + { .reg = CCI_REG8(0x3799), .val = 0x00 }, + { .reg = CCI_REG8(0x379a), .val = 0x32 }, + { .reg = CCI_REG8(0x379b), .val = 0x00 }, + { .reg = CCI_REG8(0x37a0), .val = 0x50 }, + { .reg = CCI_REG8(0x37a1), .val = 0x00 }, + { .reg = CCI_REG8(0x37a2), .val = 0x50 }, + { .reg = CCI_REG8(0x37a3), .val = 0x00 }, + { .reg = CCI_REG8(0x37a4), .val = 0x50 }, + { .reg = CCI_REG8(0x37a5), .val = 0x00 }, + { .reg = CCI_REG8(0x37a6), .val = 0x50 }, + { .reg = CCI_REG8(0x37a7), .val = 0x00 }, + { .reg = CCI_REG8(0x37a8), .val = 0x50 }, + { .reg = CCI_REG8(0x37a9), .val = 0x00 }, + { .reg = CCI_REG8(0x37aa), .val = 0x50 }, + { .reg = CCI_REG8(0x37ab), .val = 0x00 }, + { .reg = CCI_REG8(0x37b0), .val = 0x64 }, + { .reg = CCI_REG8(0x37b1), .val = 0x00 }, + { .reg = CCI_REG8(0x37b2), .val = 0x64 }, + { .reg = CCI_REG8(0x37b3), .val = 0x00 }, + { .reg = CCI_REG8(0x37b4), .val = 0x64 }, + { .reg = CCI_REG8(0x37b5), .val = 0x00 }, + { .reg = CCI_REG8(0x37b6), .val = 0x64 }, + { .reg = CCI_REG8(0x37b7), .val = 0x00 }, + { .reg = CCI_REG8(0x37b8), .val = 0x64 }, + { .reg = CCI_REG8(0x37b9), .val = 0x00 }, + { .reg = CCI_REG8(0x37ba), .val = 0x64 }, + { .reg = CCI_REG8(0x37bb), .val = 0x00 }, + { .reg = CCI_REG8(0x37c0), .val = 0x50 }, + { .reg = CCI_REG8(0x37c1), .val = 0x00 }, + { .reg = CCI_REG8(0x37c2), .val = 0x50 }, + { .reg = CCI_REG8(0x37c3), .val = 0x00 }, + { .reg = CCI_REG8(0x37c4), .val = 0x50 }, + { .reg = CCI_REG8(0x37c5), .val = 0x00 }, + { .reg = CCI_REG8(0x37c6), .val = 0x50 }, + { .reg = CCI_REG8(0x37c7), .val = 0x00 }, + { .reg = CCI_REG8(0x37c8), .val = 0x50 }, + { .reg = CCI_REG8(0x37c9), .val = 0x00 }, + { .reg = CCI_REG8(0x37ca), .val = 0x50 }, + { .reg = CCI_REG8(0x37cb), .val = 0x00 }, + { .reg = CCI_REG8(0x37d0), .val = 0x32 }, + { .reg = CCI_REG8(0x37d1), .val = 0x00 }, + { .reg = CCI_REG8(0x37d2), .val = 0x32 }, + { .reg = CCI_REG8(0x37d3), .val = 0x00 }, + { .reg = CCI_REG8(0x37d4), .val = 0x32 }, + { .reg = CCI_REG8(0x37d5), .val = 0x00 }, + { .reg = CCI_REG8(0x37d6), .val = 0x32 }, + { .reg = CCI_REG8(0x37d7), .val = 0x00 }, + { .reg = CCI_REG8(0x37d8), .val = 0x32 }, + { .reg = CCI_REG8(0x37d9), .val = 0x00 }, + { .reg = CCI_REG8(0x37da), .val = 0x32 }, + { .reg = CCI_REG8(0x37db), .val = 0x00 }, + { .reg = CCI_REG8(0x37e0), .val = 0x1e }, + { .reg = CCI_REG8(0x37e1), .val = 0x00 }, + { .reg = CCI_REG8(0x37e2), .val = 0x1e }, + { .reg = CCI_REG8(0x37e3), .val = 0x00 }, + { .reg = CCI_REG8(0x37e4), .val = 0x1e }, + { .reg = CCI_REG8(0x37e5), .val = 0x00 }, + { .reg = CCI_REG8(0x37e6), .val = 0x1e }, + { .reg = CCI_REG8(0x37e7), .val = 0x00 }, + { .reg = CCI_REG8(0x37e8), .val = 0x1e }, + { .reg = CCI_REG8(0x37e9), .val = 0x00 }, + { .reg = CCI_REG8(0x37ea), .val = 0x1e }, + { .reg = CCI_REG8(0x37eb), .val = 0x00 }, + { .reg = CCI_REG8(0x37f0), .val = 0x1e }, + { .reg = CCI_REG8(0x37f1), .val = 0x00 }, + { .reg = CCI_REG8(0x37f2), .val = 0x1e }, + { .reg = CCI_REG8(0x37f3), .val = 0x00 }, + { .reg = CCI_REG8(0x37f4), .val = 0x1e }, + { .reg = CCI_REG8(0x37f5), .val = 0x00 }, + { .reg = CCI_REG8(0x37f6), .val = 0x1e }, + { .reg = CCI_REG8(0x37f7), .val = 0x00 }, + { .reg = CCI_REG8(0x37f8), .val = 0x1e }, + { .reg = CCI_REG8(0x37f9), .val = 0x00 }, + { .reg = CCI_REG8(0x37fa), .val = 0x1e }, + { .reg = CCI_REG8(0x37fb), .val = 0x00 }, + { .reg = CCI_REG8(0x3800), .val = 0x1e }, + { .reg = CCI_REG8(0x3801), .val = 0x00 }, + { .reg = CCI_REG8(0x3802), .val = 0x1e }, + { .reg = CCI_REG8(0x3803), .val = 0x00 }, + { .reg = CCI_REG8(0x3804), .val = 0x1e }, + { .reg = CCI_REG8(0x3805), .val = 0x00 }, + { .reg = CCI_REG8(0x3806), .val = 0x1e }, + { .reg = CCI_REG8(0x3807), .val = 0x00 }, + { .reg = CCI_REG8(0x3808), .val = 0x1e }, + { .reg = CCI_REG8(0x3809), .val = 0x00 }, + { .reg = CCI_REG8(0x380a), .val = 0x1e }, + { .reg = CCI_REG8(0x380b), .val = 0x00 }, + { .reg = CCI_REG8(0x3810), .val = 0x1e }, + { .reg = CCI_REG8(0x3811), .val = 0x00 }, + { .reg = CCI_REG8(0x3812), .val = 0x1e }, + { .reg = CCI_REG8(0x3813), .val = 0x00 }, + { .reg = CCI_REG8(0x3814), .val = 0x1e }, + { .reg = CCI_REG8(0x3815), .val = 0x00 }, + { .reg = CCI_REG8(0x3816), .val = 0x1e }, + { .reg = CCI_REG8(0x3817), .val = 0x00 }, + { .reg = CCI_REG8(0x3818), .val = 0x1e }, + { .reg = CCI_REG8(0x3819), .val = 0x00 }, + { .reg = CCI_REG8(0x381a), .val = 0x1e }, + { .reg = CCI_REG8(0x381b), .val = 0x00 }, + { .reg = CCI_REG8(0x3820), .val = 0x1e }, + { .reg = CCI_REG8(0x3821), .val = 0x00 }, + { .reg = CCI_REG8(0x3822), .val = 0x1e }, + { .reg = CCI_REG8(0x3823), .val = 0x00 }, + { .reg = CCI_REG8(0x3824), .val = 0x1e }, + { .reg = CCI_REG8(0x3825), .val = 0x00 }, + { .reg = CCI_REG8(0x3826), .val = 0x1e }, + { .reg = CCI_REG8(0x3827), .val = 0x00 }, + { .reg = CCI_REG8(0x3828), .val = 0x1e }, + { .reg = CCI_REG8(0x3829), .val = 0x00 }, + { .reg = CCI_REG8(0x382a), .val = 0x1e }, + { .reg = CCI_REG8(0x382b), .val = 0x00 }, + { .reg = CCI_REG8(0x3870), .val = 0x32 }, + { .reg = CCI_REG8(0x3871), .val = 0x00 }, + { .reg = CCI_REG8(0x3872), .val = 0x32 }, + { .reg = CCI_REG8(0x3873), .val = 0x00 }, + { .reg = CCI_REG8(0x3874), .val = 0x32 }, + { .reg = CCI_REG8(0x3875), .val = 0x00 }, + { .reg = CCI_REG8(0x3876), .val = 0x32 }, + { .reg = CCI_REG8(0x3877), .val = 0x00 }, + { .reg = CCI_REG8(0x3878), .val = 0x32 }, + { .reg = CCI_REG8(0x3879), .val = 0x00 }, + { .reg = CCI_REG8(0x387a), .val = 0x32 }, + { .reg = CCI_REG8(0x387b), .val = 0x00 }, + { .reg = CCI_REG8(0x3880), .val = 0x32 }, + { .reg = CCI_REG8(0x3881), .val = 0x00 }, + { .reg = CCI_REG8(0x3882), .val = 0x32 }, + { .reg = CCI_REG8(0x3883), .val = 0x00 }, + { .reg = CCI_REG8(0x3884), .val = 0x32 }, + { .reg = CCI_REG8(0x3885), .val = 0x00 }, + { .reg = CCI_REG8(0x3886), .val = 0x32 }, + { .reg = CCI_REG8(0x3887), .val = 0x00 }, + { .reg = CCI_REG8(0x3888), .val = 0x32 }, + { .reg = CCI_REG8(0x3889), .val = 0x00 }, + { .reg = CCI_REG8(0x388a), .val = 0x32 }, + { .reg = CCI_REG8(0x388b), .val = 0x00 }, + { .reg = CCI_REG8(0x3890), .val = 0x32 }, + { .reg = CCI_REG8(0x3891), .val = 0x00 }, + { .reg = CCI_REG8(0x3892), .val = 0x32 }, + { .reg = CCI_REG8(0x3893), .val = 0x00 }, + { .reg = CCI_REG8(0x3894), .val = 0x32 }, + { .reg = CCI_REG8(0x3895), .val = 0x00 }, + { .reg = CCI_REG8(0x3896), .val = 0x32 }, + { .reg = CCI_REG8(0x3897), .val = 0x00 }, + { .reg = CCI_REG8(0x3898), .val = 0x32 }, + { .reg = CCI_REG8(0x3899), .val = 0x00 }, + { .reg = CCI_REG8(0x389a), .val = 0x32 }, + { .reg = CCI_REG8(0x389b), .val = 0x00 }, + { .reg = CCI_REG8(0x38a0), .val = 0x32 }, + { .reg = CCI_REG8(0x38a1), .val = 0x00 }, + { .reg = CCI_REG8(0x38a2), .val = 0x32 }, + { .reg = CCI_REG8(0x38a3), .val = 0x00 }, + { .reg = CCI_REG8(0x38a4), .val = 0x32 }, + { .reg = CCI_REG8(0x38a5), .val = 0x00 }, + { .reg = CCI_REG8(0x38a6), .val = 0x32 }, + { .reg = CCI_REG8(0x38a7), .val = 0x00 }, + { .reg = CCI_REG8(0x38a8), .val = 0x32 }, + { .reg = CCI_REG8(0x38a9), .val = 0x00 }, + { .reg = CCI_REG8(0x38aa), .val = 0x32 }, + { .reg = CCI_REG8(0x38ab), .val = 0x00 }, + { .reg = CCI_REG8(0x38b0), .val = 0x32 }, + { .reg = CCI_REG8(0x38b1), .val = 0x00 }, + { .reg = CCI_REG8(0x38b2), .val = 0x32 }, + { .reg = CCI_REG8(0x38b3), .val = 0x00 }, + { .reg = CCI_REG8(0x38b4), .val = 0x32 }, + { .reg = CCI_REG8(0x38b5), .val = 0x00 }, + { .reg = CCI_REG8(0x38b6), .val = 0x32 }, + { .reg = CCI_REG8(0x38b7), .val = 0x00 }, + { .reg = CCI_REG8(0x38b8), .val = 0x32 }, + { .reg = CCI_REG8(0x38b9), .val = 0x00 }, + { .reg = CCI_REG8(0x38ba), .val = 0x32 }, + { .reg = CCI_REG8(0x38bb), .val = 0x00 }, + { .reg = CCI_REG8(0x320a), .val = 0xff }, + { .reg = CCI_REG8(0x320b), .val = 0x03 }, + { .reg = CCI_REG8(0x320c), .val = 0x07 }, + { .reg = CCI_REG8(0x320d), .val = 0x00 }, + { .reg = CCI_REG8(0x320e), .val = 0xff }, + { .reg = CCI_REG8(0x320f), .val = 0x03 }, + { .reg = CCI_REG8(0x3210), .val = 0x07 }, + { .reg = CCI_REG8(0x3211), .val = 0x00 }, + { .reg = CCI_REG16(0x321e), .val = 0x0000 }, + { .reg = CCI_REG16(0x31d4), .val = 0x00ff }, + { .reg = CCI_REG16(0x321a), .val = 0x0406 }, + { .reg = CCI_REG8(0x3244), .val = 0x01 }, + { .reg = CCI_REG8(0x3245), .val = 0x01 }, + { .reg = CCI_REG8(0x3246), .val = 0x01 }, + { .reg = CCI_REG8(0x3247), .val = 0x01 }, + { .reg = CCI_REG8(0x3248), .val = 0x00 }, + { .reg = CCI_REG8(0x3249), .val = 0x10 }, + { .reg = CCI_REG16(0x3266), .val = 0x0100 }, + { .reg = CCI_REG16(0x3330), .val = 0x0108 }, + { .reg = CCI_REG8(0x3334), .val = 0x01 }, + { .reg = CCI_REG8(0x3335), .val = 0x00 }, + { .reg = CCI_REG8(0x3336), .val = 0x00 }, + { .reg = CCI_REG8(0x3337), .val = 0x00 }, + { .reg = CCI_REG16(0xfcfc), .val = 0x2002 }, + { .burst = s5kjn5_data_bb8a, .burst_addr = 0xbb8a, + .burst_len = ARRAY_SIZE(s5kjn5_data_bb8a) }, + { .reg = CCI_REG16(0xfcfc), .val = 0x4000 }, + { .reg = CCI_REG16(0xfcfc), .val = 0x2000 }, + { .reg = CCI_REG16(0x68d8), .val = 0x0100 }, + { .reg = CCI_REG16(0xfcfc), .val = 0x4000 }, + { .reg = CCI_REG16(0x0e04), .val = 0x0803 }, + { .reg = CCI_REG8(0x0e10), .val = 0x01 }, + { .reg = CCI_REG8(0x0e11), .val = 0x00 }, + { .reg = CCI_REG8(0x0e12), .val = 0x00 }, + { .reg = CCI_REG8(0x0e13), .val = 0x20 }, + { .reg = CCI_REG8(0x0e14), .val = 0x00 }, + { .reg = CCI_REG8(0x0e15), .val = 0x2b }, + { .reg = CCI_REG8(0x0e16), .val = 0x02 }, + { .reg = CCI_REG8(0x0e17), .val = 0x00 }, + { .reg = CCI_REG8(0x0e18), .val = 0x00 }, + { .reg = CCI_REG8(0x0e19), .val = 0x40 }, + { .reg = CCI_REG8(0x0e1a), .val = 0x01 }, + { .reg = CCI_REG8(0x0e1b), .val = 0x2b }, + { .reg = CCI_REG8(0x0106), .val = 0x01 }, + { .reg = CCI_REG8(0x0bcc), .val = 0x00 }, + { .reg = CCI_REG8(0x0101), .val = 0x03 }, +}; + +static const struct cci_reg_sequence s5kjn5_4096x3072_regs[] = { + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x6170), 0xffff }, + { CCI_REG16(0x6180), 0x0000 }, + { CCI_REG16(0x6190), 0x0000 }, + { CCI_REG16(0x6200), 0xffff }, + { CCI_REG16(0x6202), 0xffff }, + { CCI_REG16(0x6204), 0x0000 }, + { CCI_REG16(0x6206), 0x0000 }, + { CCI_REG16(0x6208), 0x0000 }, + { CCI_REG16(0xa100), 0xffff }, + { CCI_REG16(0xa102), 0x0000 }, + { CCI_REG16(0xa104), 0x0000 }, + { CCI_REG16(0xfcfc), 0x4001 }, + { CCI_REG16(0x0102), 0xffff }, + { CCI_REG16(0x0104), 0x0000 }, + { CCI_REG16(0x0108), 0x0000 }, + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x8100), 0xffff }, + { CCI_REG16(0x8104), 0x0000 }, + { CCI_REG16(0x8108), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0x7806), 0x0001 }, + { CCI_REG16(0x7808), 0x2408 }, + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x0344), 0x0000 }, + { CCI_REG16(0x0348), 0x201f }, + { CCI_REG16(0x0346), 0x0000 }, + { CCI_REG16(0x034a), 0x181f }, + { CCI_REG16(0x034c), 0x1000 }, + { CCI_REG16(0x034e), 0x0c00 }, + { CCI_REG16(0x0350), 0x0008 }, + { CCI_REG16(0x0352), 0x0008 }, + { CCI_REG16(0x0340), 0x14b0 }, + { CCI_REG16(0x0342), 0x16a8 }, + { CCI_REG16(0x0136), 0x1300 }, + { CCI_REG16(0x013e), 0x00c8 }, + { CCI_REG16(0x0304), 0x0002 }, + { CCI_REG16(0x0306), 0x00c0 }, + { CCI_REG16(0x030c), 0x0000 }, + { CCI_REG16(0x030e), 0x0003 }, + { CCI_REG16(0x0310), 0x00c3 }, + { CCI_REG16(0x0312), 0x0000 }, + { CCI_REG16(0x031a), 0x0003 }, + { CCI_REG16(0x031c), 0x0032 }, + { CCI_REG16(0x031e), 0x0002 }, + { CCI_REG16(0x0202), 0x0014 }, + { CCI_REG16(0x0226), 0x0014 }, + { CCI_REG16(0x022c), 0x0014 }, + { CCI_REG16(0x0702), 0x0000 }, + { CCI_REG16(0x0704), 0x0000 }, + { CCI_REG16(0x0114), 0x0301 }, + { CCI_REG16(0x0118), 0x0004 }, + { CCI_REG16(0x011a), 0x0001 }, + { CCI_REG16(0x011c), 0x0100 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xb176), 0x0602 }, + { CCI_REG16(0xb178), 0x0000 }, + { CCI_REG16(0x7996), 0x0101 }, + { CCI_REG16(0x7994), 0x2020 }, + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x0900), 0x2222 }, + { CCI_REG16(0x0380), 0x0002 }, + { CCI_REG16(0x0382), 0x0002 }, + { CCI_REG16(0x0384), 0x0002 }, + { CCI_REG16(0x0386), 0x0002 }, + { CCI_REG16(0x040c), 0x0000 }, + { CCI_REG16(0x0400), 0x1010 }, + { CCI_REG16(0x0408), 0x0100 }, + { CCI_REG16(0x040a), 0x0100 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xd1f6), 0x3a00 }, + { CCI_REG16(0xd20c), 0x0908 }, + { CCI_REG16(0xd314), 0x2002 }, + { CCI_REG16(0xd27a), 0x0500 }, + { CCI_REG16(0xd3f0), 0xb01c }, + { CCI_REG16(0xd410), 0x4802 }, + { CCI_REG16(0xd426), 0xd204 }, + { CCI_REG16(0xd43c), 0x0140 }, + { CCI_REG16(0xd412), 0xd204 }, + { CCI_REG16(0xd428), 0xea0a }, + { CCI_REG16(0xd43e), 0x0140 }, + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x0260), 0x0001 }, + { CCI_REG16(0x0262), 0x0000 }, + { CCI_REG16(0x0264), 0x0106 }, + { CCI_REG16(0x0266), 0x0700 }, + { CCI_REG16(0x0112), 0x0a0a }, + { CCI_REG16(0x0270), 0x2b2b }, + { CCI_REG16(0x0272), 0x2b10 }, + { CCI_REG16(0x0274), 0x302b }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x44c6), 0x0000 }, + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x0b02), 0x0102 }, + { CCI_REG16(0x0720), 0x0001 }, + { CCI_REG16(0x0722), 0x0800 }, + { CCI_REG16(0x0724), 0x0000 }, + { CCI_REG16(0x0728), 0x0000 }, + { CCI_REG16(0x072a), 0x0000 }, + { CCI_REG16(0x072c), 0x0000 }, + { CCI_REG16(0x072e), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x3132), 0x0200 }, + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x021e), 0x0000 }, + { CCI_REG16(0x0228), 0x0100 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x31d0), 0x0000 }, + { CCI_REG16(0x5a70), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xdc94), 0x0103 }, + { CCI_REG16(0xef80), 0x0000 }, + { CCI_REG16(0x23f0), 0x0001 }, + { CCI_REG16(0xf3e4), 0x0300 }, + { CCI_REG16(0xf288), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x2a30), 0x01ff }, + { CCI_REG16(0x4270), 0x0000 }, + { CCI_REG16(0x29ba), 0x2000 }, + { CCI_REG16(0x29a8), 0x0100 }, + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x0b04), 0x0001 }, + { CCI_REG16(0x0b06), 0x0101 }, + { CCI_REG16(0x0b08), 0x0100 }, + { CCI_REG16(0x0b0a), 0x0101 }, + { CCI_REG16(0x0b0c), 0x0100 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xc4e0), 0x0100 }, + { CCI_REG16(0xc4f6), 0x0000 }, + { CCI_REG16(0xc4e2), 0x0000 }, + { CCI_REG16(0xc53c), 0x0500 }, + { CCI_REG16(0xc544), 0x0005 }, + { CCI_REG16(0xc53e), 0x0000 }, + { CCI_REG16(0xb23c), 0x6060 }, + { CCI_REG16(0xb242), 0x6060 }, + { CCI_REG16(0xc554), 0x0010 }, + { CCI_REG16(0xc556), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x2920), 0x0100 }, + { CCI_REG16(0x31f8), 0x0000 }, + { CCI_REG16(0x31fa), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xd856), 0x0507 }, + { CCI_REG16(0xd6d4), 0x0000 }, + { CCI_REG16(0x799a), 0x0000 }, + { CCI_REG16(0xd8a2), 0x0100 }, + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x020a), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0x78c0), 0x0101 }, + { CCI_REG16(0x22c2), 0x0600 }, + { CCI_REG16(0x22c4), 0xff1f }, + { CCI_REG16(0x22ec), 0x1f00 }, + { CCI_REG16(0x2306), 0xff3f }, + { CCI_REG16(0x2314), 0xff00 }, + { CCI_REG16(0x2354), 0x0300 }, + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x0936), 0x0000 }, + { CCI_REG16(0x0c40), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0x68de), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x2540), 0x0000 }, + { CCI_REG16(0x25e0), 0x0000 }, + { CCI_REG16(0x25e2), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xd718), 0x0002 }, + { CCI_REG16(0xbf30), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x3c42), 0x0000 }, + { CCI_REG16(0x3c46), 0xeb05 }, + { CCI_REG16(0x3c52), 0x4006 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xd326), 0x0110 }, + { CCI_REG16(0xd3ec), 0xb01c }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x195e), 0x0100 }, + { CCI_REG16(0x1966), 0x0000 }, + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x0086), 0x1400 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xe980), 0x9e04 }, + { CCI_REG16(0xc4d8), 0x2000 }, + { CCI_REG16(0x795a), 0x2000 }, + { CCI_REG16(0x7970), 0x2000 }, + { CCI_REG16(0xfcfc), 0x2002 }, + { CCI_REG16(0x849e), 0x0000 }, + { CCI_REG16(0x84a0), 0x0000 }, + { CCI_REG16(0x84a2), 0x0005 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x2bb2), 0x1000 }, + { CCI_REG16(0x2d32), 0x0010 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0x703c), 0x0101 }, + { CCI_REG16(0x7046), 0x7f02 }, + { CCI_REG16(0x7058), 0x8002 }, + { CCI_REG16(0x71d4), 0x3f00 }, + { CCI_REG16(0x71d6), 0x3d00 }, + { CCI_REG16(0x71d8), 0x84f3 }, + { CCI_REG16(0x71da), 0x0040 }, + { CCI_REG16(0x7048), 0x1f02 }, + { CCI_REG16(0x705a), 0x2002 }, + { CCI_REG16(0x7274), 0x0c00 }, + { CCI_REG16(0x7276), 0x0b00 }, + { CCI_REG16(0x7278), 0x36d2 }, + { CCI_REG16(0x727a), 0x0040 }, + { CCI_REG16(0x727c), 0x0000 }, + { CCI_REG16(0x727e), 0x0000 }, + { CCI_REG16(0x7280), 0x0000 }, + { CCI_REG16(0x7282), 0x0000 }, + { CCI_REG16(0x703e), 0x0100 }, + { CCI_REG16(0x704a), 0x000a }, + { CCI_REG16(0x705c), 0x010a }, + { CCI_REG16(0x7314), 0x2e00 }, + { CCI_REG16(0x7316), 0x3000 }, + { CCI_REG16(0x7318), 0x9efd }, + { CCI_REG16(0x731a), 0x0040 }, + { CCI_REG16(0xbedc), 0xc526 }, + { CCI_REG16(0xbede), 0x903e }, + { CCI_REG16(0xbee0), 0xc00f }, + { CCI_REG16(0xbee2), 0x0008 }, + { CCI_REG16(0xbee4), 0x0c00 }, + { CCI_REG16(0xbee6), 0x8000 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x2a54), 0x0000 }, + { CCI_REG16(0x2a56), 0x0400 }, + { CCI_REG16(0x2a42), 0x0100 }, + { CCI_REG16(0x2a44), 0x3907 }, + { CCI_REG16(0x2a46), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xd704), 0x0278 }, + { CCI_REG16(0x7a0e), 0x0f00 }, + { CCI_REG16(0x7a6e), 0x1900 }, + { CCI_REG16(0x7a86), 0x1900 }, + { CCI_REG16(0x8c9e), 0x3500 }, + { CCI_REG16(0x8cce), 0x9600 }, + { CCI_REG16(0x7a10), 0x0f00 }, + { CCI_REG16(0x7a70), 0x1900 }, + { CCI_REG16(0x7a88), 0x1900 }, + { CCI_REG16(0x8ca0), 0x3500 }, + { CCI_REG16(0x8cd0), 0x9600 }, + { CCI_REG16(0xb224), 0x0103 }, + { CCI_REG16(0xb226), 0x0000 }, + { CCI_REG16(0xb220), 0x0103 }, + { CCI_REG16(0x7a12), 0x0f00 }, + { CCI_REG16(0x7a72), 0x1900 }, + { CCI_REG16(0x7a8a), 0x1900 }, + { CCI_REG16(0x8ca2), 0x5000 }, + { CCI_REG16(0x8cd2), 0xbe00 }, + { CCI_REG16(0x7ee6), 0x2c00 }, + { CCI_REG16(0x7ef2), 0x2c00 }, + { CCI_REG16(0x7efe), 0x6400 }, + { CCI_REG16(0x7f0a), 0x5800 }, + { CCI_REG16(0x8d0e), 0x0000 }, + { CCI_REG16(0x9032), 0x0000 }, + { CCI_REG16(0x903e), 0x0000 }, + { CCI_REG16(0x7a14), 0x0f00 }, + { CCI_REG16(0x7a74), 0x1900 }, + { CCI_REG16(0x7a8c), 0x1900 }, + { CCI_REG16(0x8ca4), 0x3500 }, + { CCI_REG16(0x7f0e), 0x5800 }, + { CCI_REG16(0x8cd6), 0x9600 }, + { CCI_REG16(0x7bda), 0x4c00 }, + { CCI_REG16(0xd49c), 0x2100 }, + { CCI_REG16(0xd4d0), 0x0a00 }, + { CCI_REG16(0xd4a8), 0x0100 }, + { CCI_REG16(0xd4d6), 0x1a00 }, + { CCI_REG16(0xd4e2), 0x0000 }, + { CCI_REG16(0xd4bc), 0x3700 }, + { CCI_REG16(0xd4b0), 0x9603 }, + { CCI_REG16(0xd4c8), 0x0100 }, + { CCI_REG16(0xd624), 0x0000 }, + { CCI_REG16(0xd62e), 0x0000 }, + { CCI_REG16(0xd638), 0x0000 }, + { CCI_REG16(0xd4ea), 0x0100 }, + { CCI_REG16(0xd554), 0xc400 }, + { CCI_REG16(0xd556), 0xc400 }, + { CCI_REG16(0xd560), 0x5203 }, + { CCI_REG16(0xd562), 0x5203 }, + { CCI_REG16(0xd4da), 0x0000 }, + { CCI_REG16(0xd4e6), 0x0100 }, + { CCI_REG16(0xd4c0), 0x1400 }, + { CCI_REG16(0xd4b4), 0x0100 }, + { CCI_REG16(0xd4cc), 0x0000 }, + { CCI_REG16(0xd5bc), 0x0000 }, + { CCI_REG16(0xd5be), 0x0000 }, + { CCI_REG16(0xd5c8), 0x0000 }, + { CCI_REG16(0xd5ca), 0x0000 }, + { CCI_REG16(0xd4d2), 0x0000 }, + { CCI_REG16(0xd4de), 0x0100 }, + { CCI_REG16(0xd4b8), 0x1400 }, + { CCI_REG16(0xd4ac), 0x0100 }, + { CCI_REG16(0xd4c4), 0x0000 }, + { CCI_REG16(0xd4ec), 0x0000 }, + { CCI_REG16(0xd4ee), 0x0000 }, + { CCI_REG16(0xd4f8), 0x0000 }, + { CCI_REG16(0xd4fa), 0x0000 }, + { CCI_REG16(0xbf78), 0x5333 }, + { CCI_REG16(0xd896), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x1c24), 0x0002 }, + { CCI_REG16(0x1c26), 0x8001 }, + { CCI_REG16(0x1c28), 0x8004 }, + { CCI_REG16(0x1c2a), 0x2010 }, + { CCI_REG16(0x1c2c), 0x2010 }, + { CCI_REG16(0x1c2e), 0x0005 }, + { CCI_REG16(0x1c30), 0x00a0 }, + { CCI_REG16(0x1c32), 0x2810 }, + { CCI_REG16(0x1c34), 0x2810 }, + { CCI_REG16(0x1c4e), 0x8001 }, + { CCI_REG16(0x1c50), 0x8004 }, + { CCI_REG16(0x1c52), 0x0010 }, + { CCI_REG16(0x1c54), 0x0010 }, + { CCI_REG16(0x1c56), 0x0005 }, + { CCI_REG16(0x1c58), 0x00a0 }, + { CCI_REG16(0x1c5a), 0x2810 }, + { CCI_REG16(0x1c5c), 0x2810 }, + { CCI_REG16(0x1c5e), 0x0000 }, + { CCI_REG16(0x1c60), 0x0000 }, + { CCI_REG16(0x1c62), 0x0000 }, + { CCI_REG16(0x1c64), 0x0000 }, + { CCI_REG16(0x1c66), 0x0000 }, + { CCI_REG16(0x1c68), 0x0000 }, + { CCI_REG16(0x1c6a), 0x0000 }, + { CCI_REG16(0x1c6c), 0x0000 }, + { CCI_REG16(0x1c76), 0x8001 }, + { CCI_REG16(0x1c78), 0x8004 }, + { CCI_REG16(0x1c7a), 0x2010 }, + { CCI_REG16(0x1c7c), 0x2010 }, + { CCI_REG16(0x1c7e), 0x0005 }, + { CCI_REG16(0x1c80), 0x00a0 }, + { CCI_REG16(0x1c82), 0x2810 }, + { CCI_REG16(0x1c84), 0x2810 }, + { CCI_REG16(0x1c86), 0x0000 }, + { CCI_REG16(0x1c88), 0x0000 }, + { CCI_REG16(0x1c8a), 0x0000 }, + { CCI_REG16(0x1c8c), 0x0000 }, + { CCI_REG16(0x1c8e), 0x0000 }, + { CCI_REG16(0x1c90), 0x0000 }, + { CCI_REG16(0x1c92), 0x0000 }, + { CCI_REG16(0x1c94), 0x0000 }, + { CCI_REG16(0x1c9e), 0x8001 }, + { CCI_REG16(0x1ca0), 0x8004 }, + { CCI_REG16(0x1ca2), 0x2010 }, + { CCI_REG16(0x1ca4), 0x2010 }, + { CCI_REG16(0x1ca6), 0x0005 }, + { CCI_REG16(0x1ca8), 0x00a0 }, + { CCI_REG16(0x1caa), 0x2810 }, + { CCI_REG16(0x1cac), 0x2810 }, + { CCI_REG16(0x1cc6), 0x8001 }, + { CCI_REG16(0x1cc8), 0x8004 }, + { CCI_REG16(0x1cca), 0x2010 }, + { CCI_REG16(0x1ccc), 0x2010 }, + { CCI_REG16(0x1cce), 0x0005 }, + { CCI_REG16(0x1cd0), 0x00a0 }, + { CCI_REG16(0x1cd2), 0x2810 }, + { CCI_REG16(0x1cd4), 0x2810 }, + { CCI_REG16(0x1cee), 0x8001 }, + { CCI_REG16(0x1cf0), 0x8004 }, + { CCI_REG16(0x1cf2), 0x0010 }, + { CCI_REG16(0x1cf4), 0x0010 }, + { CCI_REG16(0x1cf6), 0x0005 }, + { CCI_REG16(0x1cf8), 0x00a0 }, + { CCI_REG16(0x1cfa), 0x2810 }, + { CCI_REG16(0x1cfc), 0x2810 }, + { CCI_REG16(0x1cfe), 0x0000 }, + { CCI_REG16(0x1d00), 0x0000 }, + { CCI_REG16(0x1d02), 0x0000 }, + { CCI_REG16(0x1d04), 0x0000 }, + { CCI_REG16(0x1d06), 0x0000 }, + { CCI_REG16(0x1d08), 0x0000 }, + { CCI_REG16(0x1d0a), 0x0000 }, + { CCI_REG16(0x1d0c), 0x0000 }, + { CCI_REG16(0x1d16), 0x8001 }, + { CCI_REG16(0x1d18), 0x8004 }, + { CCI_REG16(0x1d1a), 0x2010 }, + { CCI_REG16(0x1d1c), 0x2010 }, + { CCI_REG16(0x1d1e), 0x0005 }, + { CCI_REG16(0x1d20), 0x00a0 }, + { CCI_REG16(0x1d22), 0x2810 }, + { CCI_REG16(0x1d24), 0x2810 }, + { CCI_REG16(0x1d26), 0x0000 }, + { CCI_REG16(0x1d28), 0x0000 }, + { CCI_REG16(0x1d2a), 0x0000 }, + { CCI_REG16(0x1d2c), 0x0000 }, + { CCI_REG16(0x1d2e), 0x0000 }, + { CCI_REG16(0x1d30), 0x0000 }, + { CCI_REG16(0x1d32), 0x0000 }, + { CCI_REG16(0x1d34), 0x0000 }, + { CCI_REG16(0x1d3e), 0x8001 }, + { CCI_REG16(0x1d40), 0x8004 }, + { CCI_REG16(0x1d42), 0x2010 }, + { CCI_REG16(0x1d44), 0x2010 }, + { CCI_REG16(0x1d46), 0x0005 }, + { CCI_REG16(0x1d48), 0x00a0 }, + { CCI_REG16(0x1d4a), 0x2810 }, + { CCI_REG16(0x1d4c), 0x2810 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xb21e), 0x0000 }, + { CCI_REG16(0xb222), 0xc000 }, + { CCI_REG16(0xb20c), 0x2e00 }, + { CCI_REG16(0xb21a), 0x0402 }, + { CCI_REG16(0xb378), 0x0100 }, + { CCI_REG16(0xdd70), 0x0000 }, + { CCI_REG16(0xde38), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2002 }, + { CCI_REG16(0xa574), 0x0100 }, + { CCI_REG16(0xa59c), 0xa2fd }, + { CCI_REG16(0xa59e), 0xfefe }, + { CCI_REG16(0xa576), 0x4000 }, + { CCI_REG16(0xa588), 0x0e00 }, + { CCI_REG16(0xa578), 0x8000 }, + { CCI_REG16(0xa58a), 0x2000 }, + { CCI_REG16(0xa57a), 0xa000 }, + { CCI_REG16(0xa58c), 0x2800 }, + { CCI_REG16(0xa57c), 0x4001 }, + { CCI_REG16(0xa58e), 0x1400 }, + { CCI_REG16(0xa57e), 0x8002 }, + { CCI_REG16(0xa590), 0x2200 }, + { CCI_REG16(0xa580), 0x0005 }, + { CCI_REG16(0xa592), 0x2800 }, + { CCI_REG16(0xa582), 0x000a }, + { CCI_REG16(0xa594), 0x2c00 }, + { CCI_REG16(0xa584), 0xa00f }, + { CCI_REG16(0xa596), 0x2e00 }, + { CCI_REG16(0xa586), 0x4011 }, + { CCI_REG16(0xa598), 0x3200 }, + { CCI_REG16(0xa59a), 0x3800 }, + { CCI_REG16(0xa548), 0x0000 }, + { CCI_REG16(0xa570), 0x0000 }, + { CCI_REG16(0xa54a), 0x0000 }, + { CCI_REG16(0xa54c), 0x0000 }, + { CCI_REG16(0xa54e), 0x0000 }, + { CCI_REG16(0xa550), 0x0000 }, + { CCI_REG16(0xa552), 0x0000 }, + { CCI_REG16(0xa554), 0x0000 }, + { CCI_REG16(0xa556), 0x0000 }, + { CCI_REG16(0xa55c), 0x0000 }, + { CCI_REG16(0xa55e), 0x0000 }, + { CCI_REG16(0xa560), 0x0000 }, + { CCI_REG16(0xa562), 0x0000 }, + { CCI_REG16(0xa564), 0x0000 }, + { CCI_REG16(0xa566), 0x0000 }, + { CCI_REG16(0xa568), 0x0000 }, + { CCI_REG16(0xa56a), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x1e16), 0x0000 }, + { CCI_REG16(0x1e1e), 0x0000 }, + { CCI_REG16(0x1e56), 0x0000 }, + { CCI_REG16(0x1e5e), 0x0000 }, + { CCI_REG16(0x1df2), 0x0000 }, + { CCI_REG16(0x1dfa), 0x0000 }, + { CCI_REG16(0x1e32), 0x0000 }, + { CCI_REG16(0x1e3a), 0x0000 }, + { CCI_REG16(0x1e12), 0x0000 }, + { CCI_REG16(0x1e1a), 0x0000 }, + { CCI_REG16(0x1e52), 0x0000 }, + { CCI_REG16(0x1e5a), 0x0000 }, + { CCI_REG16(0x1df6), 0x0000 }, + { CCI_REG16(0x1dfe), 0x0000 }, + { CCI_REG16(0x1e36), 0x0000 }, + { CCI_REG16(0x1e3e), 0x0000 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0x82ba), 0x3300 }, + { CCI_REG16(0x82a2), 0x1400 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x427c), 0x2000 }, + { CCI_REG16(0x4280), 0x1000 }, + { CCI_REG16(0x4362), 0x0100 }, + { CCI_REG16(0x43aa), 0x0000 }, + { CCI_REG16(0x43ac), 0x0000 }, + { CCI_REG16(0x43c6), 0x010a }, + { CCI_REG16(0x43b4), 0x0000 }, + { CCI_REG16(0x43b6), 0x0000 }, + { CCI_REG16(0x4396), 0x0d00 }, + { CCI_REG16(0x4398), 0x0e00 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xb322), 0x0101 }, + { CCI_REG16(0xb324), 0x0100 }, + { CCI_REG16(0xb330), 0x2828 }, + { CCI_REG16(0xb34a), 0x2828 }, + { CCI_REG16(0xb360), 0x2828 }, + { CCI_REG16(0xfcfc), 0x2001 }, + { CCI_REG16(0x4292), 0x0000 }, + { CCI_REG16(0x4364), 0x0000 }, + { CCI_REG16(0x4366), 0x0000 }, + { CCI_REG16(0x4370), 0x0000 }, + { CCI_REG16(0x4290), 0x0100 }, + { CCI_REG16(0xfcfc), 0x2002 }, + { CCI_REG16(0x84c4), 0x0100 }, + { CCI_REG16(0xfcfc), 0x2000 }, + { CCI_REG16(0xd684), 0x80f3 }, + { CCI_REG16(0xb268), 0x80f3 }, + { CCI_REG16(0xf09a), 0x00ff }, + { CCI_REG16(0xf2e0), 0x0000 }, + { CCI_REG16(0xf372), 0x0000 }, + { CCI_REG16(0xf0aa), 0xffff }, + { CCI_REG16(0xf0ac), 0xffff }, + { CCI_REG16(0xf2ea), 0x4000 }, + { CCI_REG16(0xdada), 0x0001 }, + { CCI_REG16(0xdb3c), 0x12d2 }, + { CCI_REG16(0xdadc), 0x0000 }, + { CCI_REG16(0xdb0c), 0x0000 }, + { CCI_REG16(0xdb3e), 0x12d2 }, + { CCI_REG16(0xdade), 0x4000 }, + { CCI_REG16(0xdb0e), 0x0040 }, + { CCI_REG16(0xdb40), 0x12d2 }, + { CCI_REG16(0xdae0), 0xe001 }, + { CCI_REG16(0xdb10), 0x0000 }, + { CCI_REG16(0xdb42), 0x12d2 }, + { CCI_REG16(0xdae2), 0x2003 }, + { CCI_REG16(0xdb12), 0x00b0 }, + { CCI_REG16(0xdb44), 0x12d2 }, + { CCI_REG16(0xdae4), 0x8007 }, + { CCI_REG16(0xdb14), 0x00d0 }, + { CCI_REG16(0xdb46), 0x12d2 }, + { CCI_REG16(0xdae6), 0x000b }, + { CCI_REG16(0xdb16), 0x00f0 }, + { CCI_REG16(0xdbcc), 0x0000 }, + { CCI_REG16(0xdb6c), 0x0000 }, + { CCI_REG16(0xdb9c), 0x0000 }, + { CCI_REG16(0xdbce), 0x0000 }, + { CCI_REG16(0xdb6e), 0x0000 }, + { CCI_REG16(0xdb9e), 0x0000 }, + { CCI_REG16(0xdbd0), 0x0000 }, + { CCI_REG16(0xdb70), 0x0000 }, + { CCI_REG16(0xdba0), 0x0000 }, + { CCI_REG16(0xdbd2), 0x0000 }, + { CCI_REG16(0xdb72), 0x0000 }, + { CCI_REG16(0xdba2), 0x0000 }, + { CCI_REG16(0xdbd4), 0x0000 }, + { CCI_REG16(0xdb74), 0x0000 }, + { CCI_REG16(0xdba4), 0x0000 }, + { CCI_REG16(0xdbd6), 0x0000 }, + { CCI_REG16(0xdb76), 0x0000 }, + { CCI_REG16(0xdba6), 0x0000 }, + { CCI_REG16(0xf370), 0x0203 }, + { CCI_REG16(0xf3e4), 0x0301 }, + { CCI_REG16(0xf3f4), 0x7310 }, + { CCI_REG16(0xf3f6), 0x1f20 }, + { CCI_REG16(0xf014), 0x0600 }, + { CCI_REG16(0xb270), 0x8708 }, + { CCI_REG16(0xb266), 0xc004 }, + { CCI_REG16(0xd682), 0xc004 }, + { CCI_REG16(0xbf16), 0x0baa }, + { CCI_REG16(0xdc8c), 0x3f0b }, + { CCI_REG16(0xfcfc), 0x4000 }, + { CCI_REG16(0x0808), 0x0000 }, + { CCI_REG16(0x0e00), 0x0003 }, +}; + +static const struct s5kjn5_mode s5kjn5_modes[] = { + { + .width = 4096, + .height = 3072, + .hts = 5800, + .vts_min = 5296, + .pixel_rate = 998400000ULL, + .exposure_margin = 12, + .regs = s5kjn5_4096x3072_regs, + .num_regs = ARRAY_SIZE(s5kjn5_4096x3072_regs), + }, +}; + +struct s5kjn5 { + struct v4l2_subdev sd; + struct media_pad pad; + struct regmap *regmap; + struct clk *inclk; + struct gpio_desc *reset_gpio; + struct regulator_bulk_data supplies[S5KJN5_NUM_SUPPLIES]; + struct v4l2_ctrl_handler ctrl_handler; + struct v4l2_ctrl *link_freq; + struct v4l2_ctrl *pixel_rate; + struct v4l2_ctrl *vblank; + struct v4l2_ctrl *hblank; + struct v4l2_ctrl *exposure; + struct v4l2_ctrl *gain; + struct v4l2_ctrl *digital_gain; + struct v4l2_ctrl *test_pattern; +}; + +static inline struct s5kjn5 *sd_to_s5kjn5(struct v4l2_subdev *sd) +{ + return container_of(sd, struct s5kjn5, sd); +} + +static int s5kjn5_write_init(struct s5kjn5 *s5kjn5) +{ + const struct s5kjn5_init_op *op; + int ret; + + for (op = s5kjn5_init_ops; + op < s5kjn5_init_ops + ARRAY_SIZE(s5kjn5_init_ops); op++) { + if (op->burst) + ret = regmap_bulk_write(s5kjn5->regmap, op->burst_addr, + op->burst, op->burst_len); + else if (op->reg) + ret = cci_write(s5kjn5->regmap, op->reg, op->val, NULL); + else + ret = 0; + if (ret) + return ret; + + if (op->delay_us) + fsleep(op->delay_us); + } + + return 0; +} + +static int s5kjn5_power_on(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct s5kjn5 *s5kjn5 = sd_to_s5kjn5(sd); + int ret; + + ret = regulator_bulk_enable(S5KJN5_NUM_SUPPLIES, s5kjn5->supplies); + if (ret) { + dev_err(dev, "failed to enable regulators: %d\n", ret); + return ret; + } + + gpiod_set_value_cansleep(s5kjn5->reset_gpio, 0); + usleep_range(8000, 10000); + + ret = clk_prepare_enable(s5kjn5->inclk); + if (ret) { + dev_err(dev, "failed to enable clock: %d\n", ret); + gpiod_set_value_cansleep(s5kjn5->reset_gpio, 1); + goto err_regulators; + } + + usleep_range(10000, 12000); + + return 0; + +err_regulators: + regulator_bulk_disable(S5KJN5_NUM_SUPPLIES, s5kjn5->supplies); + return ret; +} + +static int s5kjn5_power_off(struct device *dev) +{ + struct v4l2_subdev *sd = dev_get_drvdata(dev); + struct s5kjn5 *s5kjn5 = sd_to_s5kjn5(sd); + + clk_disable_unprepare(s5kjn5->inclk); + gpiod_set_value_cansleep(s5kjn5->reset_gpio, 1); + regulator_bulk_disable(S5KJN5_NUM_SUPPLIES, s5kjn5->supplies); + + return 0; +} + +static int s5kjn5_check_id(struct s5kjn5 *s5kjn5) +{ + struct device *dev = s5kjn5->sd.dev; + u64 chip_id; + int ret; + + ret = cci_read(s5kjn5->regmap, S5KJN5_REG_CHIP_ID, &chip_id, NULL); + if (ret) + return dev_err_probe(dev, ret, "failed to read chip ID\n"); + + if (chip_id != S5KJN5_CHIP_ID) + return dev_err_probe(dev, -ENODEV, + "unexpected chip ID 0x%04llx, expected 0x%04x\n", + chip_id, S5KJN5_CHIP_ID); + + return 0; +} + +static int s5kjn5_check_hwcfg(struct device *dev) +{ + struct fwnode_handle *fwnode = dev_fwnode(dev), *ep; + struct v4l2_fwnode_endpoint bus_cfg = { + .bus_type = V4L2_MBUS_CSI2_DPHY, + }; + unsigned long freq_bitmap; + int ret; + + if (!fwnode) + return -ENODEV; + + ep = fwnode_graph_get_next_endpoint(fwnode, NULL); + if (!ep) + return dev_err_probe(dev, -EINVAL, "no endpoint found\n"); + + ret = v4l2_fwnode_endpoint_alloc_parse(ep, &bus_cfg); + fwnode_handle_put(ep); + if (ret) + return dev_err_probe(dev, ret, "failed to parse endpoint\n"); + + if (bus_cfg.bus.mipi_csi2.num_data_lanes != S5KJN5_DATA_LANES) { + ret = dev_err_probe(dev, -EINVAL, + "only %u data lanes supported\n", + S5KJN5_DATA_LANES); + goto out; + } + + ret = v4l2_link_freq_to_bitmap(dev, bus_cfg.link_frequencies, + bus_cfg.nr_of_link_frequencies, + s5kjn5_link_freqs, + ARRAY_SIZE(s5kjn5_link_freqs), + &freq_bitmap); + +out: + v4l2_fwnode_endpoint_free(&bus_cfg); + + return ret; +} + +static int s5kjn5_init(struct s5kjn5 *s5kjn5, + const struct s5kjn5_mode *mode) +{ + int ret; + + ret = s5kjn5_write_init(s5kjn5); + if (ret) + return ret; + + return cci_multi_reg_write(s5kjn5->regmap, mode->regs, + mode->num_regs, NULL); +} + +static const char * const s5kjn5_test_pattern_menu[] = { + "Disabled", + "Solid Color", + "Color Bars", + "Fade To Grey Color Bars", + "PN9", +}; + +static int s5kjn5_s_ctrl(struct v4l2_ctrl *ctrl) +{ + struct s5kjn5 *s5kjn5 = + container_of(ctrl->handler, struct s5kjn5, ctrl_handler); + const struct s5kjn5_mode *mode = &s5kjn5_modes[0]; + struct device *dev = s5kjn5->sd.dev; + u32 exposure_max; + int ret = 0; + + if (ctrl->id == V4L2_CID_VBLANK) { + /* Update max exposure while meeting expected vblanking */ + exposure_max = mode->height + ctrl->val - mode->exposure_margin; + __v4l2_ctrl_modify_range(s5kjn5->exposure, + s5kjn5->exposure->minimum, + exposure_max, + s5kjn5->exposure->step, + s5kjn5->exposure->default_value); + } + + if (pm_runtime_get_if_active(dev) <= 0) + return 0; + + switch (ctrl->id) { + case V4L2_CID_EXPOSURE: + ret = cci_write(s5kjn5->regmap, S5KJN5_REG_EXPOSURE, + ctrl->val, NULL); + break; + + case V4L2_CID_ANALOGUE_GAIN: + ret = cci_write(s5kjn5->regmap, S5KJN5_REG_AGAIN, + ctrl->val, NULL); + break; + + case V4L2_CID_DIGITAL_GAIN: + ret = cci_write(s5kjn5->regmap, S5KJN5_REG_DGAIN, + ctrl->val, NULL); + break; + + case V4L2_CID_VBLANK: + ret = cci_write(s5kjn5->regmap, S5KJN5_REG_VTS, + mode->height + ctrl->val, NULL); + break; + + case V4L2_CID_TEST_PATTERN: + ret = cci_write(s5kjn5->regmap, S5KJN5_REG_TEST_PATTERN, + ctrl->val, NULL); + break; + + default: + ret = -EINVAL; + break; + } + + pm_runtime_put_autosuspend(dev); + + return ret; +} + +static const struct v4l2_ctrl_ops s5kjn5_ctrl_ops = { + .s_ctrl = s5kjn5_s_ctrl, +}; + +static int s5kjn5_init_controls(struct s5kjn5 *s5kjn5) +{ + const struct s5kjn5_mode *mode = &s5kjn5_modes[0]; + struct v4l2_ctrl_handler *hdlr = &s5kjn5->ctrl_handler; + struct v4l2_fwnode_device_properties props; + u32 vblank_min, vblank_def, vblank_max, hblank; + int ret; + + v4l2_ctrl_handler_init(hdlr, 10); + + s5kjn5->link_freq = + v4l2_ctrl_new_int_menu(hdlr, NULL, V4L2_CID_LINK_FREQ, + ARRAY_SIZE(s5kjn5_link_freqs) - 1, 0, + s5kjn5_link_freqs); + if (s5kjn5->link_freq) + s5kjn5->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + s5kjn5->pixel_rate = + v4l2_ctrl_new_std(hdlr, NULL, V4L2_CID_PIXEL_RATE, + mode->pixel_rate, mode->pixel_rate, 1, + mode->pixel_rate); + + vblank_min = mode->vts_min - mode->height; + vblank_def = mode->vts_min - mode->height; + vblank_max = S5KJN5_VTS_MAX - mode->height; + s5kjn5->vblank = + v4l2_ctrl_new_std(hdlr, &s5kjn5_ctrl_ops, V4L2_CID_VBLANK, + vblank_min, vblank_max, 1, vblank_def); + + hblank = mode->hts - mode->width; + s5kjn5->hblank = + v4l2_ctrl_new_std(hdlr, NULL, V4L2_CID_HBLANK, + hblank, hblank, 1, hblank); + if (s5kjn5->hblank) + s5kjn5->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY; + + s5kjn5->exposure = + v4l2_ctrl_new_std(hdlr, &s5kjn5_ctrl_ops, V4L2_CID_EXPOSURE, + S5KJN5_EXPOSURE_MIN, + mode->vts_min - mode->exposure_margin, + 1, S5KJN5_EXPOSURE_DEFAULT); + + s5kjn5->gain = + v4l2_ctrl_new_std(hdlr, &s5kjn5_ctrl_ops, + V4L2_CID_ANALOGUE_GAIN, + S5KJN5_AGAIN_MIN, S5KJN5_AGAIN_MAX, + S5KJN5_AGAIN_STEP, S5KJN5_AGAIN_DEFAULT); + + s5kjn5->digital_gain = + v4l2_ctrl_new_std(hdlr, &s5kjn5_ctrl_ops, + V4L2_CID_DIGITAL_GAIN, + S5KJN5_DGAIN_MIN, S5KJN5_DGAIN_MAX, + S5KJN5_DGAIN_STEP, S5KJN5_DGAIN_DEFAULT); + + s5kjn5->test_pattern = + v4l2_ctrl_new_std_menu_items(hdlr, &s5kjn5_ctrl_ops, + V4L2_CID_TEST_PATTERN, + ARRAY_SIZE(s5kjn5_test_pattern_menu) - 1, + 0, 0, s5kjn5_test_pattern_menu); + + ret = v4l2_fwnode_device_parse(s5kjn5->sd.dev, &props); + if (ret) { + v4l2_ctrl_handler_free(hdlr); + return ret; + } + + ret = v4l2_ctrl_new_fwnode_properties(hdlr, &s5kjn5_ctrl_ops, &props); + if (ret) { + v4l2_ctrl_handler_free(hdlr); + return ret; + } + + if (hdlr->error) { + ret = hdlr->error; + v4l2_ctrl_handler_free(hdlr); + return ret; + } + + s5kjn5->sd.ctrl_handler = hdlr; + + return 0; +} + +static int s5kjn5_enable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) +{ + struct s5kjn5 *s5kjn5 = sd_to_s5kjn5(sd); + struct device *dev = sd->dev; + const struct s5kjn5_mode *mode = &s5kjn5_modes[0]; + int ret; + + ret = pm_runtime_resume_and_get(dev); + if (ret < 0) + return ret; + + ret = s5kjn5_init(s5kjn5, mode); + if (ret) { + dev_err(dev, "failed to write init registers: %d\n", ret); + goto err_pm; + } + + ret = __v4l2_ctrl_handler_setup(&s5kjn5->ctrl_handler); + if (ret) + goto err_pm; + + ret = cci_write(s5kjn5->regmap, S5KJN5_REG_STREAMING, + S5KJN5_STREAMING_ON, NULL); + if (ret) { + dev_err(dev, "failed to start streaming: %d\n", ret); + goto err_pm; + } + + return 0; + +err_pm: + pm_runtime_put_autosuspend(dev); + return ret; +} + +static int s5kjn5_disable_streams(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + u32 pad, u64 streams_mask) +{ + struct s5kjn5 *s5kjn5 = sd_to_s5kjn5(sd); + struct device *dev = sd->dev; + u64 val; + int ret, i; + + ret = cci_write(s5kjn5->regmap, S5KJN5_REG_STREAMING, + S5KJN5_STREAMING_OFF, NULL); + if (ret) + dev_warn(dev, "failed to stop streaming: %d\n", ret); + + /* Poll frame count register until it reads standby */ + for (i = 0; i < S5KJN5_STANDBY_POLL_ITERS; i++) { + usleep_range(5000, 6000); + ret = cci_read(s5kjn5->regmap, S5KJN5_REG_FRAME_COUNT, + &val, NULL); + if (!ret && val == S5KJN5_FRAME_COUNT_STANDBY) + break; + } + if (i == S5KJN5_STANDBY_POLL_ITERS) + dev_warn(dev, "timed out waiting for standby\n"); + + pm_runtime_put_autosuspend(dev); + + return 0; +} + +static int s5kjn5_enum_mbus_code(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_mbus_code_enum *code) +{ + if (code->index != 0) + return -EINVAL; + + code->code = MEDIA_BUS_FMT_SGBRG10_1X10; + + return 0; +} + +static int s5kjn5_enum_frame_size(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_frame_size_enum *fse) +{ + if (fse->code != MEDIA_BUS_FMT_SGBRG10_1X10 || + fse->index >= ARRAY_SIZE(s5kjn5_modes)) + return -EINVAL; + + fse->min_width = s5kjn5_modes[fse->index].width; + fse->max_width = s5kjn5_modes[fse->index].width; + fse->min_height = s5kjn5_modes[fse->index].height; + fse->max_height = s5kjn5_modes[fse->index].height; + + return 0; +} + +static void s5kjn5_fill_format(const struct s5kjn5_mode *mode, + struct v4l2_mbus_framefmt *fmt) +{ + fmt->width = mode->width; + fmt->height = mode->height; + fmt->code = MEDIA_BUS_FMT_SGBRG10_1X10; + fmt->field = V4L2_FIELD_NONE; + fmt->colorspace = V4L2_COLORSPACE_RAW; + fmt->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; + fmt->quantization = V4L2_QUANTIZATION_DEFAULT; + fmt->xfer_func = V4L2_XFER_FUNC_NONE; +} + +static int s5kjn5_set_fmt(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state, + struct v4l2_subdev_format *fmt) +{ + const struct s5kjn5_mode *mode = &s5kjn5_modes[0]; + struct v4l2_mbus_framefmt *format; + + s5kjn5_fill_format(mode, &fmt->format); + + format = v4l2_subdev_state_get_format(state, 0); + *format = fmt->format; + + return 0; +} + +static int s5kjn5_init_state(struct v4l2_subdev *sd, + struct v4l2_subdev_state *state) +{ + struct v4l2_mbus_framefmt *fmt = + v4l2_subdev_state_get_format(state, 0); + + s5kjn5_fill_format(&s5kjn5_modes[0], fmt); + + return 0; +} + +static const struct v4l2_subdev_video_ops s5kjn5_video_ops = { + .s_stream = v4l2_subdev_s_stream_helper, +}; + +static const struct v4l2_subdev_pad_ops s5kjn5_pad_ops = { + .enum_mbus_code = s5kjn5_enum_mbus_code, + .enum_frame_size = s5kjn5_enum_frame_size, + .get_fmt = v4l2_subdev_get_fmt, + .set_fmt = s5kjn5_set_fmt, + .enable_streams = s5kjn5_enable_streams, + .disable_streams = s5kjn5_disable_streams, +}; + +static const struct v4l2_subdev_ops s5kjn5_subdev_ops = { + .video = &s5kjn5_video_ops, + .pad = &s5kjn5_pad_ops, +}; + +static const struct v4l2_subdev_internal_ops s5kjn5_internal_ops = { + .init_state = s5kjn5_init_state, +}; + +static const struct media_entity_operations s5kjn5_entity_ops = { + .link_validate = v4l2_subdev_link_validate, +}; + +static int s5kjn5_probe(struct i2c_client *client) +{ + struct device *dev = &client->dev; + struct s5kjn5 *s5kjn5; + unsigned int i; + int ret; + + s5kjn5 = devm_kzalloc(dev, sizeof(*s5kjn5), GFP_KERNEL); + if (!s5kjn5) + return -ENOMEM; + + ret = s5kjn5_check_hwcfg(dev); + if (ret) + return ret; + + v4l2_i2c_subdev_init(&s5kjn5->sd, client, &s5kjn5_subdev_ops); + + s5kjn5->inclk = devm_v4l2_sensor_clk_get(dev, NULL); + if (IS_ERR(s5kjn5->inclk)) + return dev_err_probe(dev, PTR_ERR(s5kjn5->inclk), + "failed to get clock\n"); + + if (clk_get_rate(s5kjn5->inclk) != S5KJN5_XVCLK_RATE) + return dev_err_probe(dev, -EINVAL, + "clock rate %lu Hz != required %u Hz\n", + clk_get_rate(s5kjn5->inclk), + S5KJN5_XVCLK_RATE); + + s5kjn5->reset_gpio = devm_gpiod_get_optional(dev, "reset", + GPIOD_OUT_HIGH); + if (IS_ERR(s5kjn5->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(s5kjn5->reset_gpio), + "failed to get reset GPIO\n"); + + for (i = 0; i < S5KJN5_NUM_SUPPLIES; i++) + s5kjn5->supplies[i].supply = s5kjn5_supply_names[i]; + + ret = devm_regulator_bulk_get(dev, S5KJN5_NUM_SUPPLIES, + s5kjn5->supplies); + if (ret) + return dev_err_probe(dev, ret, + "failed to get regulators\n"); + + s5kjn5->regmap = devm_cci_regmap_init_i2c(client, 16); + if (IS_ERR(s5kjn5->regmap)) + return dev_err_probe(dev, PTR_ERR(s5kjn5->regmap), + "failed to init CCI regmap\n"); + + ret = s5kjn5_power_on(dev); + if (ret) + return dev_err_probe(dev, ret, "failed to power on\n"); + + ret = s5kjn5_check_id(s5kjn5); + if (ret) + goto err_power_off; + + ret = s5kjn5_init_controls(s5kjn5); + if (ret) + goto err_power_off; + + s5kjn5->sd.internal_ops = &s5kjn5_internal_ops; + s5kjn5->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; + s5kjn5->sd.entity.ops = &s5kjn5_entity_ops; + s5kjn5->sd.entity.function = MEDIA_ENT_F_CAM_SENSOR; + s5kjn5->pad.flags = MEDIA_PAD_FL_SOURCE; + + ret = media_entity_pads_init(&s5kjn5->sd.entity, 1, &s5kjn5->pad); + if (ret) + goto err_controls; + + s5kjn5->sd.state_lock = s5kjn5->ctrl_handler.lock; + + ret = v4l2_subdev_init_finalize(&s5kjn5->sd); + if (ret) + goto err_entity; + + pm_runtime_set_active(dev); + pm_runtime_enable(dev); + + ret = v4l2_async_register_subdev_sensor(&s5kjn5->sd); + if (ret) { + dev_err(dev, "failed to register subdev: %d\n", ret); + goto err_pm; + } + + pm_runtime_set_autosuspend_delay(dev, 1000); + pm_runtime_use_autosuspend(dev); + pm_runtime_idle(dev); + + dev_info(dev, "S5KJN5 sensor detected (chip ID 0x%04x)\n", + S5KJN5_CHIP_ID); + + return 0; + +err_pm: + pm_runtime_disable(dev); + pm_runtime_set_suspended(dev); +err_entity: + media_entity_cleanup(&s5kjn5->sd.entity); + v4l2_subdev_cleanup(&s5kjn5->sd); +err_controls: + v4l2_ctrl_handler_free(&s5kjn5->ctrl_handler); +err_power_off: + s5kjn5_power_off(dev); + return ret; +} + +static void s5kjn5_remove(struct i2c_client *client) +{ + struct v4l2_subdev *sd = i2c_get_clientdata(client); + struct device *dev = &client->dev; + + v4l2_async_unregister_subdev(sd); + v4l2_subdev_cleanup(sd); + v4l2_ctrl_handler_free(sd->ctrl_handler); + media_entity_cleanup(&sd->entity); + + pm_runtime_dont_use_autosuspend(dev); + pm_runtime_disable(dev); + + if (!pm_runtime_status_suspended(dev)) { + s5kjn5_power_off(dev); + pm_runtime_set_suspended(dev); + } +} + +static const struct dev_pm_ops s5kjn5_pm_ops = { + SET_RUNTIME_PM_OPS(s5kjn5_power_off, s5kjn5_power_on, NULL) +}; + +static const struct of_device_id s5kjn5_of_match[] = { + { .compatible = "samsung,s5kjn5" }, + { } +}; +MODULE_DEVICE_TABLE(of, s5kjn5_of_match); + +static struct i2c_driver s5kjn5_i2c_driver = { + .driver = { + .name = "s5kjn5", + .pm = pm_ptr(&s5kjn5_pm_ops), + .of_match_table = s5kjn5_of_match, + }, + .probe = s5kjn5_probe, + .remove = s5kjn5_remove, +}; + +module_i2c_driver(s5kjn5_i2c_driver); + +MODULE_AUTHOR("Wenmeng Liu "); +MODULE_DESCRIPTION("Samsung S5KJN5 50 MP GBRG 10-bit RAW sensor driver"); +MODULE_LICENSE("GPL"); From a84eccab64424499970a99c61207b2a3733d4e91 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 14 Aug 2026 11:15:39 +0800 Subject: [PATCH 50/53] Revert "FROMLIST: dt-bindings: media: Add bindings for qcom,x1p42100-camss" This reverts commit 2c06f1f8c80404a40a96e283559935b1042d5799. --- .../bindings/media/qcom,x1p42100-camss.yaml | 424 ------------------ 1 file changed, 424 deletions(-) delete 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 deleted file mode 100644 index 8bfa7e616c3b6..0000000000000 --- a/Documentation/devicetree/bindings/media/qcom,x1p42100-camss.yaml +++ /dev/null @@ -1,424 +0,0 @@ -# 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 d9ffc5a596bcbe3b763fc3b100baeb5d01eacb54 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 14 Aug 2026 11:17:26 +0800 Subject: [PATCH 51/53] Revert "FROMLIST: media: qcom: camss: add support for X1P42100 camss" This reverts commit ca32238f45c5674c83a93fe19c1dbe58f9a6bad9. --- .../qcom/camss/camss-csiphy-3ph-1-0.c | 6 +- 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, 4 insertions(+), 114 deletions(-) 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 82aaeffffbfab..7502c2943999e 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 @@ -1680,7 +1680,6 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_GLYMUR: case CAMSS_KAANAPALI: case CAMSS_X1E80100: - case CAMSS_X1P42100: ret = true; break; } @@ -1901,7 +1900,10 @@ static int csiphy_init(struct csiphy_device *csiphy) switch (csiphy->camss->res->version) { case CAMSS_GLYMUR: 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; + break; case CAMSS_8550: case CAMSS_8650: regs->offset = 0x1000; diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c index c12814085b077..90b96d052f97c 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -358,7 +358,6 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_GLYMUR: case CAMSS_KAANAPALI: case CAMSS_X1E80100: - case CAMSS_X1P42100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: { @@ -2025,7 +2024,6 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_GLYMUR: case CAMSS_KAANAPALI: 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 10631c7360d27..253137c5d942c 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5198,98 +5198,6 @@ 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 - }, - }, -}; - static const struct camss_subdev_resources csiphy_res_glymur[] = { /* CSIPHY0 */ { @@ -6681,22 +6589,6 @@ 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 camss_resources glymur_resources = { .version = CAMSS_GLYMUR, .pd_name = "top", @@ -6737,7 +6629,6 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sm8650-camss", .data = &sm8650_resources }, { .compatible = "qcom,sm8750-camss", .data = &sm8750_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 b447815b353f3..44b4c4af123b1 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -101,7 +101,6 @@ enum camss_version { CAMSS_GLYMUR, CAMSS_KAANAPALI, CAMSS_X1E80100, - CAMSS_X1P42100, }; enum icc_count { From 95061575b8056831474e15f23ad69c5bb09a1bf2 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:31 +0800 Subject: [PATCH 52/53] PENDING: 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 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 eb66f07a711fe79a325dc67e5c10ca90a4517d28 Mon Sep 17 00:00:00 2001 From: Wenmeng Liu Date: Fri, 10 Apr 2026 12:25:32 +0800 Subject: [PATCH 53/53] PENDING: 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. 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 7502c2943999e..5e11999ec6245 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 @@ -1680,6 +1680,7 @@ static bool csiphy_is_gen2(u32 version) case CAMSS_GLYMUR: case CAMSS_KAANAPALI: case CAMSS_X1E80100: + case CAMSS_X1P42100: ret = true; break; } @@ -1900,6 +1901,7 @@ static int csiphy_init(struct csiphy_device *csiphy) switch (csiphy->camss->res->version) { case CAMSS_GLYMUR: 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 90b96d052f97c..c12814085b077 100644 --- a/drivers/media/platform/qcom/camss/camss-vfe.c +++ b/drivers/media/platform/qcom/camss/camss-vfe.c @@ -358,6 +358,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code, case CAMSS_GLYMUR: case CAMSS_KAANAPALI: case CAMSS_X1E80100: + case CAMSS_X1P42100: switch (sink_code) { case MEDIA_BUS_FMT_YUYV8_1X16: { @@ -2024,6 +2025,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe) case CAMSS_GLYMUR: case CAMSS_KAANAPALI: 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 253137c5d942c..10631c7360d27 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -5198,6 +5198,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 + }, + }, +}; + static const struct camss_subdev_resources csiphy_res_glymur[] = { /* CSIPHY0 */ { @@ -6589,6 +6681,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 camss_resources glymur_resources = { .version = CAMSS_GLYMUR, .pd_name = "top", @@ -6629,6 +6737,7 @@ static const struct of_device_id camss_dt_match[] = { { .compatible = "qcom,sm8650-camss", .data = &sm8650_resources }, { .compatible = "qcom,sm8750-camss", .data = &sm8750_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 44b4c4af123b1..b447815b353f3 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -101,6 +101,7 @@ enum camss_version { CAMSS_GLYMUR, CAMSS_KAANAPALI, CAMSS_X1E80100, + CAMSS_X1P42100, }; enum icc_count {