diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2014-02-24 09:44:50 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-03-14 09:35:28 -0400 |
commit | fa91f1056f17c87bc0fa601f80d1b1a4487fd701 (patch) | |
tree | 5b11033aa1a1399a0952639465b70ec5168e4043 | |
parent | d3f5e0c54f1bfa5f48e92ac45a279fa8cfdc55b7 (diff) |
[media] exynos4-is: Add support for asynchronous subdevices registration
Add support for registering external sensor subdevs using
v4l2-async API. The async API is used only for sensor subdevs
and only for booting from DT.
Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
Acked-by: Kyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r-- | drivers/media/platform/exynos4-is/media-dev.c | 238 | ||||
-rw-r--r-- | drivers/media/platform/exynos4-is/media-dev.h | 13 |
2 files changed, 147 insertions, 104 deletions
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c index f047a9f1043c..c670d67001f7 100644 --- a/drivers/media/platform/exynos4-is/media-dev.c +++ b/drivers/media/platform/exynos4-is/media-dev.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <media/v4l2-async.h> | ||
29 | #include <media/v4l2-ctrls.h> | 30 | #include <media/v4l2-ctrls.h> |
30 | #include <media/v4l2-of.h> | 31 | #include <media/v4l2-of.h> |
31 | #include <media/media-device.h> | 32 | #include <media/media-device.h> |
@@ -220,6 +221,7 @@ static int __fimc_pipeline_open(struct exynos_media_pipeline *ep, | |||
220 | if (ret < 0) | 221 | if (ret < 0) |
221 | return ret; | 222 | return ret; |
222 | } | 223 | } |
224 | |||
223 | ret = fimc_md_set_camclk(sd, true); | 225 | ret = fimc_md_set_camclk(sd, true); |
224 | if (ret < 0) | 226 | if (ret < 0) |
225 | goto err_wbclk; | 227 | goto err_wbclk; |
@@ -380,77 +382,18 @@ static void fimc_md_unregister_sensor(struct v4l2_subdev *sd) | |||
380 | struct i2c_client *client = v4l2_get_subdevdata(sd); | 382 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
381 | struct i2c_adapter *adapter; | 383 | struct i2c_adapter *adapter; |
382 | 384 | ||
383 | if (!client) | 385 | if (!client || client->dev.of_node) |
384 | return; | 386 | return; |
385 | 387 | ||
386 | v4l2_device_unregister_subdev(sd); | 388 | v4l2_device_unregister_subdev(sd); |
387 | 389 | ||
388 | if (!client->dev.of_node) { | 390 | adapter = client->adapter; |
389 | adapter = client->adapter; | 391 | i2c_unregister_device(client); |
390 | i2c_unregister_device(client); | 392 | if (adapter) |
391 | if (adapter) | 393 | i2c_put_adapter(adapter); |
392 | i2c_put_adapter(adapter); | ||
393 | } | ||
394 | } | 394 | } |
395 | 395 | ||
396 | #ifdef CONFIG_OF | 396 | #ifdef CONFIG_OF |
397 | /* Register I2C client subdev associated with @node. */ | ||
398 | static int fimc_md_of_add_sensor(struct fimc_md *fmd, | ||
399 | struct device_node *node, int index) | ||
400 | { | ||
401 | struct fimc_sensor_info *si; | ||
402 | struct i2c_client *client; | ||
403 | struct v4l2_subdev *sd; | ||
404 | int ret; | ||
405 | |||
406 | if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) | ||
407 | return -EINVAL; | ||
408 | si = &fmd->sensor[index]; | ||
409 | |||
410 | client = of_find_i2c_device_by_node(node); | ||
411 | if (!client) | ||
412 | return -EPROBE_DEFER; | ||
413 | |||
414 | device_lock(&client->dev); | ||
415 | |||
416 | if (!client->dev.driver || | ||
417 | !try_module_get(client->dev.driver->owner)) { | ||
418 | ret = -EPROBE_DEFER; | ||
419 | v4l2_info(&fmd->v4l2_dev, "No driver found for %s\n", | ||
420 | node->full_name); | ||
421 | goto dev_put; | ||
422 | } | ||
423 | |||
424 | /* Enable sensor's master clock */ | ||
425 | ret = __fimc_md_set_camclk(fmd, &si->pdata, true); | ||
426 | if (ret < 0) | ||
427 | goto mod_put; | ||
428 | sd = i2c_get_clientdata(client); | ||
429 | |||
430 | ret = v4l2_device_register_subdev(&fmd->v4l2_dev, sd); | ||
431 | __fimc_md_set_camclk(fmd, &si->pdata, false); | ||
432 | if (ret < 0) | ||
433 | goto mod_put; | ||
434 | |||
435 | v4l2_set_subdev_hostdata(sd, &si->pdata); | ||
436 | if (si->pdata.fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK) | ||
437 | sd->grp_id = GRP_ID_FIMC_IS_SENSOR; | ||
438 | else | ||
439 | sd->grp_id = GRP_ID_SENSOR; | ||
440 | |||
441 | si->subdev = sd; | ||
442 | v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s (%d)\n", | ||
443 | sd->name, fmd->num_sensors); | ||
444 | fmd->num_sensors++; | ||
445 | |||
446 | mod_put: | ||
447 | module_put(client->dev.driver->owner); | ||
448 | dev_put: | ||
449 | device_unlock(&client->dev); | ||
450 | put_device(&client->dev); | ||
451 | return ret; | ||
452 | } | ||
453 | |||
454 | /* Parse port node and register as a sub-device any sensor specified there. */ | 397 | /* Parse port node and register as a sub-device any sensor specified there. */ |
455 | static int fimc_md_parse_port_node(struct fimc_md *fmd, | 398 | static int fimc_md_parse_port_node(struct fimc_md *fmd, |
456 | struct device_node *port, | 399 | struct device_node *port, |
@@ -459,7 +402,6 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, | |||
459 | struct device_node *rem, *ep, *np; | 402 | struct device_node *rem, *ep, *np; |
460 | struct fimc_source_info *pd; | 403 | struct fimc_source_info *pd; |
461 | struct v4l2_of_endpoint endpoint; | 404 | struct v4l2_of_endpoint endpoint; |
462 | int ret; | ||
463 | u32 val; | 405 | u32 val; |
464 | 406 | ||
465 | pd = &fmd->sensor[index].pdata; | 407 | pd = &fmd->sensor[index].pdata; |
@@ -487,6 +429,8 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, | |||
487 | 429 | ||
488 | if (!of_property_read_u32(rem, "clock-frequency", &val)) | 430 | if (!of_property_read_u32(rem, "clock-frequency", &val)) |
489 | pd->clk_frequency = val; | 431 | pd->clk_frequency = val; |
432 | else | ||
433 | pd->clk_frequency = DEFAULT_SENSOR_CLK_FREQ; | ||
490 | 434 | ||
491 | if (pd->clk_frequency == 0) { | 435 | if (pd->clk_frequency == 0) { |
492 | v4l2_err(&fmd->v4l2_dev, "Wrong clock frequency at node %s\n", | 436 | v4l2_err(&fmd->v4l2_dev, "Wrong clock frequency at node %s\n", |
@@ -526,10 +470,17 @@ static int fimc_md_parse_port_node(struct fimc_md *fmd, | |||
526 | else | 470 | else |
527 | pd->fimc_bus_type = pd->sensor_bus_type; | 471 | pd->fimc_bus_type = pd->sensor_bus_type; |
528 | 472 | ||
529 | ret = fimc_md_of_add_sensor(fmd, rem, index); | 473 | if (WARN_ON(index >= ARRAY_SIZE(fmd->sensor))) |
530 | of_node_put(rem); | 474 | return -EINVAL; |
531 | 475 | ||
532 | return ret; | 476 | fmd->sensor[index].asd.match_type = V4L2_ASYNC_MATCH_OF; |
477 | fmd->sensor[index].asd.match.of.node = rem; | ||
478 | fmd->async_subdevs[index] = &fmd->sensor[index].asd; | ||
479 | |||
480 | fmd->num_sensors++; | ||
481 | |||
482 | of_node_put(rem); | ||
483 | return 0; | ||
533 | } | 484 | } |
534 | 485 | ||
535 | /* Register all SoC external sub-devices */ | 486 | /* Register all SoC external sub-devices */ |
@@ -885,11 +836,13 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd) | |||
885 | v4l2_device_unregister_subdev(fmd->csis[i].sd); | 836 | v4l2_device_unregister_subdev(fmd->csis[i].sd); |
886 | fmd->csis[i].sd = NULL; | 837 | fmd->csis[i].sd = NULL; |
887 | } | 838 | } |
888 | for (i = 0; i < fmd->num_sensors; i++) { | 839 | if (fmd->pdev->dev.of_node == NULL) { |
889 | if (fmd->sensor[i].subdev == NULL) | 840 | for (i = 0; i < fmd->num_sensors; i++) { |
890 | continue; | 841 | if (fmd->sensor[i].subdev == NULL) |
891 | fimc_md_unregister_sensor(fmd->sensor[i].subdev); | 842 | continue; |
892 | fmd->sensor[i].subdev = NULL; | 843 | fimc_md_unregister_sensor(fmd->sensor[i].subdev); |
844 | fmd->sensor[i].subdev = NULL; | ||
845 | } | ||
893 | } | 846 | } |
894 | 847 | ||
895 | if (fmd->fimc_is) | 848 | if (fmd->fimc_is) |
@@ -1224,6 +1177,14 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd, | |||
1224 | struct fimc_camclk_info *camclk; | 1177 | struct fimc_camclk_info *camclk; |
1225 | int ret = 0; | 1178 | int ret = 0; |
1226 | 1179 | ||
1180 | /* | ||
1181 | * When device tree is used the sensor drivers are supposed to | ||
1182 | * control the clock themselves. This whole function will be | ||
1183 | * removed once S5PV210 platform is converted to the device tree. | ||
1184 | */ | ||
1185 | if (fmd->pdev->dev.of_node) | ||
1186 | return 0; | ||
1187 | |||
1227 | if (WARN_ON(si->clk_id >= FIMC_MAX_CAMCLKS) || !fmd || !fmd->pmf) | 1188 | if (WARN_ON(si->clk_id >= FIMC_MAX_CAMCLKS) || !fmd || !fmd->pmf) |
1228 | return -EINVAL; | 1189 | return -EINVAL; |
1229 | 1190 | ||
@@ -1544,6 +1505,56 @@ err: | |||
1544 | #define fimc_md_unregister_clk_provider(fmd) (0) | 1505 | #define fimc_md_unregister_clk_provider(fmd) (0) |
1545 | #endif | 1506 | #endif |
1546 | 1507 | ||
1508 | static int subdev_notifier_bound(struct v4l2_async_notifier *notifier, | ||
1509 | struct v4l2_subdev *subdev, | ||
1510 | struct v4l2_async_subdev *asd) | ||
1511 | { | ||
1512 | struct fimc_md *fmd = notifier_to_fimc_md(notifier); | ||
1513 | struct fimc_sensor_info *si = NULL; | ||
1514 | int i; | ||
1515 | |||
1516 | /* Find platform data for this sensor subdev */ | ||
1517 | for (i = 0; i < ARRAY_SIZE(fmd->sensor); i++) | ||
1518 | if (fmd->sensor[i].asd.match.of.node == subdev->dev->of_node) | ||
1519 | si = &fmd->sensor[i]; | ||
1520 | |||
1521 | if (si == NULL) | ||
1522 | return -EINVAL; | ||
1523 | |||
1524 | v4l2_set_subdev_hostdata(subdev, &si->pdata); | ||
1525 | |||
1526 | if (si->pdata.fimc_bus_type == FIMC_BUS_TYPE_ISP_WRITEBACK) | ||
1527 | subdev->grp_id = GRP_ID_FIMC_IS_SENSOR; | ||
1528 | else | ||
1529 | subdev->grp_id = GRP_ID_SENSOR; | ||
1530 | |||
1531 | si->subdev = subdev; | ||
1532 | |||
1533 | v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice: %s (%d)\n", | ||
1534 | subdev->name, fmd->num_sensors); | ||
1535 | |||
1536 | fmd->num_sensors++; | ||
1537 | |||
1538 | return 0; | ||
1539 | } | ||
1540 | |||
1541 | static int subdev_notifier_complete(struct v4l2_async_notifier *notifier) | ||
1542 | { | ||
1543 | struct fimc_md *fmd = notifier_to_fimc_md(notifier); | ||
1544 | int ret; | ||
1545 | |||
1546 | mutex_lock(&fmd->media_dev.graph_mutex); | ||
1547 | |||
1548 | ret = fimc_md_create_links(fmd); | ||
1549 | if (ret < 0) | ||
1550 | goto unlock; | ||
1551 | |||
1552 | ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev); | ||
1553 | unlock: | ||
1554 | mutex_unlock(&fmd->media_dev.graph_mutex); | ||
1555 | return ret; | ||
1556 | } | ||
1557 | |||
1547 | static int fimc_md_probe(struct platform_device *pdev) | 1558 | static int fimc_md_probe(struct platform_device *pdev) |
1548 | { | 1559 | { |
1549 | struct device *dev = &pdev->dev; | 1560 | struct device *dev = &pdev->dev; |
@@ -1571,12 +1582,6 @@ static int fimc_md_probe(struct platform_device *pdev) | |||
1571 | 1582 | ||
1572 | fmd->use_isp = fimc_md_is_isp_available(dev->of_node); | 1583 | fmd->use_isp = fimc_md_is_isp_available(dev->of_node); |
1573 | 1584 | ||
1574 | ret = fimc_md_register_clk_provider(fmd); | ||
1575 | if (ret < 0) { | ||
1576 | v4l2_err(v4l2_dev, "clock provider registration failed\n"); | ||
1577 | return ret; | ||
1578 | } | ||
1579 | |||
1580 | ret = v4l2_device_register(dev, &fmd->v4l2_dev); | 1585 | ret = v4l2_device_register(dev, &fmd->v4l2_dev); |
1581 | if (ret < 0) { | 1586 | if (ret < 0) { |
1582 | v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); | 1587 | v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); |
@@ -1586,64 +1591,88 @@ static int fimc_md_probe(struct platform_device *pdev) | |||
1586 | ret = media_device_register(&fmd->media_dev); | 1591 | ret = media_device_register(&fmd->media_dev); |
1587 | if (ret < 0) { | 1592 | if (ret < 0) { |
1588 | v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret); | 1593 | v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret); |
1589 | goto err_md; | 1594 | goto err_v4l2_dev; |
1590 | } | 1595 | } |
1591 | 1596 | ||
1592 | ret = fimc_md_get_clocks(fmd); | 1597 | ret = fimc_md_get_clocks(fmd); |
1593 | if (ret) | 1598 | if (ret) |
1594 | goto err_clk; | 1599 | goto err_md; |
1595 | 1600 | ||
1596 | fmd->user_subdev_api = (dev->of_node != NULL); | 1601 | fmd->user_subdev_api = (dev->of_node != NULL); |
1597 | 1602 | ||
1598 | /* Protect the media graph while we're registering entities */ | ||
1599 | mutex_lock(&fmd->media_dev.graph_mutex); | ||
1600 | |||
1601 | ret = fimc_md_get_pinctrl(fmd); | 1603 | ret = fimc_md_get_pinctrl(fmd); |
1602 | if (ret < 0) { | 1604 | if (ret < 0) { |
1603 | if (ret != EPROBE_DEFER) | 1605 | if (ret != EPROBE_DEFER) |
1604 | dev_err(dev, "Failed to get pinctrl: %d\n", ret); | 1606 | dev_err(dev, "Failed to get pinctrl: %d\n", ret); |
1605 | goto err_unlock; | 1607 | goto err_clk; |
1606 | } | 1608 | } |
1607 | 1609 | ||
1610 | platform_set_drvdata(pdev, fmd); | ||
1611 | |||
1612 | /* Protect the media graph while we're registering entities */ | ||
1613 | mutex_lock(&fmd->media_dev.graph_mutex); | ||
1614 | |||
1608 | if (dev->of_node) | 1615 | if (dev->of_node) |
1609 | ret = fimc_md_register_of_platform_entities(fmd, dev->of_node); | 1616 | ret = fimc_md_register_of_platform_entities(fmd, dev->of_node); |
1610 | else | 1617 | else |
1611 | ret = bus_for_each_dev(&platform_bus_type, NULL, fmd, | 1618 | ret = bus_for_each_dev(&platform_bus_type, NULL, fmd, |
1612 | fimc_md_pdev_match); | 1619 | fimc_md_pdev_match); |
1613 | if (ret) | 1620 | if (ret) { |
1614 | goto err_unlock; | 1621 | mutex_unlock(&fmd->media_dev.graph_mutex); |
1622 | goto err_clk; | ||
1623 | } | ||
1615 | 1624 | ||
1616 | if (dev->platform_data || dev->of_node) { | 1625 | if (dev->platform_data || dev->of_node) { |
1617 | ret = fimc_md_register_sensor_entities(fmd); | 1626 | ret = fimc_md_register_sensor_entities(fmd); |
1618 | if (ret) | 1627 | if (ret) { |
1619 | goto err_unlock; | 1628 | mutex_unlock(&fmd->media_dev.graph_mutex); |
1629 | goto err_m_ent; | ||
1630 | } | ||
1620 | } | 1631 | } |
1621 | 1632 | ||
1622 | ret = fimc_md_create_links(fmd); | 1633 | mutex_unlock(&fmd->media_dev.graph_mutex); |
1623 | if (ret) | ||
1624 | goto err_unlock; | ||
1625 | |||
1626 | ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev); | ||
1627 | if (ret) | ||
1628 | goto err_unlock; | ||
1629 | 1634 | ||
1630 | ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode); | 1635 | ret = device_create_file(&pdev->dev, &dev_attr_subdev_conf_mode); |
1631 | if (ret) | 1636 | if (ret) |
1632 | goto err_unlock; | 1637 | goto err_m_ent; |
1638 | /* | ||
1639 | * FIMC platform devices need to be registered before the sclk_cam | ||
1640 | * clocks provider, as one of these devices needs to be activated | ||
1641 | * to enable the clock. | ||
1642 | */ | ||
1643 | ret = fimc_md_register_clk_provider(fmd); | ||
1644 | if (ret < 0) { | ||
1645 | v4l2_err(v4l2_dev, "clock provider registration failed\n"); | ||
1646 | goto err_attr; | ||
1647 | } | ||
1648 | |||
1649 | if (fmd->num_sensors > 0) { | ||
1650 | fmd->subdev_notifier.subdevs = fmd->async_subdevs; | ||
1651 | fmd->subdev_notifier.num_subdevs = fmd->num_sensors; | ||
1652 | fmd->subdev_notifier.bound = subdev_notifier_bound; | ||
1653 | fmd->subdev_notifier.complete = subdev_notifier_complete; | ||
1654 | fmd->num_sensors = 0; | ||
1655 | |||
1656 | ret = v4l2_async_notifier_register(&fmd->v4l2_dev, | ||
1657 | &fmd->subdev_notifier); | ||
1658 | if (ret) | ||
1659 | goto err_clk_p; | ||
1660 | } | ||
1633 | 1661 | ||
1634 | platform_set_drvdata(pdev, fmd); | ||
1635 | mutex_unlock(&fmd->media_dev.graph_mutex); | ||
1636 | return 0; | 1662 | return 0; |
1637 | 1663 | ||
1638 | err_unlock: | 1664 | err_clk_p: |
1639 | mutex_unlock(&fmd->media_dev.graph_mutex); | 1665 | fimc_md_unregister_clk_provider(fmd); |
1666 | err_attr: | ||
1667 | device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); | ||
1640 | err_clk: | 1668 | err_clk: |
1641 | fimc_md_put_clocks(fmd); | 1669 | fimc_md_put_clocks(fmd); |
1670 | err_m_ent: | ||
1642 | fimc_md_unregister_entities(fmd); | 1671 | fimc_md_unregister_entities(fmd); |
1643 | media_device_unregister(&fmd->media_dev); | ||
1644 | err_md: | 1672 | err_md: |
1673 | media_device_unregister(&fmd->media_dev); | ||
1674 | err_v4l2_dev: | ||
1645 | v4l2_device_unregister(&fmd->v4l2_dev); | 1675 | v4l2_device_unregister(&fmd->v4l2_dev); |
1646 | fimc_md_unregister_clk_provider(fmd); | ||
1647 | return ret; | 1676 | return ret; |
1648 | } | 1677 | } |
1649 | 1678 | ||
@@ -1655,12 +1684,15 @@ static int fimc_md_remove(struct platform_device *pdev) | |||
1655 | return 0; | 1684 | return 0; |
1656 | 1685 | ||
1657 | fimc_md_unregister_clk_provider(fmd); | 1686 | fimc_md_unregister_clk_provider(fmd); |
1687 | v4l2_async_notifier_unregister(&fmd->subdev_notifier); | ||
1688 | |||
1658 | v4l2_device_unregister(&fmd->v4l2_dev); | 1689 | v4l2_device_unregister(&fmd->v4l2_dev); |
1659 | device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); | 1690 | device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); |
1660 | fimc_md_unregister_entities(fmd); | 1691 | fimc_md_unregister_entities(fmd); |
1661 | fimc_md_pipelines_free(fmd); | 1692 | fimc_md_pipelines_free(fmd); |
1662 | media_device_unregister(&fmd->media_dev); | 1693 | media_device_unregister(&fmd->media_dev); |
1663 | fimc_md_put_clocks(fmd); | 1694 | fimc_md_put_clocks(fmd); |
1695 | |||
1664 | return 0; | 1696 | return 0; |
1665 | } | 1697 | } |
1666 | 1698 | ||
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h index a88cee59fd2f..ee1e2519f728 100644 --- a/drivers/media/platform/exynos4-is/media-dev.h +++ b/drivers/media/platform/exynos4-is/media-dev.h | |||
@@ -32,8 +32,9 @@ | |||
32 | 32 | ||
33 | #define PINCTRL_STATE_IDLE "idle" | 33 | #define PINCTRL_STATE_IDLE "idle" |
34 | 34 | ||
35 | #define FIMC_MAX_SENSORS 8 | 35 | #define FIMC_MAX_SENSORS 4 |
36 | #define FIMC_MAX_CAMCLKS 2 | 36 | #define FIMC_MAX_CAMCLKS 2 |
37 | #define DEFAULT_SENSOR_CLK_FREQ 24000000U | ||
37 | 38 | ||
38 | /* LCD/ISP Writeback clocks (PIXELASYNCMx) */ | 39 | /* LCD/ISP Writeback clocks (PIXELASYNCMx) */ |
39 | enum { | 40 | enum { |
@@ -79,6 +80,7 @@ struct fimc_camclk_info { | |||
79 | /** | 80 | /** |
80 | * struct fimc_sensor_info - image data source subdev information | 81 | * struct fimc_sensor_info - image data source subdev information |
81 | * @pdata: sensor's atrributes passed as media device's platform data | 82 | * @pdata: sensor's atrributes passed as media device's platform data |
83 | * @asd: asynchronous subdev registration data structure | ||
82 | * @subdev: image sensor v4l2 subdev | 84 | * @subdev: image sensor v4l2 subdev |
83 | * @host: fimc device the sensor is currently linked to | 85 | * @host: fimc device the sensor is currently linked to |
84 | * | 86 | * |
@@ -86,6 +88,7 @@ struct fimc_camclk_info { | |||
86 | */ | 88 | */ |
87 | struct fimc_sensor_info { | 89 | struct fimc_sensor_info { |
88 | struct fimc_source_info pdata; | 90 | struct fimc_source_info pdata; |
91 | struct v4l2_async_subdev asd; | ||
89 | struct v4l2_subdev *subdev; | 92 | struct v4l2_subdev *subdev; |
90 | struct fimc_dev *host; | 93 | struct fimc_dev *host; |
91 | }; | 94 | }; |
@@ -145,6 +148,9 @@ struct fimc_md { | |||
145 | int num_clocks; | 148 | int num_clocks; |
146 | } clk_provider; | 149 | } clk_provider; |
147 | 150 | ||
151 | struct v4l2_async_notifier subdev_notifier; | ||
152 | struct v4l2_async_subdev *async_subdevs[FIMC_MAX_SENSORS]; | ||
153 | |||
148 | bool user_subdev_api; | 154 | bool user_subdev_api; |
149 | spinlock_t slock; | 155 | spinlock_t slock; |
150 | struct list_head pipelines; | 156 | struct list_head pipelines; |
@@ -162,6 +168,11 @@ static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me) | |||
162 | container_of(me->parent, struct fimc_md, media_dev); | 168 | container_of(me->parent, struct fimc_md, media_dev); |
163 | } | 169 | } |
164 | 170 | ||
171 | static inline struct fimc_md *notifier_to_fimc_md(struct v4l2_async_notifier *n) | ||
172 | { | ||
173 | return container_of(n, struct fimc_md, subdev_notifier); | ||
174 | } | ||
175 | |||
165 | static inline void fimc_md_graph_lock(struct exynos_video_entity *ve) | 176 | static inline void fimc_md_graph_lock(struct exynos_video_entity *ve) |
166 | { | 177 | { |
167 | mutex_lock(&ve->vdev.entity.parent->graph_mutex); | 178 | mutex_lock(&ve->vdev.entity.parent->graph_mutex); |