diff mbox series

[04/10] media: qcom: camss: populate CAMSS children subdevices of CSIPHY IPs

Message ID 20250612011531.2923701-5-vladimir.zapolskiy@linaro.org
State New
Headers show
Series media: qcom: camss: add support for csiphy devices | expand

Commit Message

Vladimir Zapolskiy June 12, 2025, 1:15 a.m. UTC
To add a number of CSIPHY devices under CAMSS device tree node populate
the children devices, if they are present, and exclude handling of such
discovered CSIPHY devices in runtime from the CAMSS device driver.

Signed-off-by: Vladimir Zapolskiy <vladimir.zapolskiy@linaro.org>
---
 .../media/platform/qcom/camss/camss-csiphy.h  |  1 +
 drivers/media/platform/qcom/camss/camss.c     | 77 ++++++++++++++++++-
 2 files changed, 74 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/drivers/media/platform/qcom/camss/camss-csiphy.h b/drivers/media/platform/qcom/camss/camss-csiphy.h
index 3b73248f1364..f092b7ff2f26 100644
--- a/drivers/media/platform/qcom/camss/camss-csiphy.h
+++ b/drivers/media/platform/qcom/camss/camss-csiphy.h
@@ -91,6 +91,7 @@  struct csiphy_device_regs {
 };
 
 struct csiphy_device {
+	struct device *dev;
 	struct camss *camss;
 	u8 id;
 	struct v4l2_subdev subdev;
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c
index 695f113472a5..71a37447e17a 100644
--- a/drivers/media/platform/qcom/camss/camss.c
+++ b/drivers/media/platform/qcom/camss/camss.c
@@ -16,6 +16,7 @@ 
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/of_graph.h>
+#include <linux/of_platform.h>
 #include <linux/pm_runtime.h>
 #include <linux/pm_domain.h>
 #include <linux/slab.h>
@@ -3059,6 +3060,47 @@  static int camss_parse_ports(struct camss *camss)
 	return ret;
 }
 
+static void camss_csiphy_put(struct camss *camss)
+{
+	unsigned int i;
+
+	for (i = 0; i < camss->res->csiphy_num; i++)
+		put_device(camss->csiphy[i].dev);
+}
+
+static void camss_csiphy_get(struct camss *camss)
+{
+	struct device_node *camss_node = dev_of_node(camss->dev);
+	unsigned int i;
+	int phys;
+
+	phys = of_count_phandle_with_args(camss_node, "phys", NULL);
+	if (phys < 0)
+		return;
+
+	if (phys != camss->res->csiphy_num)
+		dev_info(camss->dev, "Number of phys is unexpected\n");
+
+	for (i = 0; i < camss->res->csiphy_num; i++) {
+		struct platform_device *phy_pdev;
+		struct device_node *phy_node;
+
+		phy_node = of_parse_phandle(camss_node, "phys", i);
+		if (!phy_node ||
+		    !of_node_name_eq(phy_node, "phy") ||
+		    !of_device_is_available(phy_node))
+			continue;
+
+		/* At this point it shall be possible to reference the phy */
+		phy_pdev = of_find_device_by_node(phy_node);
+		of_node_put(phy_node);
+		if (!phy_pdev)
+			continue;
+
+		camss->csiphy[i].dev = &phy_pdev->dev;
+	}
+}
+
 /*
  * camss_init_subdevices - Initialize subdev structures and resources
  * @camss: CAMSS device
@@ -3073,6 +3115,10 @@  static int camss_init_subdevices(struct camss *camss)
 	int ret;
 
 	for (i = 0; i < camss->res->csiphy_num; i++) {
+		/* Initialize only non-registered CSIPHY subdevices */
+		if (camss->csiphy[i].dev)
+			continue;
+
 		ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i],
 					     res->csiphy_res[i].csiphy.id);
 		if (ret < 0) {
@@ -3155,6 +3201,9 @@  static int camss_link_entities(struct camss *camss)
 	int ret;
 
 	for (i = 0; i < camss->res->csiphy_num; i++) {
+		if (camss->csiphy[i].dev)
+			continue;
+
 		for (j = 0; j < camss->res->csid_num; j++) {
 			ret = media_create_pad_link(&camss->csiphy[i].subdev.entity,
 						    MSM_CSIPHY_PAD_SRC,
@@ -3265,6 +3314,9 @@  static int camss_register_entities(struct camss *camss)
 	int ret;
 
 	for (i = 0; i < camss->res->csiphy_num; i++) {
+		if (camss->csiphy[i].dev)
+			continue;
+
 		ret = msm_csiphy_register_entity(&camss->csiphy[i],
 						 &camss->v4l2_dev);
 		if (ret < 0) {
@@ -3321,7 +3373,8 @@  static int camss_register_entities(struct camss *camss)
 	i = camss->res->csiphy_num;
 err_reg_csiphy:
 	for (i--; i >= 0; i--)
-		msm_csiphy_unregister_entity(&camss->csiphy[i]);
+		if (!camss->csiphy[i].dev)
+			msm_csiphy_unregister_entity(&camss->csiphy[i]);
 
 	return ret;
 }
@@ -3337,7 +3390,8 @@  static void camss_unregister_entities(struct camss *camss)
 	unsigned int i;
 
 	for (i = 0; i < camss->res->csiphy_num; i++)
-		msm_csiphy_unregister_entity(&camss->csiphy[i]);
+		if (!camss->csiphy[i].dev)
+			msm_csiphy_unregister_entity(&camss->csiphy[i]);
 
 	for (i = 0; i < camss->res->csid_num; i++)
 		msm_csid_unregister_entity(&camss->csid[i]);
@@ -3379,6 +3433,9 @@  static int camss_subdev_notifier_complete(struct v4l2_async_notifier *async)
 		if (!csiphy)
 			continue;
 
+		if (csiphy->dev)
+			continue;
+
 		input = &csiphy->subdev.entity;
 		sensor = &sd->entity;
 
@@ -3585,13 +3642,22 @@  static int camss_probe(struct platform_device *pdev)
 		return ret;
 	}
 
+	ret = devm_of_platform_populate(camss->dev);
+	if (ret) {
+		dev_err(camss->dev,
+			"Failed to populate camss children devices: %d\n", ret);
+		goto err_genpd_cleanup;
+	}
+
+	camss_csiphy_get(camss);
+
 	ret = camss_init_subdevices(camss);
 	if (ret < 0)
-		goto err_genpd_cleanup;
+		goto err_csiphy_put;
 
 	ret = dma_set_mask_and_coherent(dev, 0xffffffff);
 	if (ret)
-		goto err_genpd_cleanup;
+		goto err_csiphy_put;
 
 	camss->media_dev.dev = camss->dev;
 	strscpy(camss->media_dev.model, "Qualcomm Camera Subsystem",
@@ -3648,6 +3714,8 @@  static int camss_probe(struct platform_device *pdev)
 	pm_runtime_disable(dev);
 err_media_device_cleanup:
 	media_device_cleanup(&camss->media_dev);
+err_csiphy_put:
+	camss_csiphy_put(camss);
 err_genpd_cleanup:
 	camss_genpd_cleanup(camss);
 
@@ -3680,6 +3748,7 @@  static void camss_remove(struct platform_device *pdev)
 	if (atomic_read(&camss->ref_count) == 0)
 		camss_delete(camss);
 
+	camss_csiphy_put(camss);
 	camss_genpd_cleanup(camss);
 }