[PATCH v2 10/23] staging: media: tegra-video: csi: add support for SoCs with integrated MIPI calibration

Svyatoslav Ryhel
2025-09-06T13:54:19Z

Tegra20/Tegra30 SoC have MIPI calibration logic integrated into CSI block.
This commit adds support for using the entire CSI block for MIPI
calibration not only for CSI itself but for DSI too.

Signed-off-by: Svyatoslav Ryhel <clamor95@gmail.com>
---
drivers/gpu/host1x/mipi.c | 18 ++++++++---
drivers/staging/media/tegra-video/csi.c | 7 +++-
drivers/staging/media/tegra-video/tegra20.c | 1 +
drivers/staging/media/tegra-video/tegra210.c | 2 +-
drivers/staging/media/tegra-video/vi.h | 3 +-
.../csi.h => include/linux/tegra-csi.h | 6 ++++
include/linux/tegra-mipi-cal.h | 32 +++++++++++++++++++
7 files changed, 61 insertions(+), 8 deletions(-)
rename drivers/staging/media/tegra-video/csi.h => include/linux/tegra-csi.h (95%)

diff --git a/drivers/gpu/host1x/mipi.c b/drivers/gpu/host1x/mipi.c
index 2fa339a428f3..262f71296b75 100644
--- a/drivers/gpu/host1x/mipi.c
+++ b/drivers/gpu/host1x/mipi.c
@@ -215,10 +215,20 @@ struct tegra_mipi_device *tegra_mipi_request(struct device *device,
goto free;
}

- dev->mipi = platform_get_drvdata(dev->pdev);
- if (!dev->mipi) {
- err = -EPROBE_DEFER;
- goto put;
+ /* Tegra20/Tegra30 add CSI structure to MIPI device */
+ if (of_machine_is_compatible("nvidia,tegra20") ||
+ of_machine_is_compatible("nvidia,tegra30")) {
+ dev->csi = platform_get_drvdata(dev->pdev);
+ if (!dev->csi) {
+ err = -EPROBE_DEFER;
+ goto put;
+ }
+ } else {
+ dev->mipi = platform_get_drvdata(dev->pdev);
+ if (!dev->mipi) {
+ err = -EPROBE_DEFER;
+ goto put;
+ }
}

of_node_put(args.np);
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
index 9e3bd6109781..3d1d5e1615c2 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -12,11 +12,11 @@
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
+#include <linux/tegra-csi.h>
#include <linux/tegra-mipi-cal.h>

#include <media/v4l2-fwnode.h>

-#include "csi.h"
#include "video.h"

#define MHZ 1000000
@@ -794,6 +794,11 @@ static int tegra_csi_probe(struct platform_device *pdev)

csi->dev = &pdev->dev;
csi->ops = csi->soc->ops;
+ if (csi->soc->mipi_ops)
+ csi->mipi_ops = csi->soc->mipi_ops;
+
+ mutex_init(&csi->mipi_lock);
+
platform_set_drvdata(pdev, csi);
pm_runtime_enable(&pdev->dev);

diff --git a/drivers/staging/media/tegra-video/tegra20.c b/drivers/staging/media/tegra-video/tegra20.c
index 7b8f8f810b35..461593c49594 100644
--- a/drivers/staging/media/tegra-video/tegra20.c
+++ b/drivers/staging/media/tegra-video/tegra20.c
@@ -16,6 +16,7 @@
#include <linux/host1x.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
+#include <linux/tegra-csi.h>
#include <linux/v4l2-mediabus.h>

#include "vip.h"
diff --git a/drivers/staging/media/tegra-video/tegra210.c b/drivers/staging/media/tegra-video/tegra210.c
index da99f19a39e7..59224c2f9948 100644
--- a/drivers/staging/media/tegra-video/tegra210.c
+++ b/drivers/staging/media/tegra-video/tegra210.c
@@ -13,8 +13,8 @@
#include <linux/delay.h>
#include <linux/host1x.h>
#include <linux/kthread.h>
+#include <linux/tegra-csi.h>

-#include "csi.h"
#include "vi.h"

#define TEGRA210_MIN_WIDTH 32U
diff --git a/drivers/staging/media/tegra-video/vi.h b/drivers/staging/media/tegra-video/vi.h
index cac0c0d0e225..64655ac1b41f 100644
--- a/drivers/staging/media/tegra-video/vi.h
+++ b/drivers/staging/media/tegra-video/vi.h
@@ -12,6 +12,7 @@
#include <linux/mutex.h>
#include <linux/spinlock.h>
#include <linux/wait.h>
+#include <linux/tegra-csi.h>

#include <media/media-entity.h>
#include <media/v4l2-async.h>
@@ -21,8 +22,6 @@
#include <media/v4l2-subdev.h>
#include <media/videobuf2-v4l2.h>

-#include "csi.h"
-
#define V4L2_CID_TEGRA_SYNCPT_TIMEOUT_RETRY (V4L2_CTRL_CLASS_CAMERA | 0x1001)

#define TEGRA_DEF_WIDTH 1920
diff --git a/drivers/staging/media/tegra-video/csi.h b/include/linux/tegra-csi.h
similarity index 95%
rename from drivers/staging/media/tegra-video/csi.h
rename to include/linux/tegra-csi.h
index 3ed2dbc73ce9..b47f48ef7115 100644
--- a/drivers/staging/media/tegra-video/csi.h
+++ b/include/linux/tegra-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;
@@ -139,6 +141,8 @@ struct tegra_csi_soc {
* @clks: clock for CSI and CIL
* @soc: pointer to SoC data structure
* @ops: csi operations
+ * @mipi_ops: MIPI calibration operations
+ * @mipi_lock: for MIPI calibration operations
* @csi_chans: list head for CSI channels
*/
struct tegra_csi {
@@ -148,6 +152,8 @@ struct tegra_csi {
struct clk_bulk_data *clks;
const struct tegra_csi_soc *soc;
const struct tegra_csi_ops *ops;
+ const struct tegra_mipi_ops *mipi_ops;
+ struct mutex mipi_lock;
struct list_head csi_chans;
};

diff --git a/include/linux/tegra-mipi-cal.h b/include/linux/tegra-mipi-cal.h
index 2bfdbfd3cb77..81784b1f2135 100644
--- a/include/linux/tegra-mipi-cal.h
+++ b/include/linux/tegra-mipi-cal.h
@@ -3,6 +3,8 @@
#ifndef __TEGRA_MIPI_CAL_H_
#define __TEGRA_MIPI_CAL_H_

+#include <linux/tegra-csi.h>
+
struct tegra_mipi {
const struct tegra_mipi_soc *soc;
const struct tegra_mipi_ops *ops;
@@ -17,6 +19,7 @@ struct tegra_mipi {
struct tegra_mipi_device {
struct platform_device *pdev;
struct tegra_mipi *mipi;
+ struct tegra_csi *csi;
struct device *device;
unsigned long pads;
};
@@ -69,6 +72,14 @@ static inline int tegra_mipi_enable(struct tegra_mipi_device *device)
return device->mipi->ops->tegra_mipi_enable(device);
}

+ /* Tegra20/Tegra30 have MIPI calibration logic inside CSI block */
+ if (device->csi) {
+ if (!device->csi->mipi_ops->tegra_mipi_enable)
+ return 0;
+
+ return device->csi->mipi_ops->tegra_mipi_enable(device);
+ }
+
return -ENOSYS;
}

@@ -81,6 +92,13 @@ static inline int tegra_mipi_disable(struct tegra_mipi_device *device)
return device->mipi->ops->tegra_mipi_disable(device);
}

+ if (device->csi) {
+ if (!device->csi->mipi_ops->tegra_mipi_disable)
+ return 0;
+
+ return device->csi->mipi_ops->tegra_mipi_disable(device);
+ }
+
return -ENOSYS;
}

@@ -93,6 +111,13 @@ static inline int tegra_mipi_start_calibration(struct tegra_mipi_device *device)
return device->mipi->ops->tegra_mipi_start_calibration(device);
}

+ if (device->csi) {
+ if (!device->csi->mipi_ops->tegra_mipi_start_calibration)
+ return 0;
+
+ return device->csi->mipi_ops->tegra_mipi_start_calibration(device);
+ }
+
return -ENOSYS;
}

@@ -105,6 +130,13 @@ static inline int tegra_mipi_finish_calibration(struct tegra_mipi_device *device
return device->mipi->ops->tegra_mipi_finish_calibration(device);
}

+ if (device->csi) {
+ if (!device->csi->mipi_ops->tegra_mipi_finish_calibration)
+ return 0;
+
+ return device->csi->mipi_ops->tegra_mipi_finish_calibration(device);
+ }
+
return -ENOSYS;
}

--
2.48.1