[PATCH v6 7/7] media: qcom: camss: tpg: Add support for v2.3.0 TPG

From: Hangxiang Ma

Date: Tue Jul 21 2026 - 08:47:49 EST


Add support for the TPG found on SM8750. This TPG uses hardware version
2.3.0, which drives test-enable and reset through a separate
TPG_CTRL_CMD register instead of TPG_CTRL, and routes its output into
the CSID 980 RX via the CSI2 TPG mux.

The 2.3.0 and 2.4.0 (Kaanapali) TPGs share the same programming model,
so reuse the Kaanapali TPG resources for SM8750 and lower the hardware
version gate in the TPG gen1 driver from 2.4.0 to 2.3.0.

Signed-off-by: Hangxiang Ma <hangxiang.ma@xxxxxxxxxxxxxxxx>
---
drivers/media/platform/qcom/camss/camss-csid-980.c | 15 +++++++++++++--
drivers/media/platform/qcom/camss/camss-tpg-gen1.c | 9 +++++----
drivers/media/platform/qcom/camss/camss.c | 2 ++
3 files changed, 20 insertions(+), 6 deletions(-)

diff --git a/drivers/media/platform/qcom/camss/camss-csid-980.c b/drivers/media/platform/qcom/camss/camss-csid-980.c
index 6714b8aa8c2a..16184fe69398 100644
--- a/drivers/media/platform/qcom/camss/camss-csid-980.c
+++ b/drivers/media/platform/qcom/camss/camss-csid-980.c
@@ -68,6 +68,8 @@
#define CSI2_RX_CFG0_PHY_SEL_BASE_IDX 1
#define CSI2_RX_CFG0_DL0_INPUT_SEL 4
#define CSI2_RX_CFG0_PHY_NUM_SEL 20
+#define CSI2_RX_CFG0_TPG_MUX_EN BIT(27)
+#define CSI2_RX_CFG0_TPG_MUX_SEL GENMASK(29, 28)
#define CSID_CSI2_RX_CFG1 (csid_is_lite(csid) ? 0x204 : 0x404)
#define CSI2_RX_CFG1_ECC_CORRECTION_EN BIT(0)
#define CSI2_RX_CFG1_VC_MODE BIT(2)
@@ -183,12 +185,21 @@ static void __csid_aup_rup_clear(struct csid_device *csid, int port_id)
static void __csid_configure_rx(struct csid_device *csid,
struct csid_phy_config *phy)
{
+ struct camss *camss = csid->camss;
int val;

val = (phy->lane_cnt - 1) << CSI2_RX_CFG0_NUM_ACTIVE_LANES;
val |= phy->lane_assign << CSI2_RX_CFG0_DL0_INPUT_SEL;
- val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX)
- << CSI2_RX_CFG0_PHY_NUM_SEL;
+
+ if (camss->tpg && csid->tpg_linked &&
+ camss->tpg[phy->csiphy_id].testgen.mode != TPG_PAYLOAD_MODE_DISABLED) {
+ val |= FIELD_PREP(CSI2_RX_CFG0_TPG_MUX_SEL, phy->csiphy_id + 1);
+ val |= CSI2_RX_CFG0_TPG_MUX_EN;
+ } else {
+ val |= (phy->csiphy_id + CSI2_RX_CFG0_PHY_SEL_BASE_IDX)
+ << CSI2_RX_CFG0_PHY_NUM_SEL;
+ }
+
writel(val, csid->base + CSID_CSI2_RX_CFG0);

val = CSI2_RX_CFG1_ECC_CORRECTION_EN;
diff --git a/drivers/media/platform/qcom/camss/camss-tpg-gen1.c b/drivers/media/platform/qcom/camss/camss-tpg-gen1.c
index 770a9e5d5ba5..5c452f7a412d 100644
--- a/drivers/media/platform/qcom/camss/camss-tpg-gen1.c
+++ b/drivers/media/platform/qcom/camss/camss-tpg-gen1.c
@@ -22,6 +22,7 @@

#define TPG_HW_VER_2_0_0 TPG_HW_VER(2, 0, 0)
#define TPG_HW_VER_2_1_0 TPG_HW_VER(2, 1, 0)
+#define TPG_HW_VER_2_3_0 TPG_HW_VER(2, 3, 0)
#define TPG_HW_VER_2_4_0 TPG_HW_VER(2, 4, 0)

#define TPG_HW_STATUS 0x4
@@ -170,7 +171,7 @@ static int tpg_stream_on(struct tpg_device *tpg)
val = FIELD_PREP(TPG_CTRL_NUM_ACTIVE_LANES, lane_cnt - 1) |
FIELD_PREP(TPG_CTRL_NUM_ACTIVE_VC, last_vc);

- if (tpg->hw_version >= TPG_HW_VER_2_4_0) {
+ if (tpg->hw_version >= TPG_HW_VER_2_3_0) {
writel(val, tpg->base + TPG_CTRL);
writel(TPG_CTRL_CMD_TEST_EN, tpg->base + TPG_CTRL_CMD);
} else {
@@ -184,10 +185,10 @@ static int tpg_stream_on(struct tpg_device *tpg)
static int tpg_reset(struct tpg_device *tpg)
{
/*
- * On TPG older than v2.4.0 test-enable lives in TPG_CTRL, so clear it
- * first; v2.4.0+ drives both test-enable and reset through TPG_CTRL_CMD.
+ * On TPG older than v2.3.0 test-enable lives in TPG_CTRL, so clear it
+ * first; v2.3.0+ drives both test-enable and reset through TPG_CTRL_CMD.
*/
- if (tpg->hw_version < TPG_HW_VER_2_4_0)
+ if (tpg->hw_version < TPG_HW_VER_2_3_0)
writel(0, tpg->base + TPG_CTRL);

writel(TPG_CTRL_CMD_HW_RESET, tpg->base + TPG_CTRL_CMD);
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 011ece0a7692..418deb74cd98 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -6159,10 +6159,12 @@ static const struct camss_resources sm8750_resources = {
.version = CAMSS_8750,
.pd_name = "top",
.csiphy_res = csiphy_res_kaanapali,
+ .tpg_res = tpg_res_x1e80100,
.csid_res = csid_res_sm8750,
.vfe_res = vfe_res_kaanapali,
.icc_res = icc_res_sm8750,
.csiphy_num = ARRAY_SIZE(csiphy_res_kaanapali),
+ .tpg_num = ARRAY_SIZE(tpg_res_x1e80100),
.csid_num = ARRAY_SIZE(csid_res_sm8750),
.vfe_num = ARRAY_SIZE(vfe_res_kaanapali),
.icc_path_num = ARRAY_SIZE(icc_res_sm8750),

--
2.34.1