From ae85c074103db214c843f86f2694b3e80c6cd2fc Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:19 +0200 Subject: [PATCH 01/15] 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 babf7e663bdd3..a3c9b5980528f 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 @@ -999,7 +999,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 b8f134584c550420e3b2449f3d5722f1aae1a24c Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:20 +0200 Subject: [PATCH 02/15] 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 3a45271c33a62..bb109e05bedde 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4576,9 +4576,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 ef27754fa1a3e0dba449ec1fbefdbfb49612fbda Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:21 +0200 Subject: [PATCH 03/15] 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 a3c9b5980528f..348367e1e59f8 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)) @@ -993,13 +994,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; } @@ -1041,10 +1051,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 2d1b59994adbc7ebb6d39b274d173d31686e9806 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:22 +0200 Subject: [PATCH 04/15] 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 2a1746dcc1c5b..fd8d47a310dfb 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 5296b10f6bac8..e65590b0df69f 100644 --- a/drivers/media/platform/qcom/camss/camss-csid.h +++ b/drivers/media/platform/qcom/camss/camss-csid.h @@ -44,6 +44,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; @@ -70,6 +75,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 84ea60f9ae13b4ae15161921393d3f7734df30a7 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:23 +0200 Subject: [PATCH 05/15] 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 | 121 +++++++++++++----- 1 file changed, 86 insertions(+), 35 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 348367e1e59f8..e091579664802 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 @@ -1049,6 +1049,91 @@ 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_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_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; + 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); @@ -1101,51 +1186,17 @@ 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_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_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; default: + regs->offset = 0x800; break; } From 24ec131b78dbab3d4a444f77ade2cf2142864128 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:24 +0200 Subject: [PATCH 06/15] 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 e091579664802..ea490959fd2a5 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[] = { @@ -1055,8 +1129,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 9f324bf2af0ff62904654f836e8b4c429207d97c Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:25 +0200 Subject: [PATCH 07/15] 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 ea490959fd2a5..6c38f1fb1eb16 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 63e250209fc090daeb7bedff909b807dba9a10ff Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:26 +0200 Subject: [PATCH 08/15] 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 b9f7d6573a0f0..66ae6d9610661 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 bb109e05bedde..12be716956942 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_8x16[] = { @@ -4434,19 +4442,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 0e49aaba3438e..fc79e24f98f9e 100644 --- a/drivers/media/platform/qcom/camss/camss.h +++ b/drivers/media/platform/qcom/camss/camss.h @@ -171,7 +171,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 ecae214433421497d4e8ea9421ceddada9d2de06 Mon Sep 17 00:00:00 2001 From: David Heidelberg Date: Wed, 17 Jun 2026 10:32:27 +0200 Subject: [PATCH 09/15] 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 12be716956942..ac76674bfd8cb 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4575,11 +4575,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 a6eeb6b0b1281a8f1a375aa6263dad27dbe6b319 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 17 Jul 2026 16:13:26 -0700 Subject: [PATCH 10/15] 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 6c38f1fb1eb16..9a8a6aba6d5bc 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 @@ -911,8 +911,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) @@ -1217,9 +1215,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 80a3e017ca0349577f7f0d422c857b70cf7124e2 Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 17 Jul 2026 16:13:27 -0700 Subject: [PATCH 11/15] 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 222765fe7914d..10d571127ff6d 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) @@ -115,6 +116,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 edebe134e2e1897f49f70d5f4eea9eacf8ddd1da Mon Sep 17 00:00:00 2001 From: Jigarkumar Zala Date: Fri, 17 Jul 2026 16:13:28 -0700 Subject: [PATCH 12/15] 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 9a8a6aba6d5bc..5d71caabbbf59 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 @@ -1189,7 +1290,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); @@ -1198,6 +1298,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 3c787ee935da9f1da5b0f45c98572adddcb659d0 Mon Sep 17 00:00:00 2001 From: Anusha Arun Nandi Date: Fri, 17 Jul 2026 16:13:29 -0700 Subject: [PATCH 13/15] 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 --- drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c | 9 +-------- 1 file changed, 1 insertion(+), 8 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 5d71caabbbf59..26aa471ead8b2 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 @@ -1289,15 +1289,8 @@ 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_8300: case CAMSS_8775P: if (c->phy_cfg == V4L2_MBUS_CSI2_CPHY) { regs->lane_regs = &lane_regs_sa8775p_3ph[0]; From 1e891c71eebba9a49053c1369b5583639444988a Mon Sep 17 00:00:00 2001 From: Anusha Arun Nandi Date: Fri, 17 Jul 2026 16:13:30 -0700 Subject: [PATCH 14/15] 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 26aa471ead8b2..fe88f0db8e104 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 @@ -1137,6 +1319,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) { @@ -1217,6 +1453,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; @@ -1295,6 +1533,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); @@ -1358,6 +1598,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 de05558f3f46ada9757c628e54feaad7c54df0d1 Mon Sep 17 00:00:00 2001 From: Anusha Arun Nandi Date: Fri, 17 Jul 2026 16:13:31 -0700 Subject: [PATCH 15/15] 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 ac76674bfd8cb..ee592a1633552 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -4567,7 +4567,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; @@ -4584,6 +4586,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;