[v4 3/6] media: platform: dwc: Add MIPI CSI-2 platform data

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This allows the driver loading via platform data which makes the driver
not device tree dependent.

Signed-off-by: Luis Oliveira <luis.oliveira@xxxxxxxxxxxx>
---
Changelog
v3-v4
- not present on v3, allows configuration using pdata

 MAINTAINERS                              |   1 +
 drivers/media/platform/dwc/dw-csi-plat.c | 105 +++++++++++++++++++++----------
 include/media/dwc/dw-csi-data.h          |  26 ++++++++
 3 files changed, 100 insertions(+), 32 deletions(-)
 create mode 100644 include/media/dwc/dw-csi-data.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 6ffe4fd..2df1f7c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15193,6 +15193,7 @@ L:	linux-media@xxxxxxxxxxxxxxx
 T:	git git://linuxtv.org/media_tree.git
 S:	Maintained
 F:	drivers/media/platform/dwc
+F:	include/media/dwc/dw-csi-data.h
 F:	Documentation/devicetree/bindings/media/snps,dw-csi.txt
 
 SYNOPSYS DESIGNWARE DMAC DRIVER
diff --git a/drivers/media/platform/dwc/dw-csi-plat.c b/drivers/media/platform/dwc/dw-csi-plat.c
index 9828d55..c7117c6 100644
--- a/drivers/media/platform/dwc/dw-csi-plat.c
+++ b/drivers/media/platform/dwc/dw-csi-plat.c
@@ -8,6 +8,7 @@
  * Author: Luis Oliveira <luis.oliveira@xxxxxxxxxxxx>
  */
 
+#include <media/dwc/dw-csi-data.h>
 #include <media/dwc/dw-dphy-data.h>
 
 #include "dw-csi-plat.h"
@@ -312,12 +313,16 @@ static const struct of_device_id dw_mipi_csi_of_match[];
 static int dw_csi_probe(struct platform_device *pdev)
 {
 	const struct of_device_id *of_id = NULL;
+	struct dw_csih_pdata *pdata;
 	struct device *dev = &pdev->dev;
 	struct resource *res = NULL;
 	struct dw_csi *csi;
 	struct v4l2_subdev *sd;
 	int ret;
 
+	if (!IS_ENABLED(CONFIG_OF))
+		pdata = pdev->dev.platform_data;
+
 	dev_vdbg(dev, "Probing started\n");
 
 	/* Resource allocation */
@@ -329,18 +334,29 @@ static int dw_csi_probe(struct platform_device *pdev)
 	spin_lock_init(&csi->slock);
 	csi->dev = dev;
 
-	of_id = of_match_node(dw_mipi_csi_of_match, dev->of_node);
-	if (!of_id)
-		return -EINVAL;
+	if (dev->of_node) {
+		of_id = of_match_node(dw_mipi_csi_of_match, dev->of_node);
+		if (!of_id)
+			return -EINVAL;
 
-	ret = dw_mipi_csi_parse_dt(pdev, csi);
-	if (ret < 0)
-		return ret;
+		ret = dw_mipi_csi_parse_dt(pdev, csi);
+		if (ret < 0)
+			return ret;
 
-	csi->phy = devm_of_phy_get(dev, dev->of_node, NULL);
-	if (IS_ERR(csi->phy)) {
-		dev_err(dev, "No DPHY available\n");
-		return PTR_ERR(csi->phy);
+		csi->phy = devm_of_phy_get(dev, dev->of_node, NULL);
+		if (IS_ERR(csi->phy)) {
+			dev_err(dev, "No DPHY available\n");
+			return PTR_ERR(csi->phy);
+		}
+	} else {
+		csi->phy = devm_phy_get(dev, phys[pdata->id].name);
+		if (IS_ERR(csi->phy)) {
+			dev_err(dev, "No '%s' DPHY available\n",
+				phys[pdata->id].name);
+			return PTR_ERR(csi->phy);
+		}
+		dev_vdbg(dev, "got D-PHY %s with id %d\n", phys[pdata->id].name,
+			 csi->phy->id);
 	}
 	/* Registers mapping */
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -370,7 +386,10 @@ static int dw_csi_probe(struct platform_device *pdev)
 			       dw_mipi_csi_irq1, IRQF_SHARED,
 			       dev_name(dev), csi);
 	if (ret) {
-		dev_err(dev, "irq csi %s failed\n", of_id->name);
+		if (dev->of_node)
+			dev_err(dev, "irq csi %s failed\n", of_id->name);
+	else
+		dev_err(dev, "irq csi %d failed\n", pdata->id);
 
 		goto end;
 	}
@@ -379,25 +398,44 @@ static int dw_csi_probe(struct platform_device *pdev)
 	v4l2_subdev_init(sd, &dw_mipi_csi_subdev_ops);
 	csi->sd.owner = THIS_MODULE;
 
-	snprintf(sd->name, sizeof(sd->name), "%s.%d",
-		 "dw-csi", csi->index);
+	if (dev->of_node) {
+		snprintf(sd->name, sizeof(sd->name), "%s.%d",
+			 "dw-csi", csi->index);
 
-	csi->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+		csi->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	} else {
+		strlcpy(sd->name, dev_name(dev), sizeof(sd->name));
+		strlcpy(csi->v4l2_dev.name, dev_name(dev),
+			sizeof(csi->v4l2_dev.name));
+	}
 	csi->fmt = &dw_mipi_csi_formats[0];
 	csi->format.code = dw_mipi_csi_formats[0].mbus_code;
 
 	sd->entity.function = MEDIA_ENT_F_IO_V4L;
-	csi->pads[CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
-	csi->pads[CSI_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
-	ret = media_entity_pads_init(&csi->sd.entity,
-				     CSI_PADS_NUM, csi->pads);
 
-	dev_vdbg(dev, "v4l2.name: %s\n", csi->v4l2_dev.name);
+	if (dev->of_node) {
+		csi->pads[CSI_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+		csi->pads[CSI_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
 
-	if (ret < 0) {
-		dev_err(dev, "media entity init failed\n");
-		goto end;
+		ret = media_entity_pads_init(&csi->sd.entity,
+					     CSI_PADS_NUM, csi->pads);
+		if (ret < 0) {
+			dev_err(dev, "media entity init failed\n");
+			goto end;
+		}
+	} else {
+		csi->hw.num_lanes = pdata->lanes;
+		csi->hw.pclk = pdata->pclk;
+		csi->hw.fps = pdata->fps;
+		csi->hw.dphy_freq = pdata->hs_freq;
+
+		ret = v4l2_device_register(NULL, &csi->v4l2_dev);
+		if (ret) {
+			dev_err(dev, "failed to register v4l2 device\n");
+			goto end;
+		}
 	}
+	dev_vdbg(dev, "v4l2.name: %s\n", csi->v4l2_dev.name);
 
 	v4l2_set_subdevdata(&csi->sd, pdev);
 	platform_set_drvdata(pdev, &csi->sd);
@@ -405,6 +443,7 @@ static int dw_csi_probe(struct platform_device *pdev)
 
 	if (csi->rst)
 		reset_control_deassert(csi->rst);
+
 #if IS_ENABLED(CONFIG_DWC_MIPI_TC_DPHY_GEN3)
 	dw_csi_create_capabilities_sysfs(pdev);
 #endif
@@ -418,11 +457,12 @@ static int dw_csi_probe(struct platform_device *pdev)
 	phy_init(csi->phy);
 
 	return 0;
-
 end:
+#if IS_ENABLED(CONFIG_OF)
 	media_entity_cleanup(&csi->sd.entity);
+	return ret;
+#endif
 	v4l2_device_unregister(csi->vdev.v4l2_dev);
-
 	return ret;
 }
 
@@ -436,35 +476,36 @@ static int dw_csi_remove(struct platform_device *pdev)
 	struct v4l2_subdev *sd = platform_get_drvdata(pdev);
 	struct dw_csi *mipi_csi = sd_to_mipi_csi_dev(sd);
 
-	dev_dbg(&pdev->dev, "Removing MIPI CSI-2 module\n");
+	dev_dbg(&pdev->dev, "Removing DW MIPI CSI-2 Host module\n");
 
 	if (mipi_csi->rst)
 		reset_control_assert(mipi_csi->rst);
+#if IS_ENABLED(CONFIG_OF)
 	media_entity_cleanup(&mipi_csi->sd.entity);
-
+#else
+	v4l2_device_unregister(mipi_csi->vdev.v4l2_dev);
+#endif
 	return 0;
 }
 
-/**
- * @short of_device_id structure
- */
+#if IS_ENABLED(CONFIG_OF)
 static const struct of_device_id dw_mipi_csi_of_match[] = {
 	{ .compatible = "snps,dw-csi" },
 	{},
 };
 
 MODULE_DEVICE_TABLE(of, dw_mipi_csi_of_match);
+#endif
 
-/**
- * @short Platform driver structure
- */
 static struct platform_driver dw_mipi_csi_driver = {
 	.remove = dw_csi_remove,
 	.probe = dw_csi_probe,
 	.driver = {
 		.name = "dw-csi",
 		.owner = THIS_MODULE,
+#if IS_ENABLED(CONFIG_OF)
 		.of_match_table = of_match_ptr(dw_mipi_csi_of_match),
+#endif
 	},
 };
 
diff --git a/include/media/dwc/dw-csi-data.h b/include/media/dwc/dw-csi-data.h
new file mode 100644
index 0000000..87942ab
--- /dev/null
+++ b/include/media/dwc/dw-csi-data.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018-2019 Synopsys, Inc. and/or its affiliates.
+ *
+ * Synopsys DesignWare MIPI CSI-2 platform data
+ *
+ * Author: Luis Oliveira <Luis.Oliveira@xxxxxxxxxxxx>
+ */
+
+#include <linux/kernel.h>
+#include <media/dwc/dw-mipi-csi-pltfrm.h>
+
+struct dw_csih_pdata {
+	u8 eotp_enabled;
+	u32 hs_freq;
+	u32 lanes;
+	u32 pclk;
+	u32 fps;
+	u32 bpp;
+	u8 id;
+};
+
+static const struct pdata_names csis[] = {
+	{ .name = "dw-csi.0", },
+	{ .name = "dw-csi.1", },
+};
-- 
2.7.4





[Index of Archives]     [Linux Input]     [Video for Linux]     [Gstreamer Embedded]     [Mplayer Users]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux