@@ -91,6 +91,7 @@ struct csiphy_device_regs {
};
struct csiphy_device {
+ struct device *dev;
struct camss *camss;
u8 id;
struct v4l2_subdev subdev;
@@ -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);
}
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(-)