[PATCH 2/8] media: qcom: camss: Add SM8150 support

From: Gaurav Suman via B4 Relay

Date: Mon Nov 09 2026 - 17:43:38 EST


From: Gaurav Suman <gauravsuman007@xxxxxxxxx>

Add the SM8150 (Titan 175) camera subsystem. The CSID, VFE and bus
blocks are the same as on SM6150/SDM845 (Titan 17x), so the gen2 CSID
and VFE 17x code is reused, but SM8150 needs its own resources:

- four CSIPHYs, four CSIDs and four VFEs (two of each are lite),
- clock rates from the SM8150 camera clock controller tables,
- camnoc_axi at 400 MHz. At its 19.2 MHz boot rate the VFE gets a
start of frame and one reg update but never a buffer done,
- the CSIPHY v1.1 lane settings (downstream cam_csiphy_1_1_hwreg.h).
The SM6150 entry uses the QCM2290 v1.2 table; with it the sensor
streams but the CSID never sees data.

Tested on an LG G8x ThinQ with three sensors on CSIPHY0, 1 and 2 (4
lanes each, up to 1190 Mbps per lane): 30 fps RAW10 through CSID0
and VFE0 RDI0, with libcamera's simple pipeline handler.

This was written and tested with the help of an AI coding assistant
(Claude Opus 5.5, Anthropic); I reviewed the change and the results.

Signed-off-by: Gaurav Suman <gauravsuman007@xxxxxxxxx>
---
.../platform/qcom/camss/camss-csiphy-3ph-1-0.c | 80 +++++++
drivers/media/platform/qcom/camss/camss-vfe.c | 2 +
drivers/media/platform/qcom/camss/camss.c | 250 +++++++++++++++++++++
drivers/media/platform/qcom/camss/camss.h | 1 +
4 files changed, 333 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 dac8d2ecf79957dc05c5524dc439791ce097c785..3d8992d5dbc7bfd1f7447303f44386e67d90b830 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
@@ -144,6 +144,81 @@ csiphy_lane_regs lane_regs_sa8775p[] = {
{0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
};

+/* SM8150 (Titan 175): CSIPHY v1.1, 2-phase lane settings */
+static const struct
+csiphy_lane_regs lane_regs_sm8150[] = {
+ {0x0004, 0x0C, 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},
+ {0x0028, 0x00, 0x00, CSIPHY_DNP_PARAMS},
+ {0x003C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0000, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0008, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x000C, 0x00, 0x00, CSIPHY_DNP_PARAMS},
+ {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0064, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0704, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x072C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0734, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x071C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0714, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0728, 0x04, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x073C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0700, 0x80, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0708, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0764, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0204, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x022C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0234, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x021C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0214, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0228, 0x00, 0x00, CSIPHY_DNP_PARAMS},
+ {0x023C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0200, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0208, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x020C, 0x00, 0x00, CSIPHY_DNP_PARAMS},
+ {0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0264, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0404, 0x0C, 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},
+ {0x0428, 0x00, 0x00, CSIPHY_DNP_PARAMS},
+ {0x043C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0400, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0408, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x040C, 0x00, 0x00, CSIPHY_DNP_PARAMS},
+ {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0464, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0604, 0x0C, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x062C, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0634, 0x0F, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x061C, 0x0A, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0614, 0x60, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0628, 0x00, 0x00, CSIPHY_DNP_PARAMS},
+ {0x063C, 0xB8, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0600, 0x90, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0608, 0x0E, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+ {0x060C, 0x00, 0x00, CSIPHY_DNP_PARAMS},
+ {0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0638, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+ {0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
+};
+
/* GEN2 1.0 2PH */
static const struct
csiphy_lane_regs lane_regs_sdm845[] = {
@@ -1131,6 +1206,7 @@ static bool csiphy_is_gen2(u32 version)
switch (version) {
case CAMSS_2290:
case CAMSS_6150:
+ case CAMSS_8150:
case CAMSS_6350:
case CAMSS_7280:
case CAMSS_8250:
@@ -1221,6 +1297,10 @@ static int csiphy_init(struct csiphy_device *csiphy)
regs->lane_regs = &lane_regs_sdm845[0];
regs->lane_array_size = ARRAY_SIZE(lane_regs_sdm845);
break;
+ case CAMSS_8150:
+ regs->lane_regs = &lane_regs_sm8150[0];
+ regs->lane_array_size = ARRAY_SIZE(lane_regs_sm8150);
+ break;
case CAMSS_2290:
case CAMSS_6150:
regs->lane_regs = &lane_regs_qcm2290[0];
diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
index 2680a9914765fa2c8f3c2b38a5f4f0e0bcf4d873..4f89e8901d530410b243581d3953b6b023a8c7c3 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe.c
@@ -343,6 +343,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
case CAMSS_660:
case CAMSS_2290:
case CAMSS_6150:
+ case CAMSS_8150:
case CAMSS_6350:
case CAMSS_7280:
case CAMSS_8x96:
@@ -2004,6 +2005,7 @@ static int vfe_bpl_align_rdi(struct vfe_device *vfe)

switch (vfe->camss->res->version) {
case CAMSS_6150:
+ case CAMSS_8150:
case CAMSS_6350:
case CAMSS_7280:
case CAMSS_8250:
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index c54185c93a8a98fc6a20fdb8e0f9f8e61bc41058..bda61bf1f573965e662c00545bc207f5a30867b9 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -5699,6 +5699,255 @@ static const struct camss_resources sdm845_resources = {
.vfe_num = ARRAY_SIZE(vfe_res_845),
};

+static const struct camss_subdev_resources csiphy_res_sm8150[] = {
+ /* CSIPHY0 */
+ {
+ .regulators = {
+ { .supply = "vdd-csiphy-1p2", .init_load_uA = 35000 },
+ { .supply = "vdd-csiphy-1p8", .init_load_uA = 5000 }
+ },
+ .clock = { "csiphy0", "csiphy0_timer" },
+ .clock_rate = { { 400000000 },
+ { 300000000 } },
+ .reg = { "csiphy0" },
+ .interrupt = { "csiphy0" },
+ .csiphy = {
+ .id = 0,
+ .hw_ops = &csiphy_ops_3ph_1_0,
+ .formats = &csiphy_formats_sdm845
+ }
+ },
+ /* CSIPHY1 */
+ {
+ .regulators = {
+ { .supply = "vdd-csiphy-1p2", .init_load_uA = 35000 },
+ { .supply = "vdd-csiphy-1p8", .init_load_uA = 5000 }
+ },
+ .clock = { "csiphy1", "csiphy1_timer" },
+ .clock_rate = { { 400000000 },
+ { 300000000 } },
+ .reg = { "csiphy1" },
+ .interrupt = { "csiphy1" },
+ .csiphy = {
+ .id = 1,
+ .hw_ops = &csiphy_ops_3ph_1_0,
+ .formats = &csiphy_formats_sdm845
+ }
+ },
+ /* CSIPHY2 */
+ {
+ .regulators = {
+ { .supply = "vdd-csiphy-1p2", .init_load_uA = 35000 },
+ { .supply = "vdd-csiphy-1p8", .init_load_uA = 5000 }
+ },
+ .clock = { "csiphy2", "csiphy2_timer" },
+ .clock_rate = { { 400000000 },
+ { 300000000 } },
+ .reg = { "csiphy2" },
+ .interrupt = { "csiphy2" },
+ .csiphy = {
+ .id = 2,
+ .hw_ops = &csiphy_ops_3ph_1_0,
+ .formats = &csiphy_formats_sdm845
+ }
+ },
+ /* CSIPHY3 */
+ {
+ .regulators = {
+ { .supply = "vdd-csiphy-1p2", .init_load_uA = 35000 },
+ { .supply = "vdd-csiphy-1p8", .init_load_uA = 5000 }
+ },
+ .clock = { "csiphy3", "csiphy3_timer" },
+ .clock_rate = { { 400000000 },
+ { 300000000 } },
+ .reg = { "csiphy3" },
+ .interrupt = { "csiphy3" },
+ .csiphy = {
+ .id = 3,
+ .hw_ops = &csiphy_ops_3ph_1_0,
+ .formats = &csiphy_formats_sdm845
+ }
+ },
+};
+
+static const struct camss_subdev_resources csid_res_sm8150[] = {
+ /* CSID0 */
+ {
+ .regulators = {},
+ .clock = { "vfe0_cphy_rx", "vfe0_csid" },
+ .clock_rate = { { 400000000 },
+ { 400000000, 480000000, 600000000 } },
+ .reg = { "csid0" },
+ .interrupt = { "csid0" },
+ .csid = {
+ .is_lite = false,
+ .hw_ops = &csid_ops_gen2,
+ .parent_dev_ops = &vfe_parent_dev_ops,
+ .formats = &csid_formats_gen2
+ }
+ },
+ /* CSID1 */
+ {
+ .regulators = {},
+ .clock = { "vfe1_cphy_rx", "vfe1_csid" },
+ .clock_rate = { { 400000000 },
+ { 400000000, 480000000, 600000000 } },
+ .reg = { "csid1" },
+ .interrupt = { "csid1" },
+ .csid = {
+ .is_lite = false,
+ .hw_ops = &csid_ops_gen2,
+ .parent_dev_ops = &vfe_parent_dev_ops,
+ .formats = &csid_formats_gen2
+ }
+ },
+ /* CSID_LITE0 */
+ {
+ .regulators = {},
+ .clock = { "vfe_lite0_cphy_rx", "vfe_lite0_csid" },
+ .clock_rate = { { 400000000 },
+ { 400000000, 480000000, 600000000 } },
+ .reg = { "csid_lite0" },
+ .interrupt = { "csid_lite0" },
+ .csid = {
+ .is_lite = true,
+ .hw_ops = &csid_ops_gen2,
+ .parent_dev_ops = &vfe_parent_dev_ops,
+ .formats = &csid_formats_gen2
+ }
+ },
+ /* CSID_LITE1 */
+ {
+ .regulators = {},
+ .clock = { "vfe_lite1_cphy_rx", "vfe_lite1_csid" },
+ .clock_rate = { { 400000000 },
+ { 400000000, 480000000, 600000000 } },
+ .reg = { "csid_lite1" },
+ .interrupt = { "csid_lite1" },
+ .csid = {
+ .is_lite = true,
+ .hw_ops = &csid_ops_gen2,
+ .parent_dev_ops = &vfe_parent_dev_ops,
+ .formats = &csid_formats_gen2
+ }
+ },
+};
+
+static const struct camss_subdev_resources vfe_res_sm8150[] = {
+ /* VFE0 */
+ {
+ .regulators = {},
+ .clock = { "gcc_axi_hf", "camnoc_axi", "cpas_ahb", "slow_ahb_src",
+ "vfe0", "vfe0_axi" },
+ .clock_rate = { { 0 },
+ { 400000000 },
+ { 0 },
+ { 0 },
+ { 400000000, 558000000, 637000000, 847000000, 950000000 },
+ { 0 } },
+ .reg = { "vfe0" },
+ .interrupt = { "vfe0" },
+ .vfe = {
+ .line_num = 3,
+ .is_lite = false,
+ .has_pd = true,
+ .pd_name = "ife0",
+ .hw_ops = &vfe_ops_170,
+ .formats_rdi = &vfe_formats_rdi_845,
+ .formats_pix = &vfe_formats_pix_845
+ }
+ },
+ /* VFE1 */
+ {
+ .regulators = {},
+ .clock = { "gcc_axi_hf", "camnoc_axi", "cpas_ahb", "slow_ahb_src",
+ "vfe1", "vfe1_axi" },
+ .clock_rate = { { 0 },
+ { 400000000 },
+ { 0 },
+ { 0 },
+ { 400000000, 558000000, 637000000, 847000000, 950000000 },
+ { 0 } },
+ .reg = { "vfe1" },
+ .interrupt = { "vfe1" },
+ .vfe = {
+ .line_num = 3,
+ .is_lite = false,
+ .has_pd = true,
+ .pd_name = "ife1",
+ .hw_ops = &vfe_ops_170,
+ .formats_rdi = &vfe_formats_rdi_845,
+ .formats_pix = &vfe_formats_pix_845
+ }
+ },
+ /* VFE_LITE0 */
+ {
+ .regulators = {},
+ .clock = { "gcc_axi_hf", "camnoc_axi", "cpas_ahb", "slow_ahb_src",
+ "vfe_lite0" },
+ .clock_rate = { { 0 },
+ { 400000000 },
+ { 0 },
+ { 0 },
+ { 320000000, 400000000, 480000000, 600000000 } },
+ .reg = { "vfe_lite0" },
+ .interrupt = { "vfe_lite0" },
+ .vfe = {
+ .line_num = 4,
+ .is_lite = true,
+ .hw_ops = &vfe_ops_170,
+ .formats_rdi = &vfe_formats_rdi_845,
+ .formats_pix = &vfe_formats_pix_845
+ }
+ },
+ /* VFE_LITE1 */
+ {
+ .regulators = {},
+ .clock = { "gcc_axi_hf", "camnoc_axi", "cpas_ahb", "slow_ahb_src",
+ "vfe_lite1" },
+ .clock_rate = { { 0 },
+ { 400000000 },
+ { 0 },
+ { 0 },
+ { 320000000, 400000000, 480000000, 600000000 } },
+ .reg = { "vfe_lite1" },
+ .interrupt = { "vfe_lite1" },
+ .vfe = {
+ .line_num = 4,
+ .is_lite = true,
+ .hw_ops = &vfe_ops_170,
+ .formats_rdi = &vfe_formats_rdi_845,
+ .formats_pix = &vfe_formats_pix_845
+ }
+ },
+};
+
+static const struct resources_icc icc_res_sm8150[] = {
+ {
+ .name = "ahb",
+ .icc_bw_tbl.avg = 38400,
+ .icc_bw_tbl.peak = 76800,
+ },
+ {
+ .name = "hf_0",
+ .icc_bw_tbl.avg = 2097152,
+ .icc_bw_tbl.peak = 2097152,
+ },
+};
+
+static const struct camss_resources sm8150_resources = {
+ .version = CAMSS_8150,
+ .pd_name = "top",
+ .csiphy_res = csiphy_res_sm8150,
+ .csid_res = csid_res_sm8150,
+ .vfe_res = vfe_res_sm8150,
+ .icc_res = icc_res_sm8150,
+ .icc_path_num = ARRAY_SIZE(icc_res_sm8150),
+ .csiphy_num = ARRAY_SIZE(csiphy_res_sm8150),
+ .csid_num = ARRAY_SIZE(csid_res_sm8150),
+ .vfe_num = ARRAY_SIZE(vfe_res_sm8150),
+};
+
static const struct camss_resources sm6150_resources = {
.version = CAMSS_6150,
.pd_name = "top",
@@ -5824,6 +6073,7 @@ static const struct of_device_id camss_dt_match[] = {
{ .compatible = "qcom,sdm845-camss", .data = &sdm845_resources },
{ .compatible = "qcom,sm6150-camss", .data = &sm6150_resources },
{ .compatible = "qcom,sm6350-camss", .data = &sm6350_resources },
+ { .compatible = "qcom,sm8150-camss", .data = &sm8150_resources },
{ .compatible = "qcom,sm8250-camss", .data = &sm8250_resources },
{ .compatible = "qcom,sm8550-camss", .data = &sm8550_resources },
{ .compatible = "qcom,sm8650-camss", .data = &sm8650_resources },
diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
index 7dc2fd9f03e0dc2ded8e4a603d6cfec4d8e6a62b..74d8cc2921be9da7673494cd0785c8f9b90b4a3e 100644
--- a/drivers/media/platform/qcom/camss/camss.h
+++ b/drivers/media/platform/qcom/camss/camss.h
@@ -89,6 +89,7 @@ enum camss_version {
CAMSS_8x39,
CAMSS_8x53,
CAMSS_8x96,
+ CAMSS_8150,
CAMSS_8250,
CAMSS_8280XP,
CAMSS_8300,

--
2.49.1