aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2013-12-20 16:53:53 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2014-03-14 09:34:44 -0400
commitd3f5e0c54f1bfa5f48e92ac45a279fa8cfdc55b7 (patch)
tree27badefa1ce44fa53126c86cfc8b2c9fcc08f3b0 /drivers/media/platform
parentd265d9ac6c7c3201f0fea737cdf9c74e50415178 (diff)
[media] exynos4-is: Add clock provider for the SCLK_CAM clock outputs
This patch adds clock provider so the the SCLK_CAM0/1 output clocks can be accessed by image sensor devices through the clk API. 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>
Diffstat (limited to 'drivers/media/platform')
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.c118
-rw-r--r--drivers/media/platform/exynos4-is/media-dev.h19
2 files changed, 136 insertions, 1 deletions
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index c1bce170df6f..f047a9f1043c 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -11,6 +11,8 @@
11 */ 11 */
12 12
13#include <linux/bug.h> 13#include <linux/bug.h>
14#include <linux/clk.h>
15#include <linux/clk-provider.h>
14#include <linux/device.h> 16#include <linux/device.h>
15#include <linux/errno.h> 17#include <linux/errno.h>
16#include <linux/i2c.h> 18#include <linux/i2c.h>
@@ -1276,6 +1278,14 @@ int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on)
1276 struct fimc_source_info *si = v4l2_get_subdev_hostdata(sd); 1278 struct fimc_source_info *si = v4l2_get_subdev_hostdata(sd);
1277 struct fimc_md *fmd = entity_to_fimc_mdev(&sd->entity); 1279 struct fimc_md *fmd = entity_to_fimc_mdev(&sd->entity);
1278 1280
1281 /*
1282 * If there is a clock provider registered the sensors will
1283 * handle their clock themselves, no need to control it on
1284 * the host interface side.
1285 */
1286 if (fmd->clk_provider.num_clocks > 0)
1287 return 0;
1288
1279 return __fimc_md_set_camclk(fmd, si, on); 1289 return __fimc_md_set_camclk(fmd, si, on);
1280} 1290}
1281 1291
@@ -1437,6 +1447,103 @@ static int fimc_md_get_pinctrl(struct fimc_md *fmd)
1437 return 0; 1447 return 0;
1438} 1448}
1439 1449
1450#ifdef CONFIG_OF
1451static int cam_clk_prepare(struct clk_hw *hw)
1452{
1453 struct cam_clk *camclk = to_cam_clk(hw);
1454 int ret;
1455
1456 if (camclk->fmd->pmf == NULL)
1457 return -ENODEV;
1458
1459 ret = pm_runtime_get_sync(camclk->fmd->pmf);
1460 return ret < 0 ? ret : 0;
1461}
1462
1463static void cam_clk_unprepare(struct clk_hw *hw)
1464{
1465 struct cam_clk *camclk = to_cam_clk(hw);
1466
1467 if (camclk->fmd->pmf == NULL)
1468 return;
1469
1470 pm_runtime_put_sync(camclk->fmd->pmf);
1471}
1472
1473static const struct clk_ops cam_clk_ops = {
1474 .prepare = cam_clk_prepare,
1475 .unprepare = cam_clk_unprepare,
1476};
1477
1478static void fimc_md_unregister_clk_provider(struct fimc_md *fmd)
1479{
1480 struct cam_clk_provider *cp = &fmd->clk_provider;
1481 unsigned int i;
1482
1483 if (cp->of_node)
1484 of_clk_del_provider(cp->of_node);
1485
1486 for (i = 0; i < cp->num_clocks; i++)
1487 clk_unregister(cp->clks[i]);
1488}
1489
1490static int fimc_md_register_clk_provider(struct fimc_md *fmd)
1491{
1492 struct cam_clk_provider *cp = &fmd->clk_provider;
1493 struct device *dev = &fmd->pdev->dev;
1494 int i, ret;
1495
1496 for (i = 0; i < FIMC_MAX_CAMCLKS; i++) {
1497 struct cam_clk *camclk = &cp->camclk[i];
1498 struct clk_init_data init;
1499 const char *p_name;
1500
1501 ret = of_property_read_string_index(dev->of_node,
1502 "clock-output-names", i, &init.name);
1503 if (ret < 0)
1504 break;
1505
1506 p_name = __clk_get_name(fmd->camclk[i].clock);
1507
1508 /* It's safe since clk_register() will duplicate the string. */
1509 init.parent_names = &p_name;
1510 init.num_parents = 1;
1511 init.ops = &cam_clk_ops;
1512 init.flags = CLK_SET_RATE_PARENT;
1513 camclk->hw.init = &init;
1514 camclk->fmd = fmd;
1515
1516 cp->clks[i] = clk_register(NULL, &camclk->hw);
1517 if (IS_ERR(cp->clks[i])) {
1518 dev_err(dev, "failed to register clock: %s (%ld)\n",
1519 init.name, PTR_ERR(cp->clks[i]));
1520 ret = PTR_ERR(cp->clks[i]);
1521 goto err;
1522 }
1523 cp->num_clocks++;
1524 }
1525
1526 if (cp->num_clocks == 0) {
1527 dev_warn(dev, "clk provider not registered\n");
1528 return 0;
1529 }
1530
1531 cp->clk_data.clks = cp->clks;
1532 cp->clk_data.clk_num = cp->num_clocks;
1533 cp->of_node = dev->of_node;
1534 ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
1535 &cp->clk_data);
1536 if (ret == 0)
1537 return 0;
1538err:
1539 fimc_md_unregister_clk_provider(fmd);
1540 return ret;
1541}
1542#else
1543#define fimc_md_register_clk_provider(fmd) (0)
1544#define fimc_md_unregister_clk_provider(fmd) (0)
1545#endif
1546
1440static int fimc_md_probe(struct platform_device *pdev) 1547static int fimc_md_probe(struct platform_device *pdev)
1441{ 1548{
1442 struct device *dev = &pdev->dev; 1549 struct device *dev = &pdev->dev;
@@ -1464,16 +1571,24 @@ static int fimc_md_probe(struct platform_device *pdev)
1464 1571
1465 fmd->use_isp = fimc_md_is_isp_available(dev->of_node); 1572 fmd->use_isp = fimc_md_is_isp_available(dev->of_node);
1466 1573
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
1467 ret = v4l2_device_register(dev, &fmd->v4l2_dev); 1580 ret = v4l2_device_register(dev, &fmd->v4l2_dev);
1468 if (ret < 0) { 1581 if (ret < 0) {
1469 v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret); 1582 v4l2_err(v4l2_dev, "Failed to register v4l2_device: %d\n", ret);
1470 return ret; 1583 return ret;
1471 } 1584 }
1585
1472 ret = media_device_register(&fmd->media_dev); 1586 ret = media_device_register(&fmd->media_dev);
1473 if (ret < 0) { 1587 if (ret < 0) {
1474 v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret); 1588 v4l2_err(v4l2_dev, "Failed to register media device: %d\n", ret);
1475 goto err_md; 1589 goto err_md;
1476 } 1590 }
1591
1477 ret = fimc_md_get_clocks(fmd); 1592 ret = fimc_md_get_clocks(fmd);
1478 if (ret) 1593 if (ret)
1479 goto err_clk; 1594 goto err_clk;
@@ -1507,6 +1622,7 @@ static int fimc_md_probe(struct platform_device *pdev)
1507 ret = fimc_md_create_links(fmd); 1622 ret = fimc_md_create_links(fmd);
1508 if (ret) 1623 if (ret)
1509 goto err_unlock; 1624 goto err_unlock;
1625
1510 ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev); 1626 ret = v4l2_device_register_subdev_nodes(&fmd->v4l2_dev);
1511 if (ret) 1627 if (ret)
1512 goto err_unlock; 1628 goto err_unlock;
@@ -1527,6 +1643,7 @@ err_clk:
1527 media_device_unregister(&fmd->media_dev); 1643 media_device_unregister(&fmd->media_dev);
1528err_md: 1644err_md:
1529 v4l2_device_unregister(&fmd->v4l2_dev); 1645 v4l2_device_unregister(&fmd->v4l2_dev);
1646 fimc_md_unregister_clk_provider(fmd);
1530 return ret; 1647 return ret;
1531} 1648}
1532 1649
@@ -1537,6 +1654,7 @@ static int fimc_md_remove(struct platform_device *pdev)
1537 if (!fmd) 1654 if (!fmd)
1538 return 0; 1655 return 0;
1539 1656
1657 fimc_md_unregister_clk_provider(fmd);
1540 v4l2_device_unregister(&fmd->v4l2_dev); 1658 v4l2_device_unregister(&fmd->v4l2_dev);
1541 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode); 1659 device_remove_file(&pdev->dev, &dev_attr_subdev_conf_mode);
1542 fimc_md_unregister_entities(fmd); 1660 fimc_md_unregister_entities(fmd);
diff --git a/drivers/media/platform/exynos4-is/media-dev.h b/drivers/media/platform/exynos4-is/media-dev.h
index 62599fd7756f..a88cee59fd2f 100644
--- a/drivers/media/platform/exynos4-is/media-dev.h
+++ b/drivers/media/platform/exynos4-is/media-dev.h
@@ -10,6 +10,7 @@
10#define FIMC_MDEVICE_H_ 10#define FIMC_MDEVICE_H_
11 11
12#include <linux/clk.h> 12#include <linux/clk.h>
13#include <linux/clk-provider.h>
13#include <linux/platform_device.h> 14#include <linux/platform_device.h>
14#include <linux/mutex.h> 15#include <linux/mutex.h>
15#include <linux/of.h> 16#include <linux/of.h>
@@ -89,6 +90,12 @@ struct fimc_sensor_info {
89 struct fimc_dev *host; 90 struct fimc_dev *host;
90}; 91};
91 92
93struct cam_clk {
94 struct clk_hw hw;
95 struct fimc_md *fmd;
96};
97#define to_cam_clk(_hw) container_of(_hw, struct cam_clk, hw)
98
92/** 99/**
93 * struct fimc_md - fimc media device information 100 * struct fimc_md - fimc media device information
94 * @csis: MIPI CSIS subdevs data 101 * @csis: MIPI CSIS subdevs data
@@ -105,6 +112,7 @@ struct fimc_sensor_info {
105 * @pinctrl: camera port pinctrl handle 112 * @pinctrl: camera port pinctrl handle
106 * @state_default: pinctrl default state handle 113 * @state_default: pinctrl default state handle
107 * @state_idle: pinctrl idle state handle 114 * @state_idle: pinctrl idle state handle
115 * @cam_clk_provider: CAMCLK clock provider structure
108 * @user_subdev_api: true if subdevs are not configured by the host driver 116 * @user_subdev_api: true if subdevs are not configured by the host driver
109 * @slock: spinlock protecting @sensor array 117 * @slock: spinlock protecting @sensor array
110 */ 118 */
@@ -122,13 +130,22 @@ struct fimc_md {
122 struct media_device media_dev; 130 struct media_device media_dev;
123 struct v4l2_device v4l2_dev; 131 struct v4l2_device v4l2_dev;
124 struct platform_device *pdev; 132 struct platform_device *pdev;
133
125 struct fimc_pinctrl { 134 struct fimc_pinctrl {
126 struct pinctrl *pinctrl; 135 struct pinctrl *pinctrl;
127 struct pinctrl_state *state_default; 136 struct pinctrl_state *state_default;
128 struct pinctrl_state *state_idle; 137 struct pinctrl_state *state_idle;
129 } pinctl; 138 } pinctl;
130 bool user_subdev_api;
131 139
140 struct cam_clk_provider {
141 struct clk *clks[FIMC_MAX_CAMCLKS];
142 struct clk_onecell_data clk_data;
143 struct device_node *of_node;
144 struct cam_clk camclk[FIMC_MAX_CAMCLKS];
145 int num_clocks;
146 } clk_provider;
147
148 bool user_subdev_api;
132 spinlock_t slock; 149 spinlock_t slock;
133 struct list_head pipelines; 150 struct list_head pipelines;
134}; 151};