Lines Matching +full:sdm660 +full:- +full:camss
1 // SPDX-License-Identifier: GPL-2.0
3 * camss.c
5 * Qualcomm MSM Camera Subsystem - Core
8 * Copyright (C) 2015-2018 Linaro Ltd.
12 #include <linux/media-bus-format.h>
23 #include <media/media-device.h>
24 #include <media/v4l2-async.h>
25 #include <media/v4l2-device.h>
26 #include <media/v4l2-mc.h>
27 #include <media/v4l2-fwnode.h>
29 #include "camss.h"
546 .regulators = { "vdda-phy", "vdda-pll" },
566 .regulators = { "vdda-phy", "vdda-pll" },
586 .regulators = { "vdda-phy", "vdda-pll" },
646 /* VFE-lite */
726 .regulators = { "vdda-phy", "vdda-pll" },
738 .regulators = { "vdda-phy", "vdda-pll" },
750 .regulators = { "vdda-phy", "vdda-pll" },
761 .regulators = { "vdda-phy", "vdda-pll" },
869 * camss_add_clock_margin - Add margin to clock frequency rate
882 * camss_enable_clocks - Enable multiple clocks
906 for (i--; i >= 0; i--) in camss_enable_clocks()
913 * camss_disable_clocks - Disable multiple clocks
921 for (i = nclocks - 1; i >= 0; i--) in camss_disable_clocks()
926 * camss_find_sensor - Find a linked media entity which represents a sensor
936 pad = &entity->pads[0]; in camss_find_sensor()
937 if (!(pad->flags & MEDIA_PAD_FL_SINK)) in camss_find_sensor()
941 if (!pad || !is_media_entity_v4l2_subdev(pad->entity)) in camss_find_sensor()
944 entity = pad->entity; in camss_find_sensor()
946 if (entity->function == MEDIA_ENT_F_CAM_SENSOR) in camss_find_sensor()
952 * camss_get_link_freq - Get link frequency from sensor
967 return -ENODEV; in camss_get_link_freq()
971 return v4l2_get_link_freq(subdev->ctrl_handler, bpp, 2 * lanes); in camss_get_link_freq()
975 * camss_get_pixel_clock - Get pixel clock rate from sensor
989 return -ENODEV; in camss_get_pixel_clock()
993 ctrl = v4l2_ctrl_find(subdev->ctrl_handler, V4L2_CID_PIXEL_RATE); in camss_get_pixel_clock()
996 return -EINVAL; in camss_get_pixel_clock()
1003 int camss_pm_domain_on(struct camss *camss, int id) in camss_pm_domain_on() argument
1007 if (id < camss->vfe_num) { in camss_pm_domain_on()
1008 struct vfe_device *vfe = &camss->vfe[id]; in camss_pm_domain_on()
1010 ret = vfe->ops->pm_domain_on(vfe); in camss_pm_domain_on()
1016 void camss_pm_domain_off(struct camss *camss, int id) in camss_pm_domain_off() argument
1018 if (id < camss->vfe_num) { in camss_pm_domain_off()
1019 struct vfe_device *vfe = &camss->vfe[id]; in camss_pm_domain_off()
1021 vfe->ops->pm_domain_off(vfe); in camss_pm_domain_off()
1026 * camss_of_parse_endpoint_node - Parse port endpoint node
1037 struct csiphy_lanes_cfg *lncfg = &csd->interface.csi2.lane_cfg; in camss_of_parse_endpoint_node()
1044 csd->interface.csiphy_id = vep.base.port; in camss_of_parse_endpoint_node()
1047 lncfg->clk.pos = mipi_csi2->clock_lane; in camss_of_parse_endpoint_node()
1048 lncfg->clk.pol = mipi_csi2->lane_polarities[0]; in camss_of_parse_endpoint_node()
1049 lncfg->num_data = mipi_csi2->num_data_lanes; in camss_of_parse_endpoint_node()
1051 lncfg->data = devm_kcalloc(dev, in camss_of_parse_endpoint_node()
1052 lncfg->num_data, sizeof(*lncfg->data), in camss_of_parse_endpoint_node()
1054 if (!lncfg->data) in camss_of_parse_endpoint_node()
1055 return -ENOMEM; in camss_of_parse_endpoint_node()
1057 for (i = 0; i < lncfg->num_data; i++) { in camss_of_parse_endpoint_node()
1058 lncfg->data[i].pos = mipi_csi2->data_lanes[i]; in camss_of_parse_endpoint_node()
1059 lncfg->data[i].pol = mipi_csi2->lane_polarities[i + 1]; in camss_of_parse_endpoint_node()
1066 * camss_of_parse_ports - Parse ports node
1072 static int camss_of_parse_ports(struct camss *camss) in camss_of_parse_ports() argument
1074 struct device *dev = camss->dev; in camss_of_parse_ports()
1079 for_each_endpoint_of_node(dev->of_node, node) { in camss_of_parse_ports()
1088 ret = -EINVAL; in camss_of_parse_ports()
1092 csd = v4l2_async_nf_add_fwnode(&camss->notifier, in camss_of_parse_ports()
1116 * camss_init_subdevices - Initialize subdev structures and resources
1117 * @camss: CAMSS device
1121 static int camss_init_subdevices(struct camss *camss) in camss_init_subdevices() argument
1130 if (camss->version == CAMSS_8x16) { in camss_init_subdevices()
1135 } else if (camss->version == CAMSS_8x96) { in camss_init_subdevices()
1140 } else if (camss->version == CAMSS_660) { in camss_init_subdevices()
1145 } else if (camss->version == CAMSS_845) { in camss_init_subdevices()
1151 } else if (camss->version == CAMSS_8250) { in camss_init_subdevices()
1158 return -EINVAL; in camss_init_subdevices()
1161 for (i = 0; i < camss->csiphy_num; i++) { in camss_init_subdevices()
1162 ret = msm_csiphy_subdev_init(camss, &camss->csiphy[i], in camss_init_subdevices()
1165 dev_err(camss->dev, in camss_init_subdevices()
1166 "Failed to init csiphy%d sub-device: %d\n", in camss_init_subdevices()
1173 for (i = 0; i < camss->vfe_num; i++) { in camss_init_subdevices()
1174 ret = msm_vfe_subdev_init(camss, &camss->vfe[i], in camss_init_subdevices()
1177 dev_err(camss->dev, in camss_init_subdevices()
1178 "Fail to init vfe%d sub-device: %d\n", i, ret); in camss_init_subdevices()
1183 for (i = 0; i < camss->csid_num; i++) { in camss_init_subdevices()
1184 ret = msm_csid_subdev_init(camss, &camss->csid[i], in camss_init_subdevices()
1187 dev_err(camss->dev, in camss_init_subdevices()
1188 "Failed to init csid%d sub-device: %d\n", in camss_init_subdevices()
1194 ret = msm_ispif_subdev_init(camss, ispif_res); in camss_init_subdevices()
1196 dev_err(camss->dev, "Failed to init ispif sub-device: %d\n", in camss_init_subdevices()
1205 * camss_register_entities - Register subdev nodes and create links
1206 * @camss: CAMSS device
1210 static int camss_register_entities(struct camss *camss) in camss_register_entities() argument
1215 for (i = 0; i < camss->csiphy_num; i++) { in camss_register_entities()
1216 ret = msm_csiphy_register_entity(&camss->csiphy[i], in camss_register_entities()
1217 &camss->v4l2_dev); in camss_register_entities()
1219 dev_err(camss->dev, in camss_register_entities()
1226 for (i = 0; i < camss->csid_num; i++) { in camss_register_entities()
1227 ret = msm_csid_register_entity(&camss->csid[i], in camss_register_entities()
1228 &camss->v4l2_dev); in camss_register_entities()
1230 dev_err(camss->dev, in camss_register_entities()
1237 ret = msm_ispif_register_entities(camss->ispif, in camss_register_entities()
1238 &camss->v4l2_dev); in camss_register_entities()
1240 dev_err(camss->dev, "Failed to register ispif entities: %d\n", in camss_register_entities()
1245 for (i = 0; i < camss->vfe_num; i++) { in camss_register_entities()
1246 ret = msm_vfe_register_entities(&camss->vfe[i], in camss_register_entities()
1247 &camss->v4l2_dev); in camss_register_entities()
1249 dev_err(camss->dev, in camss_register_entities()
1256 for (i = 0; i < camss->csiphy_num; i++) { in camss_register_entities()
1257 for (j = 0; j < camss->csid_num; j++) { in camss_register_entities()
1259 &camss->csiphy[i].subdev.entity, in camss_register_entities()
1261 &camss->csid[j].subdev.entity, in camss_register_entities()
1265 dev_err(camss->dev, in camss_register_entities()
1266 "Failed to link %s->%s entities: %d\n", in camss_register_entities()
1267 camss->csiphy[i].subdev.entity.name, in camss_register_entities()
1268 camss->csid[j].subdev.entity.name, in camss_register_entities()
1275 if (camss->ispif) { in camss_register_entities()
1276 for (i = 0; i < camss->csid_num; i++) { in camss_register_entities()
1277 for (j = 0; j < camss->ispif->line_num; j++) { in camss_register_entities()
1279 &camss->csid[i].subdev.entity, in camss_register_entities()
1281 &camss->ispif->line[j].subdev.entity, in camss_register_entities()
1285 dev_err(camss->dev, in camss_register_entities()
1286 "Failed to link %s->%s entities: %d\n", in camss_register_entities()
1287 camss->csid[i].subdev.entity.name, in camss_register_entities()
1288 camss->ispif->line[j].subdev.entity.name, in camss_register_entities()
1295 for (i = 0; i < camss->ispif->line_num; i++) in camss_register_entities()
1296 for (k = 0; k < camss->vfe_num; k++) in camss_register_entities()
1297 for (j = 0; j < camss->vfe[k].line_num; j++) { in camss_register_entities()
1298 struct v4l2_subdev *ispif = &camss->ispif->line[i].subdev; in camss_register_entities()
1299 struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev; in camss_register_entities()
1301 ret = media_create_pad_link(&ispif->entity, in camss_register_entities()
1303 &vfe->entity, in camss_register_entities()
1307 dev_err(camss->dev, in camss_register_entities()
1308 "Failed to link %s->%s entities: %d\n", in camss_register_entities()
1309 ispif->entity.name, in camss_register_entities()
1310 vfe->entity.name, in camss_register_entities()
1316 for (i = 0; i < camss->csid_num; i++) in camss_register_entities()
1317 for (k = 0; k < camss->vfe_num; k++) in camss_register_entities()
1318 for (j = 0; j < camss->vfe[k].line_num; j++) { in camss_register_entities()
1319 struct v4l2_subdev *csid = &camss->csid[i].subdev; in camss_register_entities()
1320 struct v4l2_subdev *vfe = &camss->vfe[k].line[j].subdev; in camss_register_entities()
1322 ret = media_create_pad_link(&csid->entity, in camss_register_entities()
1324 &vfe->entity, in camss_register_entities()
1328 dev_err(camss->dev, in camss_register_entities()
1329 "Failed to link %s->%s entities: %d\n", in camss_register_entities()
1330 csid->entity.name, in camss_register_entities()
1331 vfe->entity.name, in camss_register_entities()
1341 i = camss->vfe_num; in camss_register_entities()
1343 for (i--; i >= 0; i--) in camss_register_entities()
1344 msm_vfe_unregister_entities(&camss->vfe[i]); in camss_register_entities()
1347 msm_ispif_unregister_entities(camss->ispif); in camss_register_entities()
1349 i = camss->csid_num; in camss_register_entities()
1351 for (i--; i >= 0; i--) in camss_register_entities()
1352 msm_csid_unregister_entity(&camss->csid[i]); in camss_register_entities()
1354 i = camss->csiphy_num; in camss_register_entities()
1356 for (i--; i >= 0; i--) in camss_register_entities()
1357 msm_csiphy_unregister_entity(&camss->csiphy[i]); in camss_register_entities()
1363 * camss_unregister_entities - Unregister subdev nodes
1364 * @camss: CAMSS device
1368 static void camss_unregister_entities(struct camss *camss) in camss_unregister_entities() argument
1372 for (i = 0; i < camss->csiphy_num; i++) in camss_unregister_entities()
1373 msm_csiphy_unregister_entity(&camss->csiphy[i]); in camss_unregister_entities()
1375 for (i = 0; i < camss->csid_num; i++) in camss_unregister_entities()
1376 msm_csid_unregister_entity(&camss->csid[i]); in camss_unregister_entities()
1378 msm_ispif_unregister_entities(camss->ispif); in camss_unregister_entities()
1380 for (i = 0; i < camss->vfe_num; i++) in camss_unregister_entities()
1381 msm_vfe_unregister_entities(&camss->vfe[i]); in camss_unregister_entities()
1388 struct camss *camss = container_of(async, struct camss, notifier); in camss_subdev_notifier_bound() local
1391 u8 id = csd->interface.csiphy_id; in camss_subdev_notifier_bound()
1392 struct csiphy_device *csiphy = &camss->csiphy[id]; in camss_subdev_notifier_bound()
1394 csiphy->cfg.csi2 = &csd->interface.csi2; in camss_subdev_notifier_bound()
1395 subdev->host_priv = csiphy; in camss_subdev_notifier_bound()
1402 struct camss *camss = container_of(async, struct camss, notifier); in camss_subdev_notifier_complete() local
1403 struct v4l2_device *v4l2_dev = &camss->v4l2_dev; in camss_subdev_notifier_complete()
1407 list_for_each_entry(sd, &v4l2_dev->subdevs, list) { in camss_subdev_notifier_complete()
1408 if (sd->host_priv) { in camss_subdev_notifier_complete()
1409 struct media_entity *sensor = &sd->entity; in camss_subdev_notifier_complete()
1411 (struct csiphy_device *) sd->host_priv; in camss_subdev_notifier_complete()
1412 struct media_entity *input = &csiphy->subdev.entity; in camss_subdev_notifier_complete()
1415 for (i = 0; i < sensor->num_pads; i++) { in camss_subdev_notifier_complete()
1416 if (sensor->pads[i].flags & MEDIA_PAD_FL_SOURCE) in camss_subdev_notifier_complete()
1419 if (i == sensor->num_pads) { in camss_subdev_notifier_complete()
1420 dev_err(camss->dev, in camss_subdev_notifier_complete()
1422 return -EINVAL; in camss_subdev_notifier_complete()
1429 dev_err(camss->dev, in camss_subdev_notifier_complete()
1430 "Failed to link %s->%s entities: %d\n", in camss_subdev_notifier_complete()
1431 sensor->name, input->name, ret); in camss_subdev_notifier_complete()
1437 ret = v4l2_device_register_subdev_nodes(&camss->v4l2_dev); in camss_subdev_notifier_complete()
1441 return media_device_register(&camss->media_dev); in camss_subdev_notifier_complete()
1453 static int camss_configure_pd(struct camss *camss) in camss_configure_pd() argument
1455 struct device *dev = camss->dev; in camss_configure_pd()
1460 camss->genpd_num = of_count_phandle_with_args(dev->of_node, in camss_configure_pd()
1461 "power-domains", in camss_configure_pd()
1462 "#power-domain-cells"); in camss_configure_pd()
1463 if (camss->genpd_num < 0) { in camss_configure_pd()
1464 dev_err(dev, "Power domains are not defined for camss\n"); in camss_configure_pd()
1465 return camss->genpd_num; in camss_configure_pd()
1468 camss->genpd = devm_kmalloc_array(dev, camss->genpd_num, in camss_configure_pd()
1469 sizeof(*camss->genpd), GFP_KERNEL); in camss_configure_pd()
1470 if (!camss->genpd) in camss_configure_pd()
1471 return -ENOMEM; in camss_configure_pd()
1473 camss->genpd_link = devm_kmalloc_array(dev, camss->genpd_num, in camss_configure_pd()
1474 sizeof(*camss->genpd_link), in camss_configure_pd()
1476 if (!camss->genpd_link) in camss_configure_pd()
1477 return -ENOMEM; in camss_configure_pd()
1479 for (i = 0; i < camss->genpd_num; i++) { in camss_configure_pd()
1480 camss->genpd[i] = dev_pm_domain_attach_by_id(camss->dev, i); in camss_configure_pd()
1481 if (IS_ERR(camss->genpd[i])) { in camss_configure_pd()
1482 ret = PTR_ERR(camss->genpd[i]); in camss_configure_pd()
1486 camss->genpd_link[i] = device_link_add(camss->dev, camss->genpd[i], in camss_configure_pd()
1489 if (!camss->genpd_link[i]) { in camss_configure_pd()
1490 dev_pm_domain_detach(camss->genpd[i], true); in camss_configure_pd()
1491 ret = -EINVAL; in camss_configure_pd()
1502 device_link_del(camss->genpd_link[i]); in camss_configure_pd()
1503 dev_pm_domain_detach(camss->genpd[i], true); in camss_configure_pd()
1509 static int camss_icc_get(struct camss *camss) in camss_icc_get() argument
1515 if (camss->version == CAMSS_8250) { in camss_icc_get()
1521 camss->icc_path[i] = devm_of_icc_get(camss->dev, in camss_icc_get()
1523 if (IS_ERR(camss->icc_path[i])) in camss_icc_get()
1524 return PTR_ERR(camss->icc_path[i]); in camss_icc_get()
1526 camss->icc_bw_tbl[i] = icc_res[i].icc_bw_tbl; in camss_icc_get()
1533 * camss_probe - Probe CAMSS platform device
1534 * @pdev: Pointer to CAMSS platform device
1540 struct device *dev = &pdev->dev; in camss_probe()
1541 struct camss *camss; in camss_probe() local
1544 camss = devm_kzalloc(dev, sizeof(*camss), GFP_KERNEL); in camss_probe()
1545 if (!camss) in camss_probe()
1546 return -ENOMEM; in camss_probe()
1548 atomic_set(&camss->ref_count, 0); in camss_probe()
1549 camss->dev = dev; in camss_probe()
1550 platform_set_drvdata(pdev, camss); in camss_probe()
1552 if (of_device_is_compatible(dev->of_node, "qcom,msm8916-camss")) { in camss_probe()
1553 camss->version = CAMSS_8x16; in camss_probe()
1554 camss->csiphy_num = 2; in camss_probe()
1555 camss->csid_num = 2; in camss_probe()
1556 camss->vfe_num = 1; in camss_probe()
1557 } else if (of_device_is_compatible(dev->of_node, in camss_probe()
1558 "qcom,msm8996-camss")) { in camss_probe()
1559 camss->version = CAMSS_8x96; in camss_probe()
1560 camss->csiphy_num = 3; in camss_probe()
1561 camss->csid_num = 4; in camss_probe()
1562 camss->vfe_num = 2; in camss_probe()
1563 } else if (of_device_is_compatible(dev->of_node, in camss_probe()
1564 "qcom,sdm660-camss")) { in camss_probe()
1565 camss->version = CAMSS_660; in camss_probe()
1566 camss->csiphy_num = 3; in camss_probe()
1567 camss->csid_num = 4; in camss_probe()
1568 camss->vfe_num = 2; in camss_probe()
1569 } else if (of_device_is_compatible(dev->of_node, in camss_probe()
1570 "qcom,sdm845-camss")) { in camss_probe()
1571 camss->version = CAMSS_845; in camss_probe()
1572 camss->csiphy_num = 4; in camss_probe()
1573 camss->csid_num = 3; in camss_probe()
1574 camss->vfe_num = 3; in camss_probe()
1575 } else if (of_device_is_compatible(dev->of_node, in camss_probe()
1576 "qcom,sm8250-camss")) { in camss_probe()
1577 camss->version = CAMSS_8250; in camss_probe()
1578 camss->csiphy_num = 6; in camss_probe()
1579 camss->csid_num = 4; in camss_probe()
1580 camss->vfe_num = 4; in camss_probe()
1582 return -EINVAL; in camss_probe()
1585 camss->csiphy = devm_kcalloc(dev, camss->csiphy_num, in camss_probe()
1586 sizeof(*camss->csiphy), GFP_KERNEL); in camss_probe()
1587 if (!camss->csiphy) in camss_probe()
1588 return -ENOMEM; in camss_probe()
1590 camss->csid = devm_kcalloc(dev, camss->csid_num, sizeof(*camss->csid), in camss_probe()
1592 if (!camss->csid) in camss_probe()
1593 return -ENOMEM; in camss_probe()
1595 if (camss->version == CAMSS_8x16 || in camss_probe()
1596 camss->version == CAMSS_8x96) { in camss_probe()
1597 camss->ispif = devm_kcalloc(dev, 1, sizeof(*camss->ispif), GFP_KERNEL); in camss_probe()
1598 if (!camss->ispif) in camss_probe()
1599 return -ENOMEM; in camss_probe()
1602 camss->vfe = devm_kcalloc(dev, camss->vfe_num, sizeof(*camss->vfe), in camss_probe()
1604 if (!camss->vfe) in camss_probe()
1605 return -ENOMEM; in camss_probe()
1607 v4l2_async_nf_init(&camss->notifier); in camss_probe()
1609 num_subdevs = camss_of_parse_ports(camss); in camss_probe()
1615 ret = camss_icc_get(camss); in camss_probe()
1619 ret = camss_init_subdevices(camss); in camss_probe()
1627 camss->media_dev.dev = camss->dev; in camss_probe()
1628 strscpy(camss->media_dev.model, "Qualcomm Camera Subsystem", in camss_probe()
1629 sizeof(camss->media_dev.model)); in camss_probe()
1630 camss->media_dev.ops = &camss_media_ops; in camss_probe()
1631 media_device_init(&camss->media_dev); in camss_probe()
1633 camss->v4l2_dev.mdev = &camss->media_dev; in camss_probe()
1634 ret = v4l2_device_register(camss->dev, &camss->v4l2_dev); in camss_probe()
1640 ret = camss_register_entities(camss); in camss_probe()
1645 camss->notifier.ops = &camss_subdev_notifier_ops; in camss_probe()
1647 ret = v4l2_async_nf_register(&camss->v4l2_dev, in camss_probe()
1648 &camss->notifier); in camss_probe()
1656 ret = v4l2_device_register_subdev_nodes(&camss->v4l2_dev); in camss_probe()
1663 ret = media_device_register(&camss->media_dev); in camss_probe()
1671 ret = camss_configure_pd(camss); in camss_probe()
1682 camss_unregister_entities(camss); in camss_probe()
1684 v4l2_device_unregister(&camss->v4l2_dev); in camss_probe()
1686 v4l2_async_nf_cleanup(&camss->notifier); in camss_probe()
1691 void camss_delete(struct camss *camss) in camss_delete() argument
1695 v4l2_device_unregister(&camss->v4l2_dev); in camss_delete()
1696 media_device_unregister(&camss->media_dev); in camss_delete()
1697 media_device_cleanup(&camss->media_dev); in camss_delete()
1699 pm_runtime_disable(camss->dev); in camss_delete()
1701 for (i = 0; i < camss->genpd_num; i++) { in camss_delete()
1702 device_link_del(camss->genpd_link[i]); in camss_delete()
1703 dev_pm_domain_detach(camss->genpd[i], true); in camss_delete()
1708 * camss_remove - Remove CAMSS platform device
1709 * @pdev: Pointer to CAMSS platform device
1715 struct camss *camss = platform_get_drvdata(pdev); in camss_remove() local
1717 v4l2_async_nf_unregister(&camss->notifier); in camss_remove()
1718 v4l2_async_nf_cleanup(&camss->notifier); in camss_remove()
1719 camss_unregister_entities(camss); in camss_remove()
1721 if (atomic_read(&camss->ref_count) == 0) in camss_remove()
1722 camss_delete(camss); in camss_remove()
1728 { .compatible = "qcom,msm8916-camss" },
1729 { .compatible = "qcom,msm8996-camss" },
1730 { .compatible = "qcom,sdm660-camss" },
1731 { .compatible = "qcom,sdm845-camss" },
1732 { .compatible = "qcom,sm8250-camss" },
1740 struct camss *camss = dev_get_drvdata(dev); in camss_runtime_suspend() local
1745 if (camss->version == CAMSS_8250) in camss_runtime_suspend()
1749 ret = icc_set_bw(camss->icc_path[i], 0, 0); in camss_runtime_suspend()
1759 struct camss *camss = dev_get_drvdata(dev); in camss_runtime_resume() local
1764 if (camss->version == CAMSS_8250) in camss_runtime_resume()
1768 ret = icc_set_bw(camss->icc_path[i], in camss_runtime_resume()
1769 camss->icc_bw_tbl[i].avg, in camss_runtime_resume()
1770 camss->icc_bw_tbl[i].peak); in camss_runtime_resume()
1788 .name = "qcom-camss",
1796 MODULE_ALIAS("platform:qcom-camss");