diff options
Diffstat (limited to 'drivers/media/platform/qcom/camss/camss.c')
-rw-r--r-- | drivers/media/platform/qcom/camss/camss.c | 61 |
1 files changed, 38 insertions, 23 deletions
diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c index 1118c40886d5..9cda284f1e71 100644 --- a/drivers/media/platform/qcom/camss/camss.c +++ b/drivers/media/platform/qcom/camss/camss.c @@ -1170,7 +1170,7 @@ static int camss_init_subdevices(struct camss *camss) } /* note: SM8250 requires VFE to be initialized before CSID */ - for (i = 0; i < camss->vfe_num; i++) { + for (i = 0; i < camss->vfe_num + camss->vfe_lite_num; i++) { ret = msm_vfe_subdev_init(camss, &camss->vfe[i], &vfe_res[i], i); if (ret < 0) { @@ -1242,7 +1242,7 @@ static int camss_register_entities(struct camss *camss) goto err_reg_ispif; } - for (i = 0; i < camss->vfe_num; i++) { + for (i = 0; i < camss->vfe_num + camss->vfe_lite_num; i++) { ret = msm_vfe_register_entities(&camss->vfe[i], &camss->v4l2_dev); if (ret < 0) { @@ -1314,7 +1314,7 @@ static int camss_register_entities(struct camss *camss) } } else { for (i = 0; i < camss->csid_num; i++) - for (k = 0; k < camss->vfe_num; k++) + for (k = 0; k < camss->vfe_num + camss->vfe_lite_num; k++) for (j = 0; j < camss->vfe[k].line_num; j++) { struct v4l2_subdev *csid = &camss->csid[i].subdev; struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev; @@ -1338,7 +1338,7 @@ static int camss_register_entities(struct camss *camss) return 0; err_link: - i = camss->vfe_num; + i = camss->vfe_num + camss->vfe_lite_num; err_reg_vfe: for (i--; i >= 0; i--) msm_vfe_unregister_entities(&camss->vfe[i]); @@ -1377,7 +1377,7 @@ static void camss_unregister_entities(struct camss *camss) msm_ispif_unregister_entities(camss->ispif); - for (i = 0; i < camss->vfe_num; i++) + for (i = 0; i < camss->vfe_num + camss->vfe_lite_num; i++) msm_vfe_unregister_entities(&camss->vfe[i]); } @@ -1453,7 +1453,6 @@ static const struct media_device_ops camss_media_ops = { static int camss_configure_pd(struct camss *camss) { struct device *dev = camss->dev; - int last_pm_domain = 0; int i; int ret; @@ -1465,6 +1464,14 @@ static int camss_configure_pd(struct camss *camss) return camss->genpd_num; } + /* + * If a platform device has just one power domain, then it is attached + * at platform_probe() level, thus there shall be no need and even no + * option to attach it again, this is the case for CAMSS on MSM8916. + */ + if (camss->genpd_num == 1) + return 0; + camss->genpd = devm_kmalloc_array(dev, camss->genpd_num, sizeof(*camss->genpd), GFP_KERNEL); if (!camss->genpd) @@ -1476,32 +1483,34 @@ static int camss_configure_pd(struct camss *camss) if (!camss->genpd_link) return -ENOMEM; + /* + * VFE power domains are in the beginning of the list, and while all + * power domains should be attached, only if TITAN_TOP power domain is + * found in the list, it should be linked over here. + */ for (i = 0; i < camss->genpd_num; i++) { camss->genpd[i] = dev_pm_domain_attach_by_id(camss->dev, i); if (IS_ERR(camss->genpd[i])) { ret = PTR_ERR(camss->genpd[i]); goto fail_pm; } + } - camss->genpd_link[i] = device_link_add(camss->dev, camss->genpd[i], - DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME | - DL_FLAG_RPM_ACTIVE); - if (!camss->genpd_link[i]) { - dev_pm_domain_detach(camss->genpd[i], true); + if (i > camss->vfe_num) { + camss->genpd_link[i - 1] = device_link_add(camss->dev, camss->genpd[i - 1], + DL_FLAG_STATELESS | DL_FLAG_PM_RUNTIME | + DL_FLAG_RPM_ACTIVE); + if (!camss->genpd_link[i - 1]) { ret = -EINVAL; goto fail_pm; } - - last_pm_domain = i; } return 0; fail_pm: - for (i = 0; i < last_pm_domain; i++) { - device_link_del(camss->genpd_link[i]); + for (--i ; i >= 0; i--) dev_pm_domain_detach(camss->genpd[i], true); - } return ret; } @@ -1571,13 +1580,15 @@ static int camss_probe(struct platform_device *pdev) camss->version = CAMSS_845; camss->csiphy_num = 4; camss->csid_num = 3; - camss->vfe_num = 3; + camss->vfe_num = 2; + camss->vfe_lite_num = 1; } else if (of_device_is_compatible(dev->of_node, "qcom,sm8250-camss")) { camss->version = CAMSS_8250; camss->csiphy_num = 6; camss->csid_num = 4; - camss->vfe_num = 4; + camss->vfe_num = 2; + camss->vfe_lite_num = 2; } else { return -EINVAL; } @@ -1599,8 +1610,8 @@ static int camss_probe(struct platform_device *pdev) return -ENOMEM; } - camss->vfe = devm_kcalloc(dev, camss->vfe_num, sizeof(*camss->vfe), - GFP_KERNEL); + camss->vfe = devm_kcalloc(dev, camss->vfe_num + camss->vfe_lite_num, + sizeof(*camss->vfe), GFP_KERNEL); if (!camss->vfe) return -ENOMEM; @@ -1698,10 +1709,14 @@ void camss_delete(struct camss *camss) pm_runtime_disable(camss->dev); - for (i = 0; i < camss->genpd_num; i++) { - device_link_del(camss->genpd_link[i]); + if (camss->genpd_num == 1) + return; + + if (camss->genpd_num > camss->vfe_num) + device_link_del(camss->genpd_link[camss->genpd_num - 1]); + + for (i = 0; i < camss->genpd_num; i++) dev_pm_domain_detach(camss->genpd[i], true); - } } /* |