[PATCH v2 54/66] media: sun6i-csi: Add support for MIPI CSI-2 to the bridge code

From: Paul Kocialkowski
Date: Sat Feb 05 2022 - 13:58:16 EST


Introduce MIPI CSI-2 support to the bridge with a new port, source
and hardware configuration helper.

Signed-off-by: Paul Kocialkowski <paul.kocialkowski@xxxxxxxxxxx>
---
.../platform/sunxi/sun6i-csi/sun6i_csi.h | 1 +
.../sunxi/sun6i-csi/sun6i_csi_bridge.c | 35 +++++++++++++++++--
.../sunxi/sun6i-csi/sun6i_csi_bridge.h | 1 +
3 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h
index d7082e951b06..3c08b2712215 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi.h
@@ -21,6 +21,7 @@

enum sun6i_csi_port {
SUN6I_CSI_PORT_PARALLEL = 0,
+ SUN6I_CSI_PORT_MIPI_CSI2 = 1,
};

struct sun6i_csi_buffer {
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
index f5303842d169..b631220dd682 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.c
@@ -226,7 +226,7 @@ static void sun6i_csi_bridge_disable(struct sun6i_csi_device *csi_dev)
}

static void
-sun6i_csi_bridge_configure_interface(struct sun6i_csi_device *csi_dev)
+sun6i_csi_bridge_configure_parallel(struct sun6i_csi_device *csi_dev)
{
struct device *dev = csi_dev->dev;
struct regmap *regmap = csi_dev->regmap;
@@ -316,6 +316,25 @@ sun6i_csi_bridge_configure_interface(struct sun6i_csi_device *csi_dev)
regmap_write(regmap, SUN6I_CSI_IF_CFG_REG, value);
}

+static void
+sun6i_csi_bridge_configure_mipi_csi2(struct sun6i_csi_device *csi_dev)
+{
+ struct regmap *regmap = csi_dev->regmap;
+ u32 value = SUN6I_CSI_IF_CFG_IF_MIPI;
+ u32 field;
+
+ sun6i_csi_bridge_format(csi_dev, NULL, &field);
+
+ if (field == V4L2_FIELD_INTERLACED ||
+ field == V4L2_FIELD_INTERLACED_TB ||
+ field == V4L2_FIELD_INTERLACED_BT)
+ value |= SUN6I_CSI_IF_CFG_SRC_TYPE_INTERLACED;
+ else
+ value |= SUN6I_CSI_IF_CFG_SRC_TYPE_PROGRESSIVE;
+
+ regmap_write(regmap, SUN6I_CSI_IF_CFG_REG, value);
+}
+
static void sun6i_csi_bridge_configure_format(struct sun6i_csi_device *csi_dev)
{
struct regmap *regmap = csi_dev->regmap;
@@ -369,7 +388,11 @@ static void sun6i_csi_bridge_configure_format(struct sun6i_csi_device *csi_dev)

static void sun6i_csi_bridge_configure(struct sun6i_csi_device *csi_dev)
{
- sun6i_csi_bridge_configure_interface(csi_dev);
+ if (csi_dev->bridge.source == &csi_dev->bridge.source_parallel)
+ sun6i_csi_bridge_configure_parallel(csi_dev);
+ else if (csi_dev->bridge.source == &csi_dev->bridge.source_mipi_csi2)
+ sun6i_csi_bridge_configure_mipi_csi2(csi_dev);
+
sun6i_csi_bridge_configure_format(csi_dev);
}

@@ -552,6 +575,8 @@ static int sun6i_csi_bridge_link_validate(struct media_link *link)

if (source_subdev == bridge->source_parallel.subdev)
bridge->source = &bridge->source_parallel;
+ else if (source_subdev == bridge->source_mipi_csi2.subdev)
+ bridge->source = &bridge->source_mipi_csi2;
else
return -EINVAL;

@@ -638,6 +663,10 @@ sun6i_csi_bridge_notifier_bound(struct v4l2_async_notifier *notifier,
source = &bridge->source_parallel;
enabled = true;
break;
+ case SUN6I_CSI_PORT_MIPI_CSI2:
+ source = &bridge->source_mipi_csi2;
+ enabled = !bridge->source_parallel.expected;
+ break;
default:
break;
}
@@ -784,6 +813,8 @@ int sun6i_csi_bridge_setup(struct sun6i_csi_device *csi_dev)
sun6i_csi_bridge_source_setup(csi_dev, &bridge->source_parallel,
SUN6I_CSI_PORT_PARALLEL,
parallel_mbus_types);
+ sun6i_csi_bridge_source_setup(csi_dev, &bridge->source_mipi_csi2,
+ SUN6I_CSI_PORT_MIPI_CSI2, NULL);

ret = v4l2_async_nf_register(v4l2_dev, notifier);
if (ret) {
diff --git a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
index 079227c02482..e59c40611872 100644
--- a/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
+++ b/drivers/media/platform/sunxi/sun6i-csi/sun6i_csi_bridge.h
@@ -40,6 +40,7 @@ struct sun6i_csi_bridge {
struct v4l2_mbus_framefmt mbus_format;

struct sun6i_csi_bridge_source source_parallel;
+ struct sun6i_csi_bridge_source source_mipi_csi2;
struct sun6i_csi_bridge_source *source;
};

--
2.34.1