aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/i2c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-04-05 16:10:00 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-04-05 16:10:00 -0400
commit463b21fb27509061b3e97fb4fa69f26d089ddaf4 (patch)
tree4d8fb4302e4edbfb5c4dfe7c6570a4c1b4c07756 /drivers/media/i2c
parent8e0c0832348c7fda1c85d67697cfe4adf077344c (diff)
parent97e9858ed5525af5355769cd98b25b5ec94c0c85 (diff)
Merge branch 'topic/exynos' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media
Pull exynos media updates from Mauro Carvalho Chehab: "These are the remaining patches I have for the merge windows. It basically adds a new sensor and adds the needed DT bits for it to work" * 'topic/exynos' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media: [media] s5p-fimc: Remove reference to outdated macro [media] s5p-jpeg: Fix broken indentation in jpeg-regs.h [media] exynos4-is: Add the FIMC-IS ISP capture DMA driver [media] exynos4-is: Add support for asynchronous subdevices registration [media] exynos4-is: Add clock provider for the SCLK_CAM clock outputs [media] exynos4-is: Use external s5k6a3 sensor driver [media] V4L: s5c73m3: Add device tree support [media] V4L: Add driver for s5k6a3 image sensor [media] Documentation: devicetree: Update Samsung FIMC DT binding [media] Documentation: dt: Add binding documentation for S5C73M3 camera [media] Documentation: dt: Add binding documentation for S5K6A3 image sensor
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r--drivers/media/i2c/Kconfig8
-rw-r--r--drivers/media/i2c/Makefile1
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-core.c207
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3-spi.c6
-rw-r--r--drivers/media/i2c/s5c73m3/s5c73m3.h4
-rw-r--r--drivers/media/i2c/s5k6a3.c389
6 files changed, 565 insertions, 50 deletions
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index c930be30eb7e..441053be7f55 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -579,6 +579,14 @@ config VIDEO_S5K6AA
579 This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M 579 This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
580 camera sensor with an embedded SoC image signal processor. 580 camera sensor with an embedded SoC image signal processor.
581 581
582config VIDEO_S5K6A3
583 tristate "Samsung S5K6A3 sensor support"
584 depends on MEDIA_CAMERA_SUPPORT
585 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
586 ---help---
587 This is a V4L2 sensor-level driver for Samsung S5K6A3 raw
588 camera sensor.
589
582config VIDEO_S5K4ECGX 590config VIDEO_S5K4ECGX
583 tristate "Samsung S5K4ECGX sensor support" 591 tristate "Samsung S5K4ECGX sensor support"
584 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API 592 depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 01b6bfc0db5b..01ae9328e582 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -66,6 +66,7 @@ obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
66obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o 66obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
67obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o 67obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
68obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o 68obj-$(CONFIG_VIDEO_S5K6AA) += s5k6aa.o
69obj-$(CONFIG_VIDEO_S5K6A3) += s5k6a3.o
69obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o 70obj-$(CONFIG_VIDEO_S5K4ECGX) += s5k4ecgx.o
70obj-$(CONFIG_VIDEO_S5K5BAF) += s5k5baf.o 71obj-$(CONFIG_VIDEO_S5K5BAF) += s5k5baf.o
71obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/ 72obj-$(CONFIG_VIDEO_S5C73M3) += s5c73m3/
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-core.c b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
index e7f555cc827a..a4459301b5f8 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-core.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-core.c
@@ -15,7 +15,7 @@
15 * GNU General Public License for more details. 15 * GNU General Public License for more details.
16 */ 16 */
17 17
18#include <linux/sizes.h> 18#include <linux/clk.h>
19#include <linux/delay.h> 19#include <linux/delay.h>
20#include <linux/firmware.h> 20#include <linux/firmware.h>
21#include <linux/gpio.h> 21#include <linux/gpio.h>
@@ -23,7 +23,9 @@
23#include <linux/init.h> 23#include <linux/init.h>
24#include <linux/media.h> 24#include <linux/media.h>
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/of_gpio.h>
26#include <linux/regulator/consumer.h> 27#include <linux/regulator/consumer.h>
28#include <linux/sizes.h>
27#include <linux/slab.h> 29#include <linux/slab.h>
28#include <linux/spi/spi.h> 30#include <linux/spi/spi.h>
29#include <linux/videodev2.h> 31#include <linux/videodev2.h>
@@ -33,6 +35,7 @@
33#include <media/v4l2-subdev.h> 35#include <media/v4l2-subdev.h>
34#include <media/v4l2-mediabus.h> 36#include <media/v4l2-mediabus.h>
35#include <media/s5c73m3.h> 37#include <media/s5c73m3.h>
38#include <media/v4l2-of.h>
36 39
37#include "s5c73m3.h" 40#include "s5c73m3.h"
38 41
@@ -46,6 +49,8 @@ static int update_fw;
46module_param(update_fw, int, 0644); 49module_param(update_fw, int, 0644);
47 50
48#define S5C73M3_EMBEDDED_DATA_MAXLEN SZ_4K 51#define S5C73M3_EMBEDDED_DATA_MAXLEN SZ_4K
52#define S5C73M3_MIPI_DATA_LANES 4
53#define S5C73M3_CLK_NAME "cis_extclk"
49 54
50static const char * const s5c73m3_supply_names[S5C73M3_MAX_SUPPLIES] = { 55static const char * const s5c73m3_supply_names[S5C73M3_MAX_SUPPLIES] = {
51 "vdd-int", /* Digital Core supply (1.2V), CAM_ISP_CORE_1.2V */ 56 "vdd-int", /* Digital Core supply (1.2V), CAM_ISP_CORE_1.2V */
@@ -1355,9 +1360,20 @@ static int __s5c73m3_power_on(struct s5c73m3 *state)
1355 for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++) { 1360 for (i = 0; i < S5C73M3_MAX_SUPPLIES; i++) {
1356 ret = regulator_enable(state->supplies[i].consumer); 1361 ret = regulator_enable(state->supplies[i].consumer);
1357 if (ret) 1362 if (ret)
1358 goto err; 1363 goto err_reg_dis;
1359 } 1364 }
1360 1365
1366 ret = clk_set_rate(state->clock, state->mclk_frequency);
1367 if (ret < 0)
1368 goto err_reg_dis;
1369
1370 ret = clk_prepare_enable(state->clock);
1371 if (ret < 0)
1372 goto err_reg_dis;
1373
1374 v4l2_dbg(1, s5c73m3_dbg, &state->oif_sd, "clock frequency: %ld\n",
1375 clk_get_rate(state->clock));
1376
1361 s5c73m3_gpio_deassert(state, STBY); 1377 s5c73m3_gpio_deassert(state, STBY);
1362 usleep_range(100, 200); 1378 usleep_range(100, 200);
1363 1379
@@ -1365,7 +1381,8 @@ static int __s5c73m3_power_on(struct s5c73m3 *state)
1365 usleep_range(50, 100); 1381 usleep_range(50, 100);
1366 1382
1367 return 0; 1383 return 0;
1368err: 1384
1385err_reg_dis:
1369 for (--i; i >= 0; i--) 1386 for (--i; i >= 0; i--)
1370 regulator_disable(state->supplies[i].consumer); 1387 regulator_disable(state->supplies[i].consumer);
1371 return ret; 1388 return ret;
@@ -1380,6 +1397,9 @@ static int __s5c73m3_power_off(struct s5c73m3 *state)
1380 1397
1381 if (s5c73m3_gpio_assert(state, STBY)) 1398 if (s5c73m3_gpio_assert(state, STBY))
1382 usleep_range(100, 200); 1399 usleep_range(100, 200);
1400
1401 clk_disable_unprepare(state->clock);
1402
1383 state->streaming = 0; 1403 state->streaming = 0;
1384 state->isp_ready = 0; 1404 state->isp_ready = 0;
1385 1405
@@ -1388,6 +1408,7 @@ static int __s5c73m3_power_off(struct s5c73m3 *state)
1388 if (ret) 1408 if (ret)
1389 goto err; 1409 goto err;
1390 } 1410 }
1411
1391 return 0; 1412 return 0;
1392err: 1413err:
1393 for (++i; i < S5C73M3_MAX_SUPPLIES; i++) { 1414 for (++i; i < S5C73M3_MAX_SUPPLIES; i++) {
@@ -1396,6 +1417,8 @@ err:
1396 v4l2_err(&state->oif_sd, "Failed to reenable %s: %d\n", 1417 v4l2_err(&state->oif_sd, "Failed to reenable %s: %d\n",
1397 state->supplies[i].supply, r); 1418 state->supplies[i].supply, r);
1398 } 1419 }
1420
1421 clk_prepare_enable(state->clock);
1399 return ret; 1422 return ret;
1400} 1423}
1401 1424
@@ -1451,17 +1474,6 @@ static int s5c73m3_oif_registered(struct v4l2_subdev *sd)
1451 S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD, 1474 S5C73M3_JPEG_PAD, &state->oif_sd.entity, OIF_JPEG_PAD,
1452 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED); 1475 MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED);
1453 1476
1454 mutex_lock(&state->lock);
1455 ret = __s5c73m3_power_on(state);
1456 if (ret == 0)
1457 s5c73m3_get_fw_version(state);
1458
1459 __s5c73m3_power_off(state);
1460 mutex_unlock(&state->lock);
1461
1462 v4l2_dbg(1, s5c73m3_dbg, sd, "%s: Booting %s (%d)\n",
1463 __func__, ret ? "failed" : "succeeded", ret);
1464
1465 return ret; 1477 return ret;
1466} 1478}
1467 1479
@@ -1519,41 +1531,112 @@ static const struct v4l2_subdev_ops oif_subdev_ops = {
1519 .video = &s5c73m3_oif_video_ops, 1531 .video = &s5c73m3_oif_video_ops,
1520}; 1532};
1521 1533
1522static int s5c73m3_configure_gpios(struct s5c73m3 *state, 1534static int s5c73m3_configure_gpios(struct s5c73m3 *state)
1523 const struct s5c73m3_platform_data *pdata) 1535{
1536 static const char * const gpio_names[] = {
1537 "S5C73M3_STBY", "S5C73M3_RST"
1538 };
1539 struct i2c_client *c = state->i2c_client;
1540 struct s5c73m3_gpio *g = state->gpio;
1541 int ret, i;
1542
1543 for (i = 0; i < GPIO_NUM; ++i) {
1544 unsigned int flags = GPIOF_DIR_OUT;
1545 if (g[i].level)
1546 flags |= GPIOF_INIT_HIGH;
1547 ret = devm_gpio_request_one(&c->dev, g[i].gpio, flags,
1548 gpio_names[i]);
1549 if (ret) {
1550 v4l2_err(c, "failed to request gpio %s\n",
1551 gpio_names[i]);
1552 return ret;
1553 }
1554 }
1555 return 0;
1556}
1557
1558static int s5c73m3_parse_gpios(struct s5c73m3 *state)
1559{
1560 static const char * const prop_names[] = {
1561 "standby-gpios", "xshutdown-gpios",
1562 };
1563 struct device *dev = &state->i2c_client->dev;
1564 struct device_node *node = dev->of_node;
1565 int ret, i;
1566
1567 for (i = 0; i < GPIO_NUM; ++i) {
1568 enum of_gpio_flags of_flags;
1569
1570 ret = of_get_named_gpio_flags(node, prop_names[i],
1571 0, &of_flags);
1572 if (ret < 0) {
1573 dev_err(dev, "failed to parse %s DT property\n",
1574 prop_names[i]);
1575 return -EINVAL;
1576 }
1577 state->gpio[i].gpio = ret;
1578 state->gpio[i].level = !(of_flags & OF_GPIO_ACTIVE_LOW);
1579 }
1580 return 0;
1581}
1582
1583static int s5c73m3_get_platform_data(struct s5c73m3 *state)
1524{ 1584{
1525 struct device *dev = &state->i2c_client->dev; 1585 struct device *dev = &state->i2c_client->dev;
1526 const struct s5c73m3_gpio *gpio; 1586 const struct s5c73m3_platform_data *pdata = dev->platform_data;
1527 unsigned long flags; 1587 struct device_node *node = dev->of_node;
1588 struct device_node *node_ep;
1589 struct v4l2_of_endpoint ep;
1528 int ret; 1590 int ret;
1529 1591
1530 state->gpio[STBY].gpio = -EINVAL; 1592 if (!node) {
1531 state->gpio[RST].gpio = -EINVAL; 1593 if (!pdata) {
1594 dev_err(dev, "Platform data not specified\n");
1595 return -EINVAL;
1596 }
1532 1597
1533 gpio = &pdata->gpio_stby; 1598 state->mclk_frequency = pdata->mclk_frequency;
1534 if (gpio_is_valid(gpio->gpio)) { 1599 state->gpio[STBY] = pdata->gpio_stby;
1535 flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) 1600 state->gpio[RST] = pdata->gpio_reset;
1536 | GPIOF_EXPORT; 1601 return 0;
1537 ret = devm_gpio_request_one(dev, gpio->gpio, flags, 1602 }
1538 "S5C73M3_STBY"); 1603
1539 if (ret < 0) 1604 state->clock = devm_clk_get(dev, S5C73M3_CLK_NAME);
1540 return ret; 1605 if (IS_ERR(state->clock))
1606 return PTR_ERR(state->clock);
1541 1607
1542 state->gpio[STBY] = *gpio; 1608 if (of_property_read_u32(node, "clock-frequency",
1609 &state->mclk_frequency)) {
1610 state->mclk_frequency = S5C73M3_DEFAULT_MCLK_FREQ;
1611 dev_info(dev, "using default %u Hz clock frequency\n",
1612 state->mclk_frequency);
1543 } 1613 }
1544 1614
1545 gpio = &pdata->gpio_reset; 1615 ret = s5c73m3_parse_gpios(state);
1546 if (gpio_is_valid(gpio->gpio)) { 1616 if (ret < 0)
1547 flags = (gpio->level ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW) 1617 return -EINVAL;
1548 | GPIOF_EXPORT;
1549 ret = devm_gpio_request_one(dev, gpio->gpio, flags,
1550 "S5C73M3_RST");
1551 if (ret < 0)
1552 return ret;
1553 1618
1554 state->gpio[RST] = *gpio; 1619 node_ep = v4l2_of_get_next_endpoint(node, NULL);
1620 if (!node_ep) {
1621 dev_warn(dev, "no endpoint defined for node: %s\n",
1622 node->full_name);
1623 return 0;
1555 } 1624 }
1556 1625
1626 v4l2_of_parse_endpoint(node_ep, &ep);
1627 of_node_put(node_ep);
1628
1629 if (ep.bus_type != V4L2_MBUS_CSI2) {
1630 dev_err(dev, "unsupported bus type\n");
1631 return -EINVAL;
1632 }
1633 /*
1634 * Number of MIPI CSI-2 data lanes is currently not configurable,
1635 * always a default value of 4 lanes is used.
1636 */
1637 if (ep.bus.mipi_csi2.num_data_lanes != S5C73M3_MIPI_DATA_LANES)
1638 dev_info(dev, "falling back to 4 MIPI CSI-2 data lanes\n");
1639
1557 return 0; 1640 return 0;
1558} 1641}
1559 1642
@@ -1561,21 +1644,20 @@ static int s5c73m3_probe(struct i2c_client *client,
1561 const struct i2c_device_id *id) 1644 const struct i2c_device_id *id)
1562{ 1645{
1563 struct device *dev = &client->dev; 1646 struct device *dev = &client->dev;
1564 const struct s5c73m3_platform_data *pdata = client->dev.platform_data;
1565 struct v4l2_subdev *sd; 1647 struct v4l2_subdev *sd;
1566 struct v4l2_subdev *oif_sd; 1648 struct v4l2_subdev *oif_sd;
1567 struct s5c73m3 *state; 1649 struct s5c73m3 *state;
1568 int ret, i; 1650 int ret, i;
1569 1651
1570 if (pdata == NULL) {
1571 dev_err(&client->dev, "Platform data not specified\n");
1572 return -EINVAL;
1573 }
1574
1575 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL); 1652 state = devm_kzalloc(dev, sizeof(*state), GFP_KERNEL);
1576 if (!state) 1653 if (!state)
1577 return -ENOMEM; 1654 return -ENOMEM;
1578 1655
1656 state->i2c_client = client;
1657 ret = s5c73m3_get_platform_data(state);
1658 if (ret < 0)
1659 return ret;
1660
1579 mutex_init(&state->lock); 1661 mutex_init(&state->lock);
1580 sd = &state->sensor_sd; 1662 sd = &state->sensor_sd;
1581 oif_sd = &state->oif_sd; 1663 oif_sd = &state->oif_sd;
@@ -1613,11 +1695,7 @@ static int s5c73m3_probe(struct i2c_client *client,
1613 if (ret < 0) 1695 if (ret < 0)
1614 return ret; 1696 return ret;
1615 1697
1616 state->mclk_frequency = pdata->mclk_frequency; 1698 ret = s5c73m3_configure_gpios(state);
1617 state->bus_type = pdata->bus_type;
1618 state->i2c_client = client;
1619
1620 ret = s5c73m3_configure_gpios(state, pdata);
1621 if (ret) 1699 if (ret)
1622 goto out_err; 1700 goto out_err;
1623 1701
@@ -1651,9 +1729,29 @@ static int s5c73m3_probe(struct i2c_client *client,
1651 if (ret < 0) 1729 if (ret < 0)
1652 goto out_err; 1730 goto out_err;
1653 1731
1732 oif_sd->dev = dev;
1733
1734 ret = __s5c73m3_power_on(state);
1735 if (ret < 0)
1736 goto out_err1;
1737
1738 ret = s5c73m3_get_fw_version(state);
1739 __s5c73m3_power_off(state);
1740
1741 if (ret < 0) {
1742 dev_err(dev, "Device detection failed: %d\n", ret);
1743 goto out_err1;
1744 }
1745
1746 ret = v4l2_async_register_subdev(oif_sd);
1747 if (ret < 0)
1748 goto out_err1;
1749
1654 v4l2_info(sd, "%s: completed successfully\n", __func__); 1750 v4l2_info(sd, "%s: completed successfully\n", __func__);
1655 return 0; 1751 return 0;
1656 1752
1753out_err1:
1754 s5c73m3_unregister_spi_driver(state);
1657out_err: 1755out_err:
1658 media_entity_cleanup(&sd->entity); 1756 media_entity_cleanup(&sd->entity);
1659 return ret; 1757 return ret;
@@ -1665,7 +1763,7 @@ static int s5c73m3_remove(struct i2c_client *client)
1665 struct s5c73m3 *state = oif_sd_to_s5c73m3(oif_sd); 1763 struct s5c73m3 *state = oif_sd_to_s5c73m3(oif_sd);
1666 struct v4l2_subdev *sensor_sd = &state->sensor_sd; 1764 struct v4l2_subdev *sensor_sd = &state->sensor_sd;
1667 1765
1668 v4l2_device_unregister_subdev(oif_sd); 1766 v4l2_async_unregister_subdev(oif_sd);
1669 1767
1670 v4l2_ctrl_handler_free(oif_sd->ctrl_handler); 1768 v4l2_ctrl_handler_free(oif_sd->ctrl_handler);
1671 media_entity_cleanup(&oif_sd->entity); 1769 media_entity_cleanup(&oif_sd->entity);
@@ -1684,8 +1782,17 @@ static const struct i2c_device_id s5c73m3_id[] = {
1684}; 1782};
1685MODULE_DEVICE_TABLE(i2c, s5c73m3_id); 1783MODULE_DEVICE_TABLE(i2c, s5c73m3_id);
1686 1784
1785#ifdef CONFIG_OF
1786static const struct of_device_id s5c73m3_of_match[] = {
1787 { .compatible = "samsung,s5c73m3" },
1788 { }
1789};
1790MODULE_DEVICE_TABLE(of, s5c73m3_of_match);
1791#endif
1792
1687static struct i2c_driver s5c73m3_i2c_driver = { 1793static struct i2c_driver s5c73m3_i2c_driver = {
1688 .driver = { 1794 .driver = {
1795 .of_match_table = of_match_ptr(s5c73m3_of_match),
1689 .name = DRIVER_NAME, 1796 .name = DRIVER_NAME,
1690 }, 1797 },
1691 .probe = s5c73m3_probe, 1798 .probe = s5c73m3_probe,
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
index 8079e26eb5e2..f60b265b4da1 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
+++ b/drivers/media/i2c/s5c73m3/s5c73m3-spi.c
@@ -27,6 +27,11 @@
27 27
28#define S5C73M3_SPI_DRV_NAME "S5C73M3-SPI" 28#define S5C73M3_SPI_DRV_NAME "S5C73M3-SPI"
29 29
30static const struct of_device_id s5c73m3_spi_ids[] = {
31 { .compatible = "samsung,s5c73m3" },
32 { }
33};
34
30enum spi_direction { 35enum spi_direction {
31 SPI_DIR_RX, 36 SPI_DIR_RX,
32 SPI_DIR_TX 37 SPI_DIR_TX
@@ -146,6 +151,7 @@ int s5c73m3_register_spi_driver(struct s5c73m3 *state)
146 spidrv->driver.name = S5C73M3_SPI_DRV_NAME; 151 spidrv->driver.name = S5C73M3_SPI_DRV_NAME;
147 spidrv->driver.bus = &spi_bus_type; 152 spidrv->driver.bus = &spi_bus_type;
148 spidrv->driver.owner = THIS_MODULE; 153 spidrv->driver.owner = THIS_MODULE;
154 spidrv->driver.of_match_table = s5c73m3_spi_ids;
149 155
150 return spi_register_driver(spidrv); 156 return spi_register_driver(spidrv);
151} 157}
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h
index 9dfa516f6944..9656b6723dc6 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3.h
+++ b/drivers/media/i2c/s5c73m3/s5c73m3.h
@@ -17,6 +17,7 @@
17#ifndef S5C73M3_H_ 17#ifndef S5C73M3_H_
18#define S5C73M3_H_ 18#define S5C73M3_H_
19 19
20#include <linux/clk.h>
20#include <linux/kernel.h> 21#include <linux/kernel.h>
21#include <linux/regulator/consumer.h> 22#include <linux/regulator/consumer.h>
22#include <media/v4l2-common.h> 23#include <media/v4l2-common.h>
@@ -321,6 +322,7 @@ enum s5c73m3_oif_pads {
321 322
322 323
323#define S5C73M3_MAX_SUPPLIES 6 324#define S5C73M3_MAX_SUPPLIES 6
325#define S5C73M3_DEFAULT_MCLK_FREQ 24000000U
324 326
325struct s5c73m3_ctrls { 327struct s5c73m3_ctrls {
326 struct v4l2_ctrl_handler handler; 328 struct v4l2_ctrl_handler handler;
@@ -391,6 +393,8 @@ struct s5c73m3 {
391 struct regulator_bulk_data supplies[S5C73M3_MAX_SUPPLIES]; 393 struct regulator_bulk_data supplies[S5C73M3_MAX_SUPPLIES];
392 struct s5c73m3_gpio gpio[GPIO_NUM]; 394 struct s5c73m3_gpio gpio[GPIO_NUM];
393 395
396 struct clk *clock;
397
394 /* External master clock frequency */ 398 /* External master clock frequency */
395 u32 mclk_frequency; 399 u32 mclk_frequency;
396 /* Video bus type - MIPI-CSI2/parallel */ 400 /* Video bus type - MIPI-CSI2/parallel */
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c
new file mode 100644
index 000000000000..7bc2271ca009
--- /dev/null
+++ b/drivers/media/i2c/s5k6a3.c
@@ -0,0 +1,389 @@
1/*
2 * Samsung S5K6A3 image sensor driver
3 *
4 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
5 * Author: Sylwester Nawrocki <s.nawrocki@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/clk.h>
13#include <linux/delay.h>
14#include <linux/device.h>
15#include <linux/errno.h>
16#include <linux/gpio.h>
17#include <linux/i2c.h>
18#include <linux/kernel.h>
19#include <linux/module.h>
20#include <linux/of_gpio.h>
21#include <linux/pm_runtime.h>
22#include <linux/regulator/consumer.h>
23#include <linux/slab.h>
24#include <linux/videodev2.h>
25#include <media/v4l2-async.h>
26#include <media/v4l2-subdev.h>
27
28#define S5K6A3_SENSOR_MAX_WIDTH 1412
29#define S5K6A3_SENSOR_MAX_HEIGHT 1412
30#define S5K6A3_SENSOR_MIN_WIDTH 32
31#define S5K6A3_SENSOR_MIN_HEIGHT 32
32
33#define S5K6A3_DEFAULT_WIDTH 1296
34#define S5K6A3_DEFAULT_HEIGHT 732
35
36#define S5K6A3_DRV_NAME "S5K6A3"
37#define S5K6A3_CLK_NAME "extclk"
38#define S5K6A3_DEFAULT_CLK_FREQ 24000000U
39
40enum {
41 S5K6A3_SUPP_VDDA,
42 S5K6A3_SUPP_VDDIO,
43 S5K6A3_SUPP_AFVDD,
44 S5K6A3_NUM_SUPPLIES,
45};
46
47/**
48 * struct s5k6a3 - fimc-is sensor data structure
49 * @dev: pointer to this I2C client device structure
50 * @subdev: the image sensor's v4l2 subdev
51 * @pad: subdev media source pad
52 * @supplies: image sensor's voltage regulator supplies
53 * @gpio_reset: GPIO connected to the sensor's reset pin
54 * @lock: mutex protecting the structure's members below
55 * @format: media bus format at the sensor's source pad
56 */
57struct s5k6a3 {
58 struct device *dev;
59 struct v4l2_subdev subdev;
60 struct media_pad pad;
61 struct regulator_bulk_data supplies[S5K6A3_NUM_SUPPLIES];
62 int gpio_reset;
63 struct mutex lock;
64 struct v4l2_mbus_framefmt format;
65 struct clk *clock;
66 u32 clock_frequency;
67 int power_count;
68};
69
70static const char * const s5k6a3_supply_names[] = {
71 [S5K6A3_SUPP_VDDA] = "svdda",
72 [S5K6A3_SUPP_VDDIO] = "svddio",
73 [S5K6A3_SUPP_AFVDD] = "afvdd",
74};
75
76static inline struct s5k6a3 *sd_to_s5k6a3(struct v4l2_subdev *sd)
77{
78 return container_of(sd, struct s5k6a3, subdev);
79}
80
81static const struct v4l2_mbus_framefmt s5k6a3_formats[] = {
82 {
83 .code = V4L2_MBUS_FMT_SGRBG10_1X10,
84 .colorspace = V4L2_COLORSPACE_SRGB,
85 .field = V4L2_FIELD_NONE,
86 }
87};
88
89static const struct v4l2_mbus_framefmt *find_sensor_format(
90 struct v4l2_mbus_framefmt *mf)
91{
92 int i;
93
94 for (i = 0; i < ARRAY_SIZE(s5k6a3_formats); i++)
95 if (mf->code == s5k6a3_formats[i].code)
96 return &s5k6a3_formats[i];
97
98 return &s5k6a3_formats[0];
99}
100
101static int s5k6a3_enum_mbus_code(struct v4l2_subdev *sd,
102 struct v4l2_subdev_fh *fh,
103 struct v4l2_subdev_mbus_code_enum *code)
104{
105 if (code->index >= ARRAY_SIZE(s5k6a3_formats))
106 return -EINVAL;
107
108 code->code = s5k6a3_formats[code->index].code;
109 return 0;
110}
111
112static void s5k6a3_try_format(struct v4l2_mbus_framefmt *mf)
113{
114 const struct v4l2_mbus_framefmt *fmt;
115
116 fmt = find_sensor_format(mf);
117 mf->code = fmt->code;
118 v4l_bound_align_image(&mf->width, S5K6A3_SENSOR_MIN_WIDTH,
119 S5K6A3_SENSOR_MAX_WIDTH, 0,
120 &mf->height, S5K6A3_SENSOR_MIN_HEIGHT,
121 S5K6A3_SENSOR_MAX_HEIGHT, 0, 0);
122}
123
124static struct v4l2_mbus_framefmt *__s5k6a3_get_format(
125 struct s5k6a3 *sensor, struct v4l2_subdev_fh *fh,
126 u32 pad, enum v4l2_subdev_format_whence which)
127{
128 if (which == V4L2_SUBDEV_FORMAT_TRY)
129 return fh ? v4l2_subdev_get_try_format(fh, pad) : NULL;
130
131 return &sensor->format;
132}
133
134static int s5k6a3_set_fmt(struct v4l2_subdev *sd,
135 struct v4l2_subdev_fh *fh,
136 struct v4l2_subdev_format *fmt)
137{
138 struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
139 struct v4l2_mbus_framefmt *mf;
140
141 s5k6a3_try_format(&fmt->format);
142
143 mf = __s5k6a3_get_format(sensor, fh, fmt->pad, fmt->which);
144 if (mf) {
145 mutex_lock(&sensor->lock);
146 if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
147 *mf = fmt->format;
148 mutex_unlock(&sensor->lock);
149 }
150 return 0;
151}
152
153static int s5k6a3_get_fmt(struct v4l2_subdev *sd,
154 struct v4l2_subdev_fh *fh,
155 struct v4l2_subdev_format *fmt)
156{
157 struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
158 struct v4l2_mbus_framefmt *mf;
159
160 mf = __s5k6a3_get_format(sensor, fh, fmt->pad, fmt->which);
161
162 mutex_lock(&sensor->lock);
163 fmt->format = *mf;
164 mutex_unlock(&sensor->lock);
165 return 0;
166}
167
168static struct v4l2_subdev_pad_ops s5k6a3_pad_ops = {
169 .enum_mbus_code = s5k6a3_enum_mbus_code,
170 .get_fmt = s5k6a3_get_fmt,
171 .set_fmt = s5k6a3_set_fmt,
172};
173
174static int s5k6a3_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
175{
176 struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
177
178 *format = s5k6a3_formats[0];
179 format->width = S5K6A3_DEFAULT_WIDTH;
180 format->height = S5K6A3_DEFAULT_HEIGHT;
181
182 return 0;
183}
184
185static const struct v4l2_subdev_internal_ops s5k6a3_sd_internal_ops = {
186 .open = s5k6a3_open,
187};
188
189static int __s5k6a3_power_on(struct s5k6a3 *sensor)
190{
191 int i = S5K6A3_SUPP_VDDA;
192 int ret;
193
194 ret = clk_set_rate(sensor->clock, sensor->clock_frequency);
195 if (ret < 0)
196 return ret;
197
198 ret = pm_runtime_get(sensor->dev);
199 if (ret < 0)
200 return ret;
201
202 ret = regulator_enable(sensor->supplies[i].consumer);
203 if (ret < 0)
204 goto error_rpm_put;
205
206 ret = clk_prepare_enable(sensor->clock);
207 if (ret < 0)
208 goto error_reg_dis;
209
210 for (i++; i < S5K6A3_NUM_SUPPLIES; i++) {
211 ret = regulator_enable(sensor->supplies[i].consumer);
212 if (ret < 0)
213 goto error_reg_dis;
214 }
215
216 gpio_set_value(sensor->gpio_reset, 1);
217 usleep_range(600, 800);
218 gpio_set_value(sensor->gpio_reset, 0);
219 usleep_range(600, 800);
220 gpio_set_value(sensor->gpio_reset, 1);
221
222 /* Delay needed for the sensor initialization */
223 msleep(20);
224 return 0;
225
226error_reg_dis:
227 for (--i; i >= 0; --i)
228 regulator_disable(sensor->supplies[i].consumer);
229error_rpm_put:
230 pm_runtime_put(sensor->dev);
231 return ret;
232}
233
234static int __s5k6a3_power_off(struct s5k6a3 *sensor)
235{
236 int i;
237
238 gpio_set_value(sensor->gpio_reset, 0);
239
240 for (i = S5K6A3_NUM_SUPPLIES - 1; i >= 0; i--)
241 regulator_disable(sensor->supplies[i].consumer);
242
243 clk_disable_unprepare(sensor->clock);
244 pm_runtime_put(sensor->dev);
245 return 0;
246}
247
248static int s5k6a3_s_power(struct v4l2_subdev *sd, int on)
249{
250 struct s5k6a3 *sensor = sd_to_s5k6a3(sd);
251 int ret = 0;
252
253 mutex_lock(&sensor->lock);
254
255 if (sensor->power_count == !on) {
256 if (on)
257 ret = __s5k6a3_power_on(sensor);
258 else
259 ret = __s5k6a3_power_off(sensor);
260
261 if (ret == 0)
262 sensor->power_count += on ? 1 : -1;
263 }
264
265 mutex_unlock(&sensor->lock);
266 return ret;
267}
268
269static struct v4l2_subdev_core_ops s5k6a3_core_ops = {
270 .s_power = s5k6a3_s_power,
271};
272
273static struct v4l2_subdev_ops s5k6a3_subdev_ops = {
274 .core = &s5k6a3_core_ops,
275 .pad = &s5k6a3_pad_ops,
276};
277
278static int s5k6a3_probe(struct i2c_client *client,
279 const struct i2c_device_id *id)
280{
281 struct device *dev = &client->dev;
282 struct s5k6a3 *sensor;
283 struct v4l2_subdev *sd;
284 int gpio, i, ret;
285
286 sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
287 if (!sensor)
288 return -ENOMEM;
289
290 mutex_init(&sensor->lock);
291 sensor->gpio_reset = -EINVAL;
292 sensor->clock = ERR_PTR(-EINVAL);
293 sensor->dev = dev;
294
295 sensor->clock = devm_clk_get(sensor->dev, S5K6A3_CLK_NAME);
296 if (IS_ERR(sensor->clock))
297 return PTR_ERR(sensor->clock);
298
299 gpio = of_get_gpio_flags(dev->of_node, 0, NULL);
300 if (!gpio_is_valid(gpio))
301 return gpio;
302
303 ret = devm_gpio_request_one(dev, gpio, GPIOF_OUT_INIT_LOW,
304 S5K6A3_DRV_NAME);
305 if (ret < 0)
306 return ret;
307
308 sensor->gpio_reset = gpio;
309
310 if (of_property_read_u32(dev->of_node, "clock-frequency",
311 &sensor->clock_frequency)) {
312 sensor->clock_frequency = S5K6A3_DEFAULT_CLK_FREQ;
313 dev_info(dev, "using default %u Hz clock frequency\n",
314 sensor->clock_frequency);
315 }
316
317 for (i = 0; i < S5K6A3_NUM_SUPPLIES; i++)
318 sensor->supplies[i].supply = s5k6a3_supply_names[i];
319
320 ret = devm_regulator_bulk_get(&client->dev, S5K6A3_NUM_SUPPLIES,
321 sensor->supplies);
322 if (ret < 0)
323 return ret;
324
325 sd = &sensor->subdev;
326 v4l2_i2c_subdev_init(sd, client, &s5k6a3_subdev_ops);
327 sensor->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
328 sd->internal_ops = &s5k6a3_sd_internal_ops;
329
330 sensor->format.code = s5k6a3_formats[0].code;
331 sensor->format.width = S5K6A3_DEFAULT_WIDTH;
332 sensor->format.height = S5K6A3_DEFAULT_HEIGHT;
333
334 sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
335 ret = media_entity_init(&sd->entity, 1, &sensor->pad, 0);
336 if (ret < 0)
337 return ret;
338
339 pm_runtime_no_callbacks(dev);
340 pm_runtime_enable(dev);
341
342 ret = v4l2_async_register_subdev(sd);
343
344 if (ret < 0) {
345 pm_runtime_disable(&client->dev);
346 media_entity_cleanup(&sd->entity);
347 }
348
349 return ret;
350}
351
352static int s5k6a3_remove(struct i2c_client *client)
353{
354 struct v4l2_subdev *sd = i2c_get_clientdata(client);
355
356 pm_runtime_disable(&client->dev);
357 v4l2_async_unregister_subdev(sd);
358 media_entity_cleanup(&sd->entity);
359 return 0;
360}
361
362static const struct i2c_device_id s5k6a3_ids[] = {
363 { }
364};
365
366#ifdef CONFIG_OF
367static const struct of_device_id s5k6a3_of_match[] = {
368 { .compatible = "samsung,s5k6a3" },
369 { /* sentinel */ }
370};
371MODULE_DEVICE_TABLE(of, s5k6a3_of_match);
372#endif
373
374static struct i2c_driver s5k6a3_driver = {
375 .driver = {
376 .of_match_table = of_match_ptr(s5k6a3_of_match),
377 .name = S5K6A3_DRV_NAME,
378 .owner = THIS_MODULE,
379 },
380 .probe = s5k6a3_probe,
381 .remove = s5k6a3_remove,
382 .id_table = s5k6a3_ids,
383};
384
385module_i2c_driver(s5k6a3_driver);
386
387MODULE_DESCRIPTION("S5K6A3 image sensor subdev driver");
388MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
389MODULE_LICENSE("GPL v2");