staging: media: tegra-video: add CSI support for Tegra20 and Tegra30

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).

Tested-by: Luca Ceresoli <luca.ceresoli@bootlin.com> # tegra20, parallel camera
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>
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: Hans Verkuil <hverkuil+cisco@kernel.org>
This commit is contained in:
Svyatoslav Ryhel
2026-03-19 08:18:36 +01:00
committed by Hans Verkuil
parent d974a67033
commit 0e2c4117c3
5 changed files with 609 additions and 48 deletions
+17
View File
@@ -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);
@@ -859,6 +870,12 @@ static void tegra_csi_remove(struct platform_device *pdev)
}
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
+10
View File
@@ -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;
@@ -130,6 +132,12 @@ struct tegra_csi_soc {
unsigned int tpg_frmrate_table_size;
};
#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
@@ -144,6 +152,7 @@ extern const struct tegra_csi_soc tegra210_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 {
@@ -154,6 +163,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;
};
File diff suppressed because it is too large Load Diff
-2
View File
@@ -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;
@@ -125,6 +125,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", },