* [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* 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
* [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* 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
* [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* 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 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
* [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* 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
* [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* 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
* [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* 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 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
* [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 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