* [PATCH v4 01/24] pinctrl: tegra20: register csus_mux clock
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-13 13:12 ` Linus Walleij
2025-10-14 12:03 ` Linus Walleij
2025-10-08 7:30 ` [PATCH v4 02/24] clk: tegra: set CSUS as vi_sensor's gate for Tegra20, Tegra30 and Tegra114 Svyatoslav Ryhel
` (22 subsequent siblings)
23 siblings, 2 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Add csus_mux for further use as the csus clock parent, similar to how the
cdev1 and cdev2 muxes are utilized. Additionally, constify the cdev parent
name lists to resolve checkpatch warnings.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/pinctrl/tegra/pinctrl-tegra20.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/pinctrl/tegra/pinctrl-tegra20.c b/drivers/pinctrl/tegra/pinctrl-tegra20.c
index 737fc2000f66..1a1758fd7def 100644
--- a/drivers/pinctrl/tegra/pinctrl-tegra20.c
+++ b/drivers/pinctrl/tegra/pinctrl-tegra20.c
@@ -2222,14 +2222,18 @@ static const struct tegra_pinctrl_soc_data tegra20_pinctrl = {
.drvtype_in_mux = false,
};
-static const char *cdev1_parents[] = {
+static const char * const cdev1_parents[] = {
"dev1_osc_div", "pll_a_out0", "pll_m_out1", "audio",
};
-static const char *cdev2_parents[] = {
+static const char * const cdev2_parents[] = {
"dev2_osc_div", "hclk", "pclk", "pll_p_out4",
};
+static const char * const csus_parents[] = {
+ "pll_c_out1", "pll_p_out2", "pll_p_out3", "vi_sensor",
+};
+
static void tegra20_pinctrl_register_clock_muxes(struct platform_device *pdev)
{
struct tegra_pmx *pmx = platform_get_drvdata(pdev);
@@ -2239,6 +2243,9 @@ static void tegra20_pinctrl_register_clock_muxes(struct platform_device *pdev)
clk_register_mux(NULL, "cdev2_mux", cdev2_parents, 4, 0,
pmx->regs[1] + 0x8, 4, 2, CLK_MUX_READ_ONLY, NULL);
+
+ clk_register_mux(NULL, "csus_mux", csus_parents, 4, 0,
+ pmx->regs[1] + 0x8, 6, 2, CLK_MUX_READ_ONLY, NULL);
}
static int tegra20_pinctrl_probe(struct platform_device *pdev)
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v4 01/24] pinctrl: tegra20: register csus_mux clock
2025-10-08 7:30 ` [PATCH v4 01/24] pinctrl: tegra20: register csus_mux clock Svyatoslav Ryhel
@ 2025-10-13 13:12 ` Linus Walleij
2025-10-14 5:15 ` Mikko Perttunen
2025-10-14 12:03 ` Linus Walleij
1 sibling, 1 reply; 40+ messages in thread
From: Linus Walleij @ 2025-10-13 13:12 UTC (permalink / raw)
To: Svyatoslav Ryhel, Thierry Reding
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jonathan Hunter, Sowjanya Komatineni, Luca Ceresoli,
Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Mauro Carvalho Chehab, Greg Kroah-Hartman,
Jonas Schwöbel, Dmitry Osipenko, Charan Pedumuru, Diogo Ivo,
Aaron Kling, Arnd Bergmann, dri-devel, devicetree, linux-tegra,
linux-kernel, linux-media, linux-clk, linux-gpio, linux-staging
On Wed, Oct 8, 2025 at 9:31 AM Svyatoslav Ryhel <clamor95@gmail.com> wrote:
> Add csus_mux for further use as the csus clock parent, similar to how the
> cdev1 and cdev2 muxes are utilized. Additionally, constify the cdev parent
> name lists to resolve checkpatch warnings.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
This patch looks like it can be applied independently from the rest,
can I get a review from Thierry or someone else at nVidia so I
can just apply it?
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v4 01/24] pinctrl: tegra20: register csus_mux clock
2025-10-13 13:12 ` Linus Walleij
@ 2025-10-14 5:15 ` Mikko Perttunen
0 siblings, 0 replies; 40+ messages in thread
From: Mikko Perttunen @ 2025-10-14 5:15 UTC (permalink / raw)
To: Svyatoslav Ryhel, Thierry Reding, Linus Walleij
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Jonathan Hunter, Sowjanya Komatineni, Luca Ceresoli,
Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mauro Carvalho Chehab, Greg Kroah-Hartman, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann, dri-devel, devicetree, linux-tegra, linux-kernel,
linux-media, linux-clk, linux-gpio, linux-staging
On Monday, October 13, 2025 10:12 PM Linus Walleij wrote:
> On Wed, Oct 8, 2025 at 9:31 AM Svyatoslav Ryhel <clamor95@gmail.com> wrote:
>
> > Add csus_mux for further use as the csus clock parent, similar to how the
> > cdev1 and cdev2 muxes are utilized. Additionally, constify the cdev parent
> > name lists to resolve checkpatch warnings.
> >
> > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
>
> This patch looks like it can be applied independently from the rest,
> can I get a review from Thierry or someone else at nVidia so I
> can just apply it?
>
> Yours,
> Linus Walleij
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v4 01/24] pinctrl: tegra20: register csus_mux clock
2025-10-08 7:30 ` [PATCH v4 01/24] pinctrl: tegra20: register csus_mux clock Svyatoslav Ryhel
2025-10-13 13:12 ` Linus Walleij
@ 2025-10-14 12:03 ` Linus Walleij
1 sibling, 0 replies; 40+ messages in thread
From: Linus Walleij @ 2025-10-14 12:03 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Mauro Carvalho Chehab, Greg Kroah-Hartman,
Jonas Schwöbel, Dmitry Osipenko, Charan Pedumuru, Diogo Ivo,
Aaron Kling, Arnd Bergmann, dri-devel, devicetree, linux-tegra,
linux-kernel, linux-media, linux-clk, linux-gpio, linux-staging
On Wed, Oct 8, 2025 at 9:31 AM Svyatoslav Ryhel <clamor95@gmail.com> wrote:
> Add csus_mux for further use as the csus clock parent, similar to how the
> cdev1 and cdev2 muxes are utilized. Additionally, constify the cdev parent
> name lists to resolve checkpatch warnings.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
This patch 1/24 applied to the pinctrl tree!
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v4 02/24] clk: tegra: set CSUS as vi_sensor's gate for Tegra20, Tegra30 and Tegra114
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 01/24] pinctrl: tegra20: register csus_mux clock Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-14 5:16 ` Mikko Perttunen
2025-10-08 7:30 ` [PATCH v4 03/24] dt-bindings: clock: tegra30: Add IDs for CSI pad clocks Svyatoslav Ryhel
` (21 subsequent siblings)
23 siblings, 1 reply; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
The CSUS clock is a clock gate for the output clock signal primarily
sourced from the VI_SENSOR clock. This clock signal is used as an input
MCLK clock for cameras.
Unlike later Tegra SoCs, the Tegra 20 can change its CSUS parent, which is
why csus_mux is added in a similar way to how CDEV1 and CDEV2 are handled.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/clk/tegra/clk-tegra114.c | 7 ++++++-
drivers/clk/tegra/clk-tegra20.c | 20 +++++++++++++-------
drivers/clk/tegra/clk-tegra30.c | 7 ++++++-
3 files changed, 25 insertions(+), 9 deletions(-)
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
index 186b0b81c1ec..00282b0d3763 100644
--- a/drivers/clk/tegra/clk-tegra114.c
+++ b/drivers/clk/tegra/clk-tegra114.c
@@ -691,7 +691,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
[tegra_clk_tsec] = { .dt_id = TEGRA114_CLK_TSEC, .present = true },
[tegra_clk_xusb_host] = { .dt_id = TEGRA114_CLK_XUSB_HOST, .present = true },
[tegra_clk_msenc] = { .dt_id = TEGRA114_CLK_MSENC, .present = true },
- [tegra_clk_csus] = { .dt_id = TEGRA114_CLK_CSUS, .present = true },
[tegra_clk_mselect] = { .dt_id = TEGRA114_CLK_MSELECT, .present = true },
[tegra_clk_tsensor] = { .dt_id = TEGRA114_CLK_TSENSOR, .present = true },
[tegra_clk_i2s3] = { .dt_id = TEGRA114_CLK_I2S3, .present = true },
@@ -1047,6 +1046,12 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base,
0, 82, periph_clk_enb_refcnt);
clks[TEGRA114_CLK_DSIB] = clk;
+ /* csus */
+ clk = tegra_clk_register_periph_gate("csus", "vi_sensor", 0,
+ clk_base, 0, TEGRA114_CLK_CSUS,
+ periph_clk_enb_refcnt);
+ clks[TEGRA114_CLK_CSUS] = clk;
+
/* emc mux */
clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
ARRAY_SIZE(mux_pllmcp_clkm),
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
index 2c58ce25af75..d8d5afeb6f9b 100644
--- a/drivers/clk/tegra/clk-tegra20.c
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -530,7 +530,6 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = {
[tegra_clk_rtc] = { .dt_id = TEGRA20_CLK_RTC, .present = true },
[tegra_clk_timer] = { .dt_id = TEGRA20_CLK_TIMER, .present = true },
[tegra_clk_kbc] = { .dt_id = TEGRA20_CLK_KBC, .present = true },
- [tegra_clk_csus] = { .dt_id = TEGRA20_CLK_CSUS, .present = true },
[tegra_clk_vcp] = { .dt_id = TEGRA20_CLK_VCP, .present = true },
[tegra_clk_bsea] = { .dt_id = TEGRA20_CLK_BSEA, .present = true },
[tegra_clk_bsev] = { .dt_id = TEGRA20_CLK_BSEV, .present = true },
@@ -834,6 +833,12 @@ static void __init tegra20_periph_clk_init(void)
clk_base, 0, 93, periph_clk_enb_refcnt);
clks[TEGRA20_CLK_CDEV2] = clk;
+ /* csus */
+ clk = tegra_clk_register_periph_gate("csus", "csus_mux", 0,
+ clk_base, 0, TEGRA20_CLK_CSUS,
+ periph_clk_enb_refcnt);
+ clks[TEGRA20_CLK_CSUS] = clk;
+
for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
data = &tegra_periph_clk_list[i];
clk = tegra_clk_register_periph_data(clk_base, data);
@@ -1093,14 +1098,15 @@ static struct clk *tegra20_clk_src_onecell_get(struct of_phandle_args *clkspec,
hw = __clk_get_hw(clk);
/*
- * Tegra20 CDEV1 and CDEV2 clocks are a bit special case, their parent
- * clock is created by the pinctrl driver. It is possible for clk user
- * to request these clocks before pinctrl driver got probed and hence
- * user will get an orphaned clock. That might be undesirable because
- * user may expect parent clock to be enabled by the child.
+ * Tegra20 CDEV1, CDEV2 and CSUS clocks are a bit special case, their
+ * parent clock is created by the pinctrl driver. It is possible for
+ * clk user to request these clocks before pinctrl driver got probed
+ * and hence user will get an orphaned clock. That might be undesirable
+ * because user may expect parent clock to be enabled by the child.
*/
if (clkspec->args[0] == TEGRA20_CLK_CDEV1 ||
- clkspec->args[0] == TEGRA20_CLK_CDEV2) {
+ clkspec->args[0] == TEGRA20_CLK_CDEV2 ||
+ clkspec->args[0] == TEGRA20_CLK_CSUS) {
parent_hw = clk_hw_get_parent(hw);
if (!parent_hw)
return ERR_PTR(-EPROBE_DEFER);
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index 82a8cb9545eb..ca367184e185 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -779,7 +779,6 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = {
[tegra_clk_rtc] = { .dt_id = TEGRA30_CLK_RTC, .present = true },
[tegra_clk_timer] = { .dt_id = TEGRA30_CLK_TIMER, .present = true },
[tegra_clk_kbc] = { .dt_id = TEGRA30_CLK_KBC, .present = true },
- [tegra_clk_csus] = { .dt_id = TEGRA30_CLK_CSUS, .present = true },
[tegra_clk_vcp] = { .dt_id = TEGRA30_CLK_VCP, .present = true },
[tegra_clk_bsea] = { .dt_id = TEGRA30_CLK_BSEA, .present = true },
[tegra_clk_bsev] = { .dt_id = TEGRA30_CLK_BSEV, .present = true },
@@ -1008,6 +1007,12 @@ static void __init tegra30_periph_clk_init(void)
0, 48, periph_clk_enb_refcnt);
clks[TEGRA30_CLK_DSIA] = clk;
+ /* csus */
+ clk = tegra_clk_register_periph_gate("csus", "vi_sensor", 0,
+ clk_base, 0, TEGRA30_CLK_CSUS,
+ periph_clk_enb_refcnt);
+ clks[TEGRA30_CLK_CSUS] = clk;
+
/* pcie */
clk = tegra_clk_register_periph_gate("pcie", "clk_m", 0, clk_base, 0,
70, periph_clk_enb_refcnt);
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v4 02/24] clk: tegra: set CSUS as vi_sensor's gate for Tegra20, Tegra30 and Tegra114
2025-10-08 7:30 ` [PATCH v4 02/24] clk: tegra: set CSUS as vi_sensor's gate for Tegra20, Tegra30 and Tegra114 Svyatoslav Ryhel
@ 2025-10-14 5:16 ` Mikko Perttunen
0 siblings, 0 replies; 40+ messages in thread
From: Mikko Perttunen @ 2025-10-14 5:16 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Linus Walleij, Mauro Carvalho Chehab, Greg Kroah-Hartman,
Svyatoslav Ryhel, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann,
Svyatoslav Ryhel
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
On Wednesday, October 8, 2025 4:30 PM Svyatoslav Ryhel wrote:
> The CSUS clock is a clock gate for the output clock signal primarily
> sourced from the VI_SENSOR clock. This clock signal is used as an input
> MCLK clock for cameras.
>
> Unlike later Tegra SoCs, the Tegra 20 can change its CSUS parent, which is
> why csus_mux is added in a similar way to how CDEV1 and CDEV2 are handled.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
> drivers/clk/tegra/clk-tegra114.c | 7 ++++++-
> drivers/clk/tegra/clk-tegra20.c | 20 +++++++++++++-------
> drivers/clk/tegra/clk-tegra30.c | 7 ++++++-
> 3 files changed, 25 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c
> index 186b0b81c1ec..00282b0d3763 100644
> --- a/drivers/clk/tegra/clk-tegra114.c
> +++ b/drivers/clk/tegra/clk-tegra114.c
> @@ -691,7 +691,6 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
> [tegra_clk_tsec] = { .dt_id = TEGRA114_CLK_TSEC, .present = true },
> [tegra_clk_xusb_host] = { .dt_id = TEGRA114_CLK_XUSB_HOST, .present = true },
> [tegra_clk_msenc] = { .dt_id = TEGRA114_CLK_MSENC, .present = true },
> - [tegra_clk_csus] = { .dt_id = TEGRA114_CLK_CSUS, .present = true },
> [tegra_clk_mselect] = { .dt_id = TEGRA114_CLK_MSELECT, .present = true },
> [tegra_clk_tsensor] = { .dt_id = TEGRA114_CLK_TSENSOR, .present = true },
> [tegra_clk_i2s3] = { .dt_id = TEGRA114_CLK_I2S3, .present = true },
> @@ -1047,6 +1046,12 @@ static __init void tegra114_periph_clk_init(void __iomem *clk_base,
> 0, 82, periph_clk_enb_refcnt);
> clks[TEGRA114_CLK_DSIB] = clk;
>
> + /* csus */
> + clk = tegra_clk_register_periph_gate("csus", "vi_sensor", 0,
> + clk_base, 0, TEGRA114_CLK_CSUS,
> + periph_clk_enb_refcnt);
> + clks[TEGRA114_CLK_CSUS] = clk;
> +
> /* emc mux */
> clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
> ARRAY_SIZE(mux_pllmcp_clkm),
> diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
> index 2c58ce25af75..d8d5afeb6f9b 100644
> --- a/drivers/clk/tegra/clk-tegra20.c
> +++ b/drivers/clk/tegra/clk-tegra20.c
> @@ -530,7 +530,6 @@ static struct tegra_clk tegra20_clks[tegra_clk_max] __initdata = {
> [tegra_clk_rtc] = { .dt_id = TEGRA20_CLK_RTC, .present = true },
> [tegra_clk_timer] = { .dt_id = TEGRA20_CLK_TIMER, .present = true },
> [tegra_clk_kbc] = { .dt_id = TEGRA20_CLK_KBC, .present = true },
> - [tegra_clk_csus] = { .dt_id = TEGRA20_CLK_CSUS, .present = true },
> [tegra_clk_vcp] = { .dt_id = TEGRA20_CLK_VCP, .present = true },
> [tegra_clk_bsea] = { .dt_id = TEGRA20_CLK_BSEA, .present = true },
> [tegra_clk_bsev] = { .dt_id = TEGRA20_CLK_BSEV, .present = true },
> @@ -834,6 +833,12 @@ static void __init tegra20_periph_clk_init(void)
> clk_base, 0, 93, periph_clk_enb_refcnt);
> clks[TEGRA20_CLK_CDEV2] = clk;
>
> + /* csus */
> + clk = tegra_clk_register_periph_gate("csus", "csus_mux", 0,
> + clk_base, 0, TEGRA20_CLK_CSUS,
> + periph_clk_enb_refcnt);
> + clks[TEGRA20_CLK_CSUS] = clk;
> +
> for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
> data = &tegra_periph_clk_list[i];
> clk = tegra_clk_register_periph_data(clk_base, data);
> @@ -1093,14 +1098,15 @@ static struct clk *tegra20_clk_src_onecell_get(struct of_phandle_args *clkspec,
> hw = __clk_get_hw(clk);
>
> /*
> - * Tegra20 CDEV1 and CDEV2 clocks are a bit special case, their parent
> - * clock is created by the pinctrl driver. It is possible for clk user
> - * to request these clocks before pinctrl driver got probed and hence
> - * user will get an orphaned clock. That might be undesirable because
> - * user may expect parent clock to be enabled by the child.
> + * Tegra20 CDEV1, CDEV2 and CSUS clocks are a bit special case, their
> + * parent clock is created by the pinctrl driver. It is possible for
> + * clk user to request these clocks before pinctrl driver got probed
> + * and hence user will get an orphaned clock. That might be undesirable
> + * because user may expect parent clock to be enabled by the child.
> */
> if (clkspec->args[0] == TEGRA20_CLK_CDEV1 ||
> - clkspec->args[0] == TEGRA20_CLK_CDEV2) {
> + clkspec->args[0] == TEGRA20_CLK_CDEV2 ||
> + clkspec->args[0] == TEGRA20_CLK_CSUS) {
> parent_hw = clk_hw_get_parent(hw);
> if (!parent_hw)
> return ERR_PTR(-EPROBE_DEFER);
> diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
> index 82a8cb9545eb..ca367184e185 100644
> --- a/drivers/clk/tegra/clk-tegra30.c
> +++ b/drivers/clk/tegra/clk-tegra30.c
> @@ -779,7 +779,6 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = {
> [tegra_clk_rtc] = { .dt_id = TEGRA30_CLK_RTC, .present = true },
> [tegra_clk_timer] = { .dt_id = TEGRA30_CLK_TIMER, .present = true },
> [tegra_clk_kbc] = { .dt_id = TEGRA30_CLK_KBC, .present = true },
> - [tegra_clk_csus] = { .dt_id = TEGRA30_CLK_CSUS, .present = true },
> [tegra_clk_vcp] = { .dt_id = TEGRA30_CLK_VCP, .present = true },
> [tegra_clk_bsea] = { .dt_id = TEGRA30_CLK_BSEA, .present = true },
> [tegra_clk_bsev] = { .dt_id = TEGRA30_CLK_BSEV, .present = true },
> @@ -1008,6 +1007,12 @@ static void __init tegra30_periph_clk_init(void)
> 0, 48, periph_clk_enb_refcnt);
> clks[TEGRA30_CLK_DSIA] = clk;
>
> + /* csus */
> + clk = tegra_clk_register_periph_gate("csus", "vi_sensor", 0,
> + clk_base, 0, TEGRA30_CLK_CSUS,
> + periph_clk_enb_refcnt);
> + clks[TEGRA30_CLK_CSUS] = clk;
> +
> /* pcie */
> clk = tegra_clk_register_periph_gate("pcie", "clk_m", 0, clk_base, 0,
> 70, periph_clk_enb_refcnt);
>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v4 03/24] dt-bindings: clock: tegra30: Add IDs for CSI pad clocks
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 01/24] pinctrl: tegra20: register csus_mux clock Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 02/24] clk: tegra: set CSUS as vi_sensor's gate for Tegra20, Tegra30 and Tegra114 Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 04/24] clk: tegra30: add CSI pad clock gates Svyatoslav Ryhel
` (20 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Tegra30 has CSI pad clock enable bits embedded into PLLD/PLLD2 registers.
Add ids for these clocks. Additionally, move TEGRA30_CLK_CLK_MAX into
clk-tegra30 source.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
drivers/clk/tegra/clk-tegra30.c | 1 +
include/dt-bindings/clock/tegra30-car.h | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index ca367184e185..ca738bc64615 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -53,6 +53,7 @@
#define SYSTEM_CLK_RATE 0x030
#define TEGRA30_CLK_PERIPH_BANKS 5
+#define TEGRA30_CLK_CLK_MAX 311
#define PLLC_BASE 0x80
#define PLLC_MISC 0x8c
diff --git a/include/dt-bindings/clock/tegra30-car.h b/include/dt-bindings/clock/tegra30-car.h
index f193663e6f28..763b81f80908 100644
--- a/include/dt-bindings/clock/tegra30-car.h
+++ b/include/dt-bindings/clock/tegra30-car.h
@@ -271,6 +271,7 @@
#define TEGRA30_CLK_AUDIO3_MUX 306
#define TEGRA30_CLK_AUDIO4_MUX 307
#define TEGRA30_CLK_SPDIF_MUX 308
-#define TEGRA30_CLK_CLK_MAX 309
+#define TEGRA30_CLK_CSIA_PAD 309
+#define TEGRA30_CLK_CSIB_PAD 310
#endif /* _DT_BINDINGS_CLOCK_TEGRA30_CAR_H */
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 04/24] clk: tegra30: add CSI pad clock gates
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (2 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 03/24] dt-bindings: clock: tegra30: Add IDs for CSI pad clocks Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 05/24] dt-bindings: display: tegra: document Tegra30 VI and VIP Svyatoslav Ryhel
` (19 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Tegra30 has CSI pad bits in both PLLD and PLLD2 clocks that are required
for the correct work of the CSI block. Add CSI pad A and pad B clock gates
with PLLD/PLLD2 parents, respectively. Add a plld2 spinlock, like one plld
uses, to prevent simultaneous access since both the PLLDx and CSIx_PAD
clocks use the same registers
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
---
drivers/clk/tegra/clk-tegra30.c | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
index ca738bc64615..61fe527ee6c1 100644
--- a/drivers/clk/tegra/clk-tegra30.c
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -154,6 +154,7 @@ static unsigned long input_freq;
static DEFINE_SPINLOCK(cml_lock);
static DEFINE_SPINLOCK(pll_d_lock);
+static DEFINE_SPINLOCK(pll_d2_lock);
#define TEGRA_INIT_DATA_MUX(_name, _parents, _offset, \
_clk_num, _gate_flags, _clk_id) \
@@ -859,7 +860,7 @@ static void __init tegra30_pll_init(void)
/* PLLD2 */
clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc_base, 0,
- &pll_d2_params, NULL);
+ &pll_d2_params, &pll_d2_lock);
clks[TEGRA30_CLK_PLL_D2] = clk;
/* PLLD2_OUT0 */
@@ -1008,6 +1009,16 @@ static void __init tegra30_periph_clk_init(void)
0, 48, periph_clk_enb_refcnt);
clks[TEGRA30_CLK_DSIA] = clk;
+ /* csia_pad */
+ clk = clk_register_gate(NULL, "csia_pad", "pll_d", CLK_SET_RATE_PARENT,
+ clk_base + PLLD_BASE, 26, 0, &pll_d_lock);
+ clks[TEGRA30_CLK_CSIA_PAD] = clk;
+
+ /* csib_pad */
+ clk = clk_register_gate(NULL, "csib_pad", "pll_d2", CLK_SET_RATE_PARENT,
+ clk_base + PLLD2_BASE, 26, 0, &pll_d2_lock);
+ clks[TEGRA30_CLK_CSIB_PAD] = clk;
+
/* csus */
clk = tegra_clk_register_periph_gate("csus", "vi_sensor", 0,
clk_base, 0, TEGRA30_CLK_CSUS,
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 05/24] dt-bindings: display: tegra: document Tegra30 VI and VIP
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (3 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 04/24] clk: tegra30: add CSI pad clock gates Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 06/24] staging: media: tegra-video: expand VI and VIP support to Tegra30 Svyatoslav Ryhel
` (18 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Existing Parallel VI interface schema for Tegra20 is fully compatible with
Tegra30; hence, lets reuse it by setting fallback for Tegra30.
Adjust existing VI schema to reflect that Tegra20 VI is compatible with
Tegra30 by setting a fallback for Tegra30. Additionally, switch to using
an enum instead of list of const.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
---
.../display/tegra/nvidia,tegra20-vi.yaml | 19 ++++++++++++-------
.../display/tegra/nvidia,tegra20-vip.yaml | 9 +++++++--
2 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml
index 2181855a0920..dd67d4162884 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vi.yaml
@@ -16,16 +16,21 @@ properties:
compatible:
oneOf:
- - const: nvidia,tegra20-vi
- - const: nvidia,tegra30-vi
- - const: nvidia,tegra114-vi
- - const: nvidia,tegra124-vi
+ - enum:
+ - nvidia,tegra20-vi
+ - nvidia,tegra114-vi
+ - nvidia,tegra124-vi
+ - nvidia,tegra210-vi
+ - nvidia,tegra186-vi
+ - nvidia,tegra194-vi
+
+ - items:
+ - const: nvidia,tegra30-vi
+ - const: nvidia,tegra20-vi
+
- items:
- const: nvidia,tegra132-vi
- const: nvidia,tegra124-vi
- - const: nvidia,tegra210-vi
- - const: nvidia,tegra186-vi
- - const: nvidia,tegra194-vi
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml
index 14294edb8d8c..9104a36e16d9 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-vip.yaml
@@ -11,8 +11,13 @@ maintainers:
properties:
compatible:
- enum:
- - nvidia,tegra20-vip
+ oneOf:
+ - enum:
+ - nvidia,tegra20-vip
+
+ - items:
+ - const: nvidia,tegra30-vip
+ - const: nvidia,tegra20-vip
ports:
$ref: /schemas/graph.yaml#/properties/ports
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 06/24] staging: media: tegra-video: expand VI and VIP support to Tegra30
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (4 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 05/24] dt-bindings: display: tegra: document Tegra30 VI and VIP Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 07/24] staging: media: tegra-video: vi: adjust get_selection op check Svyatoslav Ryhel
` (17 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Existing VI and VIP implementation for Tegra20 is fully compatible with
Tegra30.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Tested-by: Luca Ceresoli <luca.ceresoli@bootlin.com> # Tegra20 VIP
Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
---
drivers/staging/media/tegra-video/Makefile | 1 +
drivers/staging/media/tegra-video/vi.c | 2 +-
drivers/staging/media/tegra-video/vi.h | 2 +-
drivers/staging/media/tegra-video/video.c | 2 +-
drivers/staging/media/tegra-video/vip.c | 4 ++--
5 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/drivers/staging/media/tegra-video/Makefile b/drivers/staging/media/tegra-video/Makefile
index 6c7552e05109..96380b5dbd8b 100644
--- a/drivers/staging/media/tegra-video/Makefile
+++ b/drivers/staging/media/tegra-video/Makefile
@@ -6,5 +6,6 @@ tegra-video-objs := \
csi.o
tegra-video-$(CONFIG_ARCH_TEGRA_2x_SOC) += tegra20.o
+tegra-video-$(CONFIG_ARCH_TEGRA_3x_SOC) += tegra20.o
tegra-video-$(CONFIG_ARCH_TEGRA_210_SOC) += tegra210.o
obj-$(CONFIG_VIDEO_TEGRA) += tegra-video.o
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index c9276ff76157..7c44a3448588 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -1956,7 +1956,7 @@ static void tegra_vi_remove(struct platform_device *pdev)
}
static const struct of_device_id tegra_vi_of_id_table[] = {
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
{ .compatible = "nvidia,tegra20-vi", .data = &tegra20_vi_soc },
#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h
index 1e6a5caa7082..cac0c0d0e225 100644
--- a/drivers/staging/media/tegra-video/vi.h
+++ b/drivers/staging/media/tegra-video/vi.h
@@ -296,7 +296,7 @@ struct tegra_video_format {
u32 fourcc;
};
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
extern const struct tegra_vi_soc tegra20_vi_soc;
#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
diff --git a/drivers/staging/media/tegra-video/video.c b/drivers/staging/media/tegra-video/video.c
index 074ad0dc56ca..6fe8d5301b9c 100644
--- a/drivers/staging/media/tegra-video/video.c
+++ b/drivers/staging/media/tegra-video/video.c
@@ -123,7 +123,7 @@ static int host1x_video_remove(struct host1x_device *dev)
}
static const struct of_device_id host1x_video_subdevs[] = {
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
{ .compatible = "nvidia,tegra20-vip", },
{ .compatible = "nvidia,tegra20-vi", },
#endif
diff --git a/drivers/staging/media/tegra-video/vip.c b/drivers/staging/media/tegra-video/vip.c
index 5ec717f3afd5..34397b73bb61 100644
--- a/drivers/staging/media/tegra-video/vip.c
+++ b/drivers/staging/media/tegra-video/vip.c
@@ -263,12 +263,12 @@ static void tegra_vip_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
}
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
extern const struct tegra_vip_soc tegra20_vip_soc;
#endif
static const struct of_device_id tegra_vip_of_id_table[] = {
-#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC)
{ .compatible = "nvidia,tegra20-vip", .data = &tegra20_vip_soc },
#endif
{ }
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 07/24] staging: media: tegra-video: vi: adjust get_selection op check
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (5 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 06/24] staging: media: tegra-video: expand VI and VIP support to Tegra30 Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 08/24] staging: media: tegra-video: vi: add flip controls only if no source controls are provided Svyatoslav Ryhel
` (16 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Get_selection operation may be implemented only for sink pad and may
return error code. Set try_crop to 0 instead of returning error.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/staging/media/tegra-video/vi.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index 7c44a3448588..856b7c18b551 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -476,15 +476,11 @@ static int __tegra_channel_try_format(struct tegra_vi_channel *chan,
fse.code = fmtinfo->code;
ret = v4l2_subdev_call(subdev, pad, enum_frame_size, sd_state, &fse);
if (ret) {
- if (!v4l2_subdev_has_op(subdev, pad, get_selection)) {
+ if (!v4l2_subdev_has_op(subdev, pad, get_selection) ||
+ v4l2_subdev_call(subdev, pad, get_selection, NULL, &sdsel)) {
try_crop->width = 0;
try_crop->height = 0;
} else {
- ret = v4l2_subdev_call(subdev, pad, get_selection,
- NULL, &sdsel);
- if (ret)
- return -EINVAL;
-
try_crop->width = sdsel.r.width;
try_crop->height = sdsel.r.height;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 08/24] staging: media: tegra-video: vi: add flip controls only if no source controls are provided
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (6 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 07/24] staging: media: tegra-video: vi: adjust get_selection op check Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 09/24] staging: media: tegra-video: csi: move CSI helpers to header Svyatoslav Ryhel
` (15 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Because the current Tegra video driver is video-centric, it exposes all
controls via /dev/video. If both the camera sensor and the VI provide
hflip and vflip, the driver will fail because only one control is allowed.
To address this, hflip and vflip should be added from the SoC only if the
camera sensor doesn't provide those controls.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/staging/media/tegra-video/vi.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index 856b7c18b551..90473729b546 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -961,6 +961,7 @@ static int tegra_channel_setup_ctrl_handler(struct tegra_vi_channel *chan)
}
#else
struct v4l2_subdev *subdev;
+ struct v4l2_ctrl *hflip, *vflip;
/* custom control */
v4l2_ctrl_new_custom(&chan->ctrl_handler, &syncpt_timeout_ctrl, NULL);
@@ -986,11 +987,13 @@ static int tegra_channel_setup_ctrl_handler(struct tegra_vi_channel *chan)
return ret;
}
- if (chan->vi->soc->has_h_v_flip) {
+ hflip = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_HFLIP);
+ if (chan->vi->soc->has_h_v_flip && !hflip)
v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
- v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
- }
+ vflip = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_VFLIP);
+ if (chan->vi->soc->has_h_v_flip && !vflip)
+ v4l2_ctrl_new_std(&chan->ctrl_handler, &vi_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
#endif
/* setup the controls */
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 09/24] staging: media: tegra-video: csi: move CSI helpers to header
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (7 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 08/24] staging: media: tegra-video: vi: add flip controls only if no source controls are provided Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 10/24] gpu: host1x: convert MIPI to use operation function pointers Svyatoslav Ryhel
` (14 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Move CSI helpers into the header for easier access from SoC-specific video
driver parts.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/staging/media/tegra-video/csi.c | 11 -----------
drivers/staging/media/tegra-video/csi.h | 10 ++++++++++
2 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
index 604185c00a1a..74c92db1032f 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -20,17 +20,6 @@
#define MHZ 1000000
-static inline struct tegra_csi *
-host1x_client_to_csi(struct host1x_client *client)
-{
- return container_of(client, struct tegra_csi, client);
-}
-
-static inline struct tegra_csi_channel *to_csi_chan(struct v4l2_subdev *subdev)
-{
- return container_of(subdev, struct tegra_csi_channel, subdev);
-}
-
/*
* CSI is a separate subdevice which has 6 source pads to generate
* test pattern. CSI subdevice pad ops are used only for TPG and
diff --git a/drivers/staging/media/tegra-video/csi.h b/drivers/staging/media/tegra-video/csi.h
index 3e6e5ee1bb1e..3ed2dbc73ce9 100644
--- a/drivers/staging/media/tegra-video/csi.h
+++ b/drivers/staging/media/tegra-video/csi.h
@@ -151,6 +151,16 @@ struct tegra_csi {
struct list_head csi_chans;
};
+static inline struct tegra_csi *host1x_client_to_csi(struct host1x_client *client)
+{
+ return container_of(client, struct tegra_csi, client);
+}
+
+static inline struct tegra_csi_channel *to_csi_chan(struct v4l2_subdev *subdev)
+{
+ return container_of(subdev, struct tegra_csi_channel, subdev);
+}
+
void tegra_csi_error_recover(struct v4l2_subdev *subdev);
void tegra_csi_calc_settle_time(struct tegra_csi_channel *csi_chan,
u8 csi_port_num,
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 10/24] gpu: host1x: convert MIPI to use operation function pointers
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (8 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 09/24] staging: media: tegra-video: csi: move CSI helpers to header Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-14 5:35 ` Mikko Perttunen
2025-10-08 7:30 ` [PATCH v4 11/24] dt-bindings: display: tegra: document Tegra132 MIPI calibration device Svyatoslav Ryhel
` (13 subsequent siblings)
23 siblings, 1 reply; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Convert existing MIPI code to use operation function pointers, a necessary
step for supporting Tegra20/Tegra30 SoCs. All common MIPI configuration
that is SoC-independent remains in mipi.c, while all SoC-specific code is
moved to tegra114-mipi.c (The naming matches the first SoC generation with
a dedicated calibration block). Shared structures and function calls are
placed into tegra-mipi-cal.h.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/gpu/drm/tegra/dsi.c | 1 +
drivers/gpu/host1x/Makefile | 1 +
drivers/gpu/host1x/mipi.c | 525 +++---------------------
drivers/gpu/host1x/tegra114-mipi.c | 483 ++++++++++++++++++++++
drivers/staging/media/tegra-video/csi.c | 1 +
include/linux/host1x.h | 10 -
include/linux/tegra-mipi-cal.h | 57 +++
7 files changed, 599 insertions(+), 479 deletions(-)
create mode 100644 drivers/gpu/host1x/tegra114-mipi.c
create mode 100644 include/linux/tegra-mipi-cal.h
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index b2046f6ea515..502f0cd0ce53 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -14,6 +14,7 @@
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
+#include <linux/tegra-mipi-cal.h>
#include <video/mipi_display.h>
diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
index ee5286ffe08d..fead483af0b4 100644
--- a/drivers/gpu/host1x/Makefile
+++ b/drivers/gpu/host1x/Makefile
@@ -9,6 +9,7 @@ host1x-y = \
job.o \
debug.o \
mipi.o \
+ tegra114-mipi.o \
fence.o \
hw/host1x01.o \
hw/host1x02.o \
diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
index e51b43dd15a3..8d32072e2244 100644
--- a/drivers/gpu/host1x/mipi.c
+++ b/drivers/gpu/host1x/mipi.c
@@ -1,215 +1,65 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2013 NVIDIA Corporation
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that copyright
- * notice and this permission notice appear in supporting documentation, and
- * that the name of the copyright holders not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. The copyright holders make no representations
- * about the suitability of this software for any purpose. It is provided "as
- * is" without express or implied warranty.
- *
- * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
- * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- * OF THIS SOFTWARE.
+ * Copyright (C) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
*/
#include <linux/clk.h>
-#include <linux/host1x.h>
#include <linux/io.h>
#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/tegra-mipi-cal.h>
-#include "dev.h"
+/* only need to support one provider */
+static struct {
+ struct device_node *np;
+ const struct tegra_mipi_ops *ops;
+} provider;
-#define MIPI_CAL_CTRL 0x00
-#define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26)
-#define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24)
-#define MIPI_CAL_CTRL_CLKEN_OVR (1 << 4)
-#define MIPI_CAL_CTRL_START (1 << 0)
-
-#define MIPI_CAL_AUTOCAL_CTRL 0x01
-
-#define MIPI_CAL_STATUS 0x02
-#define MIPI_CAL_STATUS_DONE (1 << 16)
-#define MIPI_CAL_STATUS_ACTIVE (1 << 0)
-
-#define MIPI_CAL_CONFIG_CSIA 0x05
-#define MIPI_CAL_CONFIG_CSIB 0x06
-#define MIPI_CAL_CONFIG_CSIC 0x07
-#define MIPI_CAL_CONFIG_CSID 0x08
-#define MIPI_CAL_CONFIG_CSIE 0x09
-#define MIPI_CAL_CONFIG_CSIF 0x0a
-#define MIPI_CAL_CONFIG_DSIA 0x0e
-#define MIPI_CAL_CONFIG_DSIB 0x0f
-#define MIPI_CAL_CONFIG_DSIC 0x10
-#define MIPI_CAL_CONFIG_DSID 0x11
-
-#define MIPI_CAL_CONFIG_DSIA_CLK 0x19
-#define MIPI_CAL_CONFIG_DSIB_CLK 0x1a
-#define MIPI_CAL_CONFIG_CSIAB_CLK 0x1b
-#define MIPI_CAL_CONFIG_DSIC_CLK 0x1c
-#define MIPI_CAL_CONFIG_CSICD_CLK 0x1c
-#define MIPI_CAL_CONFIG_DSID_CLK 0x1d
-#define MIPI_CAL_CONFIG_CSIE_CLK 0x1d
-
-/* for data and clock lanes */
-#define MIPI_CAL_CONFIG_SELECT (1 << 21)
-
-/* for data lanes */
-#define MIPI_CAL_CONFIG_HSPDOS(x) (((x) & 0x1f) << 16)
-#define MIPI_CAL_CONFIG_HSPUOS(x) (((x) & 0x1f) << 8)
-#define MIPI_CAL_CONFIG_TERMOS(x) (((x) & 0x1f) << 0)
-
-/* for clock lanes */
-#define MIPI_CAL_CONFIG_HSCLKPDOSD(x) (((x) & 0x1f) << 8)
-#define MIPI_CAL_CONFIG_HSCLKPUOSD(x) (((x) & 0x1f) << 0)
-
-#define MIPI_CAL_BIAS_PAD_CFG0 0x16
-#define MIPI_CAL_BIAS_PAD_PDVCLAMP (1 << 1)
-#define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF (1 << 0)
-
-#define MIPI_CAL_BIAS_PAD_CFG1 0x17
-#define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16)
-#define MIPI_CAL_BIAS_PAD_DRV_UP_REF(x) (((x) & 0x7) << 8)
-
-#define MIPI_CAL_BIAS_PAD_CFG2 0x18
-#define MIPI_CAL_BIAS_PAD_VCLAMP(x) (((x) & 0x7) << 16)
-#define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4)
-#define MIPI_CAL_BIAS_PAD_PDVREG (1 << 1)
-
-struct tegra_mipi_pad {
- unsigned long data;
- unsigned long clk;
-};
-
-struct tegra_mipi_soc {
- bool has_clk_lane;
- const struct tegra_mipi_pad *pads;
- unsigned int num_pads;
-
- bool clock_enable_override;
- bool needs_vclamp_ref;
-
- /* bias pad configuration settings */
- u8 pad_drive_down_ref;
- u8 pad_drive_up_ref;
-
- u8 pad_vclamp_level;
- u8 pad_vauxp_level;
-
- /* calibration settings for data lanes */
- u8 hspdos;
- u8 hspuos;
- u8 termos;
-
- /* calibration settings for clock lanes */
- u8 hsclkpdos;
- u8 hsclkpuos;
-};
-
-struct tegra_mipi {
- const struct tegra_mipi_soc *soc;
- struct device *dev;
- void __iomem *regs;
- struct mutex lock;
- struct clk *clk;
-
- unsigned long usage_count;
-};
-
-struct tegra_mipi_device {
- struct platform_device *pdev;
- struct tegra_mipi *mipi;
- struct device *device;
- unsigned long pads;
-};
-
-static inline u32 tegra_mipi_readl(struct tegra_mipi *mipi,
- unsigned long offset)
+int tegra_mipi_enable(struct tegra_mipi_device *device)
{
- return readl(mipi->regs + (offset << 2));
-}
+ if (device->ops->enable)
+ return device->ops->enable(device);
-static inline void tegra_mipi_writel(struct tegra_mipi *mipi, u32 value,
- unsigned long offset)
-{
- writel(value, mipi->regs + (offset << 2));
+ return 0;
}
+EXPORT_SYMBOL(tegra_mipi_enable);
-static int tegra_mipi_power_up(struct tegra_mipi *mipi)
+int tegra_mipi_disable(struct tegra_mipi_device *device)
{
- u32 value;
- int err;
-
- err = clk_enable(mipi->clk);
- if (err < 0)
- return err;
-
- value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);
- value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP;
-
- if (mipi->soc->needs_vclamp_ref)
- value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
-
- tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
-
- value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
- value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
- tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
-
- clk_disable(mipi->clk);
+ if (device->ops->disable)
+ return device->ops->disable(device);
return 0;
}
+EXPORT_SYMBOL(tegra_mipi_disable);
-static int tegra_mipi_power_down(struct tegra_mipi *mipi)
+int tegra_mipi_start_calibration(struct tegra_mipi_device *device)
{
- u32 value;
- int err;
+ if (device->ops->start_calibration)
+ return device->ops->start_calibration(device);
- err = clk_enable(mipi->clk);
- if (err < 0)
- return err;
-
- /*
- * The MIPI_CAL_BIAS_PAD_PDVREG controls a voltage regulator that
- * supplies the DSI pads. This must be kept enabled until none of the
- * DSI lanes are used anymore.
- */
- value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
- value |= MIPI_CAL_BIAS_PAD_PDVREG;
- tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
-
- /*
- * MIPI_CAL_BIAS_PAD_PDVCLAMP and MIPI_CAL_BIAS_PAD_E_VCLAMP_REF
- * control a regulator that supplies current to the pre-driver logic.
- * Powering down this regulator causes DSI to fail, so it must remain
- * powered on until none of the DSI lanes are used anymore.
- */
- value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);
-
- if (mipi->soc->needs_vclamp_ref)
- value &= ~MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
+ return 0;
+}
+EXPORT_SYMBOL(tegra_mipi_start_calibration);
- value |= MIPI_CAL_BIAS_PAD_PDVCLAMP;
- tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
+int tegra_mipi_finish_calibration(struct tegra_mipi_device *device)
+{
+ if (device->ops->finish_calibration)
+ return device->ops->finish_calibration(device);
return 0;
}
+EXPORT_SYMBOL(tegra_mipi_finish_calibration);
struct tegra_mipi_device *tegra_mipi_request(struct device *device,
struct device_node *np)
{
- struct tegra_mipi_device *dev;
+ struct tegra_mipi_device *mipidev;
struct of_phandle_args args;
int err;
@@ -219,321 +69,58 @@ struct tegra_mipi_device *tegra_mipi_request(struct device *device,
if (err < 0)
return ERR_PTR(err);
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev) {
+ if (provider.np != args.np)
+ return ERR_PTR(-ENODEV);
+
+ mipidev = kzalloc(sizeof(*mipidev), GFP_KERNEL);
+ if (!mipidev) {
err = -ENOMEM;
goto out;
}
- dev->pdev = of_find_device_by_node(args.np);
- if (!dev->pdev) {
+ mipidev->pdev = of_find_device_by_node(args.np);
+ if (!mipidev->pdev) {
err = -ENODEV;
goto free;
}
- dev->mipi = platform_get_drvdata(dev->pdev);
- if (!dev->mipi) {
- err = -EPROBE_DEFER;
- goto put;
- }
-
of_node_put(args.np);
- dev->pads = args.args[0];
- dev->device = device;
+ mipidev->ops = provider.ops;
+ mipidev->pads = args.args[0];
- return dev;
+ return mipidev;
-put:
- platform_device_put(dev->pdev);
free:
- kfree(dev);
+ kfree(mipidev);
out:
of_node_put(args.np);
return ERR_PTR(err);
}
EXPORT_SYMBOL(tegra_mipi_request);
-void tegra_mipi_free(struct tegra_mipi_device *device)
+void tegra_mipi_free(struct tegra_mipi_device *mipidev)
{
- platform_device_put(device->pdev);
- kfree(device);
+ platform_device_put(mipidev->pdev);
+ kfree(mipidev);
}
EXPORT_SYMBOL(tegra_mipi_free);
-int tegra_mipi_enable(struct tegra_mipi_device *dev)
+static void tegra_mipi_remove_provider(void *data)
{
- int err = 0;
-
- mutex_lock(&dev->mipi->lock);
-
- if (dev->mipi->usage_count++ == 0)
- err = tegra_mipi_power_up(dev->mipi);
-
- mutex_unlock(&dev->mipi->lock);
-
- return err;
-
+ provider.np = NULL;
+ provider.ops = NULL;
}
-EXPORT_SYMBOL(tegra_mipi_enable);
-int tegra_mipi_disable(struct tegra_mipi_device *dev)
+int devm_tegra_mipi_add_provider(struct device *device, struct device_node *np,
+ const struct tegra_mipi_ops *ops)
{
- int err = 0;
-
- mutex_lock(&dev->mipi->lock);
-
- if (--dev->mipi->usage_count == 0)
- err = tegra_mipi_power_down(dev->mipi);
+ if (provider.np)
+ return -EBUSY;
- mutex_unlock(&dev->mipi->lock);
+ provider.np = np;
+ provider.ops = ops;
- return err;
-
-}
-EXPORT_SYMBOL(tegra_mipi_disable);
-
-int tegra_mipi_finish_calibration(struct tegra_mipi_device *device)
-{
- struct tegra_mipi *mipi = device->mipi;
- void __iomem *status_reg = mipi->regs + (MIPI_CAL_STATUS << 2);
- u32 value;
- int err;
-
- err = readl_relaxed_poll_timeout(status_reg, value,
- !(value & MIPI_CAL_STATUS_ACTIVE) &&
- (value & MIPI_CAL_STATUS_DONE), 50,
- 250000);
- mutex_unlock(&device->mipi->lock);
- clk_disable(device->mipi->clk);
-
- return err;
-}
-EXPORT_SYMBOL(tegra_mipi_finish_calibration);
-
-int tegra_mipi_start_calibration(struct tegra_mipi_device *device)
-{
- const struct tegra_mipi_soc *soc = device->mipi->soc;
- unsigned int i;
- u32 value;
- int err;
-
- err = clk_enable(device->mipi->clk);
- if (err < 0)
- return err;
-
- mutex_lock(&device->mipi->lock);
-
- value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |
- MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref);
- tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG1);
-
- value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2);
- value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7);
- value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7);
- value |= MIPI_CAL_BIAS_PAD_VCLAMP(soc->pad_vclamp_level);
- value |= MIPI_CAL_BIAS_PAD_VAUXP(soc->pad_vauxp_level);
- tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
-
- for (i = 0; i < soc->num_pads; i++) {
- u32 clk = 0, data = 0;
-
- if (device->pads & BIT(i)) {
- data = MIPI_CAL_CONFIG_SELECT |
- MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) |
- MIPI_CAL_CONFIG_HSPUOS(soc->hspuos) |
- MIPI_CAL_CONFIG_TERMOS(soc->termos);
- clk = MIPI_CAL_CONFIG_SELECT |
- MIPI_CAL_CONFIG_HSCLKPDOSD(soc->hsclkpdos) |
- MIPI_CAL_CONFIG_HSCLKPUOSD(soc->hsclkpuos);
- }
-
- tegra_mipi_writel(device->mipi, data, soc->pads[i].data);
-
- if (soc->has_clk_lane && soc->pads[i].clk != 0)
- tegra_mipi_writel(device->mipi, clk, soc->pads[i].clk);
- }
-
- value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL);
- value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf);
- value &= ~MIPI_CAL_CTRL_PRESCALE(0x3);
- value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa);
- value |= MIPI_CAL_CTRL_PRESCALE(0x2);
-
- if (!soc->clock_enable_override)
- value &= ~MIPI_CAL_CTRL_CLKEN_OVR;
- else
- value |= MIPI_CAL_CTRL_CLKEN_OVR;
-
- tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL);
-
- /* clear any pending status bits */
- value = tegra_mipi_readl(device->mipi, MIPI_CAL_STATUS);
- tegra_mipi_writel(device->mipi, value, MIPI_CAL_STATUS);
-
- value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL);
- value |= MIPI_CAL_CTRL_START;
- tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL);
-
- /*
- * Wait for min 72uS to let calibration logic finish calibration
- * sequence codes before waiting for pads idle state to apply the
- * results.
- */
- usleep_range(75, 80);
-
- return 0;
-}
-EXPORT_SYMBOL(tegra_mipi_start_calibration);
-
-static const struct tegra_mipi_pad tegra114_mipi_pads[] = {
- { .data = MIPI_CAL_CONFIG_CSIA },
- { .data = MIPI_CAL_CONFIG_CSIB },
- { .data = MIPI_CAL_CONFIG_CSIC },
- { .data = MIPI_CAL_CONFIG_CSID },
- { .data = MIPI_CAL_CONFIG_CSIE },
- { .data = MIPI_CAL_CONFIG_DSIA },
- { .data = MIPI_CAL_CONFIG_DSIB },
- { .data = MIPI_CAL_CONFIG_DSIC },
- { .data = MIPI_CAL_CONFIG_DSID },
-};
-
-static const struct tegra_mipi_soc tegra114_mipi_soc = {
- .has_clk_lane = false,
- .pads = tegra114_mipi_pads,
- .num_pads = ARRAY_SIZE(tegra114_mipi_pads),
- .clock_enable_override = true,
- .needs_vclamp_ref = true,
- .pad_drive_down_ref = 0x2,
- .pad_drive_up_ref = 0x0,
- .pad_vclamp_level = 0x0,
- .pad_vauxp_level = 0x0,
- .hspdos = 0x0,
- .hspuos = 0x4,
- .termos = 0x5,
- .hsclkpdos = 0x0,
- .hsclkpuos = 0x4,
-};
-
-static const struct tegra_mipi_pad tegra124_mipi_pads[] = {
- { .data = MIPI_CAL_CONFIG_CSIA, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
- { .data = MIPI_CAL_CONFIG_CSIB, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
- { .data = MIPI_CAL_CONFIG_CSIC, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
- { .data = MIPI_CAL_CONFIG_CSID, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
- { .data = MIPI_CAL_CONFIG_CSIE, .clk = MIPI_CAL_CONFIG_CSIE_CLK },
- { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK },
- { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK },
-};
-
-static const struct tegra_mipi_soc tegra124_mipi_soc = {
- .has_clk_lane = true,
- .pads = tegra124_mipi_pads,
- .num_pads = ARRAY_SIZE(tegra124_mipi_pads),
- .clock_enable_override = true,
- .needs_vclamp_ref = true,
- .pad_drive_down_ref = 0x2,
- .pad_drive_up_ref = 0x0,
- .pad_vclamp_level = 0x0,
- .pad_vauxp_level = 0x0,
- .hspdos = 0x0,
- .hspuos = 0x0,
- .termos = 0x0,
- .hsclkpdos = 0x1,
- .hsclkpuos = 0x2,
-};
-
-static const struct tegra_mipi_soc tegra132_mipi_soc = {
- .has_clk_lane = true,
- .pads = tegra124_mipi_pads,
- .num_pads = ARRAY_SIZE(tegra124_mipi_pads),
- .clock_enable_override = false,
- .needs_vclamp_ref = false,
- .pad_drive_down_ref = 0x0,
- .pad_drive_up_ref = 0x3,
- .pad_vclamp_level = 0x0,
- .pad_vauxp_level = 0x0,
- .hspdos = 0x0,
- .hspuos = 0x0,
- .termos = 0x0,
- .hsclkpdos = 0x3,
- .hsclkpuos = 0x2,
-};
-
-static const struct tegra_mipi_pad tegra210_mipi_pads[] = {
- { .data = MIPI_CAL_CONFIG_CSIA, .clk = 0 },
- { .data = MIPI_CAL_CONFIG_CSIB, .clk = 0 },
- { .data = MIPI_CAL_CONFIG_CSIC, .clk = 0 },
- { .data = MIPI_CAL_CONFIG_CSID, .clk = 0 },
- { .data = MIPI_CAL_CONFIG_CSIE, .clk = 0 },
- { .data = MIPI_CAL_CONFIG_CSIF, .clk = 0 },
- { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK },
- { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK },
- { .data = MIPI_CAL_CONFIG_DSIC, .clk = MIPI_CAL_CONFIG_DSIC_CLK },
- { .data = MIPI_CAL_CONFIG_DSID, .clk = MIPI_CAL_CONFIG_DSID_CLK },
-};
-
-static const struct tegra_mipi_soc tegra210_mipi_soc = {
- .has_clk_lane = true,
- .pads = tegra210_mipi_pads,
- .num_pads = ARRAY_SIZE(tegra210_mipi_pads),
- .clock_enable_override = true,
- .needs_vclamp_ref = false,
- .pad_drive_down_ref = 0x0,
- .pad_drive_up_ref = 0x3,
- .pad_vclamp_level = 0x1,
- .pad_vauxp_level = 0x1,
- .hspdos = 0x0,
- .hspuos = 0x2,
- .termos = 0x0,
- .hsclkpdos = 0x0,
- .hsclkpuos = 0x2,
-};
-
-static const struct of_device_id tegra_mipi_of_match[] = {
- { .compatible = "nvidia,tegra114-mipi", .data = &tegra114_mipi_soc },
- { .compatible = "nvidia,tegra124-mipi", .data = &tegra124_mipi_soc },
- { .compatible = "nvidia,tegra132-mipi", .data = &tegra132_mipi_soc },
- { .compatible = "nvidia,tegra210-mipi", .data = &tegra210_mipi_soc },
- { },
-};
-
-static int tegra_mipi_probe(struct platform_device *pdev)
-{
- const struct of_device_id *match;
- struct tegra_mipi *mipi;
-
- match = of_match_node(tegra_mipi_of_match, pdev->dev.of_node);
- if (!match)
- return -ENODEV;
-
- mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL);
- if (!mipi)
- return -ENOMEM;
-
- mipi->soc = match->data;
- mipi->dev = &pdev->dev;
-
- mipi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
- if (IS_ERR(mipi->regs))
- return PTR_ERR(mipi->regs);
-
- mutex_init(&mipi->lock);
-
- mipi->clk = devm_clk_get_prepared(&pdev->dev, NULL);
- if (IS_ERR(mipi->clk)) {
- dev_err(&pdev->dev, "failed to get clock\n");
- return PTR_ERR(mipi->clk);
- }
-
- platform_set_drvdata(pdev, mipi);
-
- return 0;
+ return devm_add_action_or_reset(device, tegra_mipi_remove_provider, NULL);
}
-
-struct platform_driver tegra_mipi_driver = {
- .driver = {
- .name = "tegra-mipi",
- .of_match_table = tegra_mipi_of_match,
- },
- .probe = tegra_mipi_probe,
-};
+EXPORT_SYMBOL(devm_tegra_mipi_add_provider);
diff --git a/drivers/gpu/host1x/tegra114-mipi.c b/drivers/gpu/host1x/tegra114-mipi.c
new file mode 100644
index 000000000000..c084a09784d1
--- /dev/null
+++ b/drivers/gpu/host1x/tegra114-mipi.c
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2013 NVIDIA Corporation
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include <linux/clk.h>
+#include <linux/host1x.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/tegra-mipi-cal.h>
+
+#include "dev.h"
+
+#define MIPI_CAL_CTRL 0x00
+#define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26)
+#define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24)
+#define MIPI_CAL_CTRL_CLKEN_OVR BIT(4)
+#define MIPI_CAL_CTRL_START BIT(0)
+
+#define MIPI_CAL_AUTOCAL_CTRL 0x01
+
+#define MIPI_CAL_STATUS 0x02
+#define MIPI_CAL_STATUS_DONE BIT(16)
+#define MIPI_CAL_STATUS_ACTIVE BIT(0)
+
+#define MIPI_CAL_CONFIG_CSIA 0x05
+#define MIPI_CAL_CONFIG_CSIB 0x06
+#define MIPI_CAL_CONFIG_CSIC 0x07
+#define MIPI_CAL_CONFIG_CSID 0x08
+#define MIPI_CAL_CONFIG_CSIE 0x09
+#define MIPI_CAL_CONFIG_CSIF 0x0a
+#define MIPI_CAL_CONFIG_DSIA 0x0e
+#define MIPI_CAL_CONFIG_DSIB 0x0f
+#define MIPI_CAL_CONFIG_DSIC 0x10
+#define MIPI_CAL_CONFIG_DSID 0x11
+
+#define MIPI_CAL_CONFIG_DSIA_CLK 0x19
+#define MIPI_CAL_CONFIG_DSIB_CLK 0x1a
+#define MIPI_CAL_CONFIG_CSIAB_CLK 0x1b
+#define MIPI_CAL_CONFIG_DSIC_CLK 0x1c
+#define MIPI_CAL_CONFIG_CSICD_CLK 0x1c
+#define MIPI_CAL_CONFIG_DSID_CLK 0x1d
+#define MIPI_CAL_CONFIG_CSIE_CLK 0x1d
+
+/* for data and clock lanes */
+#define MIPI_CAL_CONFIG_SELECT BIT(21)
+
+/* for data lanes */
+#define MIPI_CAL_CONFIG_HSPDOS(x) (((x) & 0x1f) << 16)
+#define MIPI_CAL_CONFIG_HSPUOS(x) (((x) & 0x1f) << 8)
+#define MIPI_CAL_CONFIG_TERMOS(x) (((x) & 0x1f) << 0)
+
+/* for clock lanes */
+#define MIPI_CAL_CONFIG_HSCLKPDOSD(x) (((x) & 0x1f) << 8)
+#define MIPI_CAL_CONFIG_HSCLKPUOSD(x) (((x) & 0x1f) << 0)
+
+#define MIPI_CAL_BIAS_PAD_CFG0 0x16
+#define MIPI_CAL_BIAS_PAD_PDVCLAMP BIT(1)
+#define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF BIT(0)
+
+#define MIPI_CAL_BIAS_PAD_CFG1 0x17
+#define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16)
+#define MIPI_CAL_BIAS_PAD_DRV_UP_REF(x) (((x) & 0x7) << 8)
+
+#define MIPI_CAL_BIAS_PAD_CFG2 0x18
+#define MIPI_CAL_BIAS_PAD_VCLAMP(x) (((x) & 0x7) << 16)
+#define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4)
+#define MIPI_CAL_BIAS_PAD_PDVREG BIT(1)
+
+struct tegra_mipi_pad {
+ unsigned long data;
+ unsigned long clk;
+};
+
+struct tegra_mipi_soc {
+ bool has_clk_lane;
+ const struct tegra_mipi_pad *pads;
+ unsigned int num_pads;
+
+ bool clock_enable_override;
+ bool needs_vclamp_ref;
+
+ /* bias pad configuration settings */
+ u8 pad_drive_down_ref;
+ u8 pad_drive_up_ref;
+
+ u8 pad_vclamp_level;
+ u8 pad_vauxp_level;
+
+ /* calibration settings for data lanes */
+ u8 hspdos;
+ u8 hspuos;
+ u8 termos;
+
+ /* calibration settings for clock lanes */
+ u8 hsclkpdos;
+ u8 hsclkpuos;
+};
+
+struct tegra_mipi {
+ const struct tegra_mipi_soc *soc;
+ struct device *dev;
+ void __iomem *regs;
+ struct mutex lock; /* for register access */
+ struct clk *clk;
+
+ unsigned long usage_count;
+};
+
+static inline u32 tegra_mipi_readl(struct tegra_mipi *mipi,
+ unsigned long offset)
+{
+ return readl(mipi->regs + (offset << 2));
+}
+
+static inline void tegra_mipi_writel(struct tegra_mipi *mipi, u32 value,
+ unsigned long offset)
+{
+ writel(value, mipi->regs + (offset << 2));
+}
+
+static int tegra114_mipi_power_up(struct tegra_mipi *mipi)
+{
+ u32 value;
+ int err;
+
+ err = clk_enable(mipi->clk);
+ if (err < 0)
+ return err;
+
+ value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);
+ value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP;
+
+ if (mipi->soc->needs_vclamp_ref)
+ value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
+
+ tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
+
+ value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
+ value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
+ tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
+
+ clk_disable(mipi->clk);
+
+ return 0;
+}
+
+static int tegra114_mipi_power_down(struct tegra_mipi *mipi)
+{
+ u32 value;
+ int err;
+
+ err = clk_enable(mipi->clk);
+ if (err < 0)
+ return err;
+
+ /*
+ * The MIPI_CAL_BIAS_PAD_PDVREG controls a voltage regulator that
+ * supplies the DSI pads. This must be kept enabled until none of the
+ * DSI lanes are used anymore.
+ */
+ value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
+ value |= MIPI_CAL_BIAS_PAD_PDVREG;
+ tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
+
+ /*
+ * MIPI_CAL_BIAS_PAD_PDVCLAMP and MIPI_CAL_BIAS_PAD_E_VCLAMP_REF
+ * control a regulator that supplies current to the pre-driver logic.
+ * Powering down this regulator causes DSI to fail, so it must remain
+ * powered on until none of the DSI lanes are used anymore.
+ */
+ value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);
+
+ if (mipi->soc->needs_vclamp_ref)
+ value &= ~MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
+
+ value |= MIPI_CAL_BIAS_PAD_PDVCLAMP;
+ tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
+
+ return 0;
+}
+
+static int tegra114_mipi_enable(struct tegra_mipi_device *mipidev)
+{
+ struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev);
+ int err = 0;
+
+ mutex_lock(&mipi->lock);
+
+ if (mipi->usage_count++ == 0)
+ err = tegra114_mipi_power_up(mipi);
+
+ mutex_unlock(&mipi->lock);
+
+ return err;
+}
+
+static int tegra114_mipi_disable(struct tegra_mipi_device *mipidev)
+{
+ struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev);
+ int err = 0;
+
+ mutex_lock(&mipi->lock);
+
+ if (--mipi->usage_count == 0)
+ err = tegra114_mipi_power_down(mipi);
+
+ mutex_unlock(&mipi->lock);
+
+ return err;
+}
+
+static int tegra114_mipi_finish_calibration(struct tegra_mipi_device *mipidev)
+{
+ struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev);
+ void __iomem *status_reg = mipi->regs + (MIPI_CAL_STATUS << 2);
+ u32 value;
+ int err;
+
+ err = readl_relaxed_poll_timeout(status_reg, value,
+ !(value & MIPI_CAL_STATUS_ACTIVE) &&
+ (value & MIPI_CAL_STATUS_DONE), 50,
+ 250000);
+ mutex_unlock(&mipi->lock);
+ clk_disable(mipi->clk);
+
+ return err;
+}
+
+static int tegra114_mipi_start_calibration(struct tegra_mipi_device *mipidev)
+{
+ struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev);
+ const struct tegra_mipi_soc *soc = mipi->soc;
+ unsigned int i;
+ u32 value;
+ int err;
+
+ err = clk_enable(mipi->clk);
+ if (err < 0)
+ return err;
+
+ mutex_lock(&mipi->lock);
+
+ value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |
+ MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref);
+ tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG1);
+
+ value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
+ value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7);
+ value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7);
+ value |= MIPI_CAL_BIAS_PAD_VCLAMP(soc->pad_vclamp_level);
+ value |= MIPI_CAL_BIAS_PAD_VAUXP(soc->pad_vauxp_level);
+ tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
+
+ for (i = 0; i < soc->num_pads; i++) {
+ u32 clk = 0, data = 0;
+
+ if (mipidev->pads & BIT(i)) {
+ data = MIPI_CAL_CONFIG_SELECT |
+ MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) |
+ MIPI_CAL_CONFIG_HSPUOS(soc->hspuos) |
+ MIPI_CAL_CONFIG_TERMOS(soc->termos);
+ clk = MIPI_CAL_CONFIG_SELECT |
+ MIPI_CAL_CONFIG_HSCLKPDOSD(soc->hsclkpdos) |
+ MIPI_CAL_CONFIG_HSCLKPUOSD(soc->hsclkpuos);
+ }
+
+ tegra_mipi_writel(mipi, data, soc->pads[i].data);
+
+ if (soc->has_clk_lane && soc->pads[i].clk != 0)
+ tegra_mipi_writel(mipi, clk, soc->pads[i].clk);
+ }
+
+ value = tegra_mipi_readl(mipi, MIPI_CAL_CTRL);
+ value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf);
+ value &= ~MIPI_CAL_CTRL_PRESCALE(0x3);
+ value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa);
+ value |= MIPI_CAL_CTRL_PRESCALE(0x2);
+
+ if (!soc->clock_enable_override)
+ value &= ~MIPI_CAL_CTRL_CLKEN_OVR;
+ else
+ value |= MIPI_CAL_CTRL_CLKEN_OVR;
+
+ tegra_mipi_writel(mipi, value, MIPI_CAL_CTRL);
+
+ /* clear any pending status bits */
+ value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS);
+ tegra_mipi_writel(mipi, value, MIPI_CAL_STATUS);
+
+ value = tegra_mipi_readl(mipi, MIPI_CAL_CTRL);
+ value |= MIPI_CAL_CTRL_START;
+ tegra_mipi_writel(mipi, value, MIPI_CAL_CTRL);
+
+ /*
+ * Wait for min 72uS to let calibration logic finish calibration
+ * sequence codes before waiting for pads idle state to apply the
+ * results.
+ */
+ usleep_range(75, 80);
+
+ return 0;
+}
+
+static const struct tegra_mipi_ops tegra114_mipi_ops = {
+ .enable = tegra114_mipi_enable,
+ .disable = tegra114_mipi_disable,
+ .start_calibration = tegra114_mipi_start_calibration,
+ .finish_calibration = tegra114_mipi_finish_calibration,
+};
+
+static const struct tegra_mipi_pad tegra114_mipi_pads[] = {
+ { .data = MIPI_CAL_CONFIG_CSIA },
+ { .data = MIPI_CAL_CONFIG_CSIB },
+ { .data = MIPI_CAL_CONFIG_CSIC },
+ { .data = MIPI_CAL_CONFIG_CSID },
+ { .data = MIPI_CAL_CONFIG_CSIE },
+ { .data = MIPI_CAL_CONFIG_DSIA },
+ { .data = MIPI_CAL_CONFIG_DSIB },
+ { .data = MIPI_CAL_CONFIG_DSIC },
+ { .data = MIPI_CAL_CONFIG_DSID },
+};
+
+static const struct tegra_mipi_soc tegra114_mipi_soc = {
+ .has_clk_lane = false,
+ .pads = tegra114_mipi_pads,
+ .num_pads = ARRAY_SIZE(tegra114_mipi_pads),
+ .clock_enable_override = true,
+ .needs_vclamp_ref = true,
+ .pad_drive_down_ref = 0x2,
+ .pad_drive_up_ref = 0x0,
+ .pad_vclamp_level = 0x0,
+ .pad_vauxp_level = 0x0,
+ .hspdos = 0x0,
+ .hspuos = 0x4,
+ .termos = 0x5,
+ .hsclkpdos = 0x0,
+ .hsclkpuos = 0x4,
+};
+
+static const struct tegra_mipi_pad tegra124_mipi_pads[] = {
+ { .data = MIPI_CAL_CONFIG_CSIA, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
+ { .data = MIPI_CAL_CONFIG_CSIB, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
+ { .data = MIPI_CAL_CONFIG_CSIC, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
+ { .data = MIPI_CAL_CONFIG_CSID, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
+ { .data = MIPI_CAL_CONFIG_CSIE, .clk = MIPI_CAL_CONFIG_CSIE_CLK },
+ { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK },
+ { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK },
+};
+
+static const struct tegra_mipi_soc tegra124_mipi_soc = {
+ .has_clk_lane = true,
+ .pads = tegra124_mipi_pads,
+ .num_pads = ARRAY_SIZE(tegra124_mipi_pads),
+ .clock_enable_override = true,
+ .needs_vclamp_ref = true,
+ .pad_drive_down_ref = 0x2,
+ .pad_drive_up_ref = 0x0,
+ .pad_vclamp_level = 0x0,
+ .pad_vauxp_level = 0x0,
+ .hspdos = 0x0,
+ .hspuos = 0x0,
+ .termos = 0x0,
+ .hsclkpdos = 0x1,
+ .hsclkpuos = 0x2,
+};
+
+static const struct tegra_mipi_soc tegra132_mipi_soc = {
+ .has_clk_lane = true,
+ .pads = tegra124_mipi_pads,
+ .num_pads = ARRAY_SIZE(tegra124_mipi_pads),
+ .clock_enable_override = false,
+ .needs_vclamp_ref = false,
+ .pad_drive_down_ref = 0x0,
+ .pad_drive_up_ref = 0x3,
+ .pad_vclamp_level = 0x0,
+ .pad_vauxp_level = 0x0,
+ .hspdos = 0x0,
+ .hspuos = 0x0,
+ .termos = 0x0,
+ .hsclkpdos = 0x3,
+ .hsclkpuos = 0x2,
+};
+
+static const struct tegra_mipi_pad tegra210_mipi_pads[] = {
+ { .data = MIPI_CAL_CONFIG_CSIA, .clk = 0 },
+ { .data = MIPI_CAL_CONFIG_CSIB, .clk = 0 },
+ { .data = MIPI_CAL_CONFIG_CSIC, .clk = 0 },
+ { .data = MIPI_CAL_CONFIG_CSID, .clk = 0 },
+ { .data = MIPI_CAL_CONFIG_CSIE, .clk = 0 },
+ { .data = MIPI_CAL_CONFIG_CSIF, .clk = 0 },
+ { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK },
+ { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK },
+ { .data = MIPI_CAL_CONFIG_DSIC, .clk = MIPI_CAL_CONFIG_DSIC_CLK },
+ { .data = MIPI_CAL_CONFIG_DSID, .clk = MIPI_CAL_CONFIG_DSID_CLK },
+};
+
+static const struct tegra_mipi_soc tegra210_mipi_soc = {
+ .has_clk_lane = true,
+ .pads = tegra210_mipi_pads,
+ .num_pads = ARRAY_SIZE(tegra210_mipi_pads),
+ .clock_enable_override = true,
+ .needs_vclamp_ref = false,
+ .pad_drive_down_ref = 0x0,
+ .pad_drive_up_ref = 0x3,
+ .pad_vclamp_level = 0x1,
+ .pad_vauxp_level = 0x1,
+ .hspdos = 0x0,
+ .hspuos = 0x2,
+ .termos = 0x0,
+ .hsclkpdos = 0x0,
+ .hsclkpuos = 0x2,
+};
+
+static const struct of_device_id tegra_mipi_of_match[] = {
+ { .compatible = "nvidia,tegra114-mipi", .data = &tegra114_mipi_soc },
+ { .compatible = "nvidia,tegra124-mipi", .data = &tegra124_mipi_soc },
+ { .compatible = "nvidia,tegra132-mipi", .data = &tegra132_mipi_soc },
+ { .compatible = "nvidia,tegra210-mipi", .data = &tegra210_mipi_soc },
+ { },
+};
+
+static int tegra_mipi_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ struct tegra_mipi *mipi;
+
+ match = of_match_node(tegra_mipi_of_match, pdev->dev.of_node);
+ if (!match)
+ return -ENODEV;
+
+ mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL);
+ if (!mipi)
+ return -ENOMEM;
+
+ mipi->soc = match->data;
+ mipi->dev = &pdev->dev;
+
+ mipi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
+ if (IS_ERR(mipi->regs))
+ return PTR_ERR(mipi->regs);
+
+ mutex_init(&mipi->lock);
+
+ mipi->clk = devm_clk_get_prepared(&pdev->dev, NULL);
+ if (IS_ERR(mipi->clk)) {
+ dev_err(&pdev->dev, "failed to get clock\n");
+ return PTR_ERR(mipi->clk);
+ }
+
+ platform_set_drvdata(pdev, mipi);
+
+ return devm_tegra_mipi_add_provider(&pdev->dev, pdev->dev.of_node,
+ &tegra114_mipi_ops);
+}
+
+struct platform_driver tegra_mipi_driver = {
+ .driver = {
+ .name = "tegra-mipi",
+ .of_match_table = tegra_mipi_of_match,
+ },
+ .probe = tegra_mipi_probe,
+};
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
index 74c92db1032f..9e3bd6109781 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -12,6 +12,7 @@
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/tegra-mipi-cal.h>
#include <media/v4l2-fwnode.h>
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 9fa9c30a34e6..b1c6514859d3 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -453,16 +453,6 @@ void host1x_client_unregister(struct host1x_client *client);
int host1x_client_suspend(struct host1x_client *client);
int host1x_client_resume(struct host1x_client *client);
-struct tegra_mipi_device;
-
-struct tegra_mipi_device *tegra_mipi_request(struct device *device,
- struct device_node *np);
-void tegra_mipi_free(struct tegra_mipi_device *device);
-int tegra_mipi_enable(struct tegra_mipi_device *device);
-int tegra_mipi_disable(struct tegra_mipi_device *device);
-int tegra_mipi_start_calibration(struct tegra_mipi_device *device);
-int tegra_mipi_finish_calibration(struct tegra_mipi_device *device);
-
/* host1x memory contexts */
struct host1x_memory_context {
diff --git a/include/linux/tegra-mipi-cal.h b/include/linux/tegra-mipi-cal.h
new file mode 100644
index 000000000000..2a540b50f65d
--- /dev/null
+++ b/include/linux/tegra-mipi-cal.h
@@ -0,0 +1,57 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __TEGRA_MIPI_CAL_H_
+#define __TEGRA_MIPI_CAL_H_
+
+struct tegra_mipi_device {
+ const struct tegra_mipi_ops *ops;
+ struct platform_device *pdev;
+ unsigned long pads;
+};
+
+/**
+ * Operations for Tegra MIPI calibration device
+ */
+struct tegra_mipi_ops {
+ /**
+ * @enable:
+ *
+ * Enable MIPI calibration device
+ */
+ int (*enable)(struct tegra_mipi_device *device);
+
+ /**
+ * @disable:
+ *
+ * Disable MIPI calibration device
+ */
+ int (*disable)(struct tegra_mipi_device *device);
+
+ /**
+ * @start_calibration:
+ *
+ * Start MIPI calibration
+ */
+ int (*start_calibration)(struct tegra_mipi_device *device);
+
+ /**
+ * @finish_calibration:
+ *
+ * Finish MIPI calibration
+ */
+ int (*finish_calibration)(struct tegra_mipi_device *device);
+};
+
+int devm_tegra_mipi_add_provider(struct device *device, struct device_node *np,
+ const struct tegra_mipi_ops *ops);
+
+struct tegra_mipi_device *tegra_mipi_request(struct device *device,
+ struct device_node *np);
+void tegra_mipi_free(struct tegra_mipi_device *device);
+
+int tegra_mipi_enable(struct tegra_mipi_device *device);
+int tegra_mipi_disable(struct tegra_mipi_device *device);
+int tegra_mipi_start_calibration(struct tegra_mipi_device *device);
+int tegra_mipi_finish_calibration(struct tegra_mipi_device *device);
+
+#endif /* __TEGRA_MIPI_CAL_H_ */
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v4 10/24] gpu: host1x: convert MIPI to use operation function pointers
2025-10-08 7:30 ` [PATCH v4 10/24] gpu: host1x: convert MIPI to use operation function pointers Svyatoslav Ryhel
@ 2025-10-14 5:35 ` Mikko Perttunen
0 siblings, 0 replies; 40+ messages in thread
From: Mikko Perttunen @ 2025-10-14 5:35 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Linus Walleij, Mauro Carvalho Chehab, Greg Kroah-Hartman,
Svyatoslav Ryhel, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann,
Svyatoslav Ryhel
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
On Wednesday, October 8, 2025 4:30 PM Svyatoslav Ryhel wrote:
> Convert existing MIPI code to use operation function pointers, a necessary
> step for supporting Tegra20/Tegra30 SoCs. All common MIPI configuration
> that is SoC-independent remains in mipi.c, while all SoC-specific code is
> moved to tegra114-mipi.c (The naming matches the first SoC generation with
> a dedicated calibration block). Shared structures and function calls are
> placed into tegra-mipi-cal.h.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
> drivers/gpu/drm/tegra/dsi.c | 1 +
> drivers/gpu/host1x/Makefile | 1 +
> drivers/gpu/host1x/mipi.c | 525 +++---------------------
> drivers/gpu/host1x/tegra114-mipi.c | 483 ++++++++++++++++++++++
> drivers/staging/media/tegra-video/csi.c | 1 +
> include/linux/host1x.h | 10 -
> include/linux/tegra-mipi-cal.h | 57 +++
> 7 files changed, 599 insertions(+), 479 deletions(-)
> create mode 100644 drivers/gpu/host1x/tegra114-mipi.c
> create mode 100644 include/linux/tegra-mipi-cal.h
>
> diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
> index b2046f6ea515..502f0cd0ce53 100644
> --- a/drivers/gpu/drm/tegra/dsi.c
> +++ b/drivers/gpu/drm/tegra/dsi.c
> @@ -14,6 +14,7 @@
> #include <linux/pm_runtime.h>
> #include <linux/regulator/consumer.h>
> #include <linux/reset.h>
> +#include <linux/tegra-mipi-cal.h>
>
> #include <video/mipi_display.h>
>
> diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile
> index ee5286ffe08d..fead483af0b4 100644
> --- a/drivers/gpu/host1x/Makefile
> +++ b/drivers/gpu/host1x/Makefile
> @@ -9,6 +9,7 @@ host1x-y = \
> job.o \
> debug.o \
> mipi.o \
> + tegra114-mipi.o \
> fence.o \
> hw/host1x01.o \
> hw/host1x02.o \
> diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
> index e51b43dd15a3..8d32072e2244 100644
> --- a/drivers/gpu/host1x/mipi.c
> +++ b/drivers/gpu/host1x/mipi.c
> @@ -1,215 +1,65 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> /*
> * Copyright (C) 2013 NVIDIA Corporation
> - *
> - * Permission to use, copy, modify, distribute, and sell this software and its
> - * documentation for any purpose is hereby granted without fee, provided that
> - * the above copyright notice appear in all copies and that both that copyright
> - * notice and this permission notice appear in supporting documentation, and
> - * that the name of the copyright holders not be used in advertising or
> - * publicity pertaining to distribution of the software without specific,
> - * written prior permission. The copyright holders make no representations
> - * about the suitability of this software for any purpose. It is provided "as
> - * is" without express or implied warranty.
> - *
> - * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> - * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> - * OF THIS SOFTWARE.
> + * Copyright (C) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
> */
>
> #include <linux/clk.h>
> -#include <linux/host1x.h>
> #include <linux/io.h>
> #include <linux/iopoll.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> #include <linux/of_platform.h>
> #include <linux/platform_device.h>
> #include <linux/slab.h>
> +#include <linux/tegra-mipi-cal.h>
>
> -#include "dev.h"
> +/* only need to support one provider */
> +static struct {
> + struct device_node *np;
> + const struct tegra_mipi_ops *ops;
> +} provider;
>
> -#define MIPI_CAL_CTRL 0x00
> -#define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26)
> -#define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24)
> -#define MIPI_CAL_CTRL_CLKEN_OVR (1 << 4)
> -#define MIPI_CAL_CTRL_START (1 << 0)
> -
> -#define MIPI_CAL_AUTOCAL_CTRL 0x01
> -
> -#define MIPI_CAL_STATUS 0x02
> -#define MIPI_CAL_STATUS_DONE (1 << 16)
> -#define MIPI_CAL_STATUS_ACTIVE (1 << 0)
> -
> -#define MIPI_CAL_CONFIG_CSIA 0x05
> -#define MIPI_CAL_CONFIG_CSIB 0x06
> -#define MIPI_CAL_CONFIG_CSIC 0x07
> -#define MIPI_CAL_CONFIG_CSID 0x08
> -#define MIPI_CAL_CONFIG_CSIE 0x09
> -#define MIPI_CAL_CONFIG_CSIF 0x0a
> -#define MIPI_CAL_CONFIG_DSIA 0x0e
> -#define MIPI_CAL_CONFIG_DSIB 0x0f
> -#define MIPI_CAL_CONFIG_DSIC 0x10
> -#define MIPI_CAL_CONFIG_DSID 0x11
> -
> -#define MIPI_CAL_CONFIG_DSIA_CLK 0x19
> -#define MIPI_CAL_CONFIG_DSIB_CLK 0x1a
> -#define MIPI_CAL_CONFIG_CSIAB_CLK 0x1b
> -#define MIPI_CAL_CONFIG_DSIC_CLK 0x1c
> -#define MIPI_CAL_CONFIG_CSICD_CLK 0x1c
> -#define MIPI_CAL_CONFIG_DSID_CLK 0x1d
> -#define MIPI_CAL_CONFIG_CSIE_CLK 0x1d
> -
> -/* for data and clock lanes */
> -#define MIPI_CAL_CONFIG_SELECT (1 << 21)
> -
> -/* for data lanes */
> -#define MIPI_CAL_CONFIG_HSPDOS(x) (((x) & 0x1f) << 16)
> -#define MIPI_CAL_CONFIG_HSPUOS(x) (((x) & 0x1f) << 8)
> -#define MIPI_CAL_CONFIG_TERMOS(x) (((x) & 0x1f) << 0)
> -
> -/* for clock lanes */
> -#define MIPI_CAL_CONFIG_HSCLKPDOSD(x) (((x) & 0x1f) << 8)
> -#define MIPI_CAL_CONFIG_HSCLKPUOSD(x) (((x) & 0x1f) << 0)
> -
> -#define MIPI_CAL_BIAS_PAD_CFG0 0x16
> -#define MIPI_CAL_BIAS_PAD_PDVCLAMP (1 << 1)
> -#define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF (1 << 0)
> -
> -#define MIPI_CAL_BIAS_PAD_CFG1 0x17
> -#define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16)
> -#define MIPI_CAL_BIAS_PAD_DRV_UP_REF(x) (((x) & 0x7) << 8)
> -
> -#define MIPI_CAL_BIAS_PAD_CFG2 0x18
> -#define MIPI_CAL_BIAS_PAD_VCLAMP(x) (((x) & 0x7) << 16)
> -#define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4)
> -#define MIPI_CAL_BIAS_PAD_PDVREG (1 << 1)
> -
> -struct tegra_mipi_pad {
> - unsigned long data;
> - unsigned long clk;
> -};
> -
> -struct tegra_mipi_soc {
> - bool has_clk_lane;
> - const struct tegra_mipi_pad *pads;
> - unsigned int num_pads;
> -
> - bool clock_enable_override;
> - bool needs_vclamp_ref;
> -
> - /* bias pad configuration settings */
> - u8 pad_drive_down_ref;
> - u8 pad_drive_up_ref;
> -
> - u8 pad_vclamp_level;
> - u8 pad_vauxp_level;
> -
> - /* calibration settings for data lanes */
> - u8 hspdos;
> - u8 hspuos;
> - u8 termos;
> -
> - /* calibration settings for clock lanes */
> - u8 hsclkpdos;
> - u8 hsclkpuos;
> -};
> -
> -struct tegra_mipi {
> - const struct tegra_mipi_soc *soc;
> - struct device *dev;
> - void __iomem *regs;
> - struct mutex lock;
> - struct clk *clk;
> -
> - unsigned long usage_count;
> -};
> -
> -struct tegra_mipi_device {
> - struct platform_device *pdev;
> - struct tegra_mipi *mipi;
> - struct device *device;
> - unsigned long pads;
> -};
> -
> -static inline u32 tegra_mipi_readl(struct tegra_mipi *mipi,
> - unsigned long offset)
> +int tegra_mipi_enable(struct tegra_mipi_device *device)
> {
> - return readl(mipi->regs + (offset << 2));
> -}
> + if (device->ops->enable)
> + return device->ops->enable(device);
>
> -static inline void tegra_mipi_writel(struct tegra_mipi *mipi, u32 value,
> - unsigned long offset)
> -{
> - writel(value, mipi->regs + (offset << 2));
> + return 0;
> }
> +EXPORT_SYMBOL(tegra_mipi_enable);
>
> -static int tegra_mipi_power_up(struct tegra_mipi *mipi)
> +int tegra_mipi_disable(struct tegra_mipi_device *device)
> {
> - u32 value;
> - int err;
> -
> - err = clk_enable(mipi->clk);
> - if (err < 0)
> - return err;
> -
> - value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);
> - value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP;
> -
> - if (mipi->soc->needs_vclamp_ref)
> - value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
> -
> - tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
> -
> - value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
> - value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
> - tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
> -
> - clk_disable(mipi->clk);
> + if (device->ops->disable)
> + return device->ops->disable(device);
>
> return 0;
> }
> +EXPORT_SYMBOL(tegra_mipi_disable);
>
> -static int tegra_mipi_power_down(struct tegra_mipi *mipi)
> +int tegra_mipi_start_calibration(struct tegra_mipi_device *device)
> {
> - u32 value;
> - int err;
> + if (device->ops->start_calibration)
> + return device->ops->start_calibration(device);
>
> - err = clk_enable(mipi->clk);
> - if (err < 0)
> - return err;
> -
> - /*
> - * The MIPI_CAL_BIAS_PAD_PDVREG controls a voltage regulator that
> - * supplies the DSI pads. This must be kept enabled until none of the
> - * DSI lanes are used anymore.
> - */
> - value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
> - value |= MIPI_CAL_BIAS_PAD_PDVREG;
> - tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
> -
> - /*
> - * MIPI_CAL_BIAS_PAD_PDVCLAMP and MIPI_CAL_BIAS_PAD_E_VCLAMP_REF
> - * control a regulator that supplies current to the pre-driver logic.
> - * Powering down this regulator causes DSI to fail, so it must remain
> - * powered on until none of the DSI lanes are used anymore.
> - */
> - value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);
> -
> - if (mipi->soc->needs_vclamp_ref)
> - value &= ~MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
> + return 0;
> +}
> +EXPORT_SYMBOL(tegra_mipi_start_calibration);
>
> - value |= MIPI_CAL_BIAS_PAD_PDVCLAMP;
> - tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
> +int tegra_mipi_finish_calibration(struct tegra_mipi_device *device)
> +{
> + if (device->ops->finish_calibration)
> + return device->ops->finish_calibration(device);
>
> return 0;
> }
> +EXPORT_SYMBOL(tegra_mipi_finish_calibration);
>
> struct tegra_mipi_device *tegra_mipi_request(struct device *device,
> struct device_node *np)
> {
> - struct tegra_mipi_device *dev;
> + struct tegra_mipi_device *mipidev;
> struct of_phandle_args args;
> int err;
>
> @@ -219,321 +69,58 @@ struct tegra_mipi_device *tegra_mipi_request(struct device *device,
> if (err < 0)
> return ERR_PTR(err);
>
> - dev = kzalloc(sizeof(*dev), GFP_KERNEL);
> - if (!dev) {
> + if (provider.np != args.np)
> + return ERR_PTR(-ENODEV);
> +
> + mipidev = kzalloc(sizeof(*mipidev), GFP_KERNEL);
> + if (!mipidev) {
> err = -ENOMEM;
> goto out;
> }
>
> - dev->pdev = of_find_device_by_node(args.np);
> - if (!dev->pdev) {
> + mipidev->pdev = of_find_device_by_node(args.np);
> + if (!mipidev->pdev) {
> err = -ENODEV;
> goto free;
> }
>
> - dev->mipi = platform_get_drvdata(dev->pdev);
> - if (!dev->mipi) {
> - err = -EPROBE_DEFER;
> - goto put;
> - }
> -
> of_node_put(args.np);
>
> - dev->pads = args.args[0];
> - dev->device = device;
> + mipidev->ops = provider.ops;
> + mipidev->pads = args.args[0];
>
> - return dev;
> + return mipidev;
>
> -put:
> - platform_device_put(dev->pdev);
> free:
> - kfree(dev);
> + kfree(mipidev);
> out:
> of_node_put(args.np);
> return ERR_PTR(err);
> }
> EXPORT_SYMBOL(tegra_mipi_request);
>
> -void tegra_mipi_free(struct tegra_mipi_device *device)
> +void tegra_mipi_free(struct tegra_mipi_device *mipidev)
> {
> - platform_device_put(device->pdev);
> - kfree(device);
> + platform_device_put(mipidev->pdev);
> + kfree(mipidev);
> }
> EXPORT_SYMBOL(tegra_mipi_free);
>
> -int tegra_mipi_enable(struct tegra_mipi_device *dev)
> +static void tegra_mipi_remove_provider(void *data)
> {
> - int err = 0;
> -
> - mutex_lock(&dev->mipi->lock);
> -
> - if (dev->mipi->usage_count++ == 0)
> - err = tegra_mipi_power_up(dev->mipi);
> -
> - mutex_unlock(&dev->mipi->lock);
> -
> - return err;
> -
> + provider.np = NULL;
> + provider.ops = NULL;
> }
> -EXPORT_SYMBOL(tegra_mipi_enable);
>
> -int tegra_mipi_disable(struct tegra_mipi_device *dev)
> +int devm_tegra_mipi_add_provider(struct device *device, struct device_node *np,
> + const struct tegra_mipi_ops *ops)
> {
> - int err = 0;
> -
> - mutex_lock(&dev->mipi->lock);
> -
> - if (--dev->mipi->usage_count == 0)
> - err = tegra_mipi_power_down(dev->mipi);
> + if (provider.np)
> + return -EBUSY;
>
> - mutex_unlock(&dev->mipi->lock);
> + provider.np = np;
> + provider.ops = ops;
>
> - return err;
> -
> -}
> -EXPORT_SYMBOL(tegra_mipi_disable);
> -
> -int tegra_mipi_finish_calibration(struct tegra_mipi_device *device)
> -{
> - struct tegra_mipi *mipi = device->mipi;
> - void __iomem *status_reg = mipi->regs + (MIPI_CAL_STATUS << 2);
> - u32 value;
> - int err;
> -
> - err = readl_relaxed_poll_timeout(status_reg, value,
> - !(value & MIPI_CAL_STATUS_ACTIVE) &&
> - (value & MIPI_CAL_STATUS_DONE), 50,
> - 250000);
> - mutex_unlock(&device->mipi->lock);
> - clk_disable(device->mipi->clk);
> -
> - return err;
> -}
> -EXPORT_SYMBOL(tegra_mipi_finish_calibration);
> -
> -int tegra_mipi_start_calibration(struct tegra_mipi_device *device)
> -{
> - const struct tegra_mipi_soc *soc = device->mipi->soc;
> - unsigned int i;
> - u32 value;
> - int err;
> -
> - err = clk_enable(device->mipi->clk);
> - if (err < 0)
> - return err;
> -
> - mutex_lock(&device->mipi->lock);
> -
> - value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |
> - MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref);
> - tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG1);
> -
> - value = tegra_mipi_readl(device->mipi, MIPI_CAL_BIAS_PAD_CFG2);
> - value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7);
> - value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7);
> - value |= MIPI_CAL_BIAS_PAD_VCLAMP(soc->pad_vclamp_level);
> - value |= MIPI_CAL_BIAS_PAD_VAUXP(soc->pad_vauxp_level);
> - tegra_mipi_writel(device->mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
> -
> - for (i = 0; i < soc->num_pads; i++) {
> - u32 clk = 0, data = 0;
> -
> - if (device->pads & BIT(i)) {
> - data = MIPI_CAL_CONFIG_SELECT |
> - MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) |
> - MIPI_CAL_CONFIG_HSPUOS(soc->hspuos) |
> - MIPI_CAL_CONFIG_TERMOS(soc->termos);
> - clk = MIPI_CAL_CONFIG_SELECT |
> - MIPI_CAL_CONFIG_HSCLKPDOSD(soc->hsclkpdos) |
> - MIPI_CAL_CONFIG_HSCLKPUOSD(soc->hsclkpuos);
> - }
> -
> - tegra_mipi_writel(device->mipi, data, soc->pads[i].data);
> -
> - if (soc->has_clk_lane && soc->pads[i].clk != 0)
> - tegra_mipi_writel(device->mipi, clk, soc->pads[i].clk);
> - }
> -
> - value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL);
> - value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf);
> - value &= ~MIPI_CAL_CTRL_PRESCALE(0x3);
> - value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa);
> - value |= MIPI_CAL_CTRL_PRESCALE(0x2);
> -
> - if (!soc->clock_enable_override)
> - value &= ~MIPI_CAL_CTRL_CLKEN_OVR;
> - else
> - value |= MIPI_CAL_CTRL_CLKEN_OVR;
> -
> - tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL);
> -
> - /* clear any pending status bits */
> - value = tegra_mipi_readl(device->mipi, MIPI_CAL_STATUS);
> - tegra_mipi_writel(device->mipi, value, MIPI_CAL_STATUS);
> -
> - value = tegra_mipi_readl(device->mipi, MIPI_CAL_CTRL);
> - value |= MIPI_CAL_CTRL_START;
> - tegra_mipi_writel(device->mipi, value, MIPI_CAL_CTRL);
> -
> - /*
> - * Wait for min 72uS to let calibration logic finish calibration
> - * sequence codes before waiting for pads idle state to apply the
> - * results.
> - */
> - usleep_range(75, 80);
> -
> - return 0;
> -}
> -EXPORT_SYMBOL(tegra_mipi_start_calibration);
> -
> -static const struct tegra_mipi_pad tegra114_mipi_pads[] = {
> - { .data = MIPI_CAL_CONFIG_CSIA },
> - { .data = MIPI_CAL_CONFIG_CSIB },
> - { .data = MIPI_CAL_CONFIG_CSIC },
> - { .data = MIPI_CAL_CONFIG_CSID },
> - { .data = MIPI_CAL_CONFIG_CSIE },
> - { .data = MIPI_CAL_CONFIG_DSIA },
> - { .data = MIPI_CAL_CONFIG_DSIB },
> - { .data = MIPI_CAL_CONFIG_DSIC },
> - { .data = MIPI_CAL_CONFIG_DSID },
> -};
> -
> -static const struct tegra_mipi_soc tegra114_mipi_soc = {
> - .has_clk_lane = false,
> - .pads = tegra114_mipi_pads,
> - .num_pads = ARRAY_SIZE(tegra114_mipi_pads),
> - .clock_enable_override = true,
> - .needs_vclamp_ref = true,
> - .pad_drive_down_ref = 0x2,
> - .pad_drive_up_ref = 0x0,
> - .pad_vclamp_level = 0x0,
> - .pad_vauxp_level = 0x0,
> - .hspdos = 0x0,
> - .hspuos = 0x4,
> - .termos = 0x5,
> - .hsclkpdos = 0x0,
> - .hsclkpuos = 0x4,
> -};
> -
> -static const struct tegra_mipi_pad tegra124_mipi_pads[] = {
> - { .data = MIPI_CAL_CONFIG_CSIA, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
> - { .data = MIPI_CAL_CONFIG_CSIB, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
> - { .data = MIPI_CAL_CONFIG_CSIC, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
> - { .data = MIPI_CAL_CONFIG_CSID, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
> - { .data = MIPI_CAL_CONFIG_CSIE, .clk = MIPI_CAL_CONFIG_CSIE_CLK },
> - { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK },
> - { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK },
> -};
> -
> -static const struct tegra_mipi_soc tegra124_mipi_soc = {
> - .has_clk_lane = true,
> - .pads = tegra124_mipi_pads,
> - .num_pads = ARRAY_SIZE(tegra124_mipi_pads),
> - .clock_enable_override = true,
> - .needs_vclamp_ref = true,
> - .pad_drive_down_ref = 0x2,
> - .pad_drive_up_ref = 0x0,
> - .pad_vclamp_level = 0x0,
> - .pad_vauxp_level = 0x0,
> - .hspdos = 0x0,
> - .hspuos = 0x0,
> - .termos = 0x0,
> - .hsclkpdos = 0x1,
> - .hsclkpuos = 0x2,
> -};
> -
> -static const struct tegra_mipi_soc tegra132_mipi_soc = {
> - .has_clk_lane = true,
> - .pads = tegra124_mipi_pads,
> - .num_pads = ARRAY_SIZE(tegra124_mipi_pads),
> - .clock_enable_override = false,
> - .needs_vclamp_ref = false,
> - .pad_drive_down_ref = 0x0,
> - .pad_drive_up_ref = 0x3,
> - .pad_vclamp_level = 0x0,
> - .pad_vauxp_level = 0x0,
> - .hspdos = 0x0,
> - .hspuos = 0x0,
> - .termos = 0x0,
> - .hsclkpdos = 0x3,
> - .hsclkpuos = 0x2,
> -};
> -
> -static const struct tegra_mipi_pad tegra210_mipi_pads[] = {
> - { .data = MIPI_CAL_CONFIG_CSIA, .clk = 0 },
> - { .data = MIPI_CAL_CONFIG_CSIB, .clk = 0 },
> - { .data = MIPI_CAL_CONFIG_CSIC, .clk = 0 },
> - { .data = MIPI_CAL_CONFIG_CSID, .clk = 0 },
> - { .data = MIPI_CAL_CONFIG_CSIE, .clk = 0 },
> - { .data = MIPI_CAL_CONFIG_CSIF, .clk = 0 },
> - { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK },
> - { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK },
> - { .data = MIPI_CAL_CONFIG_DSIC, .clk = MIPI_CAL_CONFIG_DSIC_CLK },
> - { .data = MIPI_CAL_CONFIG_DSID, .clk = MIPI_CAL_CONFIG_DSID_CLK },
> -};
> -
> -static const struct tegra_mipi_soc tegra210_mipi_soc = {
> - .has_clk_lane = true,
> - .pads = tegra210_mipi_pads,
> - .num_pads = ARRAY_SIZE(tegra210_mipi_pads),
> - .clock_enable_override = true,
> - .needs_vclamp_ref = false,
> - .pad_drive_down_ref = 0x0,
> - .pad_drive_up_ref = 0x3,
> - .pad_vclamp_level = 0x1,
> - .pad_vauxp_level = 0x1,
> - .hspdos = 0x0,
> - .hspuos = 0x2,
> - .termos = 0x0,
> - .hsclkpdos = 0x0,
> - .hsclkpuos = 0x2,
> -};
> -
> -static const struct of_device_id tegra_mipi_of_match[] = {
> - { .compatible = "nvidia,tegra114-mipi", .data = &tegra114_mipi_soc },
> - { .compatible = "nvidia,tegra124-mipi", .data = &tegra124_mipi_soc },
> - { .compatible = "nvidia,tegra132-mipi", .data = &tegra132_mipi_soc },
> - { .compatible = "nvidia,tegra210-mipi", .data = &tegra210_mipi_soc },
> - { },
> -};
> -
> -static int tegra_mipi_probe(struct platform_device *pdev)
> -{
> - const struct of_device_id *match;
> - struct tegra_mipi *mipi;
> -
> - match = of_match_node(tegra_mipi_of_match, pdev->dev.of_node);
> - if (!match)
> - return -ENODEV;
> -
> - mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL);
> - if (!mipi)
> - return -ENOMEM;
> -
> - mipi->soc = match->data;
> - mipi->dev = &pdev->dev;
> -
> - mipi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
> - if (IS_ERR(mipi->regs))
> - return PTR_ERR(mipi->regs);
> -
> - mutex_init(&mipi->lock);
> -
> - mipi->clk = devm_clk_get_prepared(&pdev->dev, NULL);
> - if (IS_ERR(mipi->clk)) {
> - dev_err(&pdev->dev, "failed to get clock\n");
> - return PTR_ERR(mipi->clk);
> - }
> -
> - platform_set_drvdata(pdev, mipi);
> -
> - return 0;
> + return devm_add_action_or_reset(device, tegra_mipi_remove_provider, NULL);
> }
> -
> -struct platform_driver tegra_mipi_driver = {
> - .driver = {
> - .name = "tegra-mipi",
> - .of_match_table = tegra_mipi_of_match,
> - },
> - .probe = tegra_mipi_probe,
> -};
> +EXPORT_SYMBOL(devm_tegra_mipi_add_provider);
> diff --git a/drivers/gpu/host1x/tegra114-mipi.c b/drivers/gpu/host1x/tegra114-mipi.c
> new file mode 100644
> index 000000000000..c084a09784d1
> --- /dev/null
> +++ b/drivers/gpu/host1x/tegra114-mipi.c
> @@ -0,0 +1,483 @@
> +/*
> + * Copyright (C) 2013 NVIDIA Corporation
> + *
> + * Permission to use, copy, modify, distribute, and sell this software and its
> + * documentation for any purpose is hereby granted without fee, provided that
> + * the above copyright notice appear in all copies and that both that copyright
> + * notice and this permission notice appear in supporting documentation, and
> + * that the name of the copyright holders not be used in advertising or
> + * publicity pertaining to distribution of the software without specific,
> + * written prior permission. The copyright holders make no representations
> + * about the suitability of this software for any purpose. It is provided "as
> + * is" without express or implied warranty.
> + *
> + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
> + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
> + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
> + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
> + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
> + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
> + * OF THIS SOFTWARE.
> + */
> +
> +#include <linux/clk.h>
> +#include <linux/host1x.h>
> +#include <linux/io.h>
> +#include <linux/iopoll.h>
> +#include <linux/of_platform.h>
> +#include <linux/platform_device.h>
> +#include <linux/slab.h>
> +#include <linux/tegra-mipi-cal.h>
> +
> +#include "dev.h"
> +
> +#define MIPI_CAL_CTRL 0x00
> +#define MIPI_CAL_CTRL_NOISE_FILTER(x) (((x) & 0xf) << 26)
> +#define MIPI_CAL_CTRL_PRESCALE(x) (((x) & 0x3) << 24)
> +#define MIPI_CAL_CTRL_CLKEN_OVR BIT(4)
> +#define MIPI_CAL_CTRL_START BIT(0)
> +
> +#define MIPI_CAL_AUTOCAL_CTRL 0x01
> +
> +#define MIPI_CAL_STATUS 0x02
> +#define MIPI_CAL_STATUS_DONE BIT(16)
> +#define MIPI_CAL_STATUS_ACTIVE BIT(0)
> +
> +#define MIPI_CAL_CONFIG_CSIA 0x05
> +#define MIPI_CAL_CONFIG_CSIB 0x06
> +#define MIPI_CAL_CONFIG_CSIC 0x07
> +#define MIPI_CAL_CONFIG_CSID 0x08
> +#define MIPI_CAL_CONFIG_CSIE 0x09
> +#define MIPI_CAL_CONFIG_CSIF 0x0a
> +#define MIPI_CAL_CONFIG_DSIA 0x0e
> +#define MIPI_CAL_CONFIG_DSIB 0x0f
> +#define MIPI_CAL_CONFIG_DSIC 0x10
> +#define MIPI_CAL_CONFIG_DSID 0x11
> +
> +#define MIPI_CAL_CONFIG_DSIA_CLK 0x19
> +#define MIPI_CAL_CONFIG_DSIB_CLK 0x1a
> +#define MIPI_CAL_CONFIG_CSIAB_CLK 0x1b
> +#define MIPI_CAL_CONFIG_DSIC_CLK 0x1c
> +#define MIPI_CAL_CONFIG_CSICD_CLK 0x1c
> +#define MIPI_CAL_CONFIG_DSID_CLK 0x1d
> +#define MIPI_CAL_CONFIG_CSIE_CLK 0x1d
> +
> +/* for data and clock lanes */
> +#define MIPI_CAL_CONFIG_SELECT BIT(21)
> +
> +/* for data lanes */
> +#define MIPI_CAL_CONFIG_HSPDOS(x) (((x) & 0x1f) << 16)
> +#define MIPI_CAL_CONFIG_HSPUOS(x) (((x) & 0x1f) << 8)
> +#define MIPI_CAL_CONFIG_TERMOS(x) (((x) & 0x1f) << 0)
> +
> +/* for clock lanes */
> +#define MIPI_CAL_CONFIG_HSCLKPDOSD(x) (((x) & 0x1f) << 8)
> +#define MIPI_CAL_CONFIG_HSCLKPUOSD(x) (((x) & 0x1f) << 0)
> +
> +#define MIPI_CAL_BIAS_PAD_CFG0 0x16
> +#define MIPI_CAL_BIAS_PAD_PDVCLAMP BIT(1)
> +#define MIPI_CAL_BIAS_PAD_E_VCLAMP_REF BIT(0)
> +
> +#define MIPI_CAL_BIAS_PAD_CFG1 0x17
> +#define MIPI_CAL_BIAS_PAD_DRV_DN_REF(x) (((x) & 0x7) << 16)
> +#define MIPI_CAL_BIAS_PAD_DRV_UP_REF(x) (((x) & 0x7) << 8)
> +
> +#define MIPI_CAL_BIAS_PAD_CFG2 0x18
> +#define MIPI_CAL_BIAS_PAD_VCLAMP(x) (((x) & 0x7) << 16)
> +#define MIPI_CAL_BIAS_PAD_VAUXP(x) (((x) & 0x7) << 4)
> +#define MIPI_CAL_BIAS_PAD_PDVREG BIT(1)
> +
> +struct tegra_mipi_pad {
> + unsigned long data;
> + unsigned long clk;
> +};
> +
> +struct tegra_mipi_soc {
> + bool has_clk_lane;
> + const struct tegra_mipi_pad *pads;
> + unsigned int num_pads;
> +
> + bool clock_enable_override;
> + bool needs_vclamp_ref;
> +
> + /* bias pad configuration settings */
> + u8 pad_drive_down_ref;
> + u8 pad_drive_up_ref;
> +
> + u8 pad_vclamp_level;
> + u8 pad_vauxp_level;
> +
> + /* calibration settings for data lanes */
> + u8 hspdos;
> + u8 hspuos;
> + u8 termos;
> +
> + /* calibration settings for clock lanes */
> + u8 hsclkpdos;
> + u8 hsclkpuos;
> +};
> +
> +struct tegra_mipi {
> + const struct tegra_mipi_soc *soc;
> + struct device *dev;
> + void __iomem *regs;
> + struct mutex lock; /* for register access */
> + struct clk *clk;
> +
> + unsigned long usage_count;
> +};
> +
> +static inline u32 tegra_mipi_readl(struct tegra_mipi *mipi,
> + unsigned long offset)
> +{
> + return readl(mipi->regs + (offset << 2));
> +}
> +
> +static inline void tegra_mipi_writel(struct tegra_mipi *mipi, u32 value,
> + unsigned long offset)
> +{
> + writel(value, mipi->regs + (offset << 2));
> +}
> +
> +static int tegra114_mipi_power_up(struct tegra_mipi *mipi)
> +{
> + u32 value;
> + int err;
> +
> + err = clk_enable(mipi->clk);
> + if (err < 0)
> + return err;
> +
> + value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);
> + value &= ~MIPI_CAL_BIAS_PAD_PDVCLAMP;
> +
> + if (mipi->soc->needs_vclamp_ref)
> + value |= MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
> +
> + tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
> +
> + value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
> + value &= ~MIPI_CAL_BIAS_PAD_PDVREG;
> + tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
> +
> + clk_disable(mipi->clk);
> +
> + return 0;
> +}
> +
> +static int tegra114_mipi_power_down(struct tegra_mipi *mipi)
> +{
> + u32 value;
> + int err;
> +
> + err = clk_enable(mipi->clk);
> + if (err < 0)
> + return err;
> +
> + /*
> + * The MIPI_CAL_BIAS_PAD_PDVREG controls a voltage regulator that
> + * supplies the DSI pads. This must be kept enabled until none of the
> + * DSI lanes are used anymore.
> + */
> + value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
> + value |= MIPI_CAL_BIAS_PAD_PDVREG;
> + tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
> +
> + /*
> + * MIPI_CAL_BIAS_PAD_PDVCLAMP and MIPI_CAL_BIAS_PAD_E_VCLAMP_REF
> + * control a regulator that supplies current to the pre-driver logic.
> + * Powering down this regulator causes DSI to fail, so it must remain
> + * powered on until none of the DSI lanes are used anymore.
> + */
> + value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG0);
> +
> + if (mipi->soc->needs_vclamp_ref)
> + value &= ~MIPI_CAL_BIAS_PAD_E_VCLAMP_REF;
> +
> + value |= MIPI_CAL_BIAS_PAD_PDVCLAMP;
> + tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG0);
> +
> + return 0;
> +}
> +
> +static int tegra114_mipi_enable(struct tegra_mipi_device *mipidev)
> +{
> + struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev);
> + int err = 0;
> +
> + mutex_lock(&mipi->lock);
> +
> + if (mipi->usage_count++ == 0)
> + err = tegra114_mipi_power_up(mipi);
> +
> + mutex_unlock(&mipi->lock);
> +
> + return err;
> +}
> +
> +static int tegra114_mipi_disable(struct tegra_mipi_device *mipidev)
> +{
> + struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev);
> + int err = 0;
> +
> + mutex_lock(&mipi->lock);
> +
> + if (--mipi->usage_count == 0)
> + err = tegra114_mipi_power_down(mipi);
> +
> + mutex_unlock(&mipi->lock);
> +
> + return err;
> +}
> +
> +static int tegra114_mipi_finish_calibration(struct tegra_mipi_device *mipidev)
> +{
> + struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev);
> + void __iomem *status_reg = mipi->regs + (MIPI_CAL_STATUS << 2);
> + u32 value;
> + int err;
> +
> + err = readl_relaxed_poll_timeout(status_reg, value,
> + !(value & MIPI_CAL_STATUS_ACTIVE) &&
> + (value & MIPI_CAL_STATUS_DONE), 50,
> + 250000);
> + mutex_unlock(&mipi->lock);
> + clk_disable(mipi->clk);
> +
> + return err;
> +}
> +
> +static int tegra114_mipi_start_calibration(struct tegra_mipi_device *mipidev)
> +{
> + struct tegra_mipi *mipi = platform_get_drvdata(mipidev->pdev);
> + const struct tegra_mipi_soc *soc = mipi->soc;
> + unsigned int i;
> + u32 value;
> + int err;
> +
> + err = clk_enable(mipi->clk);
> + if (err < 0)
> + return err;
> +
> + mutex_lock(&mipi->lock);
> +
> + value = MIPI_CAL_BIAS_PAD_DRV_DN_REF(soc->pad_drive_down_ref) |
> + MIPI_CAL_BIAS_PAD_DRV_UP_REF(soc->pad_drive_up_ref);
> + tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG1);
> +
> + value = tegra_mipi_readl(mipi, MIPI_CAL_BIAS_PAD_CFG2);
> + value &= ~MIPI_CAL_BIAS_PAD_VCLAMP(0x7);
> + value &= ~MIPI_CAL_BIAS_PAD_VAUXP(0x7);
> + value |= MIPI_CAL_BIAS_PAD_VCLAMP(soc->pad_vclamp_level);
> + value |= MIPI_CAL_BIAS_PAD_VAUXP(soc->pad_vauxp_level);
> + tegra_mipi_writel(mipi, value, MIPI_CAL_BIAS_PAD_CFG2);
> +
> + for (i = 0; i < soc->num_pads; i++) {
> + u32 clk = 0, data = 0;
> +
> + if (mipidev->pads & BIT(i)) {
> + data = MIPI_CAL_CONFIG_SELECT |
> + MIPI_CAL_CONFIG_HSPDOS(soc->hspdos) |
> + MIPI_CAL_CONFIG_HSPUOS(soc->hspuos) |
> + MIPI_CAL_CONFIG_TERMOS(soc->termos);
> + clk = MIPI_CAL_CONFIG_SELECT |
> + MIPI_CAL_CONFIG_HSCLKPDOSD(soc->hsclkpdos) |
> + MIPI_CAL_CONFIG_HSCLKPUOSD(soc->hsclkpuos);
> + }
> +
> + tegra_mipi_writel(mipi, data, soc->pads[i].data);
> +
> + if (soc->has_clk_lane && soc->pads[i].clk != 0)
> + tegra_mipi_writel(mipi, clk, soc->pads[i].clk);
> + }
> +
> + value = tegra_mipi_readl(mipi, MIPI_CAL_CTRL);
> + value &= ~MIPI_CAL_CTRL_NOISE_FILTER(0xf);
> + value &= ~MIPI_CAL_CTRL_PRESCALE(0x3);
> + value |= MIPI_CAL_CTRL_NOISE_FILTER(0xa);
> + value |= MIPI_CAL_CTRL_PRESCALE(0x2);
> +
> + if (!soc->clock_enable_override)
> + value &= ~MIPI_CAL_CTRL_CLKEN_OVR;
> + else
> + value |= MIPI_CAL_CTRL_CLKEN_OVR;
> +
> + tegra_mipi_writel(mipi, value, MIPI_CAL_CTRL);
> +
> + /* clear any pending status bits */
> + value = tegra_mipi_readl(mipi, MIPI_CAL_STATUS);
> + tegra_mipi_writel(mipi, value, MIPI_CAL_STATUS);
> +
> + value = tegra_mipi_readl(mipi, MIPI_CAL_CTRL);
> + value |= MIPI_CAL_CTRL_START;
> + tegra_mipi_writel(mipi, value, MIPI_CAL_CTRL);
> +
> + /*
> + * Wait for min 72uS to let calibration logic finish calibration
> + * sequence codes before waiting for pads idle state to apply the
> + * results.
> + */
> + usleep_range(75, 80);
> +
> + return 0;
> +}
> +
> +static const struct tegra_mipi_ops tegra114_mipi_ops = {
> + .enable = tegra114_mipi_enable,
> + .disable = tegra114_mipi_disable,
> + .start_calibration = tegra114_mipi_start_calibration,
> + .finish_calibration = tegra114_mipi_finish_calibration,
> +};
> +
> +static const struct tegra_mipi_pad tegra114_mipi_pads[] = {
> + { .data = MIPI_CAL_CONFIG_CSIA },
> + { .data = MIPI_CAL_CONFIG_CSIB },
> + { .data = MIPI_CAL_CONFIG_CSIC },
> + { .data = MIPI_CAL_CONFIG_CSID },
> + { .data = MIPI_CAL_CONFIG_CSIE },
> + { .data = MIPI_CAL_CONFIG_DSIA },
> + { .data = MIPI_CAL_CONFIG_DSIB },
> + { .data = MIPI_CAL_CONFIG_DSIC },
> + { .data = MIPI_CAL_CONFIG_DSID },
> +};
> +
> +static const struct tegra_mipi_soc tegra114_mipi_soc = {
> + .has_clk_lane = false,
> + .pads = tegra114_mipi_pads,
> + .num_pads = ARRAY_SIZE(tegra114_mipi_pads),
> + .clock_enable_override = true,
> + .needs_vclamp_ref = true,
> + .pad_drive_down_ref = 0x2,
> + .pad_drive_up_ref = 0x0,
> + .pad_vclamp_level = 0x0,
> + .pad_vauxp_level = 0x0,
> + .hspdos = 0x0,
> + .hspuos = 0x4,
> + .termos = 0x5,
> + .hsclkpdos = 0x0,
> + .hsclkpuos = 0x4,
> +};
> +
> +static const struct tegra_mipi_pad tegra124_mipi_pads[] = {
> + { .data = MIPI_CAL_CONFIG_CSIA, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
> + { .data = MIPI_CAL_CONFIG_CSIB, .clk = MIPI_CAL_CONFIG_CSIAB_CLK },
> + { .data = MIPI_CAL_CONFIG_CSIC, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
> + { .data = MIPI_CAL_CONFIG_CSID, .clk = MIPI_CAL_CONFIG_CSICD_CLK },
> + { .data = MIPI_CAL_CONFIG_CSIE, .clk = MIPI_CAL_CONFIG_CSIE_CLK },
> + { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK },
> + { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK },
> +};
> +
> +static const struct tegra_mipi_soc tegra124_mipi_soc = {
> + .has_clk_lane = true,
> + .pads = tegra124_mipi_pads,
> + .num_pads = ARRAY_SIZE(tegra124_mipi_pads),
> + .clock_enable_override = true,
> + .needs_vclamp_ref = true,
> + .pad_drive_down_ref = 0x2,
> + .pad_drive_up_ref = 0x0,
> + .pad_vclamp_level = 0x0,
> + .pad_vauxp_level = 0x0,
> + .hspdos = 0x0,
> + .hspuos = 0x0,
> + .termos = 0x0,
> + .hsclkpdos = 0x1,
> + .hsclkpuos = 0x2,
> +};
> +
> +static const struct tegra_mipi_soc tegra132_mipi_soc = {
> + .has_clk_lane = true,
> + .pads = tegra124_mipi_pads,
> + .num_pads = ARRAY_SIZE(tegra124_mipi_pads),
> + .clock_enable_override = false,
> + .needs_vclamp_ref = false,
> + .pad_drive_down_ref = 0x0,
> + .pad_drive_up_ref = 0x3,
> + .pad_vclamp_level = 0x0,
> + .pad_vauxp_level = 0x0,
> + .hspdos = 0x0,
> + .hspuos = 0x0,
> + .termos = 0x0,
> + .hsclkpdos = 0x3,
> + .hsclkpuos = 0x2,
> +};
> +
> +static const struct tegra_mipi_pad tegra210_mipi_pads[] = {
> + { .data = MIPI_CAL_CONFIG_CSIA, .clk = 0 },
> + { .data = MIPI_CAL_CONFIG_CSIB, .clk = 0 },
> + { .data = MIPI_CAL_CONFIG_CSIC, .clk = 0 },
> + { .data = MIPI_CAL_CONFIG_CSID, .clk = 0 },
> + { .data = MIPI_CAL_CONFIG_CSIE, .clk = 0 },
> + { .data = MIPI_CAL_CONFIG_CSIF, .clk = 0 },
> + { .data = MIPI_CAL_CONFIG_DSIA, .clk = MIPI_CAL_CONFIG_DSIA_CLK },
> + { .data = MIPI_CAL_CONFIG_DSIB, .clk = MIPI_CAL_CONFIG_DSIB_CLK },
> + { .data = MIPI_CAL_CONFIG_DSIC, .clk = MIPI_CAL_CONFIG_DSIC_CLK },
> + { .data = MIPI_CAL_CONFIG_DSID, .clk = MIPI_CAL_CONFIG_DSID_CLK },
> +};
> +
> +static const struct tegra_mipi_soc tegra210_mipi_soc = {
> + .has_clk_lane = true,
> + .pads = tegra210_mipi_pads,
> + .num_pads = ARRAY_SIZE(tegra210_mipi_pads),
> + .clock_enable_override = true,
> + .needs_vclamp_ref = false,
> + .pad_drive_down_ref = 0x0,
> + .pad_drive_up_ref = 0x3,
> + .pad_vclamp_level = 0x1,
> + .pad_vauxp_level = 0x1,
> + .hspdos = 0x0,
> + .hspuos = 0x2,
> + .termos = 0x0,
> + .hsclkpdos = 0x0,
> + .hsclkpuos = 0x2,
> +};
> +
> +static const struct of_device_id tegra_mipi_of_match[] = {
> + { .compatible = "nvidia,tegra114-mipi", .data = &tegra114_mipi_soc },
> + { .compatible = "nvidia,tegra124-mipi", .data = &tegra124_mipi_soc },
> + { .compatible = "nvidia,tegra132-mipi", .data = &tegra132_mipi_soc },
> + { .compatible = "nvidia,tegra210-mipi", .data = &tegra210_mipi_soc },
> + { },
> +};
> +
> +static int tegra_mipi_probe(struct platform_device *pdev)
> +{
> + const struct of_device_id *match;
> + struct tegra_mipi *mipi;
> +
> + match = of_match_node(tegra_mipi_of_match, pdev->dev.of_node);
> + if (!match)
> + return -ENODEV;
> +
> + mipi = devm_kzalloc(&pdev->dev, sizeof(*mipi), GFP_KERNEL);
> + if (!mipi)
> + return -ENOMEM;
> +
> + mipi->soc = match->data;
> + mipi->dev = &pdev->dev;
> +
> + mipi->regs = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
> + if (IS_ERR(mipi->regs))
> + return PTR_ERR(mipi->regs);
> +
> + mutex_init(&mipi->lock);
> +
> + mipi->clk = devm_clk_get_prepared(&pdev->dev, NULL);
> + if (IS_ERR(mipi->clk)) {
> + dev_err(&pdev->dev, "failed to get clock\n");
> + return PTR_ERR(mipi->clk);
> + }
> +
> + platform_set_drvdata(pdev, mipi);
> +
> + return devm_tegra_mipi_add_provider(&pdev->dev, pdev->dev.of_node,
> + &tegra114_mipi_ops);
> +}
> +
> +struct platform_driver tegra_mipi_driver = {
> + .driver = {
> + .name = "tegra-mipi",
> + .of_match_table = tegra_mipi_of_match,
> + },
> + .probe = tegra_mipi_probe,
> +};
> diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
> index 74c92db1032f..9e3bd6109781 100644
> --- a/drivers/staging/media/tegra-video/csi.c
> +++ b/drivers/staging/media/tegra-video/csi.c
> @@ -12,6 +12,7 @@
> #include <linux/of_graph.h>
> #include <linux/platform_device.h>
> #include <linux/pm_runtime.h>
> +#include <linux/tegra-mipi-cal.h>
>
> #include <media/v4l2-fwnode.h>
>
> diff --git a/include/linux/host1x.h b/include/linux/host1x.h
> index 9fa9c30a34e6..b1c6514859d3 100644
> --- a/include/linux/host1x.h
> +++ b/include/linux/host1x.h
> @@ -453,16 +453,6 @@ void host1x_client_unregister(struct host1x_client *client);
> int host1x_client_suspend(struct host1x_client *client);
> int host1x_client_resume(struct host1x_client *client);
>
> -struct tegra_mipi_device;
> -
> -struct tegra_mipi_device *tegra_mipi_request(struct device *device,
> - struct device_node *np);
> -void tegra_mipi_free(struct tegra_mipi_device *device);
> -int tegra_mipi_enable(struct tegra_mipi_device *device);
> -int tegra_mipi_disable(struct tegra_mipi_device *device);
> -int tegra_mipi_start_calibration(struct tegra_mipi_device *device);
> -int tegra_mipi_finish_calibration(struct tegra_mipi_device *device);
> -
> /* host1x memory contexts */
>
> struct host1x_memory_context {
> diff --git a/include/linux/tegra-mipi-cal.h b/include/linux/tegra-mipi-cal.h
> new file mode 100644
> index 000000000000..2a540b50f65d
> --- /dev/null
> +++ b/include/linux/tegra-mipi-cal.h
> @@ -0,0 +1,57 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +
> +#ifndef __TEGRA_MIPI_CAL_H_
> +#define __TEGRA_MIPI_CAL_H_
> +
> +struct tegra_mipi_device {
> + const struct tegra_mipi_ops *ops;
> + struct platform_device *pdev;
> + unsigned long pads;
> +};
> +
> +/**
> + * Operations for Tegra MIPI calibration device
> + */
> +struct tegra_mipi_ops {
> + /**
> + * @enable:
> + *
> + * Enable MIPI calibration device
> + */
> + int (*enable)(struct tegra_mipi_device *device);
> +
> + /**
> + * @disable:
> + *
> + * Disable MIPI calibration device
> + */
> + int (*disable)(struct tegra_mipi_device *device);
> +
> + /**
> + * @start_calibration:
> + *
> + * Start MIPI calibration
> + */
> + int (*start_calibration)(struct tegra_mipi_device *device);
> +
> + /**
> + * @finish_calibration:
> + *
> + * Finish MIPI calibration
> + */
> + int (*finish_calibration)(struct tegra_mipi_device *device);
> +};
> +
> +int devm_tegra_mipi_add_provider(struct device *device, struct device_node *np,
> + const struct tegra_mipi_ops *ops);
> +
> +struct tegra_mipi_device *tegra_mipi_request(struct device *device,
> + struct device_node *np);
> +void tegra_mipi_free(struct tegra_mipi_device *device);
> +
> +int tegra_mipi_enable(struct tegra_mipi_device *device);
> +int tegra_mipi_disable(struct tegra_mipi_device *device);
> +int tegra_mipi_start_calibration(struct tegra_mipi_device *device);
> +int tegra_mipi_finish_calibration(struct tegra_mipi_device *device);
> +
> +#endif /* __TEGRA_MIPI_CAL_H_ */
>
Acked-by: Mikko Perttunen <mperttunen@nvidia.com>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v4 11/24] dt-bindings: display: tegra: document Tegra132 MIPI calibration device
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (9 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 10/24] gpu: host1x: convert MIPI to use operation function pointers Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 21:14 ` Conor Dooley
2025-10-08 7:30 ` [PATCH v4 12/24] staging: media: tegra-video: vi: improve logic of source requesting Svyatoslav Ryhel
` (12 subsequent siblings)
23 siblings, 1 reply; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Document MIPI calibration device found in Tegra132.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
.../devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
index 193ddb105283..9a500f52f01d 100644
--- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
@@ -18,6 +18,7 @@ properties:
enum:
- nvidia,tegra114-mipi
- nvidia,tegra124-mipi
+ - nvidia,tegra132-mipi
- nvidia,tegra210-mipi
- nvidia,tegra186-mipi
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v4 11/24] dt-bindings: display: tegra: document Tegra132 MIPI calibration device
2025-10-08 7:30 ` [PATCH v4 11/24] dt-bindings: display: tegra: document Tegra132 MIPI calibration device Svyatoslav Ryhel
@ 2025-10-08 21:14 ` Conor Dooley
2025-10-09 5:12 ` Svyatoslav Ryhel
0 siblings, 1 reply; 40+ messages in thread
From: Conor Dooley @ 2025-10-08 21:14 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann, dri-devel,
devicetree, linux-tegra, linux-kernel, linux-media, linux-clk,
linux-gpio, linux-staging
[-- Attachment #1: Type: text/plain, Size: 1132 bytes --]
On Wed, Oct 08, 2025 at 10:30:33AM +0300, Svyatoslav Ryhel wrote:
> Document MIPI calibration device found in Tegra132.
Could you explain why a fallback is not suitable? The patchset is really
too big for me to trivially check that the change is correct.
With an explanation,
Acked-by: Conor Dooley <conor.dooley@microchip.com>
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
> .../devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
> index 193ddb105283..9a500f52f01d 100644
> --- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
> +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
> @@ -18,6 +18,7 @@ properties:
> enum:
> - nvidia,tegra114-mipi
> - nvidia,tegra124-mipi
> + - nvidia,tegra132-mipi
> - nvidia,tegra210-mipi
> - nvidia,tegra186-mipi
>
> --
> 2.48.1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v4 11/24] dt-bindings: display: tegra: document Tegra132 MIPI calibration device
2025-10-08 21:14 ` Conor Dooley
@ 2025-10-09 5:12 ` Svyatoslav Ryhel
2025-10-09 17:01 ` Conor Dooley
0 siblings, 1 reply; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-09 5:12 UTC (permalink / raw)
To: Conor Dooley
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann, dri-devel,
devicetree, linux-tegra, linux-kernel, linux-media, linux-clk,
linux-gpio, linux-staging
чт, 9 жовт. 2025 р. о 00:14 Conor Dooley <conor@kernel.org> пише:
>
> On Wed, Oct 08, 2025 at 10:30:33AM +0300, Svyatoslav Ryhel wrote:
> > Document MIPI calibration device found in Tegra132.
>
> Could you explain why a fallback is not suitable? The patchset is really
> too big for me to trivially check that the change is correct.
First of all, this compatible already exists in Linux kernel, I have
just documented it to satisfy warnings. Secondly, each Tegra SoC
generation has unique set of registers which should be configured.
They all differ, hence fallback is not suitable here.
> With an explanation,
> Acked-by: Conor Dooley <conor.dooley@microchip.com>
>
> >
> > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > ---
> > .../devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
> > index 193ddb105283..9a500f52f01d 100644
> > --- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
> > +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
> > @@ -18,6 +18,7 @@ properties:
> > enum:
> > - nvidia,tegra114-mipi
> > - nvidia,tegra124-mipi
> > + - nvidia,tegra132-mipi
> > - nvidia,tegra210-mipi
> > - nvidia,tegra186-mipi
> >
> > --
> > 2.48.1
> >
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v4 11/24] dt-bindings: display: tegra: document Tegra132 MIPI calibration device
2025-10-09 5:12 ` Svyatoslav Ryhel
@ 2025-10-09 17:01 ` Conor Dooley
0 siblings, 0 replies; 40+ messages in thread
From: Conor Dooley @ 2025-10-09 17:01 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann, dri-devel,
devicetree, linux-tegra, linux-kernel, linux-media, linux-clk,
linux-gpio, linux-staging
[-- Attachment #1: Type: text/plain, Size: 1719 bytes --]
On Thu, Oct 09, 2025 at 08:12:11AM +0300, Svyatoslav Ryhel wrote:
> чт, 9 жовт. 2025 р. о 00:14 Conor Dooley <conor@kernel.org> пише:
> >
> > On Wed, Oct 08, 2025 at 10:30:33AM +0300, Svyatoslav Ryhel wrote:
> > > Document MIPI calibration device found in Tegra132.
> >
> > Could you explain why a fallback is not suitable? The patchset is really
> > too big for me to trivially check that the change is correct.
>
> First of all, this compatible already exists in Linux kernel, I have
> just documented it to satisfy warnings. Secondly, each Tegra SoC
> generation has unique set of registers which should be configured.
> They all differ, hence fallback is not suitable here.
Okay, then put that in your commit message.
>
> > With an explanation,
> > Acked-by: Conor Dooley <conor.dooley@microchip.com>
> >
> > >
> > > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > > ---
> > > .../devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml | 1 +
> > > 1 file changed, 1 insertion(+)
> > >
> > > diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
> > > index 193ddb105283..9a500f52f01d 100644
> > > --- a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
> > > +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra114-mipi.yaml
> > > @@ -18,6 +18,7 @@ properties:
> > > enum:
> > > - nvidia,tegra114-mipi
> > > - nvidia,tegra124-mipi
> > > + - nvidia,tegra132-mipi
> > > - nvidia,tegra210-mipi
> > > - nvidia,tegra186-mipi
> > >
> > > --
> > > 2.48.1
> > >
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v4 12/24] staging: media: tegra-video: vi: improve logic of source requesting
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (10 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 11/24] dt-bindings: display: tegra: document Tegra132 MIPI calibration device Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 13/24] staging: media: tegra-video: csi: move avdd-dsi-csi-supply from VI to CSI Svyatoslav Ryhel
` (11 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
By default tegra_channel_get_remote_csi_subdev returns next device in pipe
assuming it is CSI but in case of Tegra20 and Tegra30 it can also be VIP
or even HOST.
Define tegra_channel_get_remote_csi_subdev within CSI and add check if
returned device is actually CSI by comparing subdevice operations.
Previous tegra_channel_get_remote_csi_subdev definition in VI rename to
tegra_channel_get_remote_bridge_subdev and use it only in VI driver since
core VI driver does not care about source and does not call any specific
functions.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/staging/media/tegra-video/csi.c | 16 ++++++++++++++++
drivers/staging/media/tegra-video/vi.c | 14 +++++++-------
2 files changed, 23 insertions(+), 7 deletions(-)
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
index 9e3bd6109781..ef5f054b6d49 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -445,6 +445,22 @@ static const struct v4l2_subdev_ops tegra_csi_ops = {
.pad = &tegra_csi_pad_ops,
};
+struct v4l2_subdev *tegra_channel_get_remote_csi_subdev(struct tegra_vi_channel *chan)
+{
+ struct media_pad *pad;
+ struct v4l2_subdev *subdev;
+
+ pad = media_pad_remote_pad_first(&chan->pad);
+ if (!pad)
+ return NULL;
+
+ subdev = media_entity_to_v4l2_subdev(pad->entity);
+ if (!subdev)
+ return NULL;
+
+ return subdev->ops == &tegra_csi_ops ? subdev : NULL;
+}
+
static int tegra_csi_channel_alloc(struct tegra_csi *csi,
struct device_node *node,
unsigned int port_num, unsigned int lanes,
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index 90473729b546..04b538e8b514 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -160,8 +160,8 @@ static void tegra_channel_buffer_queue(struct vb2_buffer *vb)
wake_up_interruptible(&chan->start_wait);
}
-struct v4l2_subdev *
-tegra_channel_get_remote_csi_subdev(struct tegra_vi_channel *chan)
+static struct v4l2_subdev *
+tegra_channel_get_remote_bridge_subdev(struct tegra_vi_channel *chan)
{
struct media_pad *pad;
@@ -182,7 +182,7 @@ tegra_channel_get_remote_source_subdev(struct tegra_vi_channel *chan)
struct v4l2_subdev *subdev;
struct media_entity *entity;
- subdev = tegra_channel_get_remote_csi_subdev(chan);
+ subdev = tegra_channel_get_remote_bridge_subdev(chan);
if (!subdev)
return NULL;
@@ -204,7 +204,7 @@ static int tegra_channel_enable_stream(struct tegra_vi_channel *chan)
struct v4l2_subdev *subdev;
int ret;
- subdev = tegra_channel_get_remote_csi_subdev(chan);
+ subdev = tegra_channel_get_remote_bridge_subdev(chan);
ret = v4l2_subdev_call(subdev, video, s_stream, true);
if (ret < 0 && ret != -ENOIOCTLCMD)
return ret;
@@ -217,7 +217,7 @@ static int tegra_channel_disable_stream(struct tegra_vi_channel *chan)
struct v4l2_subdev *subdev;
int ret;
- subdev = tegra_channel_get_remote_csi_subdev(chan);
+ subdev = tegra_channel_get_remote_bridge_subdev(chan);
ret = v4l2_subdev_call(subdev, video, s_stream, false);
if (ret < 0 && ret != -ENOIOCTLCMD)
return ret;
@@ -1630,11 +1630,11 @@ static int tegra_vi_graph_notify_complete(struct v4l2_async_notifier *notifier)
goto unregister_video;
}
- subdev = tegra_channel_get_remote_csi_subdev(chan);
+ subdev = tegra_channel_get_remote_bridge_subdev(chan);
if (!subdev) {
ret = -ENODEV;
dev_err(vi->dev,
- "failed to get remote csi subdev: %d\n", ret);
+ "failed to get remote bridge subdev: %d\n", ret);
goto unregister_video;
}
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 13/24] staging: media: tegra-video: csi: move avdd-dsi-csi-supply from VI to CSI
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (11 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 12/24] staging: media: tegra-video: vi: improve logic of source requesting Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 14/24] arm64: tegra: move avdd-dsi-csi-supply into CSI node Svyatoslav Ryhel
` (10 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
The avdd-dsi-csi-supply is CSI power supply not VI, hence move it to
proper place.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Tested-by: Luca Ceresoli <luca.ceresoli@bootlin.com> # Tegra20 VIP
Reviewed-by: Luca Ceresoli <luca.ceresoli@bootlin.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
---
drivers/staging/media/tegra-video/csi.c | 19 ++++++++++++++++++-
drivers/staging/media/tegra-video/csi.h | 2 ++
drivers/staging/media/tegra-video/vi.c | 23 ++---------------------
drivers/staging/media/tegra-video/vi.h | 2 --
4 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
index ef5f054b6d49..7d70478a07aa 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -710,6 +710,8 @@ static int __maybe_unused csi_runtime_suspend(struct device *dev)
clk_bulk_disable_unprepare(csi->soc->num_clks, csi->clks);
+ regulator_disable(csi->vdd);
+
return 0;
}
@@ -718,13 +720,23 @@ static int __maybe_unused csi_runtime_resume(struct device *dev)
struct tegra_csi *csi = dev_get_drvdata(dev);
int ret;
+ ret = regulator_enable(csi->vdd);
+ if (ret) {
+ dev_err(dev, "failed to enable VDD supply: %d\n", ret);
+ return ret;
+ }
+
ret = clk_bulk_prepare_enable(csi->soc->num_clks, csi->clks);
if (ret < 0) {
dev_err(csi->dev, "failed to enable clocks: %d\n", ret);
- return ret;
+ goto disable_vdd;
}
return 0;
+
+disable_vdd:
+ regulator_disable(csi->vdd);
+ return ret;
}
static int tegra_csi_init(struct host1x_client *client)
@@ -802,6 +814,11 @@ static int tegra_csi_probe(struct platform_device *pdev)
return ret;
}
+ csi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
+ if (IS_ERR(csi->vdd))
+ return dev_err_probe(&pdev->dev, PTR_ERR(csi->vdd),
+ "failed to get VDD supply");
+
if (!pdev->dev.pm_domain) {
ret = -ENOENT;
dev_warn(&pdev->dev, "PM domain is not attached: %d\n", ret);
diff --git a/drivers/staging/media/tegra-video/csi.h b/drivers/staging/media/tegra-video/csi.h
index 3ed2dbc73ce9..1550defb115a 100644
--- a/drivers/staging/media/tegra-video/csi.h
+++ b/drivers/staging/media/tegra-video/csi.h
@@ -137,6 +137,7 @@ struct tegra_csi_soc {
* @client: host1x_client struct
* @iomem: register base
* @clks: clock for CSI and CIL
+ * @vdd: vdd regulator for CSI hardware, usually avdd_dsi_csi
* @soc: pointer to SoC data structure
* @ops: csi operations
* @csi_chans: list head for CSI channels
@@ -146,6 +147,7 @@ struct tegra_csi {
struct host1x_client client;
void __iomem *iomem;
struct clk_bulk_data *clks;
+ struct regulator *vdd;
const struct tegra_csi_soc *soc;
const struct tegra_csi_ops *ops;
struct list_head csi_chans;
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index 04b538e8b514..70607a3eeee1 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -1417,29 +1417,19 @@ static int __maybe_unused vi_runtime_resume(struct device *dev)
struct tegra_vi *vi = dev_get_drvdata(dev);
int ret;
- ret = regulator_enable(vi->vdd);
- if (ret) {
- dev_err(dev, "failed to enable VDD supply: %d\n", ret);
- return ret;
- }
-
ret = clk_set_rate(vi->clk, vi->soc->vi_max_clk_hz);
if (ret) {
dev_err(dev, "failed to set vi clock rate: %d\n", ret);
- goto disable_vdd;
+ return ret;
}
ret = clk_prepare_enable(vi->clk);
if (ret) {
dev_err(dev, "failed to enable vi clock: %d\n", ret);
- goto disable_vdd;
+ return ret;
}
return 0;
-
-disable_vdd:
- regulator_disable(vi->vdd);
- return ret;
}
static int __maybe_unused vi_runtime_suspend(struct device *dev)
@@ -1448,8 +1438,6 @@ static int __maybe_unused vi_runtime_suspend(struct device *dev)
clk_disable_unprepare(vi->clk);
- regulator_disable(vi->vdd);
-
return 0;
}
@@ -1894,13 +1882,6 @@ static int tegra_vi_probe(struct platform_device *pdev)
return ret;
}
- vi->vdd = devm_regulator_get(&pdev->dev, "avdd-dsi-csi");
- if (IS_ERR(vi->vdd)) {
- ret = PTR_ERR(vi->vdd);
- dev_err(&pdev->dev, "failed to get VDD supply: %d\n", ret);
- return ret;
- }
-
if (!pdev->dev.pm_domain) {
ret = -ENOENT;
dev_warn(&pdev->dev, "PM domain is not attached: %d\n", ret);
diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h
index cac0c0d0e225..bfadde8858d4 100644
--- a/drivers/staging/media/tegra-video/vi.h
+++ b/drivers/staging/media/tegra-video/vi.h
@@ -94,7 +94,6 @@ struct tegra_vi_soc {
* @client: host1x_client struct
* @iomem: register base
* @clk: main clock for VI block
- * @vdd: vdd regulator for VI hardware, normally it is avdd_dsi_csi
* @soc: pointer to SoC data structure
* @ops: vi operations
* @vi_chans: list head for VI channels
@@ -104,7 +103,6 @@ struct tegra_vi {
struct host1x_client client;
void __iomem *iomem;
struct clk *clk;
- struct regulator *vdd;
const struct tegra_vi_soc *soc;
const struct tegra_vi_ops *ops;
struct list_head vi_chans;
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 14/24] arm64: tegra: move avdd-dsi-csi-supply into CSI node
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (12 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 13/24] staging: media: tegra-video: csi: move avdd-dsi-csi-supply from VI to CSI Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 15/24] staging: media: tegra-video: tegra20: set correct maximum width and height Svyatoslav Ryhel
` (9 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
avdd-dsi-csi-supply belongs in CSI node, not VI.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
---
arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi | 4 ++--
arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts | 4 ++--
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
index 584461f3a619..4a64fe510f03 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p2597.dtsi
@@ -20,10 +20,10 @@ dpaux@54040000 {
vi@54080000 {
status = "okay";
- avdd-dsi-csi-supply = <&vdd_dsi_csi>;
-
csi@838 {
status = "okay";
+
+ avdd-dsi-csi-supply = <&vdd_dsi_csi>;
};
};
diff --git a/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts b/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
index ec0e84cb83ef..f1d2606d9808 100644
--- a/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
+++ b/arch/arm64/boot/dts/nvidia/tegra210-p3450-0000.dts
@@ -64,10 +64,10 @@ dpaux@54040000 {
vi@54080000 {
status = "okay";
- avdd-dsi-csi-supply = <&vdd_sys_1v2>;
-
csi@838 {
status = "okay";
+
+ avdd-dsi-csi-supply = <&vdd_sys_1v2>;
};
};
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 15/24] staging: media: tegra-video: tegra20: set correct maximum width and height
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (13 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 14/24] arm64: tegra: move avdd-dsi-csi-supply into CSI node Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 16/24] staging: media: tegra-video: tegra20: add support for second output of VI Svyatoslav Ryhel
` (8 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Maximum width and height for Tegra20 and Tegra30 is determined by
respective register field, rounded down to factor of 2, which is 8191U
rounded down to 8190U.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
---
drivers/staging/media/tegra-video/tegra20.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
index 7b8f8f810b35..3e2d746638b6 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -23,11 +23,10 @@
#define TEGRA_VI_SYNCPT_WAIT_TIMEOUT msecs_to_jiffies(200)
-/* This are just good-sense numbers. The actual min/max is not documented. */
#define TEGRA20_MIN_WIDTH 32U
+#define TEGRA20_MAX_WIDTH 8190U
#define TEGRA20_MIN_HEIGHT 32U
-#define TEGRA20_MAX_WIDTH 2048U
-#define TEGRA20_MAX_HEIGHT 2048U
+#define TEGRA20_MAX_HEIGHT 8190U
/* --------------------------------------------------------------------------
* Registers
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 16/24] staging: media: tegra-video: tegra20: add support for second output of VI
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (14 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 15/24] staging: media: tegra-video: tegra20: set correct maximum width and height Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 17/24] staging: media: tegra-video: tegra20: adjust format align calculations Svyatoslav Ryhel
` (7 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
VI in Tegra20/Tegra30 has 2 VI outputs with different set of supported
formats. Convert output registers to macros for simpler work with both
outputs since apart formats their layout matches.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
---
drivers/staging/media/tegra-video/tegra20.c | 83 ++++++++++++---------
1 file changed, 47 insertions(+), 36 deletions(-)
diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
index 3e2d746638b6..7c3ff843235d 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -28,13 +28,19 @@
#define TEGRA20_MIN_HEIGHT 32U
#define TEGRA20_MAX_HEIGHT 8190U
+/* Tegra20/Tegra30 has 2 outputs in VI */
+enum tegra_vi_out {
+ TEGRA_VI_OUT_1 = 0,
+ TEGRA_VI_OUT_2 = 1,
+};
+
/* --------------------------------------------------------------------------
* Registers
*/
-#define TEGRA_VI_CONT_SYNCPT_OUT_1 0x0060
-#define VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT BIT(8)
-#define VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT 0
+#define TEGRA_VI_CONT_SYNCPT_OUT(n) (0x0060 + (n) * 4)
+#define VI_CONT_SYNCPT_OUT_CONTINUOUS_SYNCPT BIT(8)
+#define VI_CONT_SYNCPT_OUT_SYNCPT_IDX_SFT 0
#define TEGRA_VI_VI_INPUT_CONTROL 0x0088
#define VI_INPUT_FIELD_DETECT BIT(27)
@@ -46,6 +52,7 @@
#define VI_INPUT_YUV_INPUT_FORMAT_YVYU (3 << VI_INPUT_YUV_INPUT_FORMAT_SFT)
#define VI_INPUT_INPUT_FORMAT_SFT 2 /* bits [5:2] */
#define VI_INPUT_INPUT_FORMAT_YUV422 (0 << VI_INPUT_INPUT_FORMAT_SFT)
+#define VI_INPUT_INPUT_FORMAT_BAYER (2 << VI_INPUT_INPUT_FORMAT_SFT)
#define VI_INPUT_VIP_INPUT_ENABLE BIT(1)
#define TEGRA_VI_VI_CORE_CONTROL 0x008c
@@ -66,7 +73,7 @@
#define VI_VI_CORE_CONTROL_OUTPUT_TO_EPP_SFT 2
#define VI_VI_CORE_CONTROL_OUTPUT_TO_ISP_SFT 0
-#define TEGRA_VI_VI_FIRST_OUTPUT_CONTROL 0x0090
+#define TEGRA_VI_VI_OUTPUT_CONTROL(n) (0x0090 + (n) * 4)
#define VI_OUTPUT_FORMAT_EXT BIT(22)
#define VI_OUTPUT_V_DIRECTION BIT(20)
#define VI_OUTPUT_H_DIRECTION BIT(19)
@@ -80,6 +87,8 @@
#define VI_OUTPUT_OUTPUT_FORMAT_SFT 0
#define VI_OUTPUT_OUTPUT_FORMAT_YUV422POST (3 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
#define VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR (6 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
+/* TEGRA_VI_OUT_2 supported formats */
+#define VI_OUTPUT_OUTPUT_FORMAT_VIP_BAYER_DIRECT (9 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
#define TEGRA_VI_VIP_H_ACTIVE 0x00a4
#define VI_VIP_H_ACTIVE_PERIOD_SFT 16 /* active pixels/line, must be even */
@@ -89,26 +98,26 @@
#define VI_VIP_V_ACTIVE_PERIOD_SFT 16 /* active lines */
#define VI_VIP_V_ACTIVE_START_SFT 0
-#define TEGRA_VI_VB0_START_ADDRESS_FIRST 0x00c4
-#define TEGRA_VI_VB0_BASE_ADDRESS_FIRST 0x00c8
+#define TEGRA_VI_VB0_START_ADDRESS(n) (0x00c4 + (n) * 44)
+#define TEGRA_VI_VB0_BASE_ADDRESS(n) (0x00c8 + (n) * 44)
#define TEGRA_VI_VB0_START_ADDRESS_U 0x00cc
#define TEGRA_VI_VB0_BASE_ADDRESS_U 0x00d0
#define TEGRA_VI_VB0_START_ADDRESS_V 0x00d4
#define TEGRA_VI_VB0_BASE_ADDRESS_V 0x00d8
-#define TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE 0x00e0
-#define VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT 16
-#define VI_FIRST_OUTPUT_FRAME_WIDTH_SFT 0
+#define TEGRA_VI_OUTPUT_FRAME_SIZE(n) (0x00e0 + (n) * 24)
+#define VI_OUTPUT_FRAME_HEIGHT_SFT 16
+#define VI_OUTPUT_FRAME_WIDTH_SFT 0
-#define TEGRA_VI_VB0_COUNT_FIRST 0x00e4
+#define TEGRA_VI_VB0_COUNT(n) (0x00e4 + (n) * 24)
-#define TEGRA_VI_VB0_SIZE_FIRST 0x00e8
-#define VI_VB0_SIZE_FIRST_V_SFT 16
-#define VI_VB0_SIZE_FIRST_H_SFT 0
+#define TEGRA_VI_VB0_SIZE(n) (0x00e8 + (n) * 24)
+#define VI_VB0_SIZE_V_SFT 16
+#define VI_VB0_SIZE_H_SFT 0
-#define TEGRA_VI_VB0_BUFFER_STRIDE_FIRST 0x00ec
-#define VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT 30
-#define VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT 0
+#define TEGRA_VI_VB0_BUFFER_STRIDE(n) (0x00ec + (n) * 24)
+#define VI_VB0_BUFFER_STRIDE_CHROMA_SFT 30
+#define VI_VB0_BUFFER_STRIDE_LUMA_SFT 0
#define TEGRA_VI_H_LPF_CONTROL 0x0108
#define VI_H_LPF_CONTROL_CHROMA_SFT 16
@@ -136,7 +145,7 @@
#define VI_CAMERA_CONTROL_TEST_MODE BIT(1)
#define VI_CAMERA_CONTROL_VIP_ENABLE BIT(0)
-#define TEGRA_VI_VI_ENABLE 0x01a4
+#define TEGRA_VI_VI_ENABLE(n) (0x01a4 + (n) * 4)
#define VI_VI_ENABLE_SW_FLOW_CONTROL_OUT1 BIT(1)
#define VI_VI_ENABLE_FIRST_OUTPUT_TO_MEM_DISABLE BIT(0)
@@ -366,8 +375,8 @@ static void tegra20_channel_vi_buffer_setup(struct tegra_vi_channel *chan,
case V4L2_PIX_FMT_VYUY:
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
- tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS_FIRST, base);
- tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS_FIRST, base + chan->start_offset);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS(TEGRA_VI_OUT_1), base);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS(TEGRA_VI_OUT_1), base + chan->start_offset);
break;
}
}
@@ -455,6 +464,7 @@ static void tegra20_camera_capture_setup(struct tegra_vi_channel *chan)
int stride_l = chan->format.bytesperline;
int stride_c = (output_fourcc == V4L2_PIX_FMT_YUV420 ||
output_fourcc == V4L2_PIX_FMT_YVU420) ? 1 : 0;
+ enum tegra_vi_out output_channel = TEGRA_VI_OUT_1;
int main_output_format;
int yuv_output_format;
@@ -472,33 +482,33 @@ static void tegra20_camera_capture_setup(struct tegra_vi_channel *chan)
/* Set up raise-on-edge, so we get an interrupt on end of frame. */
tegra20_vi_write(chan, TEGRA_VI_VI_RAISE, VI_VI_RAISE_ON_EDGE);
- tegra20_vi_write(chan, TEGRA_VI_VI_FIRST_OUTPUT_CONTROL,
+ tegra20_vi_write(chan, TEGRA_VI_VI_OUTPUT_CONTROL(output_channel),
(chan->vflip ? VI_OUTPUT_V_DIRECTION : 0) |
(chan->hflip ? VI_OUTPUT_H_DIRECTION : 0) |
yuv_output_format << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT |
main_output_format << VI_OUTPUT_OUTPUT_FORMAT_SFT);
/* Set up frame size */
- tegra20_vi_write(chan, TEGRA_VI_FIRST_OUTPUT_FRAME_SIZE,
- height << VI_FIRST_OUTPUT_FRAME_HEIGHT_SFT |
- width << VI_FIRST_OUTPUT_FRAME_WIDTH_SFT);
+ tegra20_vi_write(chan, TEGRA_VI_OUTPUT_FRAME_SIZE(output_channel),
+ height << VI_OUTPUT_FRAME_HEIGHT_SFT |
+ width << VI_OUTPUT_FRAME_WIDTH_SFT);
/* First output memory enabled */
- tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0);
+ tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE(output_channel), 0);
/* Set the number of frames in the buffer */
- tegra20_vi_write(chan, TEGRA_VI_VB0_COUNT_FIRST, 1);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_COUNT(output_channel), 1);
/* Set up buffer frame size */
- tegra20_vi_write(chan, TEGRA_VI_VB0_SIZE_FIRST,
- height << VI_VB0_SIZE_FIRST_V_SFT |
- width << VI_VB0_SIZE_FIRST_H_SFT);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_SIZE(output_channel),
+ height << VI_VB0_SIZE_V_SFT |
+ width << VI_VB0_SIZE_H_SFT);
- tegra20_vi_write(chan, TEGRA_VI_VB0_BUFFER_STRIDE_FIRST,
- stride_l << VI_VB0_BUFFER_STRIDE_FIRST_LUMA_SFT |
- stride_c << VI_VB0_BUFFER_STRIDE_FIRST_CHROMA_SFT);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_BUFFER_STRIDE(output_channel),
+ stride_l << VI_VB0_BUFFER_STRIDE_LUMA_SFT |
+ stride_c << VI_VB0_BUFFER_STRIDE_CHROMA_SFT);
- tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE, 0);
+ tegra20_vi_write(chan, TEGRA_VI_VI_ENABLE(output_channel), 0);
}
static int tegra20_vi_start_streaming(struct vb2_queue *vq, u32 count)
@@ -587,7 +597,7 @@ const struct tegra_vi_soc tegra20_vi_soc = {
.nformats = ARRAY_SIZE(tegra20_video_formats),
.default_video_format = &tegra20_video_formats[0],
.ops = &tegra20_vi_ops,
- .vi_max_channels = 1, /* parallel input (VIP) */
+ .vi_max_channels = 2, /* TEGRA_VI_OUT_1 and TEGRA_VI_OUT_2 */
.vi_max_clk_hz = 150000000,
.has_h_v_flip = true,
};
@@ -607,6 +617,7 @@ static int tegra20_vip_start_streaming(struct tegra_vip_channel *vip_chan)
struct tegra_vi_channel *vi_chan = v4l2_get_subdev_hostdata(&vip_chan->subdev);
int width = vi_chan->format.width;
int height = vi_chan->format.height;
+ enum tegra_vi_out output_channel = TEGRA_VI_OUT_1;
unsigned int main_input_format;
unsigned int yuv_input_format;
@@ -637,10 +648,10 @@ static int tegra20_vip_start_streaming(struct tegra_vip_channel *vip_chan)
GENMASK(9, 2) << VI_DATA_INPUT_SFT);
tegra20_vi_write(vi_chan, TEGRA_VI_PIN_INVERSION, 0);
- tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_OUT_1,
- VI_CONT_SYNCPT_OUT_1_CONTINUOUS_SYNCPT |
+ tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_OUT(output_channel),
+ VI_CONT_SYNCPT_OUT_CONTINUOUS_SYNCPT |
host1x_syncpt_id(vi_chan->mw_ack_sp[0])
- << VI_CONT_SYNCPT_OUT_1_SYNCPT_IDX_SFT);
+ << VI_CONT_SYNCPT_OUT_SYNCPT_IDX_SFT);
tegra20_vi_write(vi_chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_STOP_CAPTURE);
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 17/24] staging: media: tegra-video: tegra20: adjust format align calculations
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (15 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 16/24] staging: media: tegra-video: tegra20: add support for second output of VI Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-20 2:34 ` Mikko Perttunen
2025-10-08 7:30 ` [PATCH v4 18/24] staging: media: tegra-video: tegra20: set VI HW revision Svyatoslav Ryhel
` (6 subsequent siblings)
23 siblings, 1 reply; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Expand supported formats structure with data_type and bit_width fields
required for CSI support. Adjust tegra20_fmt_align by factoring out common
bytesperline and sizeimage calculation logic shared by supported planar
and non-planar formats and leaving planar-related correction under a
switch.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/staging/media/tegra-video/tegra20.c | 39 ++++++++++-----------
1 file changed, 19 insertions(+), 20 deletions(-)
diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
index 7c3ff843235d..ffaaa2bb8269 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -280,18 +280,13 @@ static void tegra20_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp)
pix->width = clamp(pix->width, TEGRA20_MIN_WIDTH, TEGRA20_MAX_WIDTH);
pix->height = clamp(pix->height, TEGRA20_MIN_HEIGHT, TEGRA20_MAX_HEIGHT);
+ pix->bytesperline = roundup(pix->width, 8) * bpp;
+ pix->sizeimage = pix->bytesperline * pix->height;
+
switch (pix->pixelformat) {
- case V4L2_PIX_FMT_UYVY:
- case V4L2_PIX_FMT_VYUY:
- case V4L2_PIX_FMT_YUYV:
- case V4L2_PIX_FMT_YVYU:
- pix->bytesperline = roundup(pix->width, 2) * 2;
- pix->sizeimage = roundup(pix->width, 2) * 2 * pix->height;
- break;
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
- pix->bytesperline = roundup(pix->width, 8);
- pix->sizeimage = roundup(pix->width, 8) * pix->height * 3 / 2;
+ pix->sizeimage = pix->sizeimage * 3 / 2;
break;
}
}
@@ -576,20 +571,24 @@ static const struct tegra_vi_ops tegra20_vi_ops = {
.vi_stop_streaming = tegra20_vi_stop_streaming,
};
-#define TEGRA20_VIDEO_FMT(MBUS_CODE, BPP, FOURCC) \
-{ \
- .code = MEDIA_BUS_FMT_##MBUS_CODE, \
- .bpp = BPP, \
- .fourcc = V4L2_PIX_FMT_##FOURCC, \
+#define TEGRA20_VIDEO_FMT(DATA_TYPE, BIT_WIDTH, MBUS_CODE, BPP, FOURCC) \
+{ \
+ .img_dt = TEGRA_IMAGE_DT_##DATA_TYPE, \
+ .bit_width = BIT_WIDTH, \
+ .code = MEDIA_BUS_FMT_##MBUS_CODE, \
+ .bpp = BPP, \
+ .fourcc = V4L2_PIX_FMT_##FOURCC, \
}
static const struct tegra_video_format tegra20_video_formats[] = {
- TEGRA20_VIDEO_FMT(UYVY8_2X8, 2, UYVY),
- TEGRA20_VIDEO_FMT(VYUY8_2X8, 2, VYUY),
- TEGRA20_VIDEO_FMT(YUYV8_2X8, 2, YUYV),
- TEGRA20_VIDEO_FMT(YVYU8_2X8, 2, YVYU),
- TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YUV420),
- TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YVU420),
+ /* YUV422 */
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 2, UYVY),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, VYUY8_2X8, 2, VYUY),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, YUYV8_2X8, 2, YUYV),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, YVYU8_2X8, 2, YVYU),
+ /* YUV420P */
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 1, YUV420),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 1, YVU420),
};
const struct tegra_vi_soc tegra20_vi_soc = {
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v4 17/24] staging: media: tegra-video: tegra20: adjust format align calculations
2025-10-08 7:30 ` [PATCH v4 17/24] staging: media: tegra-video: tegra20: adjust format align calculations Svyatoslav Ryhel
@ 2025-10-20 2:34 ` Mikko Perttunen
0 siblings, 0 replies; 40+ messages in thread
From: Mikko Perttunen @ 2025-10-20 2:34 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Linus Walleij, Mauro Carvalho Chehab, Greg Kroah-Hartman,
Svyatoslav Ryhel, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann,
Svyatoslav Ryhel
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
On Wednesday, October 8, 2025 4:30 PM Svyatoslav Ryhel wrote:
> Expand supported formats structure with data_type and bit_width fields
> required for CSI support. Adjust tegra20_fmt_align by factoring out common
> bytesperline and sizeimage calculation logic shared by supported planar
> and non-planar formats and leaving planar-related correction under a
> switch.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
> drivers/staging/media/tegra-video/tegra20.c | 39 ++++++++++-----------
> 1 file changed, 19 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
> index 7c3ff843235d..ffaaa2bb8269 100644
> --- a/drivers/staging/media/tegra-video/tegra20.c
> +++ b/drivers/staging/media/tegra-video/tegra20.c
> @@ -280,18 +280,13 @@ static void tegra20_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp)
> pix->width = clamp(pix->width, TEGRA20_MIN_WIDTH, TEGRA20_MAX_WIDTH);
> pix->height = clamp(pix->height, TEGRA20_MIN_HEIGHT, TEGRA20_MAX_HEIGHT);
>
> + pix->bytesperline = roundup(pix->width, 8) * bpp;
> + pix->sizeimage = pix->bytesperline * pix->height;
> +
> switch (pix->pixelformat) {
> - case V4L2_PIX_FMT_UYVY:
> - case V4L2_PIX_FMT_VYUY:
> - case V4L2_PIX_FMT_YUYV:
> - case V4L2_PIX_FMT_YVYU:
> - pix->bytesperline = roundup(pix->width, 2) * 2;
> - pix->sizeimage = roundup(pix->width, 2) * 2 * pix->height;
> - break;
> case V4L2_PIX_FMT_YUV420:
> case V4L2_PIX_FMT_YVU420:
> - pix->bytesperline = roundup(pix->width, 8);
> - pix->sizeimage = roundup(pix->width, 8) * pix->height * 3 / 2;
> + pix->sizeimage = pix->sizeimage * 3 / 2;
> break;
> }
> }
> @@ -576,20 +571,24 @@ static const struct tegra_vi_ops tegra20_vi_ops = {
> .vi_stop_streaming = tegra20_vi_stop_streaming,
> };
>
> -#define TEGRA20_VIDEO_FMT(MBUS_CODE, BPP, FOURCC) \
> -{ \
> - .code = MEDIA_BUS_FMT_##MBUS_CODE, \
> - .bpp = BPP, \
> - .fourcc = V4L2_PIX_FMT_##FOURCC, \
> +#define TEGRA20_VIDEO_FMT(DATA_TYPE, BIT_WIDTH, MBUS_CODE, BPP, FOURCC) \
> +{ \
> + .img_dt = TEGRA_IMAGE_DT_##DATA_TYPE, \
> + .bit_width = BIT_WIDTH, \
> + .code = MEDIA_BUS_FMT_##MBUS_CODE, \
> + .bpp = BPP, \
> + .fourcc = V4L2_PIX_FMT_##FOURCC, \
> }
>
> static const struct tegra_video_format tegra20_video_formats[] = {
> - TEGRA20_VIDEO_FMT(UYVY8_2X8, 2, UYVY),
> - TEGRA20_VIDEO_FMT(VYUY8_2X8, 2, VYUY),
> - TEGRA20_VIDEO_FMT(YUYV8_2X8, 2, YUYV),
> - TEGRA20_VIDEO_FMT(YVYU8_2X8, 2, YVYU),
> - TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YUV420),
> - TEGRA20_VIDEO_FMT(UYVY8_2X8, 1, YVU420),
> + /* YUV422 */
> + TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 2, UYVY),
> + TEGRA20_VIDEO_FMT(YUV422_8, 16, VYUY8_2X8, 2, VYUY),
> + TEGRA20_VIDEO_FMT(YUV422_8, 16, YUYV8_2X8, 2, YUYV),
> + TEGRA20_VIDEO_FMT(YUV422_8, 16, YVYU8_2X8, 2, YVYU),
> + /* YUV420P */
> + TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 1, YUV420),
> + TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 1, YVU420),
> };
>
> const struct tegra_vi_soc tegra20_vi_soc = {
>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v4 18/24] staging: media: tegra-video: tegra20: set VI HW revision
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (16 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 17/24] staging: media: tegra-video: tegra20: adjust format align calculations Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 19/24] staging: media: tegra-video: tegra20: increase maximum VI clock frequency Svyatoslav Ryhel
` (5 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
According to TRM Tegra20, Tegra30 and Tegra114 have VI revision 1,
Tegra124 has revision 2 and Tegra210 has revision 3. Set correct revision
in tegra20_vi_soc like tegra210 does.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/staging/media/tegra-video/tegra20.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
index ffaaa2bb8269..93105ed57ca7 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -596,6 +596,7 @@ const struct tegra_vi_soc tegra20_vi_soc = {
.nformats = ARRAY_SIZE(tegra20_video_formats),
.default_video_format = &tegra20_video_formats[0],
.ops = &tegra20_vi_ops,
+ .hw_revision = 1,
.vi_max_channels = 2, /* TEGRA_VI_OUT_1 and TEGRA_VI_OUT_2 */
.vi_max_clk_hz = 150000000,
.has_h_v_flip = true,
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 19/24] staging: media: tegra-video: tegra20: increase maximum VI clock frequency
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (17 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 18/24] staging: media: tegra-video: tegra20: set VI HW revision Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 20/24] staging: media: tegra-video: tegra20: expand format support with RAW8/10 and YUV422/YUV420p 1X16 Svyatoslav Ryhel
` (4 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Increase maximum VI clock frequency to 450MHz to allow correct work with
high resolution camera sensors.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
---
drivers/staging/media/tegra-video/tegra20.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
index 93105ed57ca7..149386a15176 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -598,7 +598,7 @@ const struct tegra_vi_soc tegra20_vi_soc = {
.ops = &tegra20_vi_ops,
.hw_revision = 1,
.vi_max_channels = 2, /* TEGRA_VI_OUT_1 and TEGRA_VI_OUT_2 */
- .vi_max_clk_hz = 150000000,
+ .vi_max_clk_hz = 450000000,
.has_h_v_flip = true,
};
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 20/24] staging: media: tegra-video: tegra20: expand format support with RAW8/10 and YUV422/YUV420p 1X16
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (18 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 19/24] staging: media: tegra-video: tegra20: increase maximum VI clock frequency Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 21/24] staging: media: tegra-video: tegra20: adjust luma buffer stride Svyatoslav Ryhel
` (3 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Add support for Bayer formats (RAW8 and RAW10) and YUV422/420p 1X16
versions of existing YUV422/YUV420p 2X8.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
---
drivers/staging/media/tegra-video/tegra20.c | 74 ++++++++++++++++++++-
1 file changed, 71 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
index 149386a15176..0457209b789a 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -187,6 +187,18 @@ static void tegra20_vi_get_input_formats(struct tegra_vi_channel *chan,
case MEDIA_BUS_FMT_YVYU8_2X8:
(*yuv_input_format) = VI_INPUT_YUV_INPUT_FORMAT_YVYU;
break;
+ /* RAW8 */
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
+ case MEDIA_BUS_FMT_SGBRG8_1X8:
+ case MEDIA_BUS_FMT_SGRBG8_1X8:
+ case MEDIA_BUS_FMT_SRGGB8_1X8:
+ /* RAW10 */
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
+ (*main_input_format) = VI_INPUT_INPUT_FORMAT_BAYER;
+ break;
}
}
@@ -221,6 +233,18 @@ static void tegra20_vi_get_output_formats(struct tegra_vi_channel *chan,
case V4L2_PIX_FMT_YVU420:
(*main_output_format) = VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR;
break;
+ /* RAW8 */
+ case V4L2_PIX_FMT_SBGGR8:
+ case V4L2_PIX_FMT_SGBRG8:
+ case V4L2_PIX_FMT_SGRBG8:
+ case V4L2_PIX_FMT_SRGGB8:
+ /* RAW10 */
+ case V4L2_PIX_FMT_SBGGR10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SRGGB10:
+ (*main_output_format) = VI_OUTPUT_OUTPUT_FORMAT_VIP_BAYER_DIRECT;
+ break;
}
}
@@ -308,6 +332,16 @@ static void tegra20_channel_queue_setup(struct tegra_vi_channel *chan)
case V4L2_PIX_FMT_VYUY:
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVYU:
+ /* RAW8 */
+ case V4L2_PIX_FMT_SRGGB8:
+ case V4L2_PIX_FMT_SGRBG8:
+ case V4L2_PIX_FMT_SGBRG8:
+ case V4L2_PIX_FMT_SBGGR8:
+ /* RAW10 */
+ case V4L2_PIX_FMT_SRGGB10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SBGGR10:
if (chan->vflip)
chan->start_offset += stride * (height - 1);
if (chan->hflip)
@@ -373,6 +407,19 @@ static void tegra20_channel_vi_buffer_setup(struct tegra_vi_channel *chan,
tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS(TEGRA_VI_OUT_1), base);
tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS(TEGRA_VI_OUT_1), base + chan->start_offset);
break;
+ /* RAW8 */
+ case V4L2_PIX_FMT_SRGGB8:
+ case V4L2_PIX_FMT_SGRBG8:
+ case V4L2_PIX_FMT_SGBRG8:
+ case V4L2_PIX_FMT_SBGGR8:
+ /* RAW10 */
+ case V4L2_PIX_FMT_SRGGB10:
+ case V4L2_PIX_FMT_SGRBG10:
+ case V4L2_PIX_FMT_SGBRG10:
+ case V4L2_PIX_FMT_SBGGR10:
+ tegra20_vi_write(chan, TEGRA_VI_VB0_BASE_ADDRESS(TEGRA_VI_OUT_2), base);
+ tegra20_vi_write(chan, TEGRA_VI_VB0_START_ADDRESS(TEGRA_VI_OUT_2), base + chan->start_offset);
+ break;
}
}
@@ -454,12 +501,15 @@ static int tegra20_chan_capture_kthread_start(void *data)
static void tegra20_camera_capture_setup(struct tegra_vi_channel *chan)
{
u32 output_fourcc = chan->format.pixelformat;
+ u32 data_type = chan->fmtinfo->img_dt;
int width = chan->format.width;
int height = chan->format.height;
int stride_l = chan->format.bytesperline;
int stride_c = (output_fourcc == V4L2_PIX_FMT_YUV420 ||
output_fourcc == V4L2_PIX_FMT_YVU420) ? 1 : 0;
- enum tegra_vi_out output_channel = TEGRA_VI_OUT_1;
+ enum tegra_vi_out output_channel = (data_type == TEGRA_IMAGE_DT_RAW8 ||
+ data_type == TEGRA_IMAGE_DT_RAW10) ?
+ TEGRA_VI_OUT_2 : TEGRA_VI_OUT_1;
int main_output_format;
int yuv_output_format;
@@ -586,9 +636,25 @@ static const struct tegra_video_format tegra20_video_formats[] = {
TEGRA20_VIDEO_FMT(YUV422_8, 16, VYUY8_2X8, 2, VYUY),
TEGRA20_VIDEO_FMT(YUV422_8, 16, YUYV8_2X8, 2, YUYV),
TEGRA20_VIDEO_FMT(YUV422_8, 16, YVYU8_2X8, 2, YVYU),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_1X16, 2, UYVY),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, VYUY8_1X16, 2, VYUY),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, YUYV8_1X16, 2, YUYV),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, YVYU8_1X16, 2, YVYU),
/* YUV420P */
TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 1, YUV420),
TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_2X8, 1, YVU420),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_1X16, 1, YUV420),
+ TEGRA20_VIDEO_FMT(YUV422_8, 16, UYVY8_1X16, 1, YVU420),
+ /* RAW 8 */
+ TEGRA20_VIDEO_FMT(RAW8, 8, SRGGB8_1X8, 2, SRGGB8),
+ TEGRA20_VIDEO_FMT(RAW8, 8, SGRBG8_1X8, 2, SGRBG8),
+ TEGRA20_VIDEO_FMT(RAW8, 8, SGBRG8_1X8, 2, SGBRG8),
+ TEGRA20_VIDEO_FMT(RAW8, 8, SBGGR8_1X8, 2, SBGGR8),
+ /* RAW 10 */
+ TEGRA20_VIDEO_FMT(RAW10, 10, SRGGB10_1X10, 2, SRGGB10),
+ TEGRA20_VIDEO_FMT(RAW10, 10, SGRBG10_1X10, 2, SGRBG10),
+ TEGRA20_VIDEO_FMT(RAW10, 10, SGBRG10_1X10, 2, SGBRG10),
+ TEGRA20_VIDEO_FMT(RAW10, 10, SBGGR10_1X10, 2, SBGGR10),
};
const struct tegra_vi_soc tegra20_vi_soc = {
@@ -615,10 +681,12 @@ const struct tegra_vi_soc tegra20_vi_soc = {
static int tegra20_vip_start_streaming(struct tegra_vip_channel *vip_chan)
{
struct tegra_vi_channel *vi_chan = v4l2_get_subdev_hostdata(&vip_chan->subdev);
+ u32 data_type = vi_chan->fmtinfo->img_dt;
int width = vi_chan->format.width;
int height = vi_chan->format.height;
- enum tegra_vi_out output_channel = TEGRA_VI_OUT_1;
-
+ enum tegra_vi_out output_channel = (data_type == TEGRA_IMAGE_DT_RAW8 ||
+ data_type == TEGRA_IMAGE_DT_RAW10) ?
+ TEGRA_VI_OUT_2 : TEGRA_VI_OUT_1;
unsigned int main_input_format;
unsigned int yuv_input_format;
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 21/24] staging: media: tegra-video: tegra20: adjust luma buffer stride
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (19 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 20/24] staging: media: tegra-video: tegra20: expand format support with RAW8/10 and YUV422/YUV420p 1X16 Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 22/24] dt-bindings: display: tegra: document Tegra20 and Tegra30 CSI Svyatoslav Ryhel
` (2 subsequent siblings)
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Luma buffer stride is calculated by multiplying height in pixels of image
by bytes per line. Adjust that value accordingly.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
---
drivers/staging/media/tegra-video/tegra20.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
index 0457209b789a..626f34543853 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -504,7 +504,7 @@ static void tegra20_camera_capture_setup(struct tegra_vi_channel *chan)
u32 data_type = chan->fmtinfo->img_dt;
int width = chan->format.width;
int height = chan->format.height;
- int stride_l = chan->format.bytesperline;
+ int stride_l = chan->format.bytesperline * height;
int stride_c = (output_fourcc == V4L2_PIX_FMT_YUV420 ||
output_fourcc == V4L2_PIX_FMT_YVU420) ? 1 : 0;
enum tegra_vi_out output_channel = (data_type == TEGRA_IMAGE_DT_RAW8 ||
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* [PATCH v4 22/24] dt-bindings: display: tegra: document Tegra20 and Tegra30 CSI
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (20 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 21/24] staging: media: tegra-video: tegra20: adjust luma buffer stride Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-08 21:21 ` Conor Dooley
2025-10-13 15:53 ` Frank Li
2025-10-08 7:30 ` [PATCH v4 23/24] ARM: tegra: add CSI nodes for Tegra20 and Tegra30 Svyatoslav Ryhel
2025-10-08 7:30 ` [PATCH v4 24/24] staging: media: tegra-video: add CSI support " Svyatoslav Ryhel
23 siblings, 2 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Document CSI HW block found in Tegra20 and Tegra30 SoC.
The #nvidia,mipi-calibrate-cells is not an introduction of property, such
property already exists in nvidia,tegra114-mipi.yaml and is used in
multiple device trees. In case of Tegra30 and Tegra20 CSI block combines
mipi calibration function and CSI function, in Tegra114+ mipi calibration
got a dedicated hardware block which is already supported. This property
here is used to align with mipi-calibration logic used by Tegra114+.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
.../display/tegra/nvidia,tegra20-csi.yaml | 135 ++++++++++++++++++
1 file changed, 135 insertions(+)
create mode 100644 Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
new file mode 100644
index 000000000000..817b3097846b
--- /dev/null
+++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/display/tegra/nvidia,tegra20-csi.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NVIDIA Tegra20 CSI controller
+
+maintainers:
+ - Svyatoslav Ryhel <clamor95@gmail.com>
+
+properties:
+ compatible:
+ enum:
+ - nvidia,tegra20-csi
+ - nvidia,tegra30-csi
+
+ reg:
+ maxItems: 1
+
+ clocks: true
+ clock-names: true
+
+ avdd-dsi-csi-supply:
+ description: DSI/CSI power supply. Must supply 1.2 V.
+
+ power-domains:
+ maxItems: 1
+
+ "#nvidia,mipi-calibrate-cells":
+ description:
+ The number of cells in a MIPI calibration specifier. Should be 1.
+ The single cell specifies an id of the pad that need to be
+ calibrated for a given device. Valid pad ids for receiver would be
+ 0 for CSI-A; 1 for CSI-B; 2 for DSI-A and 3 for DSI-B.
+ $ref: /schemas/types.yaml#/definitions/uint32
+ const: 1
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+patternProperties:
+ "^channel@[0-1]$":
+ type: object
+ description: channel 0 represents CSI-A and 1 represents CSI-B
+ additionalProperties: false
+
+ properties:
+ reg:
+ maximum: 1
+
+ nvidia,mipi-calibrate:
+ description: Should contain a phandle and a specifier specifying
+ which pad is used by this CSI channel and needs to be calibrated.
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ port@0:
+ $ref: /schemas/graph.yaml#/$defs/port-base
+ unevaluatedProperties: false
+ description: port receiving the video stream from the sensor
+
+ properties:
+ endpoint:
+ $ref: /schemas/media/video-interfaces.yaml#
+ unevaluatedProperties: false
+
+ required:
+ - data-lanes
+
+ port@1:
+ $ref: /schemas/graph.yaml#/properties/port
+ description: port sending the video stream to the VI
+
+ required:
+ - reg
+ - "#address-cells"
+ - "#size-cells"
+ - port@0
+ - port@1
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nvidia,tegra20-csi
+ then:
+ properties:
+ clocks:
+ items:
+ - description: module clock
+
+ clock-names: false
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - nvidia,tegra30-csi
+ then:
+ properties:
+ clocks:
+ items:
+ - description: module clock
+ - description: PAD A clock
+ - description: PAD B clock
+
+ clock-names:
+ items:
+ - const: csi
+ - const: csia-pad
+ - const: csib-pad
+
+additionalProperties: false
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - power-domains
+ - "#address-cells"
+ - "#size-cells"
+
+# see nvidia,tegra20-vi.yaml for an example
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v4 22/24] dt-bindings: display: tegra: document Tegra20 and Tegra30 CSI
2025-10-08 7:30 ` [PATCH v4 22/24] dt-bindings: display: tegra: document Tegra20 and Tegra30 CSI Svyatoslav Ryhel
@ 2025-10-08 21:21 ` Conor Dooley
2025-10-08 21:22 ` Conor Dooley
2025-10-13 15:53 ` Frank Li
1 sibling, 1 reply; 40+ messages in thread
From: Conor Dooley @ 2025-10-08 21:21 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann, dri-devel,
devicetree, linux-tegra, linux-kernel, linux-media, linux-clk,
linux-gpio, linux-staging
[-- Attachment #1: Type: text/plain, Size: 5629 bytes --]
On Wed, Oct 08, 2025 at 10:30:44AM +0300, Svyatoslav Ryhel wrote:
> Document CSI HW block found in Tegra20 and Tegra30 SoC.
>
> The #nvidia,mipi-calibrate-cells is not an introduction of property, such
> property already exists in nvidia,tegra114-mipi.yaml and is used in
> multiple device trees. In case of Tegra30 and Tegra20 CSI block combines
> mipi calibration function and CSI function, in Tegra114+ mipi calibration
> got a dedicated hardware block which is already supported. This property
> here is used to align with mipi-calibration logic used by Tegra114+.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
> .../display/tegra/nvidia,tegra20-csi.yaml | 135 ++++++++++++++++++
> 1 file changed, 135 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
>
> diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
> new file mode 100644
> index 000000000000..817b3097846b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
> @@ -0,0 +1,135 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/tegra/nvidia,tegra20-csi.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NVIDIA Tegra20 CSI controller
> +
> +maintainers:
> + - Svyatoslav Ryhel <clamor95@gmail.com>
> +
> +properties:
> + compatible:
> + enum:
> + - nvidia,tegra20-csi
> + - nvidia,tegra30-csi
> +
> + reg:
> + maxItems: 1
> +
> + clocks: true
> + clock-names: true
> +
> + avdd-dsi-csi-supply:
> + description: DSI/CSI power supply. Must supply 1.2 V.
> +
> + power-domains:
> + maxItems: 1
> +
> + "#nvidia,mipi-calibrate-cells":
> + description:
> + The number of cells in a MIPI calibration specifier. Should be 1.
> + The single cell specifies an id of the pad that need to be
> + calibrated for a given device. Valid pad ids for receiver would be
> + 0 for CSI-A; 1 for CSI-B; 2 for DSI-A and 3 for DSI-B.
> + $ref: /schemas/types.yaml#/definitions/uint32
> + const: 1
> +
> + "#address-cells":
> + const: 1
> +
> + "#size-cells":
> + const: 0
> +
> +patternProperties:
> + "^channel@[0-1]$":
> + type: object
> + description: channel 0 represents CSI-A and 1 represents CSI-B
> + additionalProperties: false
> +
> + properties:
> + reg:
> + maximum: 1
> +
> + nvidia,mipi-calibrate:
> + description: Should contain a phandle and a specifier specifying
> + which pad is used by this CSI channel and needs to be calibrated.
> + $ref: /schemas/types.yaml#/definitions/phandle-array
> +
> + "#address-cells":
> + const: 1
> +
> + "#size-cells":
> + const: 0
> +
> + port@0:
> + $ref: /schemas/graph.yaml#/$defs/port-base
> + unevaluatedProperties: false
> + description: port receiving the video stream from the sensor
> +
> + properties:
> + endpoint:
> + $ref: /schemas/media/video-interfaces.yaml#
> + unevaluatedProperties: false
> +
> + required:
> + - data-lanes
> +
> + port@1:
> + $ref: /schemas/graph.yaml#/properties/port
> + description: port sending the video stream to the VI
> +
> + required:
> + - reg
> + - "#address-cells"
> + - "#size-cells"
> + - port@0
> + - port@1
> +
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - nvidia,tegra20-csi
> + then:
> + properties:
> + clocks:
> + items:
> + - description: module clock
> +
> + clock-names: false
> +
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - nvidia,tegra30-csi
> + then:
> + properties:
> + clocks:
> + items:
> + - description: module clock
> + - description: PAD A clock
> + - description: PAD B clock
> +
> + clock-names:
> + items:
> + - const: csi
> + - const: csia-pad
> + - const: csib-pad
This clocks section seems like it could get simpler. Since the clock
descriptions are shared, and tegra20 has no clock-names, you could just
move the detail of the properties out to where you have the ": true"
stuff (we prefer that properties are defined outside of if/then/else
blocks) and just restrict them here. For tegra20 that'd be
if:
properties:
compatible:
contains:
enum:
- nvidia,tegra20-csi
then:
properties:
clocks:
maxItems: 1
clock-names: false
(although it could easily be maxItems: 1 ?)
and for tegra30
if:
properties:
compatible:
contains:
enum:
- nvidia,tegra30-csi
then:
properties:
clocks:
minItems: 3
clock-names:
maxItems: 3
Of course you'd then have to add minItems: 1 and maxItems: 3 to the
extracted definitions.
> +
> +additionalProperties: false
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> + - power-domains
> + - "#address-cells"
> + - "#size-cells"
> +
> +# see nvidia,tegra20-vi.yaml for an example
> --
> 2.48.1
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH v4 22/24] dt-bindings: display: tegra: document Tegra20 and Tegra30 CSI
2025-10-08 21:21 ` Conor Dooley
@ 2025-10-08 21:22 ` Conor Dooley
2025-10-09 5:35 ` Svyatoslav Ryhel
0 siblings, 1 reply; 40+ messages in thread
From: Conor Dooley @ 2025-10-08 21:22 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann, dri-devel,
devicetree, linux-tegra, linux-kernel, linux-media, linux-clk,
linux-gpio, linux-staging
[-- Attachment #1: Type: text/plain, Size: 6243 bytes --]
On Wed, Oct 08, 2025 at 10:21:06PM +0100, Conor Dooley wrote:
> On Wed, Oct 08, 2025 at 10:30:44AM +0300, Svyatoslav Ryhel wrote:
> > Document CSI HW block found in Tegra20 and Tegra30 SoC.
> >
> > The #nvidia,mipi-calibrate-cells is not an introduction of property, such
> > property already exists in nvidia,tegra114-mipi.yaml and is used in
> > multiple device trees. In case of Tegra30 and Tegra20 CSI block combines
> > mipi calibration function and CSI function, in Tegra114+ mipi calibration
> > got a dedicated hardware block which is already supported. This property
> > here is used to align with mipi-calibration logic used by Tegra114+.
> >
> > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > ---
> > .../display/tegra/nvidia,tegra20-csi.yaml | 135 ++++++++++++++++++
> > 1 file changed, 135 insertions(+)
> > create mode 100644 Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
> > new file mode 100644
> > index 000000000000..817b3097846b
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
> > @@ -0,0 +1,135 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/display/tegra/nvidia,tegra20-csi.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: NVIDIA Tegra20 CSI controller
> > +
> > +maintainers:
> > + - Svyatoslav Ryhel <clamor95@gmail.com>
> > +
> > +properties:
> > + compatible:
> > + enum:
> > + - nvidia,tegra20-csi
> > + - nvidia,tegra30-csi
> > +
> > + reg:
> > + maxItems: 1
> > +
> > + clocks: true
> > + clock-names: true
> > +
> > + avdd-dsi-csi-supply:
> > + description: DSI/CSI power supply. Must supply 1.2 V.
> > +
> > + power-domains:
> > + maxItems: 1
> > +
> > + "#nvidia,mipi-calibrate-cells":
> > + description:
> > + The number of cells in a MIPI calibration specifier. Should be 1.
> > + The single cell specifies an id of the pad that need to be
> > + calibrated for a given device. Valid pad ids for receiver would be
> > + 0 for CSI-A; 1 for CSI-B; 2 for DSI-A and 3 for DSI-B.
> > + $ref: /schemas/types.yaml#/definitions/uint32
> > + const: 1
> > +
> > + "#address-cells":
> > + const: 1
> > +
> > + "#size-cells":
> > + const: 0
> > +
> > +patternProperties:
> > + "^channel@[0-1]$":
> > + type: object
> > + description: channel 0 represents CSI-A and 1 represents CSI-B
> > + additionalProperties: false
> > +
> > + properties:
> > + reg:
> > + maximum: 1
> > +
> > + nvidia,mipi-calibrate:
> > + description: Should contain a phandle and a specifier specifying
> > + which pad is used by this CSI channel and needs to be calibrated.
> > + $ref: /schemas/types.yaml#/definitions/phandle-array
> > +
> > + "#address-cells":
> > + const: 1
> > +
> > + "#size-cells":
> > + const: 0
> > +
> > + port@0:
> > + $ref: /schemas/graph.yaml#/$defs/port-base
> > + unevaluatedProperties: false
> > + description: port receiving the video stream from the sensor
> > +
> > + properties:
> > + endpoint:
> > + $ref: /schemas/media/video-interfaces.yaml#
> > + unevaluatedProperties: false
> > +
> > + required:
> > + - data-lanes
> > +
> > + port@1:
> > + $ref: /schemas/graph.yaml#/properties/port
> > + description: port sending the video stream to the VI
> > +
> > + required:
> > + - reg
> > + - "#address-cells"
> > + - "#size-cells"
> > + - port@0
> > + - port@1
> > +
> > +allOf:
> > + - if:
> > + properties:
> > + compatible:
> > + contains:
> > + enum:
> > + - nvidia,tegra20-csi
> > + then:
> > + properties:
> > + clocks:
> > + items:
> > + - description: module clock
> > +
> > + clock-names: false
> > +
> > + - if:
> > + properties:
> > + compatible:
> > + contains:
> > + enum:
> > + - nvidia,tegra30-csi
> > + then:
> > + properties:
> > + clocks:
> > + items:
> > + - description: module clock
> > + - description: PAD A clock
> > + - description: PAD B clock
> > +
> > + clock-names:
> > + items:
> > + - const: csi
> > + - const: csia-pad
> > + - const: csib-pad
>
> This clocks section seems like it could get simpler. Since the clock
> descriptions are shared, and tegra20 has no clock-names, you could just
> move the detail of the properties out to where you have the ": true"
> stuff (we prefer that properties are defined outside of if/then/else
> blocks) and just restrict them here. For tegra20 that'd be
>
> if:
> properties:
> compatible:
> contains:
> enum:
> - nvidia,tegra20-csi
> then:
> properties:
> clocks:
> maxItems: 1
>
> clock-names: false
>
> (although it could easily be maxItems: 1 ?)
> and for tegra30
>
> if:
> properties:
> compatible:
> contains:
> enum:
> - nvidia,tegra30-csi
> then:
> properties:
> clocks:
> minItems: 3
>
> clock-names:
> maxItems: 3
>
> Of course you'd then have to add minItems: 1 and maxItems: 3 to the
> extracted definitions.
Oh, also: if you want clock-names to ever actually be usable, you have
to require it. Otherwise a driver must be written to handle it not being
there.
> > +additionalProperties: false
> > +
> > +required:
> > + - compatible
> > + - reg
> > + - clocks
> > + - power-domains
> > + - "#address-cells"
> > + - "#size-cells"
> > +
> > +# see nvidia,tegra20-vi.yaml for an example
> > --
> > 2.48.1
> >
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v4 22/24] dt-bindings: display: tegra: document Tegra20 and Tegra30 CSI
2025-10-08 21:22 ` Conor Dooley
@ 2025-10-09 5:35 ` Svyatoslav Ryhel
2025-10-09 17:02 ` Conor Dooley
0 siblings, 1 reply; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-09 5:35 UTC (permalink / raw)
To: Conor Dooley
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann, dri-devel,
devicetree, linux-tegra, linux-kernel, linux-media, linux-clk,
linux-gpio, linux-staging
чт, 9 жовт. 2025 р. о 00:22 Conor Dooley <conor@kernel.org> пише:
>
> On Wed, Oct 08, 2025 at 10:21:06PM +0100, Conor Dooley wrote:
> > On Wed, Oct 08, 2025 at 10:30:44AM +0300, Svyatoslav Ryhel wrote:
> > > Document CSI HW block found in Tegra20 and Tegra30 SoC.
> > >
> > > The #nvidia,mipi-calibrate-cells is not an introduction of property, such
> > > property already exists in nvidia,tegra114-mipi.yaml and is used in
> > > multiple device trees. In case of Tegra30 and Tegra20 CSI block combines
> > > mipi calibration function and CSI function, in Tegra114+ mipi calibration
> > > got a dedicated hardware block which is already supported. This property
> > > here is used to align with mipi-calibration logic used by Tegra114+.
> > >
> > > Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> > > ---
> > > .../display/tegra/nvidia,tegra20-csi.yaml | 135 ++++++++++++++++++
> > > 1 file changed, 135 insertions(+)
> > > create mode 100644 Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
> > >
> > > diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
> > > new file mode 100644
> > > index 000000000000..817b3097846b
> > > --- /dev/null
> > > +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
> > > @@ -0,0 +1,135 @@
> > > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > > +%YAML 1.2
> > > +---
> > > +$id: http://devicetree.org/schemas/display/tegra/nvidia,tegra20-csi.yaml#
> > > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > > +
> > > +title: NVIDIA Tegra20 CSI controller
> > > +
> > > +maintainers:
> > > + - Svyatoslav Ryhel <clamor95@gmail.com>
> > > +
> > > +properties:
> > > + compatible:
> > > + enum:
> > > + - nvidia,tegra20-csi
> > > + - nvidia,tegra30-csi
> > > +
> > > + reg:
> > > + maxItems: 1
> > > +
> > > + clocks: true
> > > + clock-names: true
> > > +
> > > + avdd-dsi-csi-supply:
> > > + description: DSI/CSI power supply. Must supply 1.2 V.
> > > +
> > > + power-domains:
> > > + maxItems: 1
> > > +
> > > + "#nvidia,mipi-calibrate-cells":
> > > + description:
> > > + The number of cells in a MIPI calibration specifier. Should be 1.
> > > + The single cell specifies an id of the pad that need to be
> > > + calibrated for a given device. Valid pad ids for receiver would be
> > > + 0 for CSI-A; 1 for CSI-B; 2 for DSI-A and 3 for DSI-B.
> > > + $ref: /schemas/types.yaml#/definitions/uint32
> > > + const: 1
> > > +
> > > + "#address-cells":
> > > + const: 1
> > > +
> > > + "#size-cells":
> > > + const: 0
> > > +
> > > +patternProperties:
> > > + "^channel@[0-1]$":
> > > + type: object
> > > + description: channel 0 represents CSI-A and 1 represents CSI-B
> > > + additionalProperties: false
> > > +
> > > + properties:
> > > + reg:
> > > + maximum: 1
> > > +
> > > + nvidia,mipi-calibrate:
> > > + description: Should contain a phandle and a specifier specifying
> > > + which pad is used by this CSI channel and needs to be calibrated.
> > > + $ref: /schemas/types.yaml#/definitions/phandle-array
> > > +
> > > + "#address-cells":
> > > + const: 1
> > > +
> > > + "#size-cells":
> > > + const: 0
> > > +
> > > + port@0:
> > > + $ref: /schemas/graph.yaml#/$defs/port-base
> > > + unevaluatedProperties: false
> > > + description: port receiving the video stream from the sensor
> > > +
> > > + properties:
> > > + endpoint:
> > > + $ref: /schemas/media/video-interfaces.yaml#
> > > + unevaluatedProperties: false
> > > +
> > > + required:
> > > + - data-lanes
> > > +
> > > + port@1:
> > > + $ref: /schemas/graph.yaml#/properties/port
> > > + description: port sending the video stream to the VI
> > > +
> > > + required:
> > > + - reg
> > > + - "#address-cells"
> > > + - "#size-cells"
> > > + - port@0
> > > + - port@1
> > > +
> > > +allOf:
> > > + - if:
> > > + properties:
> > > + compatible:
> > > + contains:
> > > + enum:
> > > + - nvidia,tegra20-csi
> > > + then:
> > > + properties:
> > > + clocks:
> > > + items:
> > > + - description: module clock
> > > +
> > > + clock-names: false
> > > +
> > > + - if:
> > > + properties:
> > > + compatible:
> > > + contains:
> > > + enum:
> > > + - nvidia,tegra30-csi
> > > + then:
> > > + properties:
> > > + clocks:
> > > + items:
> > > + - description: module clock
> > > + - description: PAD A clock
> > > + - description: PAD B clock
> > > +
> > > + clock-names:
> > > + items:
> > > + - const: csi
> > > + - const: csia-pad
> > > + - const: csib-pad
> >
> > This clocks section seems like it could get simpler. Since the clock
> > descriptions are shared, and tegra20 has no clock-names, you could just
> > move the detail of the properties out to where you have the ": true"
> > stuff (we prefer that properties are defined outside of if/then/else
> > blocks) and just restrict them here. For tegra20 that'd be
> >
> > if:
> > properties:
> > compatible:
> > contains:
> > enum:
> > - nvidia,tegra20-csi
> > then:
> > properties:
> > clocks:
> > maxItems: 1
> >
> > clock-names: false
> >
> > (although it could easily be maxItems: 1 ?)
> > and for tegra30
> >
> > if:
> > properties:
> > compatible:
> > contains:
> > enum:
> > - nvidia,tegra30-csi
> > then:
> > properties:
> > clocks:
> > minItems: 3
> >
> > clock-names:
> > maxItems: 3
> >
> > Of course you'd then have to add minItems: 1 and maxItems: 3 to the
> > extracted definitions.
What do you mean by your last statement? Add minItems: 1 and maxItems:
3 like this?
This does to common properties
clocks:
minItems: 1
maxItems: 3
items:
- description: module clock
- description: PAD A clock
- description: PAD B clock
clock-names:
minItems: 1
maxItems: 3
items:
- const: csi
- const: csia-pad
- const: csib-pad
This goes to conditional
if:
properties:
compatible:
contains:
enum:
- nvidia,tegra20-csi
then:
properties:
clocks:
maxItems: 1
clock-names: false
if:
properties:
compatible:
contains:
enum:
- nvidia,tegra30-csi
then:
properties:
clocks:
minItems: 3
clock-names:
maxItems: 3
>
> Oh, also: if you want clock-names to ever actually be usable, you have
> to require it. Otherwise a driver must be written to handle it not being
> there.
>
Yes, driver takes this into account and handles it.
> > > +additionalProperties: false
> > > +
> > > +required:
> > > + - compatible
> > > + - reg
> > > + - clocks
> > > + - power-domains
> > > + - "#address-cells"
> > > + - "#size-cells"
> > > +
> > > +# see nvidia,tegra20-vi.yaml for an example
> > > --
> > > 2.48.1
> > >
>
>
^ permalink raw reply [flat|nested] 40+ messages in thread* Re: [PATCH v4 22/24] dt-bindings: display: tegra: document Tegra20 and Tegra30 CSI
2025-10-09 5:35 ` Svyatoslav Ryhel
@ 2025-10-09 17:02 ` Conor Dooley
0 siblings, 0 replies; 40+ messages in thread
From: Conor Dooley @ 2025-10-09 17:02 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann, dri-devel,
devicetree, linux-tegra, linux-kernel, linux-media, linux-clk,
linux-gpio, linux-staging
[-- Attachment #1: Type: text/plain, Size: 886 bytes --]
On Thu, Oct 09, 2025 at 08:35:22AM +0300, Svyatoslav Ryhel wrote:
> чт, 9 жовт. 2025 р. о 00:22 Conor Dooley <conor@kernel.org> пише:
> >
> > On Wed, Oct 08, 2025 at 10:21:06PM +0100, Conor Dooley wrote:
> > > On Wed, Oct 08, 2025 at 10:30:44AM +0300, Svyatoslav Ryhel wrote:
> > > Of course you'd then have to add minItems: 1 and maxItems: 3 to the
> > > extracted definitions.
>
> What do you mean by your last statement? Add minItems: 1 and maxItems:
> 3 like this?
>
> This does to common properties
> clocks:
> minItems: 1
> maxItems: 3
> items:
> - description: module clock
> - description: PAD A clock
> - description: PAD B clock
>
> clock-names:
> minItems: 1
> maxItems: 3
> items:
> - const: csi
> - const: csia-pad
> - const: csib-pad
Yes, that is what I meant.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 40+ messages in thread
* Re: [PATCH v4 22/24] dt-bindings: display: tegra: document Tegra20 and Tegra30 CSI
2025-10-08 7:30 ` [PATCH v4 22/24] dt-bindings: display: tegra: document Tegra20 and Tegra30 CSI Svyatoslav Ryhel
2025-10-08 21:21 ` Conor Dooley
@ 2025-10-13 15:53 ` Frank Li
1 sibling, 0 replies; 40+ messages in thread
From: Frank Li @ 2025-10-13 15:53 UTC (permalink / raw)
To: Svyatoslav Ryhel
Cc: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann, dri-devel,
devicetree, linux-tegra, linux-kernel, linux-media, linux-clk,
linux-gpio, linux-staging
On Wed, Oct 08, 2025 at 10:30:44AM +0300, Svyatoslav Ryhel wrote:
> Document CSI HW block found in Tegra20 and Tegra30 SoC.
>
> The #nvidia,mipi-calibrate-cells is not an introduction of property, such
> property already exists in nvidia,tegra114-mipi.yaml and is used in
> multiple device trees. In case of Tegra30 and Tegra20 CSI block combines
> mipi calibration function and CSI function, in Tegra114+ mipi calibration
> got a dedicated hardware block which is already supported. This property
> here is used to align with mipi-calibration logic used by Tegra114+.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
> .../display/tegra/nvidia,tegra20-csi.yaml | 135 ++++++++++++++++++
> 1 file changed, 135 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
>
> diff --git a/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
> new file mode 100644
> index 000000000000..817b3097846b
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/display/tegra/nvidia,tegra20-csi.yaml
> @@ -0,0 +1,135 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/display/tegra/nvidia,tegra20-csi.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: NVIDIA Tegra20 CSI controller
> +
> +maintainers:
> + - Svyatoslav Ryhel <clamor95@gmail.com>
> +
> +properties:
> + compatible:
> + enum:
> + - nvidia,tegra20-csi
> + - nvidia,tegra30-csi
> +
> + reg:
> + maxItems: 1
> +
> + clocks: true
Need limit how many clocks needs
clocks:
maxItems: <?>
> + clock-names: true
Need provide exact list, I saw you provide list at if branch, but here
need provide numbers limitations.
clock-names:
maxItems: 3
minItems: 1
> +
> + avdd-dsi-csi-supply:
> + description: DSI/CSI power supply. Must supply 1.2 V.
> +
> + power-domains:
> + maxItems: 1
> +
> + "#nvidia,mipi-calibrate-cells":
> + description:
> + The number of cells in a MIPI calibration specifier. Should be 1.
> + The single cell specifies an id of the pad that need to be
> + calibrated for a given device. Valid pad ids for receiver would be
> + 0 for CSI-A; 1 for CSI-B; 2 for DSI-A and 3 for DSI-B.
> + $ref: /schemas/types.yaml#/definitions/uint32
> + const: 1
> +
> + "#address-cells":
> + const: 1
> +
> + "#size-cells":
> + const: 0
> +
> +patternProperties:
> + "^channel@[0-1]$":
> + type: object
> + description: channel 0 represents CSI-A and 1 represents CSI-B
> + additionalProperties: false
> +
> + properties:
> + reg:
> + maximum: 1
> +
> + nvidia,mipi-calibrate:
> + description: Should contain a phandle and a specifier specifying
> + which pad is used by this CSI channel and needs to be calibrated.
> + $ref: /schemas/types.yaml#/definitions/phandle-array
> +
> + "#address-cells":
> + const: 1
> +
> + "#size-cells":
> + const: 0
> +
> + port@0:
> + $ref: /schemas/graph.yaml#/$defs/port-base
> + unevaluatedProperties: false
> + description: port receiving the video stream from the sensor
> +
> + properties:
> + endpoint:
> + $ref: /schemas/media/video-interfaces.yaml#
> + unevaluatedProperties: false
> +
> + required:
> + - data-lanes
> +
> + port@1:
> + $ref: /schemas/graph.yaml#/properties/port
> + description: port sending the video stream to the VI
The other systems looks, put port@<n> under ports.
ports {
port@0
...
port@1
...
}
> +
> + required:
> + - reg
> + - "#address-cells"
> + - "#size-cells"
> + - port@0
> + - port@1
> +
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - nvidia,tegra20-csi
> + then:
> + properties:
> + clocks:
> + items:
> + - description: module clock
> +
> + clock-names: false
> +
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - nvidia,tegra30-csi
> + then:
> + properties:
> + clocks:
> + items:
> + - description: module clock
> + - description: PAD A clock
> + - description: PAD B clock
> +
> + clock-names:
> + items:
> + - const: csi
> + - const: csia-pad
> + - const: csib-pad
This is new binding
at top
clock-names
items:
- const: csi
- const: csia-pad
- const: csib-pad
minItems: 1
here, just limit number
clock-names:
minItems: 3
Frank
> +
> +additionalProperties: false
> +
> +required:
> + - compatible
> + - reg
> + - clocks
> + - power-domains
> + - "#address-cells"
> + - "#size-cells"
> +
> +# see nvidia,tegra20-vi.yaml for an example
> --
> 2.48.1
>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v4 23/24] ARM: tegra: add CSI nodes for Tegra20 and Tegra30
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (21 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 22/24] dt-bindings: display: tegra: document Tegra20 and Tegra30 CSI Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
2025-10-20 2:36 ` Mikko Perttunen
2025-10-08 7:30 ` [PATCH v4 24/24] staging: media: tegra-video: add CSI support " Svyatoslav Ryhel
23 siblings, 1 reply; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Add CSI node to Tegra20 and Tegra30 device trees.
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
arch/arm/boot/dts/nvidia/tegra20.dtsi | 19 ++++++++++++++++++-
arch/arm/boot/dts/nvidia/tegra30.dtsi | 24 ++++++++++++++++++++++--
2 files changed, 40 insertions(+), 3 deletions(-)
diff --git a/arch/arm/boot/dts/nvidia/tegra20.dtsi b/arch/arm/boot/dts/nvidia/tegra20.dtsi
index 6ae07b316c8a..5cdbf1246cf8 100644
--- a/arch/arm/boot/dts/nvidia/tegra20.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra20.dtsi
@@ -64,7 +64,7 @@ mpe@54040000 {
vi@54080000 {
compatible = "nvidia,tegra20-vi";
- reg = <0x54080000 0x00040000>;
+ reg = <0x54080000 0x00000800>;
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA20_CLK_VI>;
resets = <&tegra_car 20>;
@@ -72,6 +72,23 @@ vi@54080000 {
power-domains = <&pd_venc>;
operating-points-v2 = <&vi_dvfs_opp_table>;
status = "disabled";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ ranges = <0x0 0x54080000 0x4000>;
+
+ csi: csi@800 {
+ compatible = "nvidia,tegra20-csi";
+ reg = <0x800 0x200>;
+ clocks = <&tegra_car TEGRA20_CLK_CSI>;
+ power-domains = <&pd_venc>;
+ #nvidia,mipi-calibrate-cells = <1>;
+ status = "disabled";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
epp@540c0000 {
diff --git a/arch/arm/boot/dts/nvidia/tegra30.dtsi b/arch/arm/boot/dts/nvidia/tegra30.dtsi
index 20b3248d4d2f..be752a245a55 100644
--- a/arch/arm/boot/dts/nvidia/tegra30.dtsi
+++ b/arch/arm/boot/dts/nvidia/tegra30.dtsi
@@ -150,8 +150,8 @@ mpe@54040000 {
};
vi@54080000 {
- compatible = "nvidia,tegra30-vi";
- reg = <0x54080000 0x00040000>;
+ compatible = "nvidia,tegra30-vi", "nvidia,tegra20-vi";
+ reg = <0x54080000 0x00000800>;
interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&tegra_car TEGRA30_CLK_VI>;
resets = <&tegra_car 20>;
@@ -162,6 +162,26 @@ vi@54080000 {
iommus = <&mc TEGRA_SWGROUP_VI>;
status = "disabled";
+
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ ranges = <0x0 0x54080000 0x4000>;
+
+ csi: csi@800 {
+ compatible = "nvidia,tegra30-csi";
+ reg = <0x800 0x200>;
+ clocks = <&tegra_car TEGRA30_CLK_CSI>,
+ <&tegra_car TEGRA30_CLK_CSIA_PAD>,
+ <&tegra_car TEGRA30_CLK_CSIB_PAD>;
+ clock-names = "csi", "csia-pad", "csib-pad";
+ power-domains = <&pd_venc>;
+ #nvidia,mipi-calibrate-cells = <1>;
+ status = "disabled";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+ };
};
epp@540c0000 {
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread* Re: [PATCH v4 23/24] ARM: tegra: add CSI nodes for Tegra20 and Tegra30
2025-10-08 7:30 ` [PATCH v4 23/24] ARM: tegra: add CSI nodes for Tegra20 and Tegra30 Svyatoslav Ryhel
@ 2025-10-20 2:36 ` Mikko Perttunen
0 siblings, 0 replies; 40+ messages in thread
From: Mikko Perttunen @ 2025-10-20 2:36 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Linus Walleij, Mauro Carvalho Chehab, Greg Kroah-Hartman,
Svyatoslav Ryhel, Jonas Schwöbel, Dmitry Osipenko,
Charan Pedumuru, Diogo Ivo, Aaron Kling, Arnd Bergmann,
Svyatoslav Ryhel
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
On Wednesday, October 8, 2025 4:30 PM Svyatoslav Ryhel wrote:
> Add CSI node to Tegra20 and Tegra30 device trees.
>
> Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
> ---
> arch/arm/boot/dts/nvidia/tegra20.dtsi | 19 ++++++++++++++++++-
> arch/arm/boot/dts/nvidia/tegra30.dtsi | 24 ++++++++++++++++++++++--
> 2 files changed, 40 insertions(+), 3 deletions(-)
>
> diff --git a/arch/arm/boot/dts/nvidia/tegra20.dtsi b/arch/arm/boot/dts/nvidia/tegra20.dtsi
> index 6ae07b316c8a..5cdbf1246cf8 100644
> --- a/arch/arm/boot/dts/nvidia/tegra20.dtsi
> +++ b/arch/arm/boot/dts/nvidia/tegra20.dtsi
> @@ -64,7 +64,7 @@ mpe@54040000 {
>
> vi@54080000 {
> compatible = "nvidia,tegra20-vi";
> - reg = <0x54080000 0x00040000>;
> + reg = <0x54080000 0x00000800>;
> interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
> clocks = <&tegra_car TEGRA20_CLK_VI>;
> resets = <&tegra_car 20>;
> @@ -72,6 +72,23 @@ vi@54080000 {
> power-domains = <&pd_venc>;
> operating-points-v2 = <&vi_dvfs_opp_table>;
> status = "disabled";
> +
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + ranges = <0x0 0x54080000 0x4000>;
> +
> + csi: csi@800 {
> + compatible = "nvidia,tegra20-csi";
> + reg = <0x800 0x200>;
> + clocks = <&tegra_car TEGRA20_CLK_CSI>;
> + power-domains = <&pd_venc>;
> + #nvidia,mipi-calibrate-cells = <1>;
> + status = "disabled";
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> + };
> };
>
> epp@540c0000 {
> diff --git a/arch/arm/boot/dts/nvidia/tegra30.dtsi b/arch/arm/boot/dts/nvidia/tegra30.dtsi
> index 20b3248d4d2f..be752a245a55 100644
> --- a/arch/arm/boot/dts/nvidia/tegra30.dtsi
> +++ b/arch/arm/boot/dts/nvidia/tegra30.dtsi
> @@ -150,8 +150,8 @@ mpe@54040000 {
> };
>
> vi@54080000 {
> - compatible = "nvidia,tegra30-vi";
> - reg = <0x54080000 0x00040000>;
> + compatible = "nvidia,tegra30-vi", "nvidia,tegra20-vi";
> + reg = <0x54080000 0x00000800>;
> interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
> clocks = <&tegra_car TEGRA30_CLK_VI>;
> resets = <&tegra_car 20>;
> @@ -162,6 +162,26 @@ vi@54080000 {
> iommus = <&mc TEGRA_SWGROUP_VI>;
>
> status = "disabled";
> +
> + #address-cells = <1>;
> + #size-cells = <1>;
> +
> + ranges = <0x0 0x54080000 0x4000>;
> +
> + csi: csi@800 {
> + compatible = "nvidia,tegra30-csi";
> + reg = <0x800 0x200>;
> + clocks = <&tegra_car TEGRA30_CLK_CSI>,
> + <&tegra_car TEGRA30_CLK_CSIA_PAD>,
> + <&tegra_car TEGRA30_CLK_CSIB_PAD>;
> + clock-names = "csi", "csia-pad", "csib-pad";
> + power-domains = <&pd_venc>;
> + #nvidia,mipi-calibrate-cells = <1>;
> + status = "disabled";
> +
> + #address-cells = <1>;
> + #size-cells = <0>;
> + };
> };
>
> epp@540c0000 {
>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
^ permalink raw reply [flat|nested] 40+ messages in thread
* [PATCH v4 24/24] staging: media: tegra-video: add CSI support for Tegra20 and Tegra30
2025-10-08 7:30 [PATCH v4 00/24] tegra-video: add CSI support for Tegra20 and Tegra30 Svyatoslav Ryhel
` (22 preceding siblings ...)
2025-10-08 7:30 ` [PATCH v4 23/24] ARM: tegra: add CSI nodes for Tegra20 and Tegra30 Svyatoslav Ryhel
@ 2025-10-08 7:30 ` Svyatoslav Ryhel
23 siblings, 0 replies; 40+ messages in thread
From: Svyatoslav Ryhel @ 2025-10-08 7:30 UTC (permalink / raw)
To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Thierry Reding, Jonathan Hunter, Sowjanya Komatineni,
Luca Ceresoli, Prashant Gaikwad, Michael Turquette, Stephen Boyd,
Mikko Perttunen, Linus Walleij, Mauro Carvalho Chehab,
Greg Kroah-Hartman, Svyatoslav Ryhel, Jonas Schwöbel,
Dmitry Osipenko, Charan Pedumuru, Diogo Ivo, Aaron Kling,
Arnd Bergmann
Cc: dri-devel, devicetree, linux-tegra, linux-kernel, linux-media,
linux-clk, linux-gpio, linux-staging
Add support for MIPI CSI device and calibration logic found in Tegra20 and
Tegra30 SoC.
To get CSI operational, an additional syncpoint was allocated to serve as
the CSI frame counter. Both VIP and CSI use an existing syncpoint for VI
frame start events. That said, the frame capture function was refactored
to reflect the addition of the CSI syncpoint, and the CSI-specific
configuration is guarded by the presence of a passed CSI channel structure
pointer.
The camera capture setup's configuration was reconsidered: the first two
writes must be done before tegra_channel_set_stream for MIPI calibration
to work properly; the third write was moved to VIP/CSI-specific functions
since it must be source-specific; the function was placed after
tegra_channel_set_stream so the initial sequence is preserved and expanded.
CSI configuration sequences were added based on downstream 3.1 kernel
sources and adjusted to the existing video-tegra framework. Although
Tegra20 and Tegra30 have the same set of configurations, they differ by
the number of clocks used by CSI.
Dropped the software syncpoint counters in favor of reading syncpoints
directly and passing the incremented value to the polling function. If the
syncpoint increase fails, the PP is reset. This change should prevent
possible race conditions.
MIPI calibration logic was registered in CSI since Tegra20 and Tegra30
have no dedicated hardware block for these operations and use CSI. These
calls are used for both CSI and DSI to work properly, which is why MIPI
calibration cannot be contained within CSI. The pads passed to the
calibration calls resemble CSI PORT_A (0), CSI PORT_B (1), DSI-A (3) and
DSI-B (4).
Co-developed-by: Jonas Schwöbel <jonasschwoebel@yahoo.de>
Signed-off-by: Jonas Schwöbel <jonasschwoebel@yahoo.de>
Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/staging/media/tegra-video/csi.c | 23 +
drivers/staging/media/tegra-video/csi.h | 4 +
drivers/staging/media/tegra-video/tegra20.c | 608 ++++++++++++++++++--
drivers/staging/media/tegra-video/vi.h | 2 -
drivers/staging/media/tegra-video/video.c | 6 +
5 files changed, 596 insertions(+), 47 deletions(-)
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
index 7d70478a07aa..7192c2e8bae7 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -827,6 +827,17 @@ static int tegra_csi_probe(struct platform_device *pdev)
csi->dev = &pdev->dev;
csi->ops = csi->soc->ops;
+
+ if (csi->soc->mipi_ops) {
+ ret = devm_tegra_mipi_add_provider(&pdev->dev, pdev->dev.of_node,
+ csi->soc->mipi_ops);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to add MIPI calibration operations\n");
+ }
+
+ mutex_init(&csi->mipi_lock);
+
platform_set_drvdata(pdev, csi);
pm_runtime_enable(&pdev->dev);
@@ -858,11 +869,23 @@ static void tegra_csi_remove(struct platform_device *pdev)
pm_runtime_disable(&pdev->dev);
}
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+extern const struct tegra_csi_soc tegra20_csi_soc;
+#endif
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
+extern const struct tegra_csi_soc tegra30_csi_soc;
+#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
extern const struct tegra_csi_soc tegra210_csi_soc;
#endif
static const struct of_device_id tegra_csi_of_id_table[] = {
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ { .compatible = "nvidia,tegra20-csi", .data = &tegra20_csi_soc },
+#endif
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
+ { .compatible = "nvidia,tegra30-csi", .data = &tegra30_csi_soc },
+#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
{ .compatible = "nvidia,tegra210-csi", .data = &tegra210_csi_soc },
#endif
diff --git a/drivers/staging/media/tegra-video/csi.h b/drivers/staging/media/tegra-video/csi.h
index 1550defb115a..58ca98da2305 100644
--- a/drivers/staging/media/tegra-video/csi.h
+++ b/drivers/staging/media/tegra-video/csi.h
@@ -115,6 +115,7 @@ struct tegra_csi_ops {
* struct tegra_csi_soc - NVIDIA Tegra CSI SoC structure
*
* @ops: csi hardware operations
+ * @mipi_ops: MIPI calibration operations
* @csi_max_channels: supported max streaming channels
* @clk_names: csi and cil clock names
* @num_clks: total clocks count
@@ -123,6 +124,7 @@ struct tegra_csi_ops {
*/
struct tegra_csi_soc {
const struct tegra_csi_ops *ops;
+ const struct tegra_mipi_ops *mipi_ops;
unsigned int csi_max_channels;
const char * const *clk_names;
unsigned int num_clks;
@@ -140,6 +142,7 @@ struct tegra_csi_soc {
* @vdd: vdd regulator for CSI hardware, usually avdd_dsi_csi
* @soc: pointer to SoC data structure
* @ops: csi operations
+ * @mipi_lock: for MIPI calibration operations
* @csi_chans: list head for CSI channels
*/
struct tegra_csi {
@@ -150,6 +153,7 @@ struct tegra_csi {
struct regulator *vdd;
const struct tegra_csi_soc *soc;
const struct tegra_csi_ops *ops;
+ struct mutex mipi_lock; /* for register access */
struct list_head csi_chans;
};
diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
index 626f34543853..cdaa97306b9c 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -4,6 +4,9 @@
*
* Copyright (C) 2023 SKIDATA GmbH
* Author: Luca Ceresoli <luca.ceresoli@bootlin.com>
+ *
+ * Copyright (c) 2025 Svyatoslav Ryhel <clamor95@gmail.com>
+ * Copyright (c) 2025 Jonas Schwöbel <jonasschwoebel@yahoo.de>
*/
/*
@@ -12,10 +15,15 @@
*/
#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk/tegra.h>
#include <linux/delay.h>
#include <linux/host1x.h>
+#include <linux/iopoll.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
+#include <linux/pm_runtime.h>
+#include <linux/tegra-mipi-cal.h>
#include <linux/v4l2-mediabus.h>
#include "vip.h"
@@ -42,6 +50,9 @@ enum tegra_vi_out {
#define VI_CONT_SYNCPT_OUT_CONTINUOUS_SYNCPT BIT(8)
#define VI_CONT_SYNCPT_OUT_SYNCPT_IDX_SFT 0
+#define TEGRA_VI_CONT_SYNCPT_CSI_PP_FRAME_START(n) (0x0070 + (n) * 8)
+#define TEGRA_VI_CONT_SYNCPT_CSI_PP_FRAME_END(n) (0x0074 + (n) * 8)
+
#define TEGRA_VI_VI_INPUT_CONTROL 0x0088
#define VI_INPUT_FIELD_DETECT BIT(27)
#define VI_INPUT_BT656 BIT(25)
@@ -88,6 +99,8 @@ enum tegra_vi_out {
#define VI_OUTPUT_OUTPUT_FORMAT_YUV422POST (3 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
#define VI_OUTPUT_OUTPUT_FORMAT_YUV420PLANAR (6 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
/* TEGRA_VI_OUT_2 supported formats */
+#define VI_OUTPUT_OUTPUT_FORMAT_CSI_PPA_BAYER (7 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
+#define VI_OUTPUT_OUTPUT_FORMAT_CSI_PPB_BAYER (8 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
#define VI_OUTPUT_OUTPUT_FORMAT_VIP_BAYER_DIRECT (9 << VI_OUTPUT_OUTPUT_FORMAT_SFT)
#define TEGRA_VI_VIP_H_ACTIVE 0x00a4
@@ -152,8 +165,106 @@ enum tegra_vi_out {
#define TEGRA_VI_VI_RAISE 0x01ac
#define VI_VI_RAISE_ON_EDGE BIT(0)
+#define TEGRA_VI_CSI_PP_RAISE_FRAME_START(n) (0x01d8 + (n) * 8)
+#define TEGRA_VI_CSI_PP_RAISE_FRAME_END(n) (0x01dc + (n) * 8)
+#define TEGRA_VI_CSI_PP_H_ACTIVE(n) (0x01e8 + (n) * 8)
+#define TEGRA_VI_CSI_PP_V_ACTIVE(n) (0x01ec + (n) * 8)
+
+/* Tegra20 CSI registers: Starts from 0x800, offset 0x0 */
+#define TEGRA_CSI_VI_INPUT_STREAM_CONTROL 0x0000
+#define TEGRA_CSI_HOST_INPUT_STREAM_CONTROL 0x0008
+#define TEGRA_CSI_INPUT_STREAM_CONTROL(n) (0x0010 + (n) * 0x2c)
+#define CSI_SKIP_PACKET_THRESHOLD(n) (((n) & 0xff) << 16)
+#define TEGRA_CSI_PIXEL_STREAM_CONTROL0(n) (0x0018 + (n) * 0x2c)
+#define CSI_PP_PAD_FRAME_PAD0S (0 << 28)
+#define CSI_PP_PAD_FRAME_PAD1S (1 << 28)
+#define CSI_PP_PAD_FRAME_NOPAD (2 << 28)
+#define CSI_PP_HEADER_EC_ENABLE BIT(27)
+#define CSI_PP_PAD_SHORT_LINE_PAD0S (0 << 24)
+#define CSI_PP_PAD_SHORT_LINE_PAD1S (1 << 24)
+#define CSI_PP_PAD_SHORT_LINE_NOPAD (2 << 24)
+#define CSI_PP_EMBEDDED_DATA_EMBEDDED BIT(20)
+#define CSI_PP_OUTPUT_FORMAT_ARBITRARY (0 << 16)
+#define CSI_PP_OUTPUT_FORMAT_PIXEL (1 << 16)
+#define CSI_PP_OUTPUT_FORMAT_PIXEL_REP (2 << 16)
+#define CSI_PP_OUTPUT_FORMAT_STORE (3 << 16)
+#define CSI_PP_VIRTUAL_CHANNEL_ID(n) (((n) - 1) << 14)
+#define CSI_PP_DATA_TYPE(n) ((n) << 8)
+#define CSI_PP_CRC_CHECK_ENABLE BIT(7)
+#define CSI_PP_WORD_COUNT_HEADER BIT(6)
+#define CSI_PP_DATA_IDENTIFIER_ENABLE BIT(5)
+#define CSI_PP_PACKET_HEADER_SENT BIT(4)
+#define TEGRA_CSI_PIXEL_STREAM_CONTROL1(n) (0x001c + (n) * 0x2c)
+#define TEGRA_CSI_PIXEL_STREAM_WORD_COUNT(n) (0x0020 + (n) * 0x2c)
+#define TEGRA_CSI_PIXEL_STREAM_GAP(n) (0x0024 + (n) * 0x2c)
+#define CSI_PP_FRAME_MIN_GAP(n) (((n) & 0xffff) << 16)
+#define CSI_PP_LINE_MIN_GAP(n) (((n) & 0xffff))
+#define TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(n) (0x0028 + (n) * 0x2c)
+#define CSI_PP_START_MARKER_FRAME_MAX(n) (((n) & 0xf) << 12)
+#define CSI_PP_START_MARKER_FRAME_MIN(n) (((n) & 0xf) << 8)
+#define CSI_PP_VSYNC_START_MARKER BIT(4)
+#define CSI_PP_SINGLE_SHOT BIT(2)
+#define CSI_PP_NOP 0
+#define CSI_PP_ENABLE 1
+#define CSI_PP_DISABLE 2
+#define CSI_PP_RESET 3
+#define TEGRA_CSI_PHY_CIL_COMMAND 0x0068
+#define CSI_A_PHY_CIL_NOP 0x0
+#define CSI_A_PHY_CIL_ENABLE 0x1
+#define CSI_A_PHY_CIL_DISABLE 0x2
+#define CSI_A_PHY_CIL_ENABLE_MASK 0x3
+#define CSI_B_PHY_CIL_NOP (0x0 << 16)
+#define CSI_B_PHY_CIL_ENABLE (0x1 << 16)
+#define CSI_B_PHY_CIL_DISABLE (0x2 << 16)
+#define CSI_B_PHY_CIL_ENABLE_MASK (0x3 << 16)
+#define TEGRA_CSI_PHY_CIL_CONTROL0(n) (0x006c + (n) * 4)
+#define CSI_CONTINUOUS_CLOCK_MODE_ENABLE BIT(5)
+#define TEGRA_CSI_CSI_PIXEL_PARSER_STATUS 0x0078
+#define TEGRA_CSI_CSI_CIL_STATUS 0x007c
+#define CSI_MIPI_AUTO_CAL_DONE BIT(15)
+#define TEGRA_CSI_CSI_PIXEL_PARSER_INTERRUPT_MASK 0x0080
+#define TEGRA_CSI_CSI_CIL_INTERRUPT_MASK 0x0084
+#define TEGRA_CSI_CSI_READONLY_STATUS 0x0088
+#define TEGRA_CSI_ESCAPE_MODE_COMMAND 0x008c
+#define TEGRA_CSI_ESCAPE_MODE_DATA 0x0090
+#define TEGRA_CSI_CIL_PAD_CONFIG0(n) (0x0094 + (n) * 8)
+#define TEGRA_CSI_CIL_PAD_CONFIG1(n) (0x0098 + (n) * 8)
+#define TEGRA_CSI_CIL_PAD_CONFIG 0x00a4
+#define TEGRA_CSI_CILA_MIPI_CAL_CONFIG 0x00a8
+#define TEGRA_CSI_CILB_MIPI_CAL_CONFIG 0x00ac
+#define CSI_CIL_MIPI_CAL_STARTCAL BIT(31)
+#define CSI_CIL_MIPI_CAL_OVERIDE_A BIT(30)
+#define CSI_CIL_MIPI_CAL_OVERIDE_B BIT(30)
+#define CSI_CIL_MIPI_CAL_NOISE_FLT(n) (((n) & 0xf) << 26)
+#define CSI_CIL_MIPI_CAL_PRESCALE(n) (((n) & 0x3) << 24)
+#define CSI_CIL_MIPI_CAL_SEL_A BIT(21)
+#define CSI_CIL_MIPI_CAL_SEL_B BIT(21)
+#define CSI_CIL_MIPI_CAL_HSPDOS(n) (((n) & 0x1f) << 16)
+#define CSI_CIL_MIPI_CAL_HSPUOS(n) (((n) & 0x1f) << 8)
+#define CSI_CIL_MIPI_CAL_TERMOS(n) (((n) & 0x1f))
+#define TEGRA_CSI_CIL_MIPI_CAL_STATUS 0x00b0
+#define TEGRA_CSI_CLKEN_OVERRIDE 0x00b4
+#define TEGRA_CSI_DEBUG_CONTROL 0x00b8
+#define CSI_DEBUG_CONTROL_DEBUG_EN_ENABLED BIT(0)
+#define CSI_DEBUG_CONTROL_CLR_DBG_CNT_0 BIT(4)
+#define CSI_DEBUG_CONTROL_CLR_DBG_CNT_1 BIT(5)
+#define CSI_DEBUG_CONTROL_CLR_DBG_CNT_2 BIT(6)
+#define CSI_DEBUG_CONTROL_DBG_CNT_SEL(n, v) ((v) << (8 + 8 * (n)))
+#define TEGRA_CSI_DEBUG_COUNTER(n) (0x00bc + (n) * 4)
+#define TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME(n) (0x00c8 + (n) * 4)
+#define CSI_PP_EXP_FRAME_HEIGHT(n) (((n) & 0x1fff) << 16)
+#define CSI_PP_MAX_CLOCKS(n) (((n) & 0xfff) << 4)
+#define CSI_PP_LINE_TIMEOUT_ENABLE BIT(0)
+#define TEGRA_CSI_DSI_MIPI_CAL_CONFIG 0x00d0
+#define TEGRA_CSI_MIPIBIAS_PAD_CONFIG 0x00d4
+#define CSI_PAD_DRIV_DN_REF(n) (((n) & 0x7) << 16)
+#define CSI_PAD_DRIV_UP_REF(n) (((n) & 0x7) << 8)
+#define CSI_PAD_TERM_REF(n) (((n) & 0x7) << 0)
+#define TEGRA_CSI_CSI_CILA_STATUS 0x00d8
+#define TEGRA_CSI_CSI_CILB_STATUS 0x00dc
+
/* --------------------------------------------------------------------------
- * VI
+ * Read and Write helpers
*/
static void tegra20_vi_write(struct tegra_vi_channel *chan, unsigned int addr, u32 val)
@@ -161,6 +272,35 @@ static void tegra20_vi_write(struct tegra_vi_channel *chan, unsigned int addr, u
writel(val, chan->vi->iomem + addr);
}
+static int __maybe_unused tegra20_vi_read(struct tegra_vi_channel *chan, unsigned int addr)
+{
+ return readl(chan->vi->iomem + addr);
+}
+
+static void tegra20_csi_write(struct tegra_csi_channel *csi_chan, unsigned int addr, u32 val)
+{
+ writel(val, csi_chan->csi->iomem + addr);
+}
+
+static int __maybe_unused tegra20_csi_read(struct tegra_csi_channel *csi_chan, unsigned int addr)
+{
+ return readl(csi_chan->csi->iomem + addr);
+}
+
+static void tegra20_mipi_write(struct tegra_csi *csi, unsigned int addr, u32 val)
+{
+ writel(val, csi->iomem + addr);
+}
+
+static int __maybe_unused tegra20_mipi_read(struct tegra_csi *csi, unsigned int addr)
+{
+ return readl(csi->iomem + addr);
+}
+
+/* --------------------------------------------------------------------------
+ * VI
+ */
+
/*
* Get the main input format (YUV/RGB...) and the YUV variant as values to
* be written into registers for the current VI input mbus code.
@@ -283,20 +423,27 @@ static int tegra20_vi_enable(struct tegra_vi *vi, bool on)
static int tegra20_channel_host1x_syncpt_init(struct tegra_vi_channel *chan)
{
struct tegra_vi *vi = chan->vi;
- struct host1x_syncpt *out_sp;
+ struct host1x_syncpt *out_sp, *fs_sp;
out_sp = host1x_syncpt_request(&vi->client, HOST1X_SYNCPT_CLIENT_MANAGED);
if (!out_sp)
- return dev_err_probe(vi->dev, -ENOMEM, "failed to request syncpoint\n");
+ return dev_err_probe(vi->dev, -EBUSY, "failed to request mw ack syncpoint\n");
chan->mw_ack_sp[0] = out_sp;
+ fs_sp = host1x_syncpt_request(&vi->client, HOST1X_SYNCPT_CLIENT_MANAGED);
+ if (!fs_sp)
+ return dev_err_probe(vi->dev, -EBUSY, "failed to request frame start syncpoint\n");
+
+ chan->frame_start_sp[0] = fs_sp;
+
return 0;
}
static void tegra20_channel_host1x_syncpt_free(struct tegra_vi_channel *chan)
{
host1x_syncpt_put(chan->mw_ack_sp[0]);
+ host1x_syncpt_put(chan->frame_start_sp[0]);
}
static void tegra20_fmt_align(struct v4l2_pix_format *pix, unsigned int bpp)
@@ -424,41 +571,79 @@ static void tegra20_channel_vi_buffer_setup(struct tegra_vi_channel *chan,
}
static int tegra20_channel_capture_frame(struct tegra_vi_channel *chan,
- struct tegra_channel_buffer *buf)
+ struct tegra_channel_buffer *buf,
+ struct tegra_csi_channel *csi_chan)
{
+ u32 val;
int err;
- chan->next_out_sp_idx++;
-
tegra20_channel_vi_buffer_setup(chan, buf);
- tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_VIP_ENABLE);
+ if (csi_chan) {
+ u32 port = csi_chan->csi_port_nums[0] & 1;
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
+ CSI_PP_START_MARKER_FRAME_MAX(0xf) |
+ CSI_PP_SINGLE_SHOT | CSI_PP_ENABLE);
+
+ val = host1x_syncpt_read(chan->frame_start_sp[0]);
+ do {
+ err = host1x_syncpt_wait(chan->frame_start_sp[0],
+ val + 1, TEGRA_VI_SYNCPT_WAIT_TIMEOUT, NULL);
+ } while (err == -ERESTARTSYS);
+
+ if (err) {
+ if (err != -ERESTARTSYS)
+ dev_err_ratelimited(&chan->video.dev,
+ "frame start syncpt timeout: %d\n", err);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
+ CSI_PP_START_MARKER_FRAME_MAX(0xf) | CSI_PP_RESET);
+ goto exit;
+ }
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
+ CSI_PP_START_MARKER_FRAME_MAX(0xf) |
+ CSI_PP_DISABLE);
+ } else {
+ tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_VIP_ENABLE);
+ }
+
+ val = host1x_syncpt_read(chan->mw_ack_sp[0]);
+ do {
+ err = host1x_syncpt_wait(chan->mw_ack_sp[0], val + 1,
+ TEGRA_VI_SYNCPT_WAIT_TIMEOUT, NULL);
+ } while (err == -ERESTARTSYS);
- /* Wait for syncpt counter to reach frame start event threshold */
- err = host1x_syncpt_wait(chan->mw_ack_sp[0], chan->next_out_sp_idx,
- TEGRA_VI_SYNCPT_WAIT_TIMEOUT, NULL);
if (err) {
- host1x_syncpt_incr(chan->mw_ack_sp[0]);
- dev_err_ratelimited(&chan->video.dev, "frame start syncpt timeout: %d\n", err);
- release_buffer(chan, buf, VB2_BUF_STATE_ERROR);
- return err;
+ if (err != -ERESTARTSYS)
+ dev_err_ratelimited(&chan->video.dev, "mw ack syncpt timeout: %d\n", err);
+ goto exit;
}
- tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL,
- VI_CAMERA_CONTROL_STOP_CAPTURE | VI_CAMERA_CONTROL_VIP_ENABLE);
+ if (!csi_chan)
+ tegra20_vi_write(chan, TEGRA_VI_CAMERA_CONTROL,
+ VI_CAMERA_CONTROL_STOP_CAPTURE | VI_CAMERA_CONTROL_VIP_ENABLE);
+exit:
release_buffer(chan, buf, VB2_BUF_STATE_DONE);
- return 0;
+ return err;
}
static int tegra20_chan_capture_kthread_start(void *data)
{
struct tegra_vi_channel *chan = data;
struct tegra_channel_buffer *buf;
+ struct v4l2_subdev *csi_subdev = NULL;
+ struct tegra_csi_channel *csi_chan = NULL;
unsigned int retries = 0;
int err = 0;
+ csi_subdev = tegra_channel_get_remote_csi_subdev(chan);
+ if (csi_subdev)
+ csi_chan = to_csi_chan(csi_subdev);
+
while (1) {
/*
* Source is not streaming if error is non-zero.
@@ -483,7 +668,7 @@ static int tegra20_chan_capture_kthread_start(void *data)
list_del_init(&buf->queue);
spin_unlock(&chan->start_lock);
- err = tegra20_channel_capture_frame(chan, buf);
+ err = tegra20_channel_capture_frame(chan, buf, csi_chan);
if (!err) {
retries = 0;
continue;
@@ -510,28 +695,6 @@ static void tegra20_camera_capture_setup(struct tegra_vi_channel *chan)
enum tegra_vi_out output_channel = (data_type == TEGRA_IMAGE_DT_RAW8 ||
data_type == TEGRA_IMAGE_DT_RAW10) ?
TEGRA_VI_OUT_2 : TEGRA_VI_OUT_1;
- int main_output_format;
- int yuv_output_format;
-
- tegra20_vi_get_output_formats(chan, &main_output_format, &yuv_output_format);
-
- /*
- * Set up low pass filter. Use 0x240 for chromaticity and 0x240
- * for luminance, which is the default and means not to touch
- * anything.
- */
- tegra20_vi_write(chan, TEGRA_VI_H_LPF_CONTROL,
- 0x0240 << VI_H_LPF_CONTROL_LUMA_SFT |
- 0x0240 << VI_H_LPF_CONTROL_CHROMA_SFT);
-
- /* Set up raise-on-edge, so we get an interrupt on end of frame. */
- tegra20_vi_write(chan, TEGRA_VI_VI_RAISE, VI_VI_RAISE_ON_EDGE);
-
- tegra20_vi_write(chan, TEGRA_VI_VI_OUTPUT_CONTROL(output_channel),
- (chan->vflip ? VI_OUTPUT_V_DIRECTION : 0) |
- (chan->hflip ? VI_OUTPUT_H_DIRECTION : 0) |
- yuv_output_format << VI_OUTPUT_YUV_OUTPUT_FORMAT_SFT |
- main_output_format << VI_OUTPUT_OUTPUT_FORMAT_SFT);
/* Set up frame size */
tegra20_vi_write(chan, TEGRA_VI_OUTPUT_FRAME_SIZE(output_channel),
@@ -562,18 +725,28 @@ static int tegra20_vi_start_streaming(struct vb2_queue *vq, u32 count)
struct media_pipeline *pipe = &chan->video.pipe;
int err;
- chan->next_out_sp_idx = host1x_syncpt_read(chan->mw_ack_sp[0]);
-
err = video_device_pipeline_start(&chan->video, pipe);
if (err)
goto error_pipeline_start;
- tegra20_camera_capture_setup(chan);
+ /*
+ * Set up low pass filter. Use 0x240 for chromaticity and 0x240
+ * for luminance, which is the default and means not to touch
+ * anything.
+ */
+ tegra20_vi_write(chan, TEGRA_VI_H_LPF_CONTROL,
+ 0x0240 << VI_H_LPF_CONTROL_LUMA_SFT |
+ 0x0240 << VI_H_LPF_CONTROL_CHROMA_SFT);
+
+ /* Set up raise-on-edge, so we get an interrupt on end of frame. */
+ tegra20_vi_write(chan, TEGRA_VI_VI_RAISE, VI_VI_RAISE_ON_EDGE);
err = tegra_channel_set_stream(chan, true);
if (err)
goto error_set_stream;
+ tegra20_camera_capture_setup(chan);
+
chan->sequence = 0;
chan->kthread_start_capture = kthread_run(tegra20_chan_capture_kthread_start,
@@ -668,6 +841,345 @@ const struct tegra_vi_soc tegra20_vi_soc = {
.has_h_v_flip = true,
};
+/* --------------------------------------------------------------------------
+ * MIPI Calibration
+ */
+static int tegra20_start_pad_calibration(struct tegra_mipi_device *mipi)
+{
+ struct tegra_csi *csi = platform_get_drvdata(mipi->pdev);
+ unsigned int port = mipi->pads;
+ u32 value;
+ int ret;
+
+ guard(mutex)(&csi->mipi_lock);
+
+ ret = pm_runtime_resume_and_get(csi->dev);
+ if (ret < 0) {
+ dev_err(csi->dev, "failed to get runtime PM: %d\n", ret);
+ return ret;
+ }
+
+ tegra20_mipi_write(csi, TEGRA_CSI_DSI_MIPI_CAL_CONFIG,
+ CSI_CIL_MIPI_CAL_HSPDOS(4) |
+ CSI_CIL_MIPI_CAL_HSPUOS(3) |
+ CSI_CIL_MIPI_CAL_TERMOS(0));
+ tegra20_mipi_write(csi, TEGRA_CSI_MIPIBIAS_PAD_CONFIG,
+ CSI_PAD_DRIV_DN_REF(5) |
+ CSI_PAD_DRIV_UP_REF(7) |
+ CSI_PAD_TERM_REF(0));
+
+ /* CSI B */
+ value = CSI_CIL_MIPI_CAL_HSPDOS(0) |
+ CSI_CIL_MIPI_CAL_HSPUOS(0) |
+ CSI_CIL_MIPI_CAL_TERMOS(4);
+
+ if (port == PORT_B)
+ value |= CSI_CIL_MIPI_CAL_SEL_B;
+
+ tegra20_mipi_write(csi, TEGRA_CSI_CILB_MIPI_CAL_CONFIG, value);
+
+ /* CSI A */
+ value = CSI_CIL_MIPI_CAL_STARTCAL |
+ CSI_CIL_MIPI_CAL_NOISE_FLT(0xa) |
+ CSI_CIL_MIPI_CAL_PRESCALE(0x2) |
+ CSI_CIL_MIPI_CAL_HSPDOS(0) |
+ CSI_CIL_MIPI_CAL_HSPUOS(0) |
+ CSI_CIL_MIPI_CAL_TERMOS(4);
+
+ if (port == PORT_A)
+ value |= CSI_CIL_MIPI_CAL_SEL_A;
+
+ tegra20_mipi_write(csi, TEGRA_CSI_CILA_MIPI_CAL_CONFIG, value);
+
+ tegra20_mipi_write(csi, TEGRA_CSI_CIL_PAD_CONFIG, 0);
+
+ return 0;
+}
+
+static int tegra20_finish_pad_calibration(struct tegra_mipi_device *mipi)
+{
+ struct tegra_csi *csi = platform_get_drvdata(mipi->pdev);
+ void __iomem *cil_status_reg = csi->iomem + TEGRA_CSI_CSI_CIL_STATUS;
+ unsigned int port = mipi->pads;
+ u32 value, pp = 0, cil = 0;
+ int ret;
+
+ /* This part is only for CSI */
+ if (port > PORT_B) {
+ pm_runtime_put(csi->dev);
+
+ return 0;
+ }
+
+ guard(mutex)(&csi->mipi_lock);
+
+ ret = readl_relaxed_poll_timeout(cil_status_reg, value,
+ value & CSI_MIPI_AUTO_CAL_DONE, 50, 250000);
+ if (ret < 0) {
+ dev_warn(csi->dev, "MIPI calibration timeout!\n");
+ goto exit;
+ }
+
+ /* clear status */
+ tegra20_mipi_write(csi, TEGRA_CSI_CSI_CIL_STATUS, value);
+ ret = readl_relaxed_poll_timeout(cil_status_reg, value,
+ !(value & CSI_MIPI_AUTO_CAL_DONE), 50, 250000);
+ if (ret < 0) {
+ dev_warn(csi->dev, "MIPI calibration status timeout!\n");
+ goto exit;
+ }
+
+ pp = tegra20_mipi_read(csi, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS);
+ cil = tegra20_mipi_read(csi, TEGRA_CSI_CSI_CIL_STATUS);
+ if (pp | cil) {
+ dev_warn(csi->dev, "Calibration status not been cleared!\n");
+ ret = -EINVAL;
+ goto exit;
+ }
+
+exit:
+ tegra20_mipi_write(csi, TEGRA_CSI_CSI_CIL_STATUS, pp);
+
+ /* un-select to avoid interference with DSI */
+ tegra20_mipi_write(csi, TEGRA_CSI_CILB_MIPI_CAL_CONFIG,
+ CSI_CIL_MIPI_CAL_HSPDOS(0) |
+ CSI_CIL_MIPI_CAL_HSPUOS(0) |
+ CSI_CIL_MIPI_CAL_TERMOS(4));
+
+ tegra20_mipi_write(csi, TEGRA_CSI_CILA_MIPI_CAL_CONFIG,
+ CSI_CIL_MIPI_CAL_NOISE_FLT(0xa) |
+ CSI_CIL_MIPI_CAL_PRESCALE(0x2) |
+ CSI_CIL_MIPI_CAL_HSPDOS(0) |
+ CSI_CIL_MIPI_CAL_HSPUOS(0) |
+ CSI_CIL_MIPI_CAL_TERMOS(4));
+
+ pm_runtime_put(csi->dev);
+
+ return ret;
+}
+
+static const struct tegra_mipi_ops tegra20_mipi_ops = {
+ .start_calibration = tegra20_start_pad_calibration,
+ .finish_calibration = tegra20_finish_pad_calibration,
+};
+
+/* --------------------------------------------------------------------------
+ * CSI
+ */
+static void tegra20_csi_capture_clean(struct tegra_csi_channel *csi_chan)
+{
+ tegra20_csi_write(csi_chan, TEGRA_CSI_VI_INPUT_STREAM_CONTROL, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_HOST_INPUT_STREAM_CONTROL, 0);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_CIL_STATUS, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_PIXEL_PARSER_INTERRUPT_MASK, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_CIL_INTERRUPT_MASK, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_READONLY_STATUS, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_ESCAPE_MODE_COMMAND, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_ESCAPE_MODE_DATA, 0);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CIL_PAD_CONFIG, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CIL_MIPI_CAL_STATUS, 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CLKEN_OVERRIDE, 0);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_DEBUG_CONTROL,
+ CSI_DEBUG_CONTROL_CLR_DBG_CNT_0 |
+ CSI_DEBUG_CONTROL_CLR_DBG_CNT_1 |
+ CSI_DEBUG_CONTROL_CLR_DBG_CNT_2);
+}
+
+static int tegra20_csi_port_start_streaming(struct tegra_csi_channel *csi_chan,
+ u8 portno)
+{
+ struct tegra_vi_channel *vi_chan = v4l2_get_subdev_hostdata(&csi_chan->subdev);
+ int width = vi_chan->format.width;
+ int height = vi_chan->format.height;
+ u32 data_type = vi_chan->fmtinfo->img_dt;
+ u32 word_count = (width * vi_chan->fmtinfo->bit_width) / 8;
+ enum tegra_vi_out output_channel = TEGRA_VI_OUT_1;
+
+ unsigned int main_output_format, yuv_output_format;
+ unsigned int port = portno & 1;
+ u32 value;
+
+ tegra20_vi_get_output_formats(vi_chan, &main_output_format, &yuv_output_format);
+
+ switch (data_type) {
+ case TEGRA_IMAGE_DT_RAW8:
+ case TEGRA_IMAGE_DT_RAW10:
+ output_channel = TEGRA_VI_OUT_2;
+ if (port == PORT_A)
+ main_output_format = VI_OUTPUT_OUTPUT_FORMAT_CSI_PPA_BAYER;
+ else
+ main_output_format = VI_OUTPUT_OUTPUT_FORMAT_CSI_PPB_BAYER;
+ break;
+ }
+
+ tegra20_csi_capture_clean(csi_chan);
+
+ /* CSI port cleanup */
+ tegra20_csi_write(csi_chan, TEGRA_CSI_INPUT_STREAM_CONTROL(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_CONTROL0(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_CONTROL1(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_WORD_COUNT(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_GAP(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PHY_CIL_CONTROL0(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CIL_PAD_CONFIG0(port), 0);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CIL_PAD_CONFIG1(port), 0);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_VI_CORE_CONTROL, BIT(25 + port)); /* CSI_PP_YUV422 */
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_H_DOWNSCALE_CONTROL, BIT(2 + port)); /* CSI_PP */
+ tegra20_vi_write(vi_chan, TEGRA_VI_V_DOWNSCALE_CONTROL, BIT(2 + port)); /* CSI_PP */
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_CSI_PP_H_ACTIVE(port), width << 16);
+ tegra20_vi_write(vi_chan, TEGRA_VI_CSI_PP_V_ACTIVE(port), height << 16);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_CONTROL1(port), 0x1);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_WORD_COUNT(port), word_count);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_GAP(port),
+ CSI_PP_FRAME_MIN_GAP(0x14)); /* 14 vi clks between frames */
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_EXPECTED_FRAME(port),
+ CSI_PP_EXP_FRAME_HEIGHT(height) |
+ CSI_PP_MAX_CLOCKS(0x300) | /* wait 0x300 vi clks for timeout */
+ CSI_PP_LINE_TIMEOUT_ENABLE);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_CONTROL0(port),
+ CSI_PP_OUTPUT_FORMAT_PIXEL |
+ CSI_PP_DATA_TYPE(data_type) |
+ CSI_PP_CRC_CHECK_ENABLE |
+ CSI_PP_WORD_COUNT_HEADER |
+ CSI_PP_DATA_IDENTIFIER_ENABLE |
+ CSI_PP_PACKET_HEADER_SENT |
+ port);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_INPUT_STREAM_CONTROL(port),
+ CSI_SKIP_PACKET_THRESHOLD(0x3f) |
+ (csi_chan->numlanes - 1));
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PHY_CIL_CONTROL0(port),
+ CSI_CONTINUOUS_CLOCK_MODE_ENABLE |
+ 0x5); /* Clock settle time */
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_CSI_PP_FRAME_START(port),
+ VI_CONT_SYNCPT_OUT_CONTINUOUS_SYNCPT |
+ host1x_syncpt_id(vi_chan->frame_start_sp[0])
+ << VI_CONT_SYNCPT_OUT_SYNCPT_IDX_SFT);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_CONT_SYNCPT_OUT(output_channel),
+ VI_CONT_SYNCPT_OUT_CONTINUOUS_SYNCPT |
+ host1x_syncpt_id(vi_chan->mw_ack_sp[0])
+ << VI_CONT_SYNCPT_OUT_SYNCPT_IDX_SFT);
+
+ value = (port == PORT_A) ? CSI_A_PHY_CIL_ENABLE | CSI_B_PHY_CIL_DISABLE :
+ CSI_B_PHY_CIL_ENABLE | CSI_A_PHY_CIL_DISABLE;
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PHY_CIL_COMMAND, value);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
+ CSI_PP_START_MARKER_FRAME_MAX(0xf) |
+ CSI_PP_DISABLE);
+
+ tegra20_vi_write(vi_chan, TEGRA_VI_VI_OUTPUT_CONTROL(output_channel),
+ (vi_chan->vflip ? VI_OUTPUT_V_DIRECTION : 0) |
+ (vi_chan->hflip ? VI_OUTPUT_H_DIRECTION : 0) |
+ yuv_output_format | main_output_format);
+
+ return 0;
+};
+
+static void tegra20_csi_port_stop_streaming(struct tegra_csi_channel *csi_chan, u8 portno)
+{
+ struct tegra_csi *csi = csi_chan->csi;
+ unsigned int port = portno & 1;
+ u32 value;
+
+ value = tegra20_csi_read(csi_chan, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS);
+ dev_dbg(csi->dev, "TEGRA_CSI_CSI_PIXEL_PARSER_STATUS 0x%08x\n", value);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_PIXEL_PARSER_STATUS, value);
+
+ value = tegra20_csi_read(csi_chan, TEGRA_CSI_CSI_CIL_STATUS);
+ dev_dbg(csi->dev, "TEGRA_CSI_CSI_CIL_STATUS 0x%08x\n", value);
+ tegra20_csi_write(csi_chan, TEGRA_CSI_CSI_CIL_STATUS, value);
+
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PIXEL_STREAM_PP_COMMAND(port),
+ CSI_PP_START_MARKER_FRAME_MAX(0xf) |
+ CSI_PP_DISABLE);
+
+ if (csi_chan->numlanes == 4) {
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PHY_CIL_COMMAND,
+ CSI_A_PHY_CIL_DISABLE | CSI_B_PHY_CIL_DISABLE);
+ } else {
+ value = (port == PORT_A) ? CSI_A_PHY_CIL_DISABLE | CSI_B_PHY_CIL_NOP :
+ CSI_B_PHY_CIL_DISABLE | CSI_A_PHY_CIL_NOP;
+ tegra20_csi_write(csi_chan, TEGRA_CSI_PHY_CIL_COMMAND, value);
+ }
+}
+
+static int tegra20_csi_start_streaming(struct tegra_csi_channel *csi_chan)
+{
+ u8 *portnos = csi_chan->csi_port_nums;
+ int ret, i;
+
+ for (i = 0; i < csi_chan->numgangports; i++) {
+ ret = tegra20_csi_port_start_streaming(csi_chan, portnos[i]);
+ if (ret)
+ goto stream_start_fail;
+ }
+
+ return 0;
+
+stream_start_fail:
+ for (i = i - 1; i >= 0; i--)
+ tegra20_csi_port_stop_streaming(csi_chan, portnos[i]);
+
+ return ret;
+}
+
+static void tegra20_csi_stop_streaming(struct tegra_csi_channel *csi_chan)
+{
+ u8 *portnos = csi_chan->csi_port_nums;
+ int i;
+
+ for (i = 0; i < csi_chan->numgangports; i++)
+ tegra20_csi_port_stop_streaming(csi_chan, portnos[i]);
+}
+
+static const struct tegra_csi_ops tegra20_csi_ops = {
+ .csi_start_streaming = tegra20_csi_start_streaming,
+ .csi_stop_streaming = tegra20_csi_stop_streaming,
+};
+
+static const char * const tegra20_csi_clks[] = {
+ NULL,
+};
+
+const struct tegra_csi_soc tegra20_csi_soc = {
+ .ops = &tegra20_csi_ops,
+ .mipi_ops = &tegra20_mipi_ops,
+ .csi_max_channels = 2, /* CSI-A and CSI-B */
+ .clk_names = tegra20_csi_clks,
+ .num_clks = ARRAY_SIZE(tegra20_csi_clks),
+};
+
+static const char * const tegra30_csi_clks[] = {
+ "csi",
+ "csia-pad",
+ "csib-pad",
+};
+
+const struct tegra_csi_soc tegra30_csi_soc = {
+ .ops = &tegra20_csi_ops,
+ .mipi_ops = &tegra20_mipi_ops,
+ .csi_max_channels = 2, /* CSI-A and CSI-B */
+ .clk_names = tegra30_csi_clks,
+ .num_clks = ARRAY_SIZE(tegra30_csi_clks),
+};
+
/* --------------------------------------------------------------------------
* VIP
*/
@@ -687,10 +1199,11 @@ static int tegra20_vip_start_streaming(struct tegra_vip_channel *vip_chan)
enum tegra_vi_out output_channel = (data_type == TEGRA_IMAGE_DT_RAW8 ||
data_type == TEGRA_IMAGE_DT_RAW10) ?
TEGRA_VI_OUT_2 : TEGRA_VI_OUT_1;
- unsigned int main_input_format;
- unsigned int yuv_input_format;
+ unsigned int main_input_format, yuv_input_format;
+ unsigned int main_output_format, yuv_output_format;
tegra20_vi_get_input_formats(vi_chan, &main_input_format, &yuv_input_format);
+ tegra20_vi_get_output_formats(vi_chan, &main_output_format, &yuv_output_format);
tegra20_vi_write(vi_chan, TEGRA_VI_VI_CORE_CONTROL, 0);
@@ -723,6 +1236,11 @@ static int tegra20_vip_start_streaming(struct tegra_vip_channel *vip_chan)
tegra20_vi_write(vi_chan, TEGRA_VI_CAMERA_CONTROL, VI_CAMERA_CONTROL_STOP_CAPTURE);
+ tegra20_vi_write(vi_chan, TEGRA_VI_VI_OUTPUT_CONTROL(output_channel),
+ (vi_chan->vflip ? VI_OUTPUT_V_DIRECTION : 0) |
+ (vi_chan->hflip ? VI_OUTPUT_H_DIRECTION : 0) |
+ yuv_output_format | main_output_format);
+
return 0;
}
diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h
index bfadde8858d4..46328e488aa3 100644
--- a/drivers/staging/media/tegra-video/vi.h
+++ b/drivers/staging/media/tegra-video/vi.h
@@ -125,7 +125,6 @@ struct tegra_vi {
* frame through host1x syncpoint counters (On Tegra20 used for the
* OUT_1 syncpt)
* @sp_incr_lock: protects cpu syncpoint increment.
- * @next_out_sp_idx: next expected value for mw_ack_sp[0], i.e. OUT_1 (Tegra20)
*
* @kthread_start_capture: kthread to start capture of single frame when
* vb buffer is available. This thread programs VI CSI hardware
@@ -188,7 +187,6 @@ struct tegra_vi_channel {
struct host1x_syncpt *mw_ack_sp[GANG_PORTS_MAX];
/* protects the cpu syncpoint increment */
spinlock_t sp_incr_lock[GANG_PORTS_MAX];
- u32 next_out_sp_idx;
struct task_struct *kthread_start_capture;
wait_queue_head_t start_wait;
diff --git a/drivers/staging/media/tegra-video/video.c b/drivers/staging/media/tegra-video/video.c
index 6fe8d5301b9c..9f2bddc460bf 100644
--- a/drivers/staging/media/tegra-video/video.c
+++ b/drivers/staging/media/tegra-video/video.c
@@ -127,6 +127,12 @@ static const struct of_device_id host1x_video_subdevs[] = {
{ .compatible = "nvidia,tegra20-vip", },
{ .compatible = "nvidia,tegra20-vi", },
#endif
+#if defined(CONFIG_ARCH_TEGRA_2x_SOC)
+ { .compatible = "nvidia,tegra20-csi", },
+#endif
+#if defined(CONFIG_ARCH_TEGRA_3x_SOC)
+ { .compatible = "nvidia,tegra30-csi", },
+#endif
#if defined(CONFIG_ARCH_TEGRA_210_SOC)
{ .compatible = "nvidia,tegra210-csi", },
{ .compatible = "nvidia,tegra210-vi", },
--
2.48.1
^ permalink raw reply related [flat|nested] 40+ messages in thread