mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/7] media: qcom: camss: Add X1 Elite support
@ 2025-01-20 15:46 Bryan O'Donoghue
  2025-01-20 15:46 ` [PATCH 1/7] media: qcom: camss: Add an id property to struct resources Bryan O'Donoghue
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Bryan O'Donoghue @ 2025-01-20 15:46 UTC (permalink / raw)
  To: Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Vladimir Zapolskiy,
	Depeng Shao, Vikram Sharma, Bryan O'Donoghue

This series adds X Elite support to CAMSS.

This drop includes support for

4 x CSIPHY in DPHY mode 2 phase 5 GB 4 lane
3 x CSI Decoder CSID
2 x CSID Lite
2 x Image Front End - IFE
2 x IFE Lite

Dependencies:

link: https://lore.kernel.org/all/20250113043133.1387162-1-quic_depengs@quicinc.com/
link: https://lore.kernel.org/all/20250119-b4-linux-next-24-11-18-dtsi-x1e80100-camss-v4-0-c2964504131c@linaro.org

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
Bryan O'Donoghue (7):
      media: qcom: camss: Add an id property to struct resources
      media: qcom: camss: Use the CSIPHY id property to find clock names
      media: qcom: camss: Add CSID 680 support
      media: qcom: camss: Add VFE680 support
      media: qcom: camss: Add support for 3ph CSIPHY write settle delay
      media: qcom: camss: csiphy-3ph: Add 4nm CSIPHY 2ph 5Gbps DPHY v2.1.2 init sequence
      media: qcom: camss: Add x1e80100 specific support

 drivers/media/platform/qcom/camss/Makefile         |   2 +
 drivers/media/platform/qcom/camss/camss-csid-680.c | 422 +++++++++++++++++++++
 drivers/media/platform/qcom/camss/camss-csid.h     |   1 +
 .../platform/qcom/camss/camss-csiphy-3ph-1-0.c     | 136 ++++++-
 drivers/media/platform/qcom/camss/camss-csiphy.c   |  28 +-
 drivers/media/platform/qcom/camss/camss-csiphy.h   |   1 +
 drivers/media/platform/qcom/camss/camss-vfe-680.c  | 243 ++++++++++++
 drivers/media/platform/qcom/camss/camss-vfe.c      |   2 +
 drivers/media/platform/qcom/camss/camss-vfe.h      |   1 +
 drivers/media/platform/qcom/camss/camss.c          | 324 +++++++++++++++-
 drivers/media/platform/qcom/camss/camss.h          |   1 +
 11 files changed, 1144 insertions(+), 17 deletions(-)
---
base-commit: 0efbd85873320a5ed76c9505719a3b383c3b8815
change-id: 20250119-linux-next-25-01-19-x1e80100-camss-driver-8dc5e018f6e9

Best regards,
-- 
Bryan O'Donoghue <bryan.odonoghue@linaro.org>


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 1/7] media: qcom: camss: Add an id property to struct resources
  2025-01-20 15:46 [PATCH 0/7] media: qcom: camss: Add X1 Elite support Bryan O'Donoghue
@ 2025-01-20 15:46 ` Bryan O'Donoghue
  2025-01-21 23:38   ` Vladimir Zapolskiy
  2025-01-20 15:46 ` [PATCH 2/7] media: qcom: camss: Use the CSIPHY id property to find clock names Bryan O'Donoghue
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Bryan O'Donoghue @ 2025-01-20 15:46 UTC (permalink / raw)
  To: Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Vladimir Zapolskiy,
	Depeng Shao, Vikram Sharma, Bryan O'Donoghue

In various places in CAMSS we assume a linear set of declared devices
{csiphy0, csiphy1, csiphy2} which currently works for upstream SoCs but for
upcoming SoCs some of the SoC resources will result in a set such as
{csiphy0, csiphy2} which will break the naive for() loops we have.

Introduce an identity property which resource declarations can populate
hence facilitating non-linear resource naming.

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 drivers/media/platform/qcom/camss/camss-csiphy.h |  1 +
 drivers/media/platform/qcom/camss/camss.c        | 38 +++++++++++++++++++++++-
 2 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h
index 86b98b37838e1..ab91273303b9e 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.h
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.h
@@ -81,6 +81,7 @@ struct csiphy_hw_ops {
 };
 
 struct csiphy_subdev_resources {
+	u8 id;
 	const struct csiphy_hw_ops *hw_ops;
 	const struct csiphy_formats *formats;
 };
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index f4fbf0d73dd1f..a128b1d1c6d57 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -46,6 +46,7 @@ static const struct camss_subdev_resources csiphy_res_8x16[] = {
 		.reg = { "csiphy0", "csiphy0_clk_mux" },
 		.interrupt = { "csiphy0" },
 		.csiphy = {
+			.id = 0,
 			.hw_ops = &csiphy_ops_2ph_1_0,
 			.formats = &csiphy_formats_8x16
 		}
@@ -62,6 +63,7 @@ static const struct camss_subdev_resources csiphy_res_8x16[] = {
 		.reg = { "csiphy1", "csiphy1_clk_mux" },
 		.interrupt = { "csiphy1" },
 		.csiphy = {
+			.id = 1,
 			.hw_ops = &csiphy_ops_2ph_1_0,
 			.formats = &csiphy_formats_8x16
 		}
@@ -318,6 +320,7 @@ static const struct camss_subdev_resources csiphy_res_8x96[] = {
 		.reg = { "csiphy0", "csiphy0_clk_mux" },
 		.interrupt = { "csiphy0" },
 		.csiphy = {
+			.id = 0,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_8x96
 		}
@@ -334,6 +337,7 @@ static const struct camss_subdev_resources csiphy_res_8x96[] = {
 		.reg = { "csiphy1", "csiphy1_clk_mux" },
 		.interrupt = { "csiphy1" },
 		.csiphy = {
+			.id = 1,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_8x96
 		}
@@ -350,6 +354,7 @@ static const struct camss_subdev_resources csiphy_res_8x96[] = {
 		.reg = { "csiphy2", "csiphy2_clk_mux" },
 		.interrupt = { "csiphy2" },
 		.csiphy = {
+			.id = 2,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_8x96
 		}
@@ -524,6 +529,7 @@ static const struct camss_subdev_resources csiphy_res_660[] = {
 		.reg = { "csiphy0", "csiphy0_clk_mux" },
 		.interrupt = { "csiphy0" },
 		.csiphy = {
+			.id = 0,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_8x96
 		}
@@ -542,6 +548,7 @@ static const struct camss_subdev_resources csiphy_res_660[] = {
 		.reg = { "csiphy1", "csiphy1_clk_mux" },
 		.interrupt = { "csiphy1" },
 		.csiphy = {
+			.id = 1,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_8x96
 		}
@@ -560,6 +567,7 @@ static const struct camss_subdev_resources csiphy_res_660[] = {
 		.reg = { "csiphy2", "csiphy2_clk_mux" },
 		.interrupt = { "csiphy2" },
 		.csiphy = {
+			.id = 2,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_8x96
 		}
@@ -756,6 +764,7 @@ static const struct camss_subdev_resources csiphy_res_845[] = {
 		.reg = { "csiphy0" },
 		.interrupt = { "csiphy0" },
 		.csiphy = {
+			.id = 0,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -778,6 +787,7 @@ static const struct camss_subdev_resources csiphy_res_845[] = {
 		.reg = { "csiphy1" },
 		.interrupt = { "csiphy1" },
 		.csiphy = {
+			.id = 1,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -800,6 +810,7 @@ static const struct camss_subdev_resources csiphy_res_845[] = {
 		.reg = { "csiphy2" },
 		.interrupt = { "csiphy2" },
 		.csiphy = {
+			.id = 2,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -822,6 +833,7 @@ static const struct camss_subdev_resources csiphy_res_845[] = {
 		.reg = { "csiphy3" },
 		.interrupt = { "csiphy3" },
 		.csiphy = {
+			.id = 3,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -998,6 +1010,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
 		.reg = { "csiphy0" },
 		.interrupt = { "csiphy0" },
 		.csiphy = {
+			.id = 0,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1011,6 +1024,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
 		.reg = { "csiphy1" },
 		.interrupt = { "csiphy1" },
 		.csiphy = {
+			.id = 1,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1024,6 +1038,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
 		.reg = { "csiphy2" },
 		.interrupt = { "csiphy2" },
 		.csiphy = {
+			.id = 2,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1037,6 +1052,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
 		.reg = { "csiphy3" },
 		.interrupt = { "csiphy3" },
 		.csiphy = {
+			.id = 3,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1050,6 +1066,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
 		.reg = { "csiphy4" },
 		.interrupt = { "csiphy4" },
 		.csiphy = {
+			.id = 4,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1063,6 +1080,7 @@ static const struct camss_subdev_resources csiphy_res_8250[] = {
 		.reg = { "csiphy5" },
 		.interrupt = { "csiphy5" },
 		.csiphy = {
+			.id = 5,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1277,6 +1295,7 @@ static const struct camss_subdev_resources csiphy_res_7280[] = {
 		.reg = { "csiphy0" },
 		.interrupt = { "csiphy0" },
 		.csiphy = {
+			.id = 0,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sc7280
 		}
@@ -1291,6 +1310,7 @@ static const struct camss_subdev_resources csiphy_res_7280[] = {
 		.reg = { "csiphy1" },
 		.interrupt = { "csiphy1" },
 		.csiphy = {
+			.id = 1,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sc7280
 		}
@@ -1305,6 +1325,7 @@ static const struct camss_subdev_resources csiphy_res_7280[] = {
 		.reg = { "csiphy2" },
 		.interrupt = { "csiphy2" },
 		.csiphy = {
+			.id = 2,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sc7280
 		}
@@ -1319,6 +1340,7 @@ static const struct camss_subdev_resources csiphy_res_7280[] = {
 		.reg = { "csiphy3" },
 		.interrupt = { "csiphy3" },
 		.csiphy = {
+			.id = 3,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sc7280
 		}
@@ -1333,6 +1355,7 @@ static const struct camss_subdev_resources csiphy_res_7280[] = {
 		.reg = { "csiphy4" },
 		.interrupt = { "csiphy4" },
 		.csiphy = {
+			.id = 4,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sc7280
 		}
@@ -1580,6 +1603,7 @@ static const struct camss_subdev_resources csiphy_res_sc8280xp[] = {
 		.reg = { "csiphy0" },
 		.interrupt = { "csiphy0" },
 		.csiphy = {
+			.id = 0,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1593,6 +1617,7 @@ static const struct camss_subdev_resources csiphy_res_sc8280xp[] = {
 		.reg = { "csiphy1" },
 		.interrupt = { "csiphy1" },
 		.csiphy = {
+			.id = 1,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1606,6 +1631,7 @@ static const struct camss_subdev_resources csiphy_res_sc8280xp[] = {
 		.reg = { "csiphy2" },
 		.interrupt = { "csiphy2" },
 		.csiphy = {
+			.id = 2,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1619,6 +1645,7 @@ static const struct camss_subdev_resources csiphy_res_sc8280xp[] = {
 		.reg = { "csiphy3" },
 		.interrupt = { "csiphy3" },
 		.csiphy = {
+			.id = 3,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1948,6 +1975,7 @@ static const struct camss_subdev_resources csiphy_res_8550[] = {
 		.reg = { "csiphy0" },
 		.interrupt = { "csiphy0" },
 		.csiphy = {
+			.id = 0,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1961,6 +1989,7 @@ static const struct camss_subdev_resources csiphy_res_8550[] = {
 		.reg = { "csiphy1" },
 		.interrupt = { "csiphy1" },
 		.csiphy = {
+			.id = 1,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1974,6 +2003,7 @@ static const struct camss_subdev_resources csiphy_res_8550[] = {
 		.reg = { "csiphy2" },
 		.interrupt = { "csiphy2" },
 		.csiphy = {
+			.id = 2,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -1987,6 +2017,7 @@ static const struct camss_subdev_resources csiphy_res_8550[] = {
 		.reg = { "csiphy3" },
 		.interrupt = { "csiphy3" },
 		.csiphy = {
+			.id = 3,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -2000,6 +2031,7 @@ static const struct camss_subdev_resources csiphy_res_8550[] = {
 		.reg = { "csiphy4" },
 		.interrupt = { "csiphy4" },
 		.csiphy = {
+			.id = 4,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -2013,6 +2045,7 @@ static const struct camss_subdev_resources csiphy_res_8550[] = {
 		.reg = { "csiphy5" },
 		.interrupt = { "csiphy5" },
 		.csiphy = {
+			.id = 5,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -2026,6 +2059,7 @@ static const struct camss_subdev_resources csiphy_res_8550[] = {
 		.reg = { "csiphy6" },
 		.interrupt = { "csiphy6" },
 		.csiphy = {
+			.id = 6,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -2039,6 +2073,7 @@ static const struct camss_subdev_resources csiphy_res_8550[] = {
 		.reg = { "csiphy7" },
 		.interrupt = { "csiphy7" },
 		.csiphy = {
+			.id = 7,
 			.hw_ops = &csiphy_ops_3ph_1_0,
 			.formats = &csiphy_formats_sdm845
 		}
@@ -2566,7 +2601,8 @@ static int camss_init_subdevices(struct camss *camss)
 
 	for (i = 0; i < camss->res->csiphy_num; i++) {
 		ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i],
-					     &res->csiphy_res[i], 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",

-- 
2.47.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 2/7] media: qcom: camss: Use the CSIPHY id property to find clock names
  2025-01-20 15:46 [PATCH 0/7] media: qcom: camss: Add X1 Elite support Bryan O'Donoghue
  2025-01-20 15:46 ` [PATCH 1/7] media: qcom: camss: Add an id property to struct resources Bryan O'Donoghue
@ 2025-01-20 15:46 ` Bryan O'Donoghue
  2025-01-21 23:40   ` Vladimir Zapolskiy
  2025-01-20 15:47 ` [PATCH 3/7] media: qcom: camss: Add CSID 680 support Bryan O'Donoghue
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Bryan O'Donoghue @ 2025-01-20 15:46 UTC (permalink / raw)
  To: Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Vladimir Zapolskiy,
	Depeng Shao, Vikram Sharma, Bryan O'Donoghue

Use the CSIPHY id property to find clock names instead of relying on
generating the clock names based on the control-loop index.

x1e80100 has CSIPHY0, CSIPHY1, CSIPHY2 and CSIPHY4 so simple index naming
won't work whereas and 'id' property allows any ordering and any stepping
between the CSIPHY names.

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 drivers/media/platform/qcom/camss/camss-csiphy.c | 28 +++++++++++-------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.c b/drivers/media/platform/qcom/camss/camss-csiphy.c
index c053616558a73..c622efcc92ff3 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.c
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.c
@@ -586,7 +586,7 @@ int msm_csiphy_subdev_init(struct camss *camss,
 {
 	struct device *dev = camss->dev;
 	struct platform_device *pdev = to_platform_device(dev);
-	int i, j, k;
+	int i, j;
 	int ret;
 
 	csiphy->camss = camss;
@@ -680,23 +680,21 @@ int msm_csiphy_subdev_init(struct camss *camss,
 		for (j = 0; j < clock->nfreqs; j++)
 			clock->freq[j] = res->clock_rate[i][j];
 
-		for (k = 0; k < camss->res->csiphy_num; k++) {
-			csiphy->rate_set[i] = csiphy_match_clock_name(clock->name,
-								      "csiphy%d_timer", k);
-			if (csiphy->rate_set[i])
-				break;
-
-			if (camss->res->version == CAMSS_660) {
-				csiphy->rate_set[i] = csiphy_match_clock_name(clock->name,
-									      "csi%d_phy", k);
-				if (csiphy->rate_set[i])
-					break;
-			}
+		csiphy->rate_set[i] = csiphy_match_clock_name(clock->name,
+							      "csiphy%d_timer",
+							      csiphy->id);
+		if (csiphy->rate_set[i])
+			continue;
 
-			csiphy->rate_set[i] = csiphy_match_clock_name(clock->name, "csiphy%d", k);
+		if (camss->res->version == CAMSS_660) {
+			csiphy->rate_set[i] = csiphy_match_clock_name(clock->name,
+								      "csi%d_phy",
+								       csiphy->id);
 			if (csiphy->rate_set[i])
-				break;
+				continue;
 		}
+
+		csiphy->rate_set[i] = csiphy_match_clock_name(clock->name, "csiphy%d", csiphy->id);
 	}
 
 	/* CSIPHY supplies */

-- 
2.47.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 3/7] media: qcom: camss: Add CSID 680 support
  2025-01-20 15:46 [PATCH 0/7] media: qcom: camss: Add X1 Elite support Bryan O'Donoghue
  2025-01-20 15:46 ` [PATCH 1/7] media: qcom: camss: Add an id property to struct resources Bryan O'Donoghue
  2025-01-20 15:46 ` [PATCH 2/7] media: qcom: camss: Use the CSIPHY id property to find clock names Bryan O'Donoghue
@ 2025-01-20 15:47 ` Bryan O'Donoghue
  2025-01-22  0:05   ` Vladimir Zapolskiy
  2025-01-20 15:47 ` [PATCH 4/7] media: qcom: camss: Add VFE680 support Bryan O'Donoghue
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Bryan O'Donoghue @ 2025-01-20 15:47 UTC (permalink / raw)
  To: Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Vladimir Zapolskiy,
	Depeng Shao, Vikram Sharma, Bryan O'Donoghue

Add CSI Decoder (CSID) 680 support to CAMSS. This version of CSID has been
shipped with SM8450 and x1e chips.

References previous work from Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 drivers/media/platform/qcom/camss/Makefile         |   1 +
 drivers/media/platform/qcom/camss/camss-csid-680.c | 422 +++++++++++++++++++++
 drivers/media/platform/qcom/camss/camss-csid.h     |   1 +
 3 files changed, 424 insertions(+)

diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile
index f6db5b3b5ace3..71797745f2f71 100644
--- a/drivers/media/platform/qcom/camss/Makefile
+++ b/drivers/media/platform/qcom/camss/Makefile
@@ -6,6 +6,7 @@ qcom-camss-objs += \
 		camss-csid.o \
 		camss-csid-4-1.o \
 		camss-csid-4-7.o \
+		camss-csid-680.o \
 		camss-csid-gen2.o \
 		camss-csid-780.o \
 		camss-csiphy-2ph-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
new file mode 100644
index 0000000000000..2a989ce33c2a4
--- /dev/null
+++ b/drivers/media/platform/qcom/camss/camss-csid-680.c
@@ -0,0 +1,422 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module
+ *
+ * Copyright (C) 2020-2023 Linaro Ltd.
+ */
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+
+#include "camss.h"
+#include "camss-csid.h"
+#include "camss-csid-gen2.h"
+
+#define CSID_TOP_IO_PATH_CFG0(csid)				(0x4 * (csid))
+#define		CSID_TOP_IO_PATH_CFG0_INTERNAL_CSID		BIT(0)
+#define		CSID_TOP_IO_PATH_CFG0_SFE_0			BIT(1)
+#define		CSID_TOP_IO_PATH_CFG0_SFE_1			GENMASK(1, 0)
+#define		CSID_TOP_IO_PATH_CFG0_SBI_0			BIT(4)
+#define		CSID_TOP_IO_PATH_CFG0_SBI_1			GENMASK(3, 0)
+#define		CSID_TOP_IO_PATH_CFG0_SBI_2			GENMASK(3, 1)
+#define		CSID_TOP_IO_PATH_CFG0_OUTPUT_IFE_EN		BIT(8)
+#define		CSID_TOP_IO_PATH_CFG0_SFE_OFFLINE_EN		BIT(12)
+
+#define CSID_RESET_CFG						0xc
+#define		CSID_RESET_CFG_MODE_IMMEDIATE			BIT(0)
+#define		CSID_RESET_CFG_LOCATION_COMPLETE		BIT(4)
+
+#define CSID_RESET_CMD						0x10
+#define		CSID_RESET_CMD_HW_RESET				BIT(0)
+#define		CSID_RESET_CMD_SW_RESET				BIT(1)
+#define		CSID_RESET_CMD_IRQ_CTRL				BIT(2)
+
+#define CSID_IRQ_CMD						0x14
+#define		CSID_IRQ_CMD_CLEAR				BIT(0)
+#define		CSID_IRQ_CMD_SET				BIT(4)
+
+#define CSID_REG_UPDATE_CMD					0x18
+
+#define CSID_CSI2_RDIN_IRQ_STATUS(rdi)					(0xec + 0x10 * (rdi))
+#define		CSID_CSI2_RDIN_CCIF_VIOLATION				BIT(29)
+#define		CSID_CSI2_RDIN_SENSOR_SWITCH_OUT_OF_SYNC_FRAME_DROP	BIT(28)
+#define		CSID_CSI2_RDIN_ERROR_REC_WIDTH_VIOLATION		BIT(27)
+#define		CSID_CSI2_RDIN_ERROR_REC_HEIGHT_VIOLATION		BIT(26)
+#define		CSID_CSI2_RDIN_BATCH_END_MISSING_VIOLATION		BIT(25)
+#define		CSID_CSI2_RDIN_ILLEGAL_BATCH_ID_IRQ			BIT(24)
+#define		CSID_CSI2_RDIN_RUP_DONE					BIT(23)
+#define		CSID_CSI2_RDIN_CAMIF_EPOCH_1_IRQ			BIT(22)
+#define		CSID_CSI2_RDIN_CAMIF_EPOCH_0_IRQ			BIT(21)
+#define		CSID_CSI2_RDIN_ERROR_REC_OVERFLOW_IRQ			BIT(19)
+#define		CSID_CSI2_RDIN_ERROR_REC_FRAME_DROP			BIT(18)
+#define		CSID_CSI2_RDIN_VCDT_GRP_CHANG				BIT(17)
+#define		CSID_CSI2_RDIN_VCDT_GRP_0_SEL				BIT(16)
+#define		CSID_CSI2_RDIN_VCDT_GRP_1_SEL				BIT(15)
+#define		CSID_CSI2_RDIN_ERROR_LINE_COUNT				BIT(14)
+#define		CSID_CSI2_RDIN_ERROR_PIX_COUNT				BIT(13)
+#define		CSID_CSI2_RDIN_INFO_INPUT_SOF				BIT(12)
+#define		CSID_CSI2_RDIN_INFO_INPUT_SOL				BIT(11)
+#define		CSID_CSI2_RDIN_INFO_INPUT_EOL				BIT(10)
+#define		CSID_CSI2_RDIN_INFO_INPUT_EOF				BIT(9)
+#define		CSID_CSI2_RDIN_INFO_FRAME_DROP_SOF			BIT(8)
+#define		CSID_CSI2_RDIN_INFO_FRAME_DROP_SOL			BIT(7)
+#define		CSID_CSI2_RDIN_INFO_FRAME_DROP_EOL			BIT(6)
+#define		CSID_CSI2_RDIN_INFO_FRAME_DROP_EOF			BIT(5)
+#define		CSID_CSI2_RDIN_INFO_CAMIF_SOF				BIT(4)
+#define		CSID_CSI2_RDIN_INFO_CAMIF_EOF				BIT(3)
+#define		CSID_CSI2_RDIN_INFO_FIFO_OVERFLOW			BIT(2)
+#define		CSID_CSI2_RDIN_RES1					BIT(1)
+#define		CSID_CSI2_RDIN_RES0					BIT(0)
+
+#define CSID_CSI2_RDIN_IRQ_MASK(rdi)				(0xf0 + 0x10 * (rdi))
+#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi)				(0xf4 + 0x10 * (rdi))
+#define CSID_CSI2_RDIN_IRQ_SET(rdi)				(0xf8 + 0x10 * (rdi))
+
+#define CSID_TOP_IRQ_STATUS					0x7c
+#define CSID_TOP_IRQ_MASK					0x80
+#define CSID_TOP_IRQ_CLEAR					0x84
+#define		CSID_TOP_IRQ_RESET				BIT(0)
+#define		CSID_TOP_IRQ_RX					BIT(2)
+#define		CSID_TOP_IRQ_LONG_PKT(rdi)			(BIT(8) << (rdi))
+#define		CSID_TOP_IRQ_BUF_DONE				BIT(13)
+
+#define CSID_BUF_DONE_IRQ_STATUS				0x8c
+#define	BUF_DONE_IRQ_STATUS_RDI_OFFSET				(csid_is_lite(csid) ? 1 : 14)
+#define CSID_BUF_DONE_IRQ_MASK					0x90
+#define CSID_BUF_DONE_IRQ_CLEAR					0x94
+
+#define CSID_CSI2_RX_IRQ_STATUS					0x9c
+#define CSID_CSI2_RX_IRQ_MASK					0xa0
+#define CSID_CSI2_RX_IRQ_CLEAR					0xa4
+
+#define CSID_CSI2_RDI_IRQ_STATUS(rdi)				(0xec + 0x10 * (rdi))
+#define CSID_CSI2_RDI_IRQ_MASK(rdi)				(0xf0 + 0x10 * (rdi))
+#define CSID_CSI2_RDI_IRQ_CLEAR(rdi)				(0xf4 + 0x10 * (rdi))
+
+#define CSID_CSI2_RX_CFG0					0x200
+#define		CSI2_RX_CFG0_NUM_ACTIVE_LANES			0
+#define		CSI2_RX_CFG0_DL0_INPUT_SEL			4
+#define		CSI2_RX_CFG0_DL1_INPUT_SEL			8
+#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 CSID_CSI2_RX_CFG1					0x204
+#define		CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN		BIT(0)
+#define		CSI2_RX_CFG1_DE_SCRAMBLE_EN			BIT(1)
+#define		CSI2_RX_CFG1_VC_MODE				BIT(2)
+#define		CSI2_RX_CFG1_COMPLETE_STREAM_EN			BIT(4)
+#define		CSI2_RX_CFG1_COMPLETE_STREAM_FRAME_TIMING	BIT(5)
+#define		CSI2_RX_CFG1_MISR_EN				BIT(6)
+#define		CSI2_RX_CFG1_CGC_MODE				BIT(7)
+
+#define CSID_CSI2_RX_CAPTURE_CTRL				0x208
+#define		CSI2_RX_CAPTURE_LONG_PKT_EN			BIT(0)
+#define		CSI2_RX_CAPTURE_SHORT_PKT_EN			BIT(1)
+#define		CSI2_RX_CAPTURE_CPHY_PKT_EN			BIT(2)
+#define		CSI2_RX_CAPTURE_LONG_PKT_DT			BIT(4)
+#define		CSI2_RX_CAPTURE_LONG_PKT_VC			BIT(10)
+#define		CSI2_RX_CAPTURE_SHORT_PKT_VC			BIT(15)
+#define		CSI2_RX_CAPTURE_CPHY_PKT_DT			BIT(20)
+#define		CSI2_RX_CAPTURE_CPHY_PKT_VC			BIT(26)
+
+#define CSID_CSI2_RX_TOTAL_PKTS_RCVD				0x240
+#define CSID_CSI2_RX_STATS_ECC					0x244
+#define CSID_CSI2_RX_CRC_ERRORS					0x248
+
+#define CSID_RDI_CFG0(rdi)					(0x500 + 0x100 * (rdi))
+#define		RDI_CFG0_DECODE_FORMAT				12
+#define		RDI_CFG0_DATA_TYPE				16
+#define		RDI_CFG0_VIRTUAL_CHANNEL			22
+#define		RDI_CFG0_DT_ID					27
+#define		RDI_CFG0_ENABLE					BIT(31)
+
+#define CSID_RDI_CTRL(rdi)					(0x504 + 0x100 * (rdi))
+#define		CSID_RDI_CTRL_HALT_CMD_HALT_AT_FRAME_BOUNDARY	0
+#define		CSID_RDI_CTRL_HALT_CMD_RESUME_AT_FRAME_BOUNDARY	1
+
+#define CSID_RDI_CFG1(rdi)					(0x510 + 0x100 * (rdi))
+#define		RDI_CFG1_TIMESTAMP_STB_FRAME			BIT(0)
+#define		RDI_CFG1_TIMESTAMP_STB_IRQ			BIT(1)
+#define		RDI_CFG1_BYTE_CNTR_EN				BIT(2)
+#define		RDI_CFG1_TIMESTAMP_EN				BIT(4)
+#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_MISR_EN				BIT(9)
+#define		RDI_CFG1_PLAIN_ALIGN_MSB			BIT(11)
+#define		RDI_CFG1_EARLY_EOF_EN				BIT(14)
+#define		RDI_CFG1_PACKING_MIPI				BIT(15)
+
+#define CSID_RDI_ERR_RECOVERY_CFG0(rdi)				(0x514 + 0x100 * (rdi))
+#define CSID_RDI_EPOCH_IRQ_CFG(rdi)				(0x52c + 0x100 * (rdi))
+#define CSID_RDI_FRM_DROP_PATTERN(rdi)				(0x540 + 0x100 * (rdi))
+#define CSID_RDI_FRM_DROP_PERIOD(rdi)				(0x544 + 0x100 * (rdi))
+#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi)			(0x548 + 0x100 * (rdi))
+#define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi)			(0x54c + 0x100 * (rdi))
+#define CSID_RDI_PIX_DROP_PATTERN(rdi)				(0x558 + 0x100 * (rdi))
+#define CSID_RDI_PIX_DROP_PERIOD(rdi)				(0x55c + 0x100 * (rdi))
+#define CSID_RDI_LINE_DROP_PATTERN(rdi)				(0x560 + 0x100 * (rdi))
+#define CSID_RDI_LINE_DROP_PERIOD(rdi)				(0x564 + 0x100 * (rdi))
+
+static inline int reg_update_rdi(struct csid_device *csid, int n)
+{
+	return BIT(n + 4) + BIT(20 + n);
+}
+
+static void csid_reg_update(struct csid_device *csid, int port_id)
+{
+	csid->reg_update |= reg_update_rdi(csid, port_id);
+	writel(csid->reg_update, csid->base + CSID_REG_UPDATE_CMD);
+}
+
+static inline void csid_reg_update_clear(struct csid_device *csid,
+					 int port_id)
+{
+	csid->reg_update &= ~reg_update_rdi(csid, port_id);
+	writel(csid->reg_update, csid->base + CSID_REG_UPDATE_CMD);
+}
+
+static void __csid_configure_rx(struct csid_device *csid,
+				struct csid_phy_config *phy, int vc)
+{
+	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_PACKET_ECC_CORRECTION_EN;
+	if (vc > 3)
+		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;
+
+	if (enable)
+		val = CSID_RDI_CTRL_HALT_CMD_RESUME_AT_FRAME_BOUNDARY;
+	else
+		val = CSID_RDI_CTRL_HALT_CMD_HALT_AT_FRAME_BOUNDARY;
+
+	writel(val, csid->base + CSID_RDI_CTRL(rdi));
+}
+
+static void __csid_configure_top(struct csid_device *csid)
+{
+	u32 val;
+
+	val = CSID_TOP_IO_PATH_CFG0_OUTPUT_IFE_EN | CSID_TOP_IO_PATH_CFG0_INTERNAL_CSID;
+	writel(val, csid->camss->csid_wrapper_base +
+	    CSID_TOP_IO_PATH_CFG0(csid->id));
+}
+
+static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc)
+{
+	u32 val;
+	u8 lane_cnt = csid->phy.lane_cnt;
+	/* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
+	struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
+	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 = 0;
+	writel(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc));
+
+	/*
+	 * 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;
+
+	/* note: for non-RDI path, this should be format->decode_format */
+	val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
+	val |= format->data_type << RDI_CFG0_DATA_TYPE;
+	val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
+	val |= dt_id << RDI_CFG0_DT_ID;
+	writel(val, csid->base + CSID_RDI_CFG0(vc));
+
+	val = RDI_CFG1_TIMESTAMP_STB_FRAME;
+	val |= RDI_CFG1_BYTE_CNTR_EN;
+	val |= RDI_CFG1_TIMESTAMP_EN;
+	val |= RDI_CFG1_DROP_H_EN;
+	val |= RDI_CFG1_DROP_V_EN;
+	val |= RDI_CFG1_CROP_H_EN;
+	val |= RDI_CFG1_CROP_V_EN;
+	val |= RDI_CFG1_PACKING_MIPI;
+
+	writel(val, csid->base + CSID_RDI_CFG1(vc));
+
+	val = 0;
+	writel(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));
+
+	val = 1;
+	writel(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));
+
+	val = 0;
+	writel(val, csid->base + CSID_RDI_CTRL(vc));
+
+	val = readl(csid->base + CSID_RDI_CFG0(vc));
+	if (enable)
+		val |= RDI_CFG0_ENABLE;
+	else
+		val &= ~RDI_CFG0_ENABLE;
+	writel(val, csid->base + CSID_RDI_CFG0(vc));
+}
+
+static void csid_configure_stream(struct csid_device *csid, u8 enable)
+{
+	int i;
+
+	__csid_configure_top(csid);
+
+       /* Loop through all enabled VCs and configure stream for each */
+	for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) {
+		if (csid->phy.en_vc & BIT(i)) {
+			__csid_configure_rdi_stream(csid, enable, i);
+			__csid_configure_rx(csid, &csid->phy, i);
+			__csid_ctrl_rdi(csid, enable, i);
+		}
+	}
+}
+
+/*
+ * 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);
+
+	writel(CSID_IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD);
+
+	/* preserve registers */
+	val = CSID_RESET_CFG_MODE_IMMEDIATE | CSID_RESET_CFG_LOCATION_COMPLETE;
+	writel(val, csid->base + CSID_RESET_CFG);
+
+	val = CSID_RESET_CMD_HW_RESET | CSID_RESET_CMD_SW_RESET;
+	writel(val, csid->base + CSID_RESET_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;
+	}
+
+	for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) {
+		/* Enable RUP done for the client port */
+		writel(CSID_CSI2_RDIN_RUP_DONE, csid->base + CSID_CSI2_RDIN_IRQ_MASK(i));
+	}
+
+	/* Clear RDI status */
+	writel(~0u, csid->base + CSID_BUF_DONE_IRQ_CLEAR);
+
+	/* Enable BUF_DONE bit for all write-master client ports */
+	writel(~0u, csid->base + CSID_BUF_DONE_IRQ_MASK);
+
+	/* Unmask all TOP interrupts */
+	writel(~0u, csid->base + CSID_TOP_IRQ_MASK);
+
+	return 0;
+}
+
+static void csid_rup_complete(struct csid_device *csid, int rdi)
+{
+	csid_reg_update_clear(csid, rdi);
+}
+
+/*
+ * 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 buf_done_val, val, val_top;
+	int i;
+
+	/* Latch and clear TOP status */
+	val_top = readl(csid->base + CSID_TOP_IRQ_STATUS);
+	writel(val_top, csid->base + CSID_TOP_IRQ_CLEAR);
+
+	/* Latch and clear CSID_CSI2 status */
+	val = readl(csid->base + CSID_CSI2_RX_IRQ_STATUS);
+	writel(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR);
+
+	/* Latch and clear top level BUF_DONE status */
+	buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS);
+	writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR);
+
+	/* Process state for each RDI channel */
+	for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) {
+		val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i));
+		if (val)
+			writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i));
+
+		if (val & CSID_CSI2_RDIN_RUP_DONE)
+			csid_rup_complete(csid, i);
+
+		if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i))
+			camss_buf_done(csid->camss, csid->id, i);
+	}
+
+	/* Issue clear command */
+	writel(CSID_IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD);
+
+	/* Reset complete */
+	if (val_top & CSID_TOP_IRQ_RESET)
+		complete(&csid->reset_complete);
+
+	return IRQ_HANDLED;
+}
+
+static void csid_subdev_reg_update(struct csid_device *csid, int port_id, bool is_clear)
+{
+	if (is_clear)
+		csid_reg_update_clear(csid, port_id);
+	else
+		csid_reg_update(csid, port_id);
+}
+
+static void csid_subdev_init(struct csid_device *csid) {}
+
+const struct csid_hw_ops csid_ops_680 = {
+	.configure_testgen_pattern = NULL,
+	.configure_stream = csid_configure_stream,
+	.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 659ffb8bb7d58..6d1d4d78011bd 100644
--- a/drivers/media/platform/qcom/camss/camss-csid.h
+++ b/drivers/media/platform/qcom/camss/camss-csid.h
@@ -236,6 +236,7 @@ extern const struct csid_formats csid_formats_gen2;
 
 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_680;
 extern const struct csid_hw_ops csid_ops_gen2;
 extern const struct csid_hw_ops csid_ops_780;
 

-- 
2.47.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 4/7] media: qcom: camss: Add VFE680 support
  2025-01-20 15:46 [PATCH 0/7] media: qcom: camss: Add X1 Elite support Bryan O'Donoghue
                   ` (2 preceding siblings ...)
  2025-01-20 15:47 ` [PATCH 3/7] media: qcom: camss: Add CSID 680 support Bryan O'Donoghue
@ 2025-01-20 15:47 ` Bryan O'Donoghue
  2025-01-22  0:17   ` Vladimir Zapolskiy
  2025-01-20 15:47 ` [PATCH 5/7] media: qcom: camss: Add support for 3ph CSIPHY write settle delay Bryan O'Donoghue
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Bryan O'Donoghue @ 2025-01-20 15:47 UTC (permalink / raw)
  To: Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Vladimir Zapolskiy,
	Depeng Shao, Vikram Sharma, Bryan O'Donoghue

Add silicon enabling support for VFE680 as found on sm8450, x1e and
derivatives thereof.

References previous work from Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 drivers/media/platform/qcom/camss/Makefile        |   1 +
 drivers/media/platform/qcom/camss/camss-vfe-680.c | 243 ++++++++++++++++++++++
 drivers/media/platform/qcom/camss/camss-vfe.h     |   1 +
 3 files changed, 245 insertions(+)

diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile
index 71797745f2f71..d26a9c24a430a 100644
--- a/drivers/media/platform/qcom/camss/Makefile
+++ b/drivers/media/platform/qcom/camss/Makefile
@@ -18,6 +18,7 @@ qcom-camss-objs += \
 		camss-vfe-4-8.o \
 		camss-vfe-17x.o \
 		camss-vfe-480.o \
+		camss-vfe-680.o \
 		camss-vfe-780.o \
 		camss-vfe-gen1.o \
 		camss-vfe.o \
diff --git a/drivers/media/platform/qcom/camss/camss-vfe-680.c b/drivers/media/platform/qcom/camss/camss-vfe-680.c
new file mode 100644
index 0000000000000..1b2aa2c98887a
--- /dev/null
+++ b/drivers/media/platform/qcom/camss/camss-vfe-680.c
@@ -0,0 +1,243 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * camss-vfe-680.c
+ *
+ * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v680
+ *
+ * Copyright (C) 2024 Linaro Ltd.
+ */
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+
+#include "camss.h"
+#include "camss-vfe.h"
+
+#define VFE_TOP_IRQn_STATUS(vfe, n)		((vfe_is_lite(vfe) ? 0x1c : 0x44) + (n) * 4)
+#define VFE_TOP_IRQn_MASK(vfe, n)		((vfe_is_lite(vfe) ? 0x24 : 0x34) + (n) * 4)
+#define VFE_TOP_IRQn_CLEAR(vfe, n)		((vfe_is_lite(vfe) ? 0x2c : 0x3c) + (n) * 4)
+#define		VFE_IRQ1_SOF(vfe, rdi)		((vfe_is_lite(vfe) ? BIT(2) : BIT(8)) << ((rdi) * 2))
+#define		VFE_IRQ1_EOF(vfe, rdi)		((vfe_is_lite(vfe) ? BIT(3) : BIT(9)) << ((rdi) * 2))
+#define VFE_TOP_IRQ_CMD(vfe)			(vfe_is_lite(vfe) ? 0x38 : 0x30)
+#define		VFE_TOP_IRQ_CMD_GLOBAL_CLEAR	BIT(0)
+#define VFE_TOP_DIAG_CONFIG			(vfe_is_lite(vfe) ? 0x40 : 0x50)
+
+#define VFE_TOP_DEBUG_11(vfe)			(vfe_is_lite(vfe) ? 0x40 : 0xcc)
+#define VFE_TOP_DEBUG_12(vfe)			(vfe_is_lite(vfe) ? 0x40 : 0xd0)
+#define VFE_TOP_DEBUG_13(vfe)			(vfe_is_lite(vfe) ? 0x40 : 0xd4)
+
+#define VFE_BUS_IRQn_MASK(vfe, n)		((vfe_is_lite(vfe) ? 0x218 : 0xc18) + (n) * 4)
+#define VFE_BUS_IRQn_CLEAR(vfe, n)		((vfe_is_lite(vfe) ? 0x220 : 0xc20) + (n) * 4)
+#define VFE_BUS_IRQn_STATUS(vfe, n)		((vfe_is_lite(vfe) ? 0x228 : 0xc28) + (n) * 4)
+#define VFE_BUS_IRQ_GLOBAL_CLEAR(vfe)		(vfe_is_lite(vfe) ? 0x230 : 0xc30)
+#define VFE_BUS_WR_VIOLATION_STATUS(vfe)	(vfe_is_lite(vfe) ? 0x264 : 0xc64)
+#define VFE_BUS_WR_OVERFLOW_STATUS(vfe)		(vfe_is_lite(vfe) ? 0x268 : 0xc68)
+#define VFE_BUS_WR_IMAGE_VIOLATION_STATUS(vfe)	(vfe_is_lite(vfe) ? 0x270 : 0xc70)
+
+#define VFE_BUS_CFG(vfe, c)			((vfe_is_lite(vfe) ? 0x400 : 0xe00) + (c) * 0x100)
+#define VFE_BUS_IMAGE_ADDR(vfe, c)		((vfe_is_lite(vfe) ? 0x404 : 0xe04) + (c) * 0x100)
+#define VFE_BUS_FRAME_INCR(vfe, c)		((vfe_is_lite(vfe) ? 0x408 : 0xe08) + (c) * 0x100)
+#define VFE_BUS_IMAGE_CFG0(vfe, c)		((vfe_is_lite(vfe) ? 0x40c : 0xe0c) + (c) * 0x100)
+#define		VFE_BUS_IMAGE_CFG0_DATA(h, s)	(((h) << 16) | ((s) >> 4))
+#define WM_IMAGE_CFG_0_DEFAULT_WIDTH		(0xFFFF)
+
+#define VFE_BUS_IMAGE_CFG1(vfe, c)		((vfe_is_lite(vfe) ? 0x410 : 0xe10) + (c) * 0x100)
+#define VFE_BUS_IMAGE_CFG2(vfe, c)		((vfe_is_lite(vfe) ? 0x414 : 0xe14) + (c) * 0x100)
+#define VFE_BUS_PACKER_CFG(vfe, c)		((vfe_is_lite(vfe) ? 0x418 : 0xe18) + (c) * 0x100)
+#define VFE_BUS_IRQ_SUBSAMPLE_PERIOD(vfe, c)	((vfe_is_lite(vfe) ? 0x430 : 0xe30) + (c) * 0x100)
+#define VFE_BUS_IRQ_SUBSAMPLE_PATTERN(vfe, c)	((vfe_is_lite(vfe) ? 0x434 : 0xe34) + (c) * 0x100)
+#define VFE_BUS_FRAMEDROP_PERIOD(vfe, c)	((vfe_is_lite(vfe) ? 0x438 : 0xe38) + (c) * 0x100)
+#define VFE_BUS_FRAMEDROP_PATTERN(vfe, c)	((vfe_is_lite(vfe) ? 0x43c : 0xe3c) + (c) * 0x100)
+#define VFE_BUS_MMU_PREFETCH_CFG(vfe, c)	((vfe_is_lite(vfe) ? 0x460 : 0xe60) + (c) * 0x100)
+#define		VFE_BUS_MMU_PREFETCH_CFG_EN	BIT(0)
+#define VFE_BUS_MMU_PREFETCH_MAX_OFFSET(vfe, c)	((vfe_is_lite(vfe) ? 0x464 : 0xe64) + (c) * 0x100)
+#define VFE_BUS_ADDR_STATUS0(vfe, c)		((vfe_is_lite(vfe) ? 0x470 : 0xe70) + (c) * 0x100)
+
+/*
+ * TODO: differentiate the port id based on requested type of RDI, BHIST etc
+ *
+ * IFE write master IDs
+ *
+ * VIDEO_FULL_Y		0
+ * VIDEO_FULL_C		1
+ * VIDEO_DS_4:1		2
+ * VIDEO_DS_16:1	3
+ * DISPLAY_FULL_Y	4
+ * DISPLAY_FULL_C	5
+ * DISPLAY_DS_4:1	6
+ * DISPLAY_DS_16:1	7
+ * FD_Y			8
+ * FD_C			9
+ * PIXEL_RAW		10
+ * STATS_BE0		11
+ * STATS_BHIST0		12
+ * STATS_TINTLESS_BG	13
+ * STATS_AWB_BG		14
+ * STATS_AWB_BFW	15
+ * STATS_BAF		16
+ * STATS_BHIST		17
+ * STATS_RS		18
+ * STATS_IHIST		19
+ * SPARSE_PD		20
+ * PDAF_V2.0_PD_DATA	21
+ * PDAF_V2.0_SAD	22
+ * LCR			23
+ * RDI0			24
+ * RDI1			25
+ * RDI2			26
+ * LTM_STATS		27
+ *
+ * IFE Lite write master IDs
+ *
+ * RDI0			0
+ * RDI1			1
+ * RDI2			2
+ * RDI3			3
+ * GAMMA		4
+ * BE			5
+ */
+
+/* TODO: assign an ENUM in resources and use the provided master
+ *       id directly for RDI, STATS, AWB_BG, BHIST.
+ *       This macro only works because RDI is all we support right now.
+ */
+#define RDI_WM(n)			((vfe_is_lite(vfe) ? 0 : 24) + (n))
+
+static void vfe_global_reset(struct vfe_device *vfe)
+{
+	/* VFE680 has no global reset, simply report a completion */
+	complete(&vfe->reset_complete);
+}
+
+/*
+ * vfe_isr - VFE module interrupt handler
+ * @irq: Interrupt line
+ * @dev: VFE device
+ *
+ * Return IRQ_HANDLED on success
+ */
+static irqreturn_t vfe_isr(int irq, void *dev)
+{
+	return IRQ_HANDLED;
+}
+
+/*
+ * vfe_halt - Trigger halt on VFE module and wait to complete
+ * @vfe: VFE device
+ *
+ * Return 0 on success or a negative error code otherwise
+ */
+static int vfe_halt(struct vfe_device *vfe)
+{
+	/* rely on vfe_disable_output() to stop the VFE */
+	return 0;
+}
+
+static void vfe_disable_irq(struct vfe_device *vfe)
+{
+	writel(0u, vfe->base + VFE_TOP_IRQn_MASK(vfe, 0));
+	writel(0u, vfe->base + VFE_TOP_IRQn_MASK(vfe, 1));
+	writel(0u, vfe->base + VFE_BUS_IRQn_MASK(vfe, 0));
+	writel(0u, vfe->base + VFE_BUS_IRQn_MASK(vfe, 1));
+}
+
+static void vfe_wm_update(struct vfe_device *vfe, u8 rdi, u32 addr,
+			  struct vfe_line *line)
+{
+	u8 wm = RDI_WM(rdi);
+
+	writel(addr, vfe->base + VFE_BUS_IMAGE_ADDR(vfe, wm));
+}
+
+static void vfe_wm_start(struct vfe_device *vfe, u8 rdi, struct vfe_line *line)
+{
+	struct v4l2_pix_format_mplane *pix =
+		&line->video_out.active_fmt.fmt.pix_mp;
+	u32 stride = pix->plane_fmt[0].bytesperline;
+	u32 cfg;
+	u8 wm;
+
+	cfg = VFE_BUS_IMAGE_CFG0_DATA(pix->height, stride);
+	wm = RDI_WM(rdi);
+
+	writel(cfg, vfe->base + VFE_BUS_IMAGE_CFG0(vfe, wm));
+	writel(0, vfe->base + VFE_BUS_IMAGE_CFG1(vfe, wm));
+	writel(stride, vfe->base + VFE_BUS_IMAGE_CFG2(vfe, wm));
+	writel(0, vfe->base + VFE_BUS_PACKER_CFG(vfe, wm));
+
+	/* Set total frame increment value */
+	writel(pix->plane_fmt[0].bytesperline * pix->height,
+	       vfe->base + VFE_BUS_FRAME_INCR(vfe, wm));
+
+	/* MMU */
+	writel(VFE_BUS_MMU_PREFETCH_CFG_EN, vfe->base + VFE_BUS_MMU_PREFETCH_CFG(vfe, wm));
+	writel(~0u, vfe->base + VFE_BUS_MMU_PREFETCH_MAX_OFFSET(vfe, wm));
+
+	/* no dropped frames, one irq per frame */
+	writel(1, vfe->base + VFE_BUS_FRAMEDROP_PATTERN(vfe, wm));
+	writel(0, vfe->base + VFE_BUS_FRAMEDROP_PERIOD(vfe, wm));
+	writel(1, vfe->base + VFE_BUS_IRQ_SUBSAMPLE_PATTERN(vfe, wm));
+	writel(0, vfe->base + VFE_BUS_IRQ_SUBSAMPLE_PERIOD(vfe, wm));
+
+	/* We don't process IRQs for VFE in RDI mode at the moment */
+	vfe_disable_irq(vfe);
+
+	/* Enable WM */
+	writel(BIT(0), vfe->base + VFE_BUS_CFG(vfe, wm));
+
+	dev_dbg(vfe->camss->dev, "RDI%d WM:%d width %d height %d\n",
+		rdi, wm, pix->width, pix->height);
+	dev_dbg(vfe->camss->dev, "WM:%d stride %d\n", wm, stride);
+}
+
+static void vfe_wm_stop(struct vfe_device *vfe, u8 rdi)
+{
+	u8 wm = RDI_WM(rdi);
+
+	writel(0, vfe->base + VFE_BUS_CFG(vfe, wm));
+}
+
+static const struct camss_video_ops vfe_video_ops_680 = {
+	.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_680;
+}
+
+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);
+}
+
+const struct vfe_hw_ops vfe_ops_680 = {
+	.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,
+	.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,
+	.reg_update = vfe_reg_update,
+	.reg_update_clear = vfe_reg_update_clear,
+};
diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h
index 9dec5bc0d1b14..a23f666be7531 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe.h
+++ b/drivers/media/platform/qcom/camss/camss-vfe.h
@@ -243,6 +243,7 @@ extern const struct vfe_hw_ops vfe_ops_4_7;
 extern const struct vfe_hw_ops vfe_ops_4_8;
 extern const struct vfe_hw_ops vfe_ops_170;
 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_780;
 
 int vfe_get(struct vfe_device *vfe);

-- 
2.47.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 5/7] media: qcom: camss: Add support for 3ph CSIPHY write settle delay
  2025-01-20 15:46 [PATCH 0/7] media: qcom: camss: Add X1 Elite support Bryan O'Donoghue
                   ` (3 preceding siblings ...)
  2025-01-20 15:47 ` [PATCH 4/7] media: qcom: camss: Add VFE680 support Bryan O'Donoghue
@ 2025-01-20 15:47 ` Bryan O'Donoghue
  2025-01-22  0:23   ` Vladimir Zapolskiy
  2025-01-20 15:47 ` [PATCH 6/7] media: qcom: camss: csiphy-3ph: Add 4nm CSIPHY 2ph 5Gbps DPHY v2.1.2 init sequence Bryan O'Donoghue
  2025-01-20 15:47 ` [PATCH 7/7] media: qcom: camss: Add x1e80100 specific support Bryan O'Donoghue
  6 siblings, 1 reply; 18+ messages in thread
From: Bryan O'Donoghue @ 2025-01-20 15:47 UTC (permalink / raw)
  To: Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Vladimir Zapolskiy,
	Depeng Shao, Vikram Sharma, Bryan O'Donoghue

Currently we have an s32 value called delay which has been inherited from
the CamX code for PHY init. This unused value relates to a post-write delay
latching time.

In the silicon test-bench which provides the basis for the CamX code the
write settle times are specified in nanoseconds.

In the upstream kernel we currently take no notice of the delay value and
use all zero in any case.

Nanosecond granularity timing from the perspective of the kernel is total
overkill, however for some PHY init sequences introduction of a settle
delay has a use.

Add support to the 3ph init sequence for microsecond level delay. A
readback of written data would probably accomplish the same thing but,
since the PHY init sequences in the wild provide a delay value - we can
just add support here for that delay and consume the values given.

Generally these delays are probably not necessary but, they do speak to a
theoretical delay that silicon test-benches utilise and therefore are
worthwhile to replicate if the given PHY init sequence has the data.

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 drivers/media/platform/qcom/camss/camss-csiphy-3ph-1-0.c | 4 +++-
 1 file changed, 3 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 a6cc957b986e1..b44939686e4bb 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
@@ -59,7 +59,7 @@
 struct csiphy_lane_regs {
 	s32 reg_addr;
 	s32 reg_data;
-	s32 delay;
+	u32 delay_us;
 	u32 csiphy_param_type;
 };
 
@@ -600,6 +600,8 @@ static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy,
 			break;
 		}
 		writel_relaxed(val, csiphy->base + r->reg_addr);
+		if (r->delay_us)
+			udelay(r->delay_us);
 	}
 }
 

-- 
2.47.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 6/7] media: qcom: camss: csiphy-3ph: Add 4nm CSIPHY 2ph 5Gbps DPHY v2.1.2 init sequence
  2025-01-20 15:46 [PATCH 0/7] media: qcom: camss: Add X1 Elite support Bryan O'Donoghue
                   ` (4 preceding siblings ...)
  2025-01-20 15:47 ` [PATCH 5/7] media: qcom: camss: Add support for 3ph CSIPHY write settle delay Bryan O'Donoghue
@ 2025-01-20 15:47 ` Bryan O'Donoghue
  2025-01-22  0:29   ` Vladimir Zapolskiy
  2025-01-20 15:47 ` [PATCH 7/7] media: qcom: camss: Add x1e80100 specific support Bryan O'Donoghue
  6 siblings, 1 reply; 18+ messages in thread
From: Bryan O'Donoghue @ 2025-01-20 15:47 UTC (permalink / raw)
  To: Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Vladimir Zapolskiy,
	Depeng Shao, Vikram Sharma, Bryan O'Donoghue

For various SoC skews at 4nm CSIPHY 2.1.2 is used. Add in the init sequence
with base control reg offset of 0x1000.

This initial version will support X1E80100. Take the silicon verification
PHY init parameters as a first/best guess pass.

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 .../platform/qcom/camss/camss-csiphy-3ph-1-0.c     | 126 +++++++++++++++++++++
 1 file changed, 126 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 b44939686e4bb..fc624a3da1c43 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
@@ -55,6 +55,7 @@
 #define CSIPHY_DNP_PARAMS		4
 #define CSIPHY_2PH_REGS			5
 #define CSIPHY_3PH_REGS			6
+#define CSIPHY_SKEW_CAL			7
 
 struct csiphy_lane_regs {
 	s32 reg_addr;
@@ -423,6 +424,130 @@ csiphy_lane_regs lane_regs_sm8550[] = {
 	{0x0C64, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
 };
 
+/* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */
+static const struct
+csiphy_lane_regs lane_regs_x1e80100[] = {
+	/* Power up lanes 2ph mode */
+	{0x1014, 0xD5, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x101C, 0x7A, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x1018, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
+
+	{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, 0x01, CSIPHY_DEFAULT_PARAMS},
+	{0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0000, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+	{0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0094, 0xD7, 0x00, CSIPHY_SKEW_CAL},
+	{0x005C, 0x00, 0x00, CSIPHY_SKEW_CAL},
+	{0x0060, 0xBD, 0x00, CSIPHY_SKEW_CAL},
+	{0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL},
+	{0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL},
+
+	{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, 0x01, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+	{0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+
+	{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, 0x01, CSIPHY_DEFAULT_PARAMS},
+	{0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0400, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+	{0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0494, 0xD7, 0x00, CSIPHY_SKEW_CAL},
+	{0x045C, 0x00, 0x00, CSIPHY_SKEW_CAL},
+	{0x0460, 0xBD, 0x00, CSIPHY_SKEW_CAL},
+	{0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL},
+	{0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL},
+
+	{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, 0x01, CSIPHY_DEFAULT_PARAMS},
+	{0x0830, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0800, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+	{0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0894, 0xD7, 0x00, CSIPHY_SKEW_CAL},
+	{0x085C, 0x00, 0x00, CSIPHY_SKEW_CAL},
+	{0x0860, 0xBD, 0x00, CSIPHY_SKEW_CAL},
+	{0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL},
+	{0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL},
+
+	{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, 0x01, CSIPHY_DEFAULT_PARAMS},
+	{0x0C30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0C00, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
+	{0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0C94, 0xD7, 0x00, CSIPHY_SKEW_CAL},
+	{0x0C5C, 0x00, 0x00, CSIPHY_SKEW_CAL},
+	{0x0C60, 0xBD, 0x00, CSIPHY_SKEW_CAL},
+	{0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL},
+	{0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL},
+};
+
 static void csiphy_hw_version_read(struct csiphy_device *csiphy,
 				   struct device *dev)
 {
@@ -594,6 +719,7 @@ static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy,
 			val = settle_cnt & 0xff;
 			break;
 		case CSIPHY_DNP_PARAMS:
+		case CSIPHY_SKEW_CAL:
 			continue;
 		default:
 			val = r->reg_data;

-- 
2.47.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH 7/7] media: qcom: camss: Add x1e80100 specific support
  2025-01-20 15:46 [PATCH 0/7] media: qcom: camss: Add X1 Elite support Bryan O'Donoghue
                   ` (5 preceding siblings ...)
  2025-01-20 15:47 ` [PATCH 6/7] media: qcom: camss: csiphy-3ph: Add 4nm CSIPHY 2ph 5Gbps DPHY v2.1.2 init sequence Bryan O'Donoghue
@ 2025-01-20 15:47 ` Bryan O'Donoghue
  2025-01-22  0:38   ` Vladimir Zapolskiy
  6 siblings, 1 reply; 18+ messages in thread
From: Bryan O'Donoghue @ 2025-01-20 15:47 UTC (permalink / raw)
  To: Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Vladimir Zapolskiy,
	Depeng Shao, Vikram Sharma, Bryan O'Donoghue

Populate CAMSS with x1e80100 specific hooks.

Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
---
 .../platform/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          | 286 +++++++++++++++++++++
 drivers/media/platform/qcom/camss/camss.h          |   1 +
 4 files changed, 295 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 fc624a3da1c43..24dd20de014e0 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
@@ -754,6 +754,7 @@ static bool csiphy_is_gen2(u32 version)
 	case CAMSS_8280XP:
 	case CAMSS_845:
 	case CAMSS_8550:
+	case CAMSS_X1E80100:
 		ret = true;
 		break;
 	}
@@ -842,6 +843,11 @@ 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_X1E80100:
+		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);
diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
index 9ffa6bc72cf1e..4f7a559f9992c 100644
--- a/drivers/media/platform/qcom/camss/camss-vfe.c
+++ b/drivers/media/platform/qcom/camss/camss-vfe.c
@@ -346,6 +346,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
 	case CAMSS_8280XP:
 	case CAMSS_845:
 	case CAMSS_8550:
+	case CAMSS_X1E80100:
 		switch (sink_code) {
 		case MEDIA_BUS_FMT_YUYV8_1X16:
 		{
@@ -1972,6 +1973,7 @@ static int vfe_bpl_align(struct vfe_device *vfe)
 	case CAMSS_8280XP:
 	case CAMSS_845:
 	case CAMSS_8550:
+	case CAMSS_X1E80100:
 		ret = 16;
 		break;
 	default:
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index a128b1d1c6d57..02fc49ff46d18 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -2294,6 +2294,276 @@ static const struct resources_icc icc_res_sm8550[] = {
 	},
 };
 
+static const struct camss_subdev_resources csiphy_res_x1e80100[] = {
+	/* CSIPHY0 */
+	{
+		.regulators = { "vdd-csiphy-0p8-supply",
+				"vdd-csiphy-1p2-supply" },
+		.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 = { "vdd-csiphy-0p8-supply",
+				"vdd-csiphy-1p2-supply" },
+		.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
+		},
+	},
+	/* CSIPHY2 */
+	{
+		.regulators = { "vdd-csiphy-0p8-supply",
+				"vdd-csiphy-1p2-supply" },
+		.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,
+			.formats = &csiphy_formats_sdm845
+		},
+	},
+	/* CSIPHY4 */
+	{
+		.regulators = { "vdd-csiphy-0p8-supply",
+				"vdd-csiphy-1p2-supply" },
+		.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
+		},
+	},
+};
+
+static const struct camss_subdev_resources csid_res_x1e80100[] = {
+	/* CSID0 */
+	{
+		.regulators = {},
+		.clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb",
+			   "cpas_fast_ahb", "csid", "csid_csiphy_rx" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 64000000, 80000000 },
+				{ 80000000,  100000000, 200000000,
+				  300000000, 400000000 },
+				{ 300000000, 400000000, 480000000 },
+				{ 300000000, 400000000, 480000000 }, },
+		.reg = { "csid0" },
+		.interrupt = { "csid0" },
+		.csid = {
+			.hw_ops = &csid_ops_680,
+			.parent_dev_ops = &vfe_parent_dev_ops,
+			.formats = &csid_formats_gen2
+		},
+	},
+	/* CSID1 */
+	{
+		.regulators = {},
+		.clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb",
+			   "cpas_fast_ahb", "csid", "csid_csiphy_rx" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 64000000, 80000000 },
+				{ 80000000,  100000000, 200000000,
+				  300000000, 400000000 },
+				{ 300000000, 400000000, 480000000 },
+				{ 300000000, 400000000, 480000000 }, },
+		.reg = { "csid1" },
+		.interrupt = { "csid1" },
+		.csid = {
+			.hw_ops = &csid_ops_680,
+			.parent_dev_ops = &vfe_parent_dev_ops,
+			.formats = &csid_formats_gen2
+		},
+	},
+	/* CSID2 */
+	{
+		.regulators = {},
+		.clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb",
+			   "cpas_fast_ahb", "csid", "csid_csiphy_rx" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 64000000, 80000000 },
+				{ 80000000,  100000000, 200000000,
+				  300000000, 400000000 },
+				{ 300000000, 400000000, 480000000 },
+				{ 300000000, 400000000, 480000000 }, },
+		.reg = { "csid2" },
+		.interrupt = { "csid2" },
+		.csid = {
+			.hw_ops = &csid_ops_680,
+			.parent_dev_ops = &vfe_parent_dev_ops,
+			.formats = &csid_formats_gen2
+		},
+	},
+	/* CSID_LITE0 */
+	{
+		.regulators = {},
+		.clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb",
+			   "cpas_fast_ahb", "csid", "csid_csiphy_rx" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 64000000, 80000000 },
+				{ 80000000,  100000000, 200000000,
+				  300000000, 400000000 },
+				{ 300000000, 400000000, 480000000 },
+				{ 300000000, 400000000, 480000000 }, },
+		.reg = { "csid_lite0" },
+		.interrupt = { "csid_lite0" },
+		.csid = {
+			.is_lite = true,
+			.hw_ops = &csid_ops_680,
+			.parent_dev_ops = &vfe_parent_dev_ops,
+			.formats = &csid_formats_gen2
+		}
+	},
+	/* CSID_LITE1 */
+	{
+		.regulators = {},
+		.clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb",
+			   "cpas_fast_ahb", "csid", "csid_csiphy_rx" },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 64000000, 80000000 },
+				{ 80000000,  100000000, 200000000,
+				  300000000, 400000000 },
+				{ 300000000, 400000000, 480000000 },
+				{ 300000000, 400000000, 480000000 }, },
+
+		.reg = { "csid_lite1" },
+		.interrupt = { "csid_lite1" },
+		.csid = {
+			.is_lite = true,
+			.hw_ops = &csid_ops_680,
+			.parent_dev_ops = &vfe_parent_dev_ops,
+			.formats = &csid_formats_gen2
+		}
+	},
+};
+
+static const struct camss_subdev_resources vfe_res_x1e80100[] = {
+	/* IFE0 */
+	{
+		.regulators = {},
+		.clock = {"camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb",
+			  "cpas_fast_ahb", "cpas_vfe0", "vfe0_fast_ahb",
+			  "vfe0" },
+		.clock_rate = { { 0 },
+				{ 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
+		},
+	},
+	/* IFE1 */
+	{
+		.regulators = {},
+		.clock = { "camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb",
+			   "cpas_fast_ahb", "cpas_vfe1", "vfe1_fast_ahb",
+			   "vfe1"  },
+		.clock_rate = { { 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 0 },
+				{ 345600000, 432000000, 594000000, 675000000,
+				  727000000 }, },
+		.reg = { "vfe1" },
+		.interrupt = { "vfe1" },
+		.vfe = {
+			.line_num = 4,
+			.pd_name = "ife1",
+			.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 = { { 0 },
+				{ 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 = { { 0 },
+				{ 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 resources_wrapper csid_wrapper_res_x1e80100 = {
+	.reg = "csid_wrapper",
+};
+
 /*
  * camss_add_clock_margin - Add margin to clock frequency rate
  * @rate: Clock frequency rate
@@ -3346,6 +3616,21 @@ static const struct camss_resources sm8550_resources = {
 	.link_entities = camss_link_entities
 };
 
+static const struct camss_resources x1e80100_resources = {
+	.version = CAMSS_X1E80100,
+	.pd_name = "top",
+	.csiphy_res = csiphy_res_x1e80100,
+	.csid_res = csid_res_x1e80100,
+	.vfe_res = vfe_res_x1e80100,
+	.csid_wrapper_res = &csid_wrapper_res_x1e80100,
+	.icc_res = icc_res_sc8280xp,
+	.icc_path_num = ARRAY_SIZE(icc_res_sc8280xp),
+	.csiphy_num = ARRAY_SIZE(csiphy_res_x1e80100),
+	.csid_num = ARRAY_SIZE(csid_res_x1e80100),
+	.vfe_num = ARRAY_SIZE(vfe_res_x1e80100),
+	.link_entities = camss_link_entities
+};
+
 static const struct of_device_id camss_dt_match[] = {
 	{ .compatible = "qcom,msm8916-camss", .data = &msm8916_resources },
 	{ .compatible = "qcom,msm8953-camss", .data = &msm8953_resources },
@@ -3356,6 +3641,7 @@ static const struct of_device_id camss_dt_match[] = {
 	{ .compatible = "qcom,sdm845-camss", .data = &sdm845_resources },
 	{ .compatible = "qcom,sm8250-camss", .data = &sm8250_resources },
 	{ .compatible = "qcom,sm8550-camss", .data = &sm8550_resources },
+	{ .compatible = "qcom,x1e80100-camss", .data = &x1e80100_resources },
 	{ }
 };
 
diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
index 58fc61e7cf7ad..426e80f1c4b52 100644
--- a/drivers/media/platform/qcom/camss/camss.h
+++ b/drivers/media/platform/qcom/camss/camss.h
@@ -86,6 +86,7 @@ enum camss_version {
 	CAMSS_8280XP,
 	CAMSS_845,
 	CAMSS_8550,
+	CAMSS_X1E80100,
 };
 
 enum icc_count {

-- 
2.47.1


^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 1/7] media: qcom: camss: Add an id property to struct resources
  2025-01-20 15:46 ` [PATCH 1/7] media: qcom: camss: Add an id property to struct resources Bryan O'Donoghue
@ 2025-01-21 23:38   ` Vladimir Zapolskiy
  0 siblings, 0 replies; 18+ messages in thread
From: Vladimir Zapolskiy @ 2025-01-21 23:38 UTC (permalink / raw)
  To: Bryan O'Donoghue, Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Depeng Shao, Vikram Sharma

On 1/20/25 17:46, Bryan O'Donoghue wrote:
> In various places in CAMSS we assume a linear set of declared devices
> {csiphy0, csiphy1, csiphy2} which currently works for upstream SoCs but for
> upcoming SoCs some of the SoC resources will result in a set such as
> {csiphy0, csiphy2} which will break the naive for() loops we have.
> 
> Introduce an identity property which resource declarations can populate
> hence facilitating non-linear resource naming.
> 
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>

Reviewed-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>

--
Best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 2/7] media: qcom: camss: Use the CSIPHY id property to find clock names
  2025-01-20 15:46 ` [PATCH 2/7] media: qcom: camss: Use the CSIPHY id property to find clock names Bryan O'Donoghue
@ 2025-01-21 23:40   ` Vladimir Zapolskiy
  0 siblings, 0 replies; 18+ messages in thread
From: Vladimir Zapolskiy @ 2025-01-21 23:40 UTC (permalink / raw)
  To: Bryan O'Donoghue, Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Depeng Shao, Vikram Sharma

On 1/20/25 17:46, Bryan O'Donoghue wrote:
> Use the CSIPHY id property to find clock names instead of relying on
> generating the clock names based on the control-loop index.
> 
> x1e80100 has CSIPHY0, CSIPHY1, CSIPHY2 and CSIPHY4 so simple index naming
> won't work whereas and 'id' property allows any ordering and any stepping
> between the CSIPHY names.
> 
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>

Reviewed-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>

--
Best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/7] media: qcom: camss: Add CSID 680 support
  2025-01-20 15:47 ` [PATCH 3/7] media: qcom: camss: Add CSID 680 support Bryan O'Donoghue
@ 2025-01-22  0:05   ` Vladimir Zapolskiy
  2025-01-22 13:33     ` Bryan O'Donoghue
  0 siblings, 1 reply; 18+ messages in thread
From: Vladimir Zapolskiy @ 2025-01-22  0:05 UTC (permalink / raw)
  To: Bryan O'Donoghue, Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Depeng Shao, Vikram Sharma

Hi Bryan.

On 1/20/25 17:47, Bryan O'Donoghue wrote:
> Add CSI Decoder (CSID) 680 support to CAMSS. This version of CSID has been
> shipped with SM8450 and x1e chips.
> 
> References previous work from Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
> 
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
>   drivers/media/platform/qcom/camss/Makefile         |   1 +
>   drivers/media/platform/qcom/camss/camss-csid-680.c | 422 +++++++++++++++++++++
>   drivers/media/platform/qcom/camss/camss-csid.h     |   1 +
>   3 files changed, 424 insertions(+)
> 
> diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile
> index f6db5b3b5ace3..71797745f2f71 100644
> --- a/drivers/media/platform/qcom/camss/Makefile
> +++ b/drivers/media/platform/qcom/camss/Makefile
> @@ -6,6 +6,7 @@ qcom-camss-objs += \
>   		camss-csid.o \
>   		camss-csid-4-1.o \
>   		camss-csid-4-7.o \
> +		camss-csid-680.o \
>   		camss-csid-gen2.o \
>   		camss-csid-780.o \

Alphabetical sorting is lost, but it's due to SM8550 change by Depeng,
I'll report it separately.

>   		camss-csiphy-2ph-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
> new file mode 100644
> index 0000000000000..2a989ce33c2a4
> --- /dev/null
> +++ b/drivers/media/platform/qcom/camss/camss-csid-680.c
> @@ -0,0 +1,422 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Qualcomm MSM Camera Subsystem - CSID (CSI Decoder) Module
> + *
> + * Copyright (C) 2020-2023 Linaro Ltd.

2025

> + */
> +#include <linux/completion.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +
> +#include "camss.h"
> +#include "camss-csid.h"
> +#include "camss-csid-gen2.h"
> +
> +#define CSID_TOP_IO_PATH_CFG0(csid)				(0x4 * (csid))
> +#define		CSID_TOP_IO_PATH_CFG0_INTERNAL_CSID		BIT(0)
> +#define		CSID_TOP_IO_PATH_CFG0_SFE_0			BIT(1)
> +#define		CSID_TOP_IO_PATH_CFG0_SFE_1			GENMASK(1, 0)
> +#define		CSID_TOP_IO_PATH_CFG0_SBI_0			BIT(4)
> +#define		CSID_TOP_IO_PATH_CFG0_SBI_1			GENMASK(3, 0)
> +#define		CSID_TOP_IO_PATH_CFG0_SBI_2			GENMASK(3, 1)
> +#define		CSID_TOP_IO_PATH_CFG0_OUTPUT_IFE_EN		BIT(8)
> +#define		CSID_TOP_IO_PATH_CFG0_SFE_OFFLINE_EN		BIT(12)
> +
> +#define CSID_RESET_CFG						0xc
> +#define		CSID_RESET_CFG_MODE_IMMEDIATE			BIT(0)
> +#define		CSID_RESET_CFG_LOCATION_COMPLETE		BIT(4)
> +
> +#define CSID_RESET_CMD						0x10
> +#define		CSID_RESET_CMD_HW_RESET				BIT(0)
> +#define		CSID_RESET_CMD_SW_RESET				BIT(1)
> +#define		CSID_RESET_CMD_IRQ_CTRL				BIT(2)
> +
> +#define CSID_IRQ_CMD						0x14
> +#define		CSID_IRQ_CMD_CLEAR				BIT(0)
> +#define		CSID_IRQ_CMD_SET				BIT(4)
> +
> +#define CSID_REG_UPDATE_CMD					0x18
> +
> +#define CSID_CSI2_RDIN_IRQ_STATUS(rdi)					(0xec + 0x10 * (rdi))

This register value is out of numeric order, you should put it
after CSID_CSI2_RX_IRQ_CLEAR on the list, and then you should
discover a redefinition easily.

> +#define		CSID_CSI2_RDIN_CCIF_VIOLATION				BIT(29)
> +#define		CSID_CSI2_RDIN_SENSOR_SWITCH_OUT_OF_SYNC_FRAME_DROP	BIT(28)
> +#define		CSID_CSI2_RDIN_ERROR_REC_WIDTH_VIOLATION		BIT(27)
> +#define		CSID_CSI2_RDIN_ERROR_REC_HEIGHT_VIOLATION		BIT(26)
> +#define		CSID_CSI2_RDIN_BATCH_END_MISSING_VIOLATION		BIT(25)
> +#define		CSID_CSI2_RDIN_ILLEGAL_BATCH_ID_IRQ			BIT(24)
> +#define		CSID_CSI2_RDIN_RUP_DONE					BIT(23)
> +#define		CSID_CSI2_RDIN_CAMIF_EPOCH_1_IRQ			BIT(22)
> +#define		CSID_CSI2_RDIN_CAMIF_EPOCH_0_IRQ			BIT(21)
> +#define		CSID_CSI2_RDIN_ERROR_REC_OVERFLOW_IRQ			BIT(19)
> +#define		CSID_CSI2_RDIN_ERROR_REC_FRAME_DROP			BIT(18)
> +#define		CSID_CSI2_RDIN_VCDT_GRP_CHANG				BIT(17)
> +#define		CSID_CSI2_RDIN_VCDT_GRP_0_SEL				BIT(16)
> +#define		CSID_CSI2_RDIN_VCDT_GRP_1_SEL				BIT(15)
> +#define		CSID_CSI2_RDIN_ERROR_LINE_COUNT				BIT(14)
> +#define		CSID_CSI2_RDIN_ERROR_PIX_COUNT				BIT(13)
> +#define		CSID_CSI2_RDIN_INFO_INPUT_SOF				BIT(12)
> +#define		CSID_CSI2_RDIN_INFO_INPUT_SOL				BIT(11)
> +#define		CSID_CSI2_RDIN_INFO_INPUT_EOL				BIT(10)
> +#define		CSID_CSI2_RDIN_INFO_INPUT_EOF				BIT(9)
> +#define		CSID_CSI2_RDIN_INFO_FRAME_DROP_SOF			BIT(8)
> +#define		CSID_CSI2_RDIN_INFO_FRAME_DROP_SOL			BIT(7)
> +#define		CSID_CSI2_RDIN_INFO_FRAME_DROP_EOL			BIT(6)
> +#define		CSID_CSI2_RDIN_INFO_FRAME_DROP_EOF			BIT(5)
> +#define		CSID_CSI2_RDIN_INFO_CAMIF_SOF				BIT(4)
> +#define		CSID_CSI2_RDIN_INFO_CAMIF_EOF				BIT(3)
> +#define		CSID_CSI2_RDIN_INFO_FIFO_OVERFLOW			BIT(2)
> +#define		CSID_CSI2_RDIN_RES1					BIT(1)
> +#define		CSID_CSI2_RDIN_RES0					BIT(0)
> +
> +#define CSID_CSI2_RDIN_IRQ_MASK(rdi)				(0xf0 + 0x10 * (rdi))
> +#define CSID_CSI2_RDIN_IRQ_CLEAR(rdi)				(0xf4 + 0x10 * (rdi))
> +#define CSID_CSI2_RDIN_IRQ_SET(rdi)				(0xf8 + 0x10 * (rdi))
> +
> +#define CSID_TOP_IRQ_STATUS					0x7c
> +#define CSID_TOP_IRQ_MASK					0x80
> +#define CSID_TOP_IRQ_CLEAR					0x84
> +#define		CSID_TOP_IRQ_RESET				BIT(0)
> +#define		CSID_TOP_IRQ_RX					BIT(2)
> +#define		CSID_TOP_IRQ_LONG_PKT(rdi)			(BIT(8) << (rdi))
> +#define		CSID_TOP_IRQ_BUF_DONE				BIT(13)
> +
> +#define CSID_BUF_DONE_IRQ_STATUS				0x8c
> +#define	BUF_DONE_IRQ_STATUS_RDI_OFFSET				(csid_is_lite(csid) ? 1 : 14)
> +#define CSID_BUF_DONE_IRQ_MASK					0x90
> +#define CSID_BUF_DONE_IRQ_CLEAR					0x94
> +
> +#define CSID_CSI2_RX_IRQ_STATUS					0x9c
> +#define CSID_CSI2_RX_IRQ_MASK					0xa0
> +#define CSID_CSI2_RX_IRQ_CLEAR					0xa4
> +
> +#define CSID_CSI2_RDI_IRQ_STATUS(rdi)				(0xec + 0x10 * (rdi))
> +#define CSID_CSI2_RDI_IRQ_MASK(rdi)				(0xf0 + 0x10 * (rdi))
> +#define CSID_CSI2_RDI_IRQ_CLEAR(rdi)				(0xf4 + 0x10 * (rdi))
> +
> +#define CSID_CSI2_RX_CFG0					0x200
> +#define		CSI2_RX_CFG0_NUM_ACTIVE_LANES			0
> +#define		CSI2_RX_CFG0_DL0_INPUT_SEL			4
> +#define		CSI2_RX_CFG0_DL1_INPUT_SEL			8
> +#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 CSID_CSI2_RX_CFG1					0x204
> +#define		CSI2_RX_CFG1_PACKET_ECC_CORRECTION_EN		BIT(0)
> +#define		CSI2_RX_CFG1_DE_SCRAMBLE_EN			BIT(1)
> +#define		CSI2_RX_CFG1_VC_MODE				BIT(2)
> +#define		CSI2_RX_CFG1_COMPLETE_STREAM_EN			BIT(4)
> +#define		CSI2_RX_CFG1_COMPLETE_STREAM_FRAME_TIMING	BIT(5)
> +#define		CSI2_RX_CFG1_MISR_EN				BIT(6)
> +#define		CSI2_RX_CFG1_CGC_MODE				BIT(7)
> +
> +#define CSID_CSI2_RX_CAPTURE_CTRL				0x208
> +#define		CSI2_RX_CAPTURE_LONG_PKT_EN			BIT(0)
> +#define		CSI2_RX_CAPTURE_SHORT_PKT_EN			BIT(1)
> +#define		CSI2_RX_CAPTURE_CPHY_PKT_EN			BIT(2)
> +#define		CSI2_RX_CAPTURE_LONG_PKT_DT			BIT(4)

To my knowledge it's not the bit value.

> +#define		CSI2_RX_CAPTURE_LONG_PKT_VC			BIT(10)

Same here.

> +#define		CSI2_RX_CAPTURE_SHORT_PKT_VC			BIT(15)
> +#define		CSI2_RX_CAPTURE_CPHY_PKT_DT			BIT(20)
> +#define		CSI2_RX_CAPTURE_CPHY_PKT_VC			BIT(26)

And apparently the same reasoning applies to the values above.

By the way I'm surprised that CSID_CSI2_RX_CAPTURE_CTRL is not written.

> +
> +#define CSID_CSI2_RX_TOTAL_PKTS_RCVD				0x240
> +#define CSID_CSI2_RX_STATS_ECC					0x244
> +#define CSID_CSI2_RX_CRC_ERRORS					0x248
> +
> +#define CSID_RDI_CFG0(rdi)					(0x500 + 0x100 * (rdi))
> +#define		RDI_CFG0_DECODE_FORMAT				12
> +#define		RDI_CFG0_DATA_TYPE				16
> +#define		RDI_CFG0_VIRTUAL_CHANNEL			22
> +#define		RDI_CFG0_DT_ID					27
> +#define		RDI_CFG0_ENABLE					BIT(31)
> +
> +#define CSID_RDI_CTRL(rdi)					(0x504 + 0x100 * (rdi))
> +#define		CSID_RDI_CTRL_HALT_CMD_HALT_AT_FRAME_BOUNDARY	0
> +#define		CSID_RDI_CTRL_HALT_CMD_RESUME_AT_FRAME_BOUNDARY	1
> +
> +#define CSID_RDI_CFG1(rdi)					(0x510 + 0x100 * (rdi))
> +#define		RDI_CFG1_TIMESTAMP_STB_FRAME			BIT(0)
> +#define		RDI_CFG1_TIMESTAMP_STB_IRQ			BIT(1)
> +#define		RDI_CFG1_BYTE_CNTR_EN				BIT(2)
> +#define		RDI_CFG1_TIMESTAMP_EN				BIT(4)
> +#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_MISR_EN				BIT(9)
> +#define		RDI_CFG1_PLAIN_ALIGN_MSB			BIT(11)
> +#define		RDI_CFG1_EARLY_EOF_EN				BIT(14)
> +#define		RDI_CFG1_PACKING_MIPI				BIT(15)
> +
> +#define CSID_RDI_ERR_RECOVERY_CFG0(rdi)				(0x514 + 0x100 * (rdi))
> +#define CSID_RDI_EPOCH_IRQ_CFG(rdi)				(0x52c + 0x100 * (rdi))
> +#define CSID_RDI_FRM_DROP_PATTERN(rdi)				(0x540 + 0x100 * (rdi))
> +#define CSID_RDI_FRM_DROP_PERIOD(rdi)				(0x544 + 0x100 * (rdi))
> +#define CSID_RDI_IRQ_SUBSAMPLE_PATTERN(rdi)			(0x548 + 0x100 * (rdi))
> +#define CSID_RDI_IRQ_SUBSAMPLE_PERIOD(rdi)			(0x54c + 0x100 * (rdi))
> +#define CSID_RDI_PIX_DROP_PATTERN(rdi)				(0x558 + 0x100 * (rdi))
> +#define CSID_RDI_PIX_DROP_PERIOD(rdi)				(0x55c + 0x100 * (rdi))
> +#define CSID_RDI_LINE_DROP_PATTERN(rdi)				(0x560 + 0x100 * (rdi))
> +#define CSID_RDI_LINE_DROP_PERIOD(rdi)				(0x564 + 0x100 * (rdi))
> +
> +static inline int reg_update_rdi(struct csid_device *csid, int n)
> +{
> +	return BIT(n + 4) + BIT(20 + n);

Please use (4 + n) and (20 + n) here.

> +}
> +
> +static void csid_reg_update(struct csid_device *csid, int port_id)
> +{
> +	csid->reg_update |= reg_update_rdi(csid, port_id);
> +	writel(csid->reg_update, csid->base + CSID_REG_UPDATE_CMD);
> +}
> +
> +static inline void csid_reg_update_clear(struct csid_device *csid,
> +					 int port_id)
> +{
> +	csid->reg_update &= ~reg_update_rdi(csid, port_id);
> +	writel(csid->reg_update, csid->base + CSID_REG_UPDATE_CMD);
> +}
> +
> +static void __csid_configure_rx(struct csid_device *csid,
> +				struct csid_phy_config *phy, int vc)
> +{
> +	int val;

u32 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_PACKET_ECC_CORRECTION_EN;
> +	if (vc > 3)
> +		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;

u32 val

> +
> +	if (enable)
> +		val = CSID_RDI_CTRL_HALT_CMD_RESUME_AT_FRAME_BOUNDARY;
> +	else
> +		val = CSID_RDI_CTRL_HALT_CMD_HALT_AT_FRAME_BOUNDARY;
> +
> +	writel(val, csid->base + CSID_RDI_CTRL(rdi));
> +}
> +
> +static void __csid_configure_top(struct csid_device *csid)
> +{
> +	u32 val;
> +
> +	val = CSID_TOP_IO_PATH_CFG0_OUTPUT_IFE_EN | CSID_TOP_IO_PATH_CFG0_INTERNAL_CSID;
> +	writel(val, csid->camss->csid_wrapper_base +
> +	    CSID_TOP_IO_PATH_CFG0(csid->id));
> +}
> +
> +static void __csid_configure_rdi_stream(struct csid_device *csid, u8 enable, u8 vc)
> +{
> +	u32 val;
> +	u8 lane_cnt = csid->phy.lane_cnt;
> +	/* Source pads matching RDI channels on hardware. Pad 1 -> RDI0, Pad 2 -> RDI1, etc. */
> +	struct v4l2_mbus_framefmt *input_format = &csid->fmt[MSM_CSID_PAD_FIRST_SRC + vc];
> +	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 = 0;
> +	writel(val, csid->base + CSID_RDI_FRM_DROP_PERIOD(vc));
> +
> +	/*
> +	 * 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;

It's a local variable declaration in the middle of the function.

> +
> +	/* note: for non-RDI path, this should be format->decode_format */
> +	val |= DECODE_FORMAT_PAYLOAD_ONLY << RDI_CFG0_DECODE_FORMAT;
> +	val |= format->data_type << RDI_CFG0_DATA_TYPE;
> +	val |= vc << RDI_CFG0_VIRTUAL_CHANNEL;
> +	val |= dt_id << RDI_CFG0_DT_ID;
> +	writel(val, csid->base + CSID_RDI_CFG0(vc));
> +
> +	val = RDI_CFG1_TIMESTAMP_STB_FRAME;
> +	val |= RDI_CFG1_BYTE_CNTR_EN;
> +	val |= RDI_CFG1_TIMESTAMP_EN;
> +	val |= RDI_CFG1_DROP_H_EN;
> +	val |= RDI_CFG1_DROP_V_EN;
> +	val |= RDI_CFG1_CROP_H_EN;
> +	val |= RDI_CFG1_CROP_V_EN;
> +	val |= RDI_CFG1_PACKING_MIPI;
> +
> +	writel(val, csid->base + CSID_RDI_CFG1(vc));
> +
> +	val = 0;
> +	writel(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PERIOD(vc));
> +
> +	val = 1;
> +	writel(val, csid->base + CSID_RDI_IRQ_SUBSAMPLE_PATTERN(vc));
> +
> +	val = 0;
> +	writel(val, csid->base + CSID_RDI_CTRL(vc));
> +
> +	val = readl(csid->base + CSID_RDI_CFG0(vc));
> +	if (enable)
> +		val |= RDI_CFG0_ENABLE;
> +	else
> +		val &= ~RDI_CFG0_ENABLE;
> +	writel(val, csid->base + CSID_RDI_CFG0(vc));
> +}
> +
> +static void csid_configure_stream(struct csid_device *csid, u8 enable)
> +{
> +	int i;
> +
> +	__csid_configure_top(csid);
> +
> +       /* Loop through all enabled VCs and configure stream for each */
> +	for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) {
> +		if (csid->phy.en_vc & BIT(i)) {
> +			__csid_configure_rdi_stream(csid, enable, i);
> +			__csid_configure_rx(csid, &csid->phy, i);
> +			__csid_ctrl_rdi(csid, enable, i);
> +		}
> +	}
> +}
> +
> +/*
> + * 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);
> +
> +	writel(CSID_IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD);
> +
> +	/* preserve registers */
> +	val = CSID_RESET_CFG_MODE_IMMEDIATE | CSID_RESET_CFG_LOCATION_COMPLETE;
> +	writel(val, csid->base + CSID_RESET_CFG);
> +
> +	val = CSID_RESET_CMD_HW_RESET | CSID_RESET_CMD_SW_RESET;
> +	writel(val, csid->base + CSID_RESET_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;
> +	}
> +
> +	for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) {
> +		/* Enable RUP done for the client port */
> +		writel(CSID_CSI2_RDIN_RUP_DONE, csid->base + CSID_CSI2_RDIN_IRQ_MASK(i));
> +	}
> +
> +	/* Clear RDI status */
> +	writel(~0u, csid->base + CSID_BUF_DONE_IRQ_CLEAR);
> +
> +	/* Enable BUF_DONE bit for all write-master client ports */
> +	writel(~0u, csid->base + CSID_BUF_DONE_IRQ_MASK);
> +
> +	/* Unmask all TOP interrupts */
> +	writel(~0u, csid->base + CSID_TOP_IRQ_MASK);
> +
> +	return 0;
> +}
> +
> +static void csid_rup_complete(struct csid_device *csid, int rdi)
> +{
> +	csid_reg_update_clear(csid, rdi);
> +}
> +
> +/*
> + * 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 buf_done_val, val, val_top;
> +	int i;
> +
> +	/* Latch and clear TOP status */
> +	val_top = readl(csid->base + CSID_TOP_IRQ_STATUS);
> +	writel(val_top, csid->base + CSID_TOP_IRQ_CLEAR);
> +
> +	/* Latch and clear CSID_CSI2 status */
> +	val = readl(csid->base + CSID_CSI2_RX_IRQ_STATUS);
> +	writel(val, csid->base + CSID_CSI2_RX_IRQ_CLEAR);
> +
> +	/* Latch and clear top level BUF_DONE status */
> +	buf_done_val = readl(csid->base + CSID_BUF_DONE_IRQ_STATUS);
> +	writel(buf_done_val, csid->base + CSID_BUF_DONE_IRQ_CLEAR);
> +
> +	/* Process state for each RDI channel */
> +	for (i = 0; i < MSM_CSID_MAX_SRC_STREAMS; i++) {
> +		val = readl(csid->base + CSID_CSI2_RDIN_IRQ_STATUS(i));
> +		if (val)
> +			writel(val, csid->base + CSID_CSI2_RDIN_IRQ_CLEAR(i));
> +
> +		if (val & CSID_CSI2_RDIN_RUP_DONE)
> +			csid_rup_complete(csid, i);
> +
> +		if (buf_done_val & BIT(BUF_DONE_IRQ_STATUS_RDI_OFFSET + i))
> +			camss_buf_done(csid->camss, csid->id, i);
> +	}
> +
> +	/* Issue clear command */
> +	writel(CSID_IRQ_CMD_CLEAR, csid->base + CSID_IRQ_CMD);
> +
> +	/* Reset complete */
> +	if (val_top & CSID_TOP_IRQ_RESET)
> +		complete(&csid->reset_complete);
> +
> +	return IRQ_HANDLED;
> +}
> +
> +static void csid_subdev_reg_update(struct csid_device *csid, int port_id, bool is_clear)
> +{
> +	if (is_clear)
> +		csid_reg_update_clear(csid, port_id);
> +	else
> +		csid_reg_update(csid, port_id);
> +}
> +
> +static void csid_subdev_init(struct csid_device *csid) {}
> +
> +const struct csid_hw_ops csid_ops_680 = {
> +	.configure_testgen_pattern = NULL,
> +	.configure_stream = csid_configure_stream,
> +	.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 659ffb8bb7d58..6d1d4d78011bd 100644
> --- a/drivers/media/platform/qcom/camss/camss-csid.h
> +++ b/drivers/media/platform/qcom/camss/camss-csid.h
> @@ -236,6 +236,7 @@ extern const struct csid_formats csid_formats_gen2;
>   
>   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_680;
>   extern const struct csid_hw_ops csid_ops_gen2;
>   extern const struct csid_hw_ops csid_ops_780;
>   

Sorting order is not preserved by a preceding changeset, unfortunately.

--
Best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 4/7] media: qcom: camss: Add VFE680 support
  2025-01-20 15:47 ` [PATCH 4/7] media: qcom: camss: Add VFE680 support Bryan O'Donoghue
@ 2025-01-22  0:17   ` Vladimir Zapolskiy
  0 siblings, 0 replies; 18+ messages in thread
From: Vladimir Zapolskiy @ 2025-01-22  0:17 UTC (permalink / raw)
  To: Bryan O'Donoghue, Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Depeng Shao, Vikram Sharma

Hi Bryan.

On 1/20/25 17:47, Bryan O'Donoghue wrote:
> Add silicon enabling support for VFE680 as found on sm8450, x1e and
> derivatives thereof.
> 
> References previous work from Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
> 
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
>   drivers/media/platform/qcom/camss/Makefile        |   1 +
>   drivers/media/platform/qcom/camss/camss-vfe-680.c | 243 ++++++++++++++++++++++
>   drivers/media/platform/qcom/camss/camss-vfe.h     |   1 +
>   3 files changed, 245 insertions(+)
> 
> diff --git a/drivers/media/platform/qcom/camss/Makefile b/drivers/media/platform/qcom/camss/Makefile
> index 71797745f2f71..d26a9c24a430a 100644
> --- a/drivers/media/platform/qcom/camss/Makefile
> +++ b/drivers/media/platform/qcom/camss/Makefile
> @@ -18,6 +18,7 @@ qcom-camss-objs += \
>   		camss-vfe-4-8.o \
>   		camss-vfe-17x.o \
>   		camss-vfe-480.o \
> +		camss-vfe-680.o \
>   		camss-vfe-780.o \
>   		camss-vfe-gen1.o \
>   		camss-vfe.o \
> diff --git a/drivers/media/platform/qcom/camss/camss-vfe-680.c b/drivers/media/platform/qcom/camss/camss-vfe-680.c
> new file mode 100644
> index 0000000000000..1b2aa2c98887a
> --- /dev/null
> +++ b/drivers/media/platform/qcom/camss/camss-vfe-680.c
> @@ -0,0 +1,243 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * camss-vfe-680.c
> + *
> + * Qualcomm MSM Camera Subsystem - VFE (Video Front End) Module v680
> + *
> + * Copyright (C) 2024 Linaro Ltd.

Please add 2025 also, and may be some earlier years to add here.

> + */
> +
> +#include <linux/delay.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +
> +#include "camss.h"
> +#include "camss-vfe.h"
> +
> +#define VFE_TOP_IRQn_STATUS(vfe, n)		((vfe_is_lite(vfe) ? 0x1c : 0x44) + (n) * 4)
> +#define VFE_TOP_IRQn_MASK(vfe, n)		((vfe_is_lite(vfe) ? 0x24 : 0x34) + (n) * 4)
> +#define VFE_TOP_IRQn_CLEAR(vfe, n)		((vfe_is_lite(vfe) ? 0x2c : 0x3c) + (n) * 4)
> +#define		VFE_IRQ1_SOF(vfe, rdi)		((vfe_is_lite(vfe) ? BIT(2) : BIT(8)) << ((rdi) * 2))
> +#define		VFE_IRQ1_EOF(vfe, rdi)		((vfe_is_lite(vfe) ? BIT(3) : BIT(9)) << ((rdi) * 2))
> +#define VFE_TOP_IRQ_CMD(vfe)			(vfe_is_lite(vfe) ? 0x38 : 0x30)
> +#define		VFE_TOP_IRQ_CMD_GLOBAL_CLEAR	BIT(0)
> +#define VFE_TOP_DIAG_CONFIG			(vfe_is_lite(vfe) ? 0x40 : 0x50)
> +
> +#define VFE_TOP_DEBUG_11(vfe)			(vfe_is_lite(vfe) ? 0x40 : 0xcc)
> +#define VFE_TOP_DEBUG_12(vfe)			(vfe_is_lite(vfe) ? 0x40 : 0xd0)
> +#define VFE_TOP_DEBUG_13(vfe)			(vfe_is_lite(vfe) ? 0x40 : 0xd4)

Those registers are unused, and it's unclear how to use them properly.

I would suggest to remove definitions of at least the VFE_TOP_DEBUG_*
registers.

> +
> +#define VFE_BUS_IRQn_MASK(vfe, n)		((vfe_is_lite(vfe) ? 0x218 : 0xc18) + (n) * 4)
> +#define VFE_BUS_IRQn_CLEAR(vfe, n)		((vfe_is_lite(vfe) ? 0x220 : 0xc20) + (n) * 4)
> +#define VFE_BUS_IRQn_STATUS(vfe, n)		((vfe_is_lite(vfe) ? 0x228 : 0xc28) + (n) * 4)
> +#define VFE_BUS_IRQ_GLOBAL_CLEAR(vfe)		(vfe_is_lite(vfe) ? 0x230 : 0xc30)
> +#define VFE_BUS_WR_VIOLATION_STATUS(vfe)	(vfe_is_lite(vfe) ? 0x264 : 0xc64)
> +#define VFE_BUS_WR_OVERFLOW_STATUS(vfe)		(vfe_is_lite(vfe) ? 0x268 : 0xc68)
> +#define VFE_BUS_WR_IMAGE_VIOLATION_STATUS(vfe)	(vfe_is_lite(vfe) ? 0x270 : 0xc70)
> +
> +#define VFE_BUS_CFG(vfe, c)			((vfe_is_lite(vfe) ? 0x400 : 0xe00) + (c) * 0x100)
> +#define VFE_BUS_IMAGE_ADDR(vfe, c)		((vfe_is_lite(vfe) ? 0x404 : 0xe04) + (c) * 0x100)
> +#define VFE_BUS_FRAME_INCR(vfe, c)		((vfe_is_lite(vfe) ? 0x408 : 0xe08) + (c) * 0x100)
> +#define VFE_BUS_IMAGE_CFG0(vfe, c)		((vfe_is_lite(vfe) ? 0x40c : 0xe0c) + (c) * 0x100)
> +#define		VFE_BUS_IMAGE_CFG0_DATA(h, s)	(((h) << 16) | ((s) >> 4))
> +#define WM_IMAGE_CFG_0_DEFAULT_WIDTH		(0xFFFF)
> +
> +#define VFE_BUS_IMAGE_CFG1(vfe, c)		((vfe_is_lite(vfe) ? 0x410 : 0xe10) + (c) * 0x100)
> +#define VFE_BUS_IMAGE_CFG2(vfe, c)		((vfe_is_lite(vfe) ? 0x414 : 0xe14) + (c) * 0x100)
> +#define VFE_BUS_PACKER_CFG(vfe, c)		((vfe_is_lite(vfe) ? 0x418 : 0xe18) + (c) * 0x100)
> +#define VFE_BUS_IRQ_SUBSAMPLE_PERIOD(vfe, c)	((vfe_is_lite(vfe) ? 0x430 : 0xe30) + (c) * 0x100)
> +#define VFE_BUS_IRQ_SUBSAMPLE_PATTERN(vfe, c)	((vfe_is_lite(vfe) ? 0x434 : 0xe34) + (c) * 0x100)
> +#define VFE_BUS_FRAMEDROP_PERIOD(vfe, c)	((vfe_is_lite(vfe) ? 0x438 : 0xe38) + (c) * 0x100)
> +#define VFE_BUS_FRAMEDROP_PATTERN(vfe, c)	((vfe_is_lite(vfe) ? 0x43c : 0xe3c) + (c) * 0x100)
> +#define VFE_BUS_MMU_PREFETCH_CFG(vfe, c)	((vfe_is_lite(vfe) ? 0x460 : 0xe60) + (c) * 0x100)
> +#define		VFE_BUS_MMU_PREFETCH_CFG_EN	BIT(0)
> +#define VFE_BUS_MMU_PREFETCH_MAX_OFFSET(vfe, c)	((vfe_is_lite(vfe) ? 0x464 : 0xe64) + (c) * 0x100)
> +#define VFE_BUS_ADDR_STATUS0(vfe, c)		((vfe_is_lite(vfe) ? 0x470 : 0xe70) + (c) * 0x100)
> +
> +/*
> + * TODO: differentiate the port id based on requested type of RDI, BHIST etc
> + *
> + * IFE write master IDs
> + *
> + * VIDEO_FULL_Y		0
> + * VIDEO_FULL_C		1
> + * VIDEO_DS_4:1		2
> + * VIDEO_DS_16:1	3
> + * DISPLAY_FULL_Y	4
> + * DISPLAY_FULL_C	5
> + * DISPLAY_DS_4:1	6
> + * DISPLAY_DS_16:1	7
> + * FD_Y			8
> + * FD_C			9
> + * PIXEL_RAW		10
> + * STATS_BE0		11
> + * STATS_BHIST0		12
> + * STATS_TINTLESS_BG	13
> + * STATS_AWB_BG		14
> + * STATS_AWB_BFW	15
> + * STATS_BAF		16
> + * STATS_BHIST		17
> + * STATS_RS		18
> + * STATS_IHIST		19
> + * SPARSE_PD		20
> + * PDAF_V2.0_PD_DATA	21
> + * PDAF_V2.0_SAD	22
> + * LCR			23
> + * RDI0			24
> + * RDI1			25
> + * RDI2			26
> + * LTM_STATS		27
> + *
> + * IFE Lite write master IDs
> + *
> + * RDI0			0
> + * RDI1			1
> + * RDI2			2
> + * RDI3			3
> + * GAMMA		4
> + * BE			5
> + */
> +
> +/* TODO: assign an ENUM in resources and use the provided master
> + *       id directly for RDI, STATS, AWB_BG, BHIST.
> + *       This macro only works because RDI is all we support right now.
> + */
> +#define RDI_WM(n)			((vfe_is_lite(vfe) ? 0 : 24) + (n))
> +
> +static void vfe_global_reset(struct vfe_device *vfe)
> +{
> +	/* VFE680 has no global reset, simply report a completion */
> +	complete(&vfe->reset_complete);
> +}
> +
> +/*
> + * vfe_isr - VFE module interrupt handler
> + * @irq: Interrupt line
> + * @dev: VFE device
> + *
> + * Return IRQ_HANDLED on success
> + */
> +static irqreturn_t vfe_isr(int irq, void *dev)
> +{
> +	return IRQ_HANDLED;
> +}
> +
> +/*
> + * vfe_halt - Trigger halt on VFE module and wait to complete
> + * @vfe: VFE device
> + *
> + * Return 0 on success or a negative error code otherwise
> + */
> +static int vfe_halt(struct vfe_device *vfe)
> +{
> +	/* rely on vfe_disable_output() to stop the VFE */
> +	return 0;
> +}
> +
> +static void vfe_disable_irq(struct vfe_device *vfe)
> +{
> +	writel(0u, vfe->base + VFE_TOP_IRQn_MASK(vfe, 0));
> +	writel(0u, vfe->base + VFE_TOP_IRQn_MASK(vfe, 1));
> +	writel(0u, vfe->base + VFE_BUS_IRQn_MASK(vfe, 0));
> +	writel(0u, vfe->base + VFE_BUS_IRQn_MASK(vfe, 1));
> +}
> +
> +static void vfe_wm_update(struct vfe_device *vfe, u8 rdi, u32 addr,
> +			  struct vfe_line *line)
> +{
> +	u8 wm = RDI_WM(rdi);
> +
> +	writel(addr, vfe->base + VFE_BUS_IMAGE_ADDR(vfe, wm));
> +}
> +
> +static void vfe_wm_start(struct vfe_device *vfe, u8 rdi, struct vfe_line *line)
> +{
> +	struct v4l2_pix_format_mplane *pix =
> +		&line->video_out.active_fmt.fmt.pix_mp;
> +	u32 stride = pix->plane_fmt[0].bytesperline;
> +	u32 cfg;
> +	u8 wm;
> +
> +	cfg = VFE_BUS_IMAGE_CFG0_DATA(pix->height, stride);
> +	wm = RDI_WM(rdi);
> +
> +	writel(cfg, vfe->base + VFE_BUS_IMAGE_CFG0(vfe, wm));
> +	writel(0, vfe->base + VFE_BUS_IMAGE_CFG1(vfe, wm));
> +	writel(stride, vfe->base + VFE_BUS_IMAGE_CFG2(vfe, wm));
> +	writel(0, vfe->base + VFE_BUS_PACKER_CFG(vfe, wm));
> +
> +	/* Set total frame increment value */
> +	writel(pix->plane_fmt[0].bytesperline * pix->height,
> +	       vfe->base + VFE_BUS_FRAME_INCR(vfe, wm));
> +
> +	/* MMU */
> +	writel(VFE_BUS_MMU_PREFETCH_CFG_EN, vfe->base + VFE_BUS_MMU_PREFETCH_CFG(vfe, wm));
> +	writel(~0u, vfe->base + VFE_BUS_MMU_PREFETCH_MAX_OFFSET(vfe, wm));
> +
> +	/* no dropped frames, one irq per frame */
> +	writel(1, vfe->base + VFE_BUS_FRAMEDROP_PATTERN(vfe, wm));
> +	writel(0, vfe->base + VFE_BUS_FRAMEDROP_PERIOD(vfe, wm));
> +	writel(1, vfe->base + VFE_BUS_IRQ_SUBSAMPLE_PATTERN(vfe, wm));
> +	writel(0, vfe->base + VFE_BUS_IRQ_SUBSAMPLE_PERIOD(vfe, wm));
> +
> +	/* We don't process IRQs for VFE in RDI mode at the moment */
> +	vfe_disable_irq(vfe);
> +
> +	/* Enable WM */
> +	writel(BIT(0), vfe->base + VFE_BUS_CFG(vfe, wm));

Please add a macro for this BIT(0).

> +
> +	dev_dbg(vfe->camss->dev, "RDI%d WM:%d width %d height %d\n",
> +		rdi, wm, pix->width, pix->height);
> +	dev_dbg(vfe->camss->dev, "WM:%d stride %d\n", wm, stride);
> +}
> +
> +static void vfe_wm_stop(struct vfe_device *vfe, u8 rdi)
> +{
> +	u8 wm = RDI_WM(rdi);
> +
> +	writel(0, vfe->base + VFE_BUS_CFG(vfe, wm));
> +}
> +
> +static const struct camss_video_ops vfe_video_ops_680 = {
> +	.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_680;
> +}
> +
> +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);
> +}
> +
> +const struct vfe_hw_ops vfe_ops_680 = {
> +	.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,
> +	.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,
> +	.reg_update = vfe_reg_update,
> +	.reg_update_clear = vfe_reg_update_clear,
> +};
> diff --git a/drivers/media/platform/qcom/camss/camss-vfe.h b/drivers/media/platform/qcom/camss/camss-vfe.h
> index 9dec5bc0d1b14..a23f666be7531 100644
> --- a/drivers/media/platform/qcom/camss/camss-vfe.h
> +++ b/drivers/media/platform/qcom/camss/camss-vfe.h
> @@ -243,6 +243,7 @@ extern const struct vfe_hw_ops vfe_ops_4_7;
>   extern const struct vfe_hw_ops vfe_ops_4_8;
>   extern const struct vfe_hw_ops vfe_ops_170;
>   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_780;
>   
>   int vfe_get(struct vfe_device *vfe);
> 

--
Best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 5/7] media: qcom: camss: Add support for 3ph CSIPHY write settle delay
  2025-01-20 15:47 ` [PATCH 5/7] media: qcom: camss: Add support for 3ph CSIPHY write settle delay Bryan O'Donoghue
@ 2025-01-22  0:23   ` Vladimir Zapolskiy
  0 siblings, 0 replies; 18+ messages in thread
From: Vladimir Zapolskiy @ 2025-01-22  0:23 UTC (permalink / raw)
  To: Bryan O'Donoghue, Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Depeng Shao, Vikram Sharma

On 1/20/25 17:47, Bryan O'Donoghue wrote:
> Currently we have an s32 value called delay which has been inherited from
> the CamX code for PHY init. This unused value relates to a post-write delay
> latching time.
> 
> In the silicon test-bench which provides the basis for the CamX code the
> write settle times are specified in nanoseconds.
> 
> In the upstream kernel we currently take no notice of the delay value and
> use all zero in any case.
> 
> Nanosecond granularity timing from the perspective of the kernel is total
> overkill, however for some PHY init sequences introduction of a settle
> delay has a use.
> 
> Add support to the 3ph init sequence for microsecond level delay. A
> readback of written data would probably accomplish the same thing but,
> since the PHY init sequences in the wild provide a delay value - we can
> just add support here for that delay and consume the values given.
> 
> Generally these delays are probably not necessary but, they do speak to a
> theoretical delay that silicon test-benches utilise and therefore are
> worthwhile to replicate if the given PHY init sequence has the data.
> 
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>

Reviewed-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>

--
Best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 6/7] media: qcom: camss: csiphy-3ph: Add 4nm CSIPHY 2ph 5Gbps DPHY v2.1.2 init sequence
  2025-01-20 15:47 ` [PATCH 6/7] media: qcom: camss: csiphy-3ph: Add 4nm CSIPHY 2ph 5Gbps DPHY v2.1.2 init sequence Bryan O'Donoghue
@ 2025-01-22  0:29   ` Vladimir Zapolskiy
  2025-01-22 13:41     ` Bryan O'Donoghue
  0 siblings, 1 reply; 18+ messages in thread
From: Vladimir Zapolskiy @ 2025-01-22  0:29 UTC (permalink / raw)
  To: Bryan O'Donoghue, Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Depeng Shao, Vikram Sharma

Hi Bryan.

On 1/20/25 17:47, Bryan O'Donoghue wrote:
> For various SoC skews at 4nm CSIPHY 2.1.2 is used. Add in the init sequence
> with base control reg offset of 0x1000.
> 
> This initial version will support X1E80100. Take the silicon verification
> PHY init parameters as a first/best guess pass.
> 
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
>   .../platform/qcom/camss/camss-csiphy-3ph-1-0.c     | 126 +++++++++++++++++++++
>   1 file changed, 126 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 b44939686e4bb..fc624a3da1c43 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
> @@ -55,6 +55,7 @@
>   #define CSIPHY_DNP_PARAMS		4
>   #define CSIPHY_2PH_REGS			5
>   #define CSIPHY_3PH_REGS			6
> +#define CSIPHY_SKEW_CAL			7

This one is not needed, having CSIPHY_DNP_PARAMS only is good enough.

>   
>   struct csiphy_lane_regs {
>   	s32 reg_addr;
> @@ -423,6 +424,130 @@ csiphy_lane_regs lane_regs_sm8550[] = {
>   	{0x0C64, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
>   };
>   
> +/* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */
> +static const struct
> +csiphy_lane_regs lane_regs_x1e80100[] = {
> +	/* Power up lanes 2ph mode */
> +	{0x1014, 0xD5, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x101C, 0x7A, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x1018, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
> +
> +	{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, 0x01, CSIPHY_DEFAULT_PARAMS},
> +	{0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x0000, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
> +	{0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x0094, 0xD7, 0x00, CSIPHY_SKEW_CAL},
> +	{0x005C, 0x00, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0060, 0xBD, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL},

Double write record, which is anyway ignored, but one should
be enough.

> +
> +	{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, 0x01, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
> +	{0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},

Writing the same value to a register 4 times in a row, apparently
it's not needed, one time write is sufficient.

> +
> +	{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, 0x01, CSIPHY_DEFAULT_PARAMS},
> +	{0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x0400, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
> +	{0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x0494, 0xD7, 0x00, CSIPHY_SKEW_CAL},
> +	{0x045C, 0x00, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0460, 0xBD, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL},

Two equal "ignored" writes.

> +
> +	{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, 0x01, CSIPHY_DEFAULT_PARAMS},
> +	{0x0830, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x0800, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
> +	{0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x0894, 0xD7, 0x00, CSIPHY_SKEW_CAL},
> +	{0x085C, 0x00, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0860, 0xBD, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL},

Two equal "ignored" writes.

> +
> +	{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, 0x01, CSIPHY_DEFAULT_PARAMS},
> +	{0x0C30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x0C00, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
> +	{0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
> +	{0x0C94, 0xD7, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0C5C, 0x00, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0C60, 0xBD, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL},
> +	{0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL},

Two equal "ignored" writes.

> +};
> +
>   static void csiphy_hw_version_read(struct csiphy_device *csiphy,
>   				   struct device *dev)
>   {
> @@ -594,6 +719,7 @@ static void csiphy_gen2_config_lanes(struct csiphy_device *csiphy,
>   			val = settle_cnt & 0xff;
>   			break;
>   		case CSIPHY_DNP_PARAMS:
> +		case CSIPHY_SKEW_CAL:

Having CSIPHY_DNP_PARAMS is good enough, no need to add another
"dummy" write type.

>   			continue;
>   		default:
>   			val = r->reg_data;
> 

--
Best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 7/7] media: qcom: camss: Add x1e80100 specific support
  2025-01-20 15:47 ` [PATCH 7/7] media: qcom: camss: Add x1e80100 specific support Bryan O'Donoghue
@ 2025-01-22  0:38   ` Vladimir Zapolskiy
  0 siblings, 0 replies; 18+ messages in thread
From: Vladimir Zapolskiy @ 2025-01-22  0:38 UTC (permalink / raw)
  To: Bryan O'Donoghue, Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Depeng Shao, Vikram Sharma

On 1/20/25 17:47, Bryan O'Donoghue wrote:
> Populate CAMSS with x1e80100 specific hooks.
> 
> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
> ---
>   .../platform/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          | 286 +++++++++++++++++++++
>   drivers/media/platform/qcom/camss/camss.h          |   1 +
>   4 files changed, 295 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 fc624a3da1c43..24dd20de014e0 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
> @@ -754,6 +754,7 @@ static bool csiphy_is_gen2(u32 version)
>   	case CAMSS_8280XP:
>   	case CAMSS_845:
>   	case CAMSS_8550:
> +	case CAMSS_X1E80100:
>   		ret = true;
>   		break;
>   	}
> @@ -842,6 +843,11 @@ 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_X1E80100:
> +		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);
> diff --git a/drivers/media/platform/qcom/camss/camss-vfe.c b/drivers/media/platform/qcom/camss/camss-vfe.c
> index 9ffa6bc72cf1e..4f7a559f9992c 100644
> --- a/drivers/media/platform/qcom/camss/camss-vfe.c
> +++ b/drivers/media/platform/qcom/camss/camss-vfe.c
> @@ -346,6 +346,7 @@ static u32 vfe_src_pad_code(struct vfe_line *line, u32 sink_code,
>   	case CAMSS_8280XP:
>   	case CAMSS_845:
>   	case CAMSS_8550:
> +	case CAMSS_X1E80100:
>   		switch (sink_code) {
>   		case MEDIA_BUS_FMT_YUYV8_1X16:
>   		{
> @@ -1972,6 +1973,7 @@ static int vfe_bpl_align(struct vfe_device *vfe)
>   	case CAMSS_8280XP:
>   	case CAMSS_845:
>   	case CAMSS_8550:
> +	case CAMSS_X1E80100:
>   		ret = 16;
>   		break;
>   	default:
> diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
> index a128b1d1c6d57..02fc49ff46d18 100644
> --- a/drivers/media/platform/qcom/camss/camss.c
> +++ b/drivers/media/platform/qcom/camss/camss.c
> @@ -2294,6 +2294,276 @@ static const struct resources_icc icc_res_sm8550[] = {
>   	},
>   };
>   
> +static const struct camss_subdev_resources csiphy_res_x1e80100[] = {
> +	/* CSIPHY0 */
> +	{
> +		.regulators = { "vdd-csiphy-0p8-supply",
> +				"vdd-csiphy-1p2-supply" },

Just a note that for SM8450 there are separate combined 01, 23, and 45
PHY supplies called as 0p9 (not 0p8) and 1p2.

Something similar is expected to be here also, I believe.

FWIW I'm in the process of completing CSIPHY rework to this respect.

> +		.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 = { "vdd-csiphy-0p8-supply",
> +				"vdd-csiphy-1p2-supply" },
> +		.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
> +		},
> +	},
> +	/* CSIPHY2 */
> +	{
> +		.regulators = { "vdd-csiphy-0p8-supply",
> +				"vdd-csiphy-1p2-supply" },
> +		.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,
> +			.formats = &csiphy_formats_sdm845
> +		},
> +	},
> +	/* CSIPHY4 */
> +	{
> +		.regulators = { "vdd-csiphy-0p8-supply",
> +				"vdd-csiphy-1p2-supply" },
> +		.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
> +		},
> +	},
> +};
> +
> +static const struct camss_subdev_resources csid_res_x1e80100[] = {
> +	/* CSID0 */
> +	{
> +		.regulators = {},
> +		.clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb",
> +			   "cpas_fast_ahb", "csid", "csid_csiphy_rx" },
> +		.clock_rate = { { 0 },
> +				{ 0 },
> +				{ 64000000, 80000000 },
> +				{ 80000000,  100000000, 200000000,
> +				  300000000, 400000000 },
> +				{ 300000000, 400000000, 480000000 },
> +				{ 300000000, 400000000, 480000000 }, },
> +		.reg = { "csid0" },
> +		.interrupt = { "csid0" },
> +		.csid = {
> +			.hw_ops = &csid_ops_680,
> +			.parent_dev_ops = &vfe_parent_dev_ops,
> +			.formats = &csid_formats_gen2
> +		},
> +	},
> +	/* CSID1 */
> +	{
> +		.regulators = {},
> +		.clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb",
> +			   "cpas_fast_ahb", "csid", "csid_csiphy_rx" },
> +		.clock_rate = { { 0 },
> +				{ 0 },
> +				{ 64000000, 80000000 },
> +				{ 80000000,  100000000, 200000000,
> +				  300000000, 400000000 },
> +				{ 300000000, 400000000, 480000000 },
> +				{ 300000000, 400000000, 480000000 }, },
> +		.reg = { "csid1" },
> +		.interrupt = { "csid1" },
> +		.csid = {
> +			.hw_ops = &csid_ops_680,
> +			.parent_dev_ops = &vfe_parent_dev_ops,
> +			.formats = &csid_formats_gen2
> +		},
> +	},
> +	/* CSID2 */
> +	{
> +		.regulators = {},
> +		.clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb",
> +			   "cpas_fast_ahb", "csid", "csid_csiphy_rx" },
> +		.clock_rate = { { 0 },
> +				{ 0 },
> +				{ 64000000, 80000000 },
> +				{ 80000000,  100000000, 200000000,
> +				  300000000, 400000000 },
> +				{ 300000000, 400000000, 480000000 },
> +				{ 300000000, 400000000, 480000000 }, },
> +		.reg = { "csid2" },
> +		.interrupt = { "csid2" },
> +		.csid = {
> +			.hw_ops = &csid_ops_680,
> +			.parent_dev_ops = &vfe_parent_dev_ops,
> +			.formats = &csid_formats_gen2
> +		},
> +	},
> +	/* CSID_LITE0 */
> +	{
> +		.regulators = {},
> +		.clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb",
> +			   "cpas_fast_ahb", "csid", "csid_csiphy_rx" },
> +		.clock_rate = { { 0 },
> +				{ 0 },
> +				{ 64000000, 80000000 },
> +				{ 80000000,  100000000, 200000000,
> +				  300000000, 400000000 },
> +				{ 300000000, 400000000, 480000000 },
> +				{ 300000000, 400000000, 480000000 }, },
> +		.reg = { "csid_lite0" },
> +		.interrupt = { "csid_lite0" },
> +		.csid = {
> +			.is_lite = true,
> +			.hw_ops = &csid_ops_680,
> +			.parent_dev_ops = &vfe_parent_dev_ops,
> +			.formats = &csid_formats_gen2
> +		}
> +	},
> +	/* CSID_LITE1 */
> +	{
> +		.regulators = {},
> +		.clock = { "gcc_axi_hf", "gcc_axi_sf", "cpas_ahb",
> +			   "cpas_fast_ahb", "csid", "csid_csiphy_rx" },
> +		.clock_rate = { { 0 },
> +				{ 0 },
> +				{ 64000000, 80000000 },
> +				{ 80000000,  100000000, 200000000,
> +				  300000000, 400000000 },
> +				{ 300000000, 400000000, 480000000 },
> +				{ 300000000, 400000000, 480000000 }, },
> +

It's an inconsistency of the added empty line here.

> +		.reg = { "csid_lite1" },
> +		.interrupt = { "csid_lite1" },
> +		.csid = {
> +			.is_lite = true,
> +			.hw_ops = &csid_ops_680,
> +			.parent_dev_ops = &vfe_parent_dev_ops,
> +			.formats = &csid_formats_gen2
> +		}
> +	},
> +};
> +
> +static const struct camss_subdev_resources vfe_res_x1e80100[] = {
> +	/* IFE0 */
> +	{
> +		.regulators = {},
> +		.clock = {"camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb",
> +			  "cpas_fast_ahb", "cpas_vfe0", "vfe0_fast_ahb",
> +			  "vfe0" },
> +		.clock_rate = { { 0 },
> +				{ 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
> +		},
> +	},
> +	/* IFE1 */
> +	{
> +		.regulators = {},
> +		.clock = { "camnoc_rt_axi", "camnoc_nrt_axi", "cpas_ahb",
> +			   "cpas_fast_ahb", "cpas_vfe1", "vfe1_fast_ahb",
> +			   "vfe1"  },
> +		.clock_rate = { { 0 },
> +				{ 0 },
> +				{ 0 },
> +				{ 0 },
> +				{ 0 },
> +				{ 0 },
> +				{ 345600000, 432000000, 594000000, 675000000,
> +				  727000000 }, },
> +		.reg = { "vfe1" },
> +		.interrupt = { "vfe1" },
> +		.vfe = {
> +			.line_num = 4,
> +			.pd_name = "ife1",
> +			.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 = { { 0 },
> +				{ 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 = { { 0 },
> +				{ 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 resources_wrapper csid_wrapper_res_x1e80100 = {
> +	.reg = "csid_wrapper",
> +};
> +
>   /*
>    * camss_add_clock_margin - Add margin to clock frequency rate
>    * @rate: Clock frequency rate
> @@ -3346,6 +3616,21 @@ static const struct camss_resources sm8550_resources = {
>   	.link_entities = camss_link_entities
>   };
>   
> +static const struct camss_resources x1e80100_resources = {
> +	.version = CAMSS_X1E80100,
> +	.pd_name = "top",
> +	.csiphy_res = csiphy_res_x1e80100,
> +	.csid_res = csid_res_x1e80100,
> +	.vfe_res = vfe_res_x1e80100,
> +	.csid_wrapper_res = &csid_wrapper_res_x1e80100,
> +	.icc_res = icc_res_sc8280xp,
> +	.icc_path_num = ARRAY_SIZE(icc_res_sc8280xp),
> +	.csiphy_num = ARRAY_SIZE(csiphy_res_x1e80100),
> +	.csid_num = ARRAY_SIZE(csid_res_x1e80100),
> +	.vfe_num = ARRAY_SIZE(vfe_res_x1e80100),
> +	.link_entities = camss_link_entities
> +};
> +
>   static const struct of_device_id camss_dt_match[] = {
>   	{ .compatible = "qcom,msm8916-camss", .data = &msm8916_resources },
>   	{ .compatible = "qcom,msm8953-camss", .data = &msm8953_resources },
> @@ -3356,6 +3641,7 @@ static const struct of_device_id camss_dt_match[] = {
>   	{ .compatible = "qcom,sdm845-camss", .data = &sdm845_resources },
>   	{ .compatible = "qcom,sm8250-camss", .data = &sm8250_resources },
>   	{ .compatible = "qcom,sm8550-camss", .data = &sm8550_resources },
> +	{ .compatible = "qcom,x1e80100-camss", .data = &x1e80100_resources },
>   	{ }
>   };
>   
> diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h
> index 58fc61e7cf7ad..426e80f1c4b52 100644
> --- a/drivers/media/platform/qcom/camss/camss.h
> +++ b/drivers/media/platform/qcom/camss/camss.h
> @@ -86,6 +86,7 @@ enum camss_version {
>   	CAMSS_8280XP,
>   	CAMSS_845,
>   	CAMSS_8550,
> +	CAMSS_X1E80100,
>   };
>   
>   enum icc_count {
> 

--
Best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 3/7] media: qcom: camss: Add CSID 680 support
  2025-01-22  0:05   ` Vladimir Zapolskiy
@ 2025-01-22 13:33     ` Bryan O'Donoghue
  0 siblings, 0 replies; 18+ messages in thread
From: Bryan O'Donoghue @ 2025-01-22 13:33 UTC (permalink / raw)
  To: Vladimir Zapolskiy, Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Depeng Shao, Vikram Sharma

On 22/01/2025 00:05, Vladimir Zapolskiy wrote:
> 
> Sorting order is not preserved by a preceding changeset, unfortunately.

No its not.

I'll just add a patch to fix it myself, no need to hold up Depeng any 
further.

---
bod

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 6/7] media: qcom: camss: csiphy-3ph: Add 4nm CSIPHY 2ph 5Gbps DPHY v2.1.2 init sequence
  2025-01-22  0:29   ` Vladimir Zapolskiy
@ 2025-01-22 13:41     ` Bryan O'Donoghue
  2025-01-22 21:29       ` Vladimir Zapolskiy
  0 siblings, 1 reply; 18+ messages in thread
From: Bryan O'Donoghue @ 2025-01-22 13:41 UTC (permalink / raw)
  To: Vladimir Zapolskiy, Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Depeng Shao, Vikram Sharma

On 22/01/2025 00:29, Vladimir Zapolskiy wrote:
> Hi Bryan.
> 
> On 1/20/25 17:47, Bryan O'Donoghue wrote:
>> For various SoC skews at 4nm CSIPHY 2.1.2 is used. Add in the init 
>> sequence
>> with base control reg offset of 0x1000.
>>
>> This initial version will support X1E80100. Take the silicon verification
>> PHY init parameters as a first/best guess pass.
>>
>> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
>> ---
>>   .../platform/qcom/camss/camss-csiphy-3ph-1-0.c     | 126 +++++++++++ 
>> ++++++++++
>>   1 file changed, 126 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 b44939686e4bb..fc624a3da1c43 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
>> @@ -55,6 +55,7 @@
>>   #define CSIPHY_DNP_PARAMS        4
>>   #define CSIPHY_2PH_REGS            5
>>   #define CSIPHY_3PH_REGS            6
>> +#define CSIPHY_SKEW_CAL            7
> 
> This one is not needed, having CSIPHY_DNP_PARAMS only is good enough.
> 
>>   struct csiphy_lane_regs {
>>       s32 reg_addr;
>> @@ -423,6 +424,130 @@ csiphy_lane_regs lane_regs_sm8550[] = {
>>       {0x0C64, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
>>   };
>> +/* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */
>> +static const struct
>> +csiphy_lane_regs lane_regs_x1e80100[] = {
>> +    /* Power up lanes 2ph mode */
>> +    {0x1014, 0xD5, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x101C, 0x7A, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x1018, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +
>> +    {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, 0x01, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0000, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
>> +    {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0094, 0xD7, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x005C, 0x00, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0060, 0xBD, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL},
> 
> Double write record, which is anyway ignored, but one should
> be enough.

Yes except having the SKEW_CAL definition allows us to import the 
downstream init sequence unmodified.

>> +
>> +    {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, 0x01, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
>> +    {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
> 
> Writing the same value to a register 4 times in a row, apparently
> it's not needed, one time write is sufficient.

To be honest I just took the downstream sequence verbatim.

I'll see if the 4 x has an effect though.

>> +
>> +    {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, 0x01, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0400, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
>> +    {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0494, 0xD7, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x045C, 0x00, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0460, 0xBD, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL},
> 
> Two equal "ignored" writes.

Again I think these init sequences "do no harm" and its at least 
possible we can improve the logic of our upstream init sequences to make 
these NOPs mean more...

At they very least they consume time in the APSS wrt the next writes..


> 
>> +
>> +    {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, 0x01, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0830, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0800, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
>> +    {0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0894, 0xD7, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x085C, 0x00, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0860, 0xBD, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL},
> 
> Two equal "ignored" writes.
> 
>> +
>> +    {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, 0x01, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0C30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0C00, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
>> +    {0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>> +    {0x0C94, 0xD7, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0C5C, 0x00, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0C60, 0xBD, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>> +    {0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL},
> 
> Two equal "ignored" writes.
> 
>> +};
>> +
>>   static void csiphy_hw_version_read(struct csiphy_device *csiphy,
>>                      struct device *dev)
>>   {
>> @@ -594,6 +719,7 @@ static void csiphy_gen2_config_lanes(struct 
>> csiphy_device *csiphy,
>>               val = settle_cnt & 0xff;
>>               break;
>>           case CSIPHY_DNP_PARAMS:
>> +        case CSIPHY_SKEW_CAL:
> 
> Having CSIPHY_DNP_PARAMS is good enough, no need to add another
> "dummy" write type.

True but, I'd like to be able to bring in unmodified init sequences from 
downstream.

I think there is value in being able to setup the PHYs in the exact same 
configuration.

So, I think we should keep the SKEW_CAL support and I'm open to 
experiment reducing repeated DNP/SKEW downwards, perhaps defining a real 
number for the delay instead.

---
bod

^ permalink raw reply	[flat|nested] 18+ messages in thread

* Re: [PATCH 6/7] media: qcom: camss: csiphy-3ph: Add 4nm CSIPHY 2ph 5Gbps DPHY v2.1.2 init sequence
  2025-01-22 13:41     ` Bryan O'Donoghue
@ 2025-01-22 21:29       ` Vladimir Zapolskiy
  0 siblings, 0 replies; 18+ messages in thread
From: Vladimir Zapolskiy @ 2025-01-22 21:29 UTC (permalink / raw)
  To: Bryan O'Donoghue, Robert Foss, Todor Tomov, Mauro Carvalho Chehab
  Cc: linux-media, linux-arm-msm, linux-kernel, Depeng Shao, Vikram Sharma

On 1/22/25 15:41, Bryan O'Donoghue wrote:
> On 22/01/2025 00:29, Vladimir Zapolskiy wrote:
>> Hi Bryan.
>>
>> On 1/20/25 17:47, Bryan O'Donoghue wrote:
>>> For various SoC skews at 4nm CSIPHY 2.1.2 is used. Add in the init
>>> sequence
>>> with base control reg offset of 0x1000.
>>>
>>> This initial version will support X1E80100. Take the silicon verification
>>> PHY init parameters as a first/best guess pass.
>>>
>>> Signed-off-by: Bryan O'Donoghue <bryan.odonoghue@linaro.org>
>>> ---
>>>    .../platform/qcom/camss/camss-csiphy-3ph-1-0.c     | 126 +++++++++++
>>> ++++++++++
>>>    1 file changed, 126 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 b44939686e4bb..fc624a3da1c43 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
>>> @@ -55,6 +55,7 @@
>>>    #define CSIPHY_DNP_PARAMS        4
>>>    #define CSIPHY_2PH_REGS            5
>>>    #define CSIPHY_3PH_REGS            6
>>> +#define CSIPHY_SKEW_CAL            7
>>
>> This one is not needed, having CSIPHY_DNP_PARAMS only is good enough.
>>
>>>    struct csiphy_lane_regs {
>>>        s32 reg_addr;
>>> @@ -423,6 +424,130 @@ csiphy_lane_regs lane_regs_sm8550[] = {
>>>        {0x0C64, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
>>>    };
>>> +/* 4nm 2PH v 2.1.2 2p5Gbps 4 lane DPHY mode */
>>> +static const struct
>>> +csiphy_lane_regs lane_regs_x1e80100[] = {
>>> +    /* Power up lanes 2ph mode */
>>> +    {0x1014, 0xD5, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x101C, 0x7A, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x1018, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +
>>> +    {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, 0x01, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0030, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0000, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
>>> +    {0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0094, 0xD7, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x005C, 0x00, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0060, 0xBD, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0064, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>>
>> Double write record, which is anyway ignored, but one should
>> be enough.
> 
> Yes except having the SKEW_CAL definition allows us to import the
> downstream init sequence unmodified.

It's not a technical benefit at all, the expectation is that the upstream
code shall be better than the downstream code.



>>> +
>>> +    {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, 0x01, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
>>> +    {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0E10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>>
>> Writing the same value to a register 4 times in a row, apparently
>> it's not needed, one time write is sufficient.
> 
> To be honest I just took the downstream sequence verbatim.
> 

I believe this could be a support to my words above, quite often
the downstream code is not good enough quality to be copied blindly.

> I'll see if the 4 x has an effect though.
> 

Thank you in advance!

>>> +
>>> +    {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, 0x01, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0430, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0400, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
>>> +    {0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0494, 0xD7, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x045C, 0x00, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0460, 0xBD, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0464, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>>
>> Two equal "ignored" writes.
> 
> Again I think these init sequences "do no harm" and its at least
> possible we can improve the logic of our upstream init sequences to make
> these NOPs mean more...
> 
> At they very least they consume time in the APSS wrt the next writes..

I disagree about "do no harm" part, since it caused a severe confusion
on my reader's side, and the next reader will return with the same
currently highlighted problem, if there is a mistake or what the hidden
sense is here.

Here I ask to remove the unused code along with the confusion it brings.

>>
>>> +
>>> +    {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, 0x01, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0830, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0800, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
>>> +    {0x0810, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0894, 0xD7, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x085C, 0x00, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0860, 0xBD, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0864, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>>
>> Two equal "ignored" writes.
>>
>>> +
>>> +    {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, 0x01, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0C30, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0C00, 0x8E, 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, 0x10, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
>>> +    {0x0C10, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
>>> +    {0x0C94, 0xD7, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0C5C, 0x00, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0C60, 0xBD, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>>> +    {0x0C64, 0x7F, 0x00, CSIPHY_SKEW_CAL},
>>
>> Two equal "ignored" writes.
>>
>>> +};
>>> +
>>>    static void csiphy_hw_version_read(struct csiphy_device *csiphy,
>>>                       struct device *dev)
>>>    {
>>> @@ -594,6 +719,7 @@ static void csiphy_gen2_config_lanes(struct
>>> csiphy_device *csiphy,
>>>                val = settle_cnt & 0xff;
>>>                break;
>>>            case CSIPHY_DNP_PARAMS:
>>> +        case CSIPHY_SKEW_CAL:
>>
>> Having CSIPHY_DNP_PARAMS is good enough, no need to add another
>> "dummy" write type.
> 
> True but, I'd like to be able to bring in unmodified init sequences from
> downstream.

It might be called reluctance, it's not a good enough reason for the
upstream code, I believe.

> I think there is value in being able to setup the PHYs in the exact same
> configuration.

Removing non-writes and/or using everywhere only one of two types
CSIPHY_DNP_PARAMS/CSIPHY_SKEW_CAL does not change the given by you
point, it's still a setup of "PHYs in the exact same configuration".

> So, I think we should keep the SKEW_CAL support and I'm open to
> experiment reducing repeated DNP/SKEW downwards, perhaps defining a real
> number for the delay instead.
> 

I care a lot about making quite low quality source code of the driver more
simple and comprehensible, while optimization of time needed to copy code
from the downstream could be a movement in quite the opposite direction.

I won't object, if you replace CSIPHY_DNP_PARAMS with CSIPHY_SKEW_CAL in
the driver, but there is no technical reason to keep both types. Again,
I do recognize the non-technical reason to simplify copying from the
downstream, I just claim it as a non-technical reason, which is out of
the engineering duty.

--
Best wishes,
Vladimir

^ permalink raw reply	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2025-01-22 21:29 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-01-20 15:46 [PATCH 0/7] media: qcom: camss: Add X1 Elite support Bryan O'Donoghue
2025-01-20 15:46 ` [PATCH 1/7] media: qcom: camss: Add an id property to struct resources Bryan O'Donoghue
2025-01-21 23:38   ` Vladimir Zapolskiy
2025-01-20 15:46 ` [PATCH 2/7] media: qcom: camss: Use the CSIPHY id property to find clock names Bryan O'Donoghue
2025-01-21 23:40   ` Vladimir Zapolskiy
2025-01-20 15:47 ` [PATCH 3/7] media: qcom: camss: Add CSID 680 support Bryan O'Donoghue
2025-01-22  0:05   ` Vladimir Zapolskiy
2025-01-22 13:33     ` Bryan O'Donoghue
2025-01-20 15:47 ` [PATCH 4/7] media: qcom: camss: Add VFE680 support Bryan O'Donoghue
2025-01-22  0:17   ` Vladimir Zapolskiy
2025-01-20 15:47 ` [PATCH 5/7] media: qcom: camss: Add support for 3ph CSIPHY write settle delay Bryan O'Donoghue
2025-01-22  0:23   ` Vladimir Zapolskiy
2025-01-20 15:47 ` [PATCH 6/7] media: qcom: camss: csiphy-3ph: Add 4nm CSIPHY 2ph 5Gbps DPHY v2.1.2 init sequence Bryan O'Donoghue
2025-01-22  0:29   ` Vladimir Zapolskiy
2025-01-22 13:41     ` Bryan O'Donoghue
2025-01-22 21:29       ` Vladimir Zapolskiy
2025-01-20 15:47 ` [PATCH 7/7] media: qcom: camss: Add x1e80100 specific support Bryan O'Donoghue
2025-01-22  0:38   ` Vladimir Zapolskiy

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®