diff options
author | Ben Dooks <ben.dooks@codethink.co.uk> | 2014-07-05 18:26:22 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-07-30 18:34:45 -0400 |
commit | 47c71bd61b772cd72159dff4aae43734257a485a (patch) | |
tree | 9511f78c0482c90e76b5105edd300cabf9319cb2 | |
parent | e9a1d94fa85542d4f3046ac82d234a3c8349c948 (diff) |
[media] rcar_vin: add devicetree support
Add support for devicetree probe for the rcar-vin
driver.
Signed-off-by: Ben Dooks <ben.dooks@codethink.co.uk>
[g.liakhovetski@gmx.de fix a typo, sort headers alphabetically]
Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
-rw-r--r-- | Documentation/devicetree/bindings/media/rcar_vin.txt | 86 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/rcar_vin.c | 72 |
2 files changed, 151 insertions, 7 deletions
diff --git a/Documentation/devicetree/bindings/media/rcar_vin.txt b/Documentation/devicetree/bindings/media/rcar_vin.txt new file mode 100644 index 000000000000..ba61782c2af9 --- /dev/null +++ b/Documentation/devicetree/bindings/media/rcar_vin.txt | |||
@@ -0,0 +1,86 @@ | |||
1 | Renesas RCar Video Input driver (rcar_vin) | ||
2 | ------------------------------------------ | ||
3 | |||
4 | The rcar_vin device provides video input capabilities for the Renesas R-Car | ||
5 | family of devices. The current blocks are always slaves and suppot one input | ||
6 | channel which can be either RGB, YUYV or BT656. | ||
7 | |||
8 | - compatible: Must be one of the following | ||
9 | - "renesas,vin-r8a7791" for the R8A7791 device | ||
10 | - "renesas,vin-r8a7790" for the R8A7790 device | ||
11 | - "renesas,vin-r8a7779" for the R8A7779 device | ||
12 | - "renesas,vin-r8a7778" for the R8A7778 device | ||
13 | - reg: the register base and size for the device registers | ||
14 | - interrupts: the interrupt for the device | ||
15 | - clocks: Reference to the parent clock | ||
16 | |||
17 | Additionally, an alias named vinX will need to be created to specify | ||
18 | which video input device this is. | ||
19 | |||
20 | The per-board settings: | ||
21 | - port sub-node describing a single endpoint connected to the vin | ||
22 | as described in video-interfaces.txt[1]. Only the first one will | ||
23 | be considered as each vin interface has one input port. | ||
24 | |||
25 | These settings are used to work out video input format and widths | ||
26 | into the system. | ||
27 | |||
28 | |||
29 | Device node example | ||
30 | ------------------- | ||
31 | |||
32 | aliases { | ||
33 | vin0 = &vin0; | ||
34 | }; | ||
35 | |||
36 | vin0: vin@0xe6ef0000 { | ||
37 | compatible = "renesas,vin-r8a7790"; | ||
38 | clocks = <&mstp8_clks R8A7790_CLK_VIN0>; | ||
39 | reg = <0 0xe6ef0000 0 0x1000>; | ||
40 | interrupts = <0 188 IRQ_TYPE_LEVEL_HIGH>; | ||
41 | status = "disabled"; | ||
42 | }; | ||
43 | |||
44 | Board setup example (vin1 composite video input) | ||
45 | ------------------------------------------------ | ||
46 | |||
47 | &i2c2 { | ||
48 | status = "ok"; | ||
49 | pinctrl-0 = <&i2c2_pins>; | ||
50 | pinctrl-names = "default"; | ||
51 | |||
52 | adv7180@20 { | ||
53 | compatible = "adi,adv7180"; | ||
54 | reg = <0x20>; | ||
55 | remote = <&vin1>; | ||
56 | |||
57 | port { | ||
58 | adv7180: endpoint { | ||
59 | bus-width = <8>; | ||
60 | remote-endpoint = <&vin1ep0>; | ||
61 | }; | ||
62 | }; | ||
63 | }; | ||
64 | }; | ||
65 | |||
66 | /* composite video input */ | ||
67 | &vin1 { | ||
68 | pinctrl-0 = <&vin1_pins>; | ||
69 | pinctrl-names = "default"; | ||
70 | |||
71 | status = "ok"; | ||
72 | |||
73 | port { | ||
74 | #address-cells = <1>; | ||
75 | #size-cells = <0>; | ||
76 | |||
77 | vin1ep0: endpoint { | ||
78 | remote-endpoint = <&adv7180>; | ||
79 | bus-width = <8>; | ||
80 | }; | ||
81 | }; | ||
82 | }; | ||
83 | |||
84 | |||
85 | |||
86 | [1] video-interfaces.txt common video media interface | ||
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c index 7c4299d9a100..85d579f65f52 100644 --- a/drivers/media/platform/soc_camera/rcar_vin.c +++ b/drivers/media/platform/soc_camera/rcar_vin.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | #include <linux/kernel.h> | 20 | #include <linux/kernel.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/of.h> | ||
23 | #include <linux/of_device.h> | ||
22 | #include <linux/platform_data/camera-rcar.h> | 24 | #include <linux/platform_data/camera-rcar.h> |
23 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
24 | #include <linux/pm_runtime.h> | 26 | #include <linux/pm_runtime.h> |
@@ -31,6 +33,7 @@ | |||
31 | #include <media/v4l2-dev.h> | 33 | #include <media/v4l2-dev.h> |
32 | #include <media/v4l2-device.h> | 34 | #include <media/v4l2-device.h> |
33 | #include <media/v4l2-mediabus.h> | 35 | #include <media/v4l2-mediabus.h> |
36 | #include <media/v4l2-of.h> | ||
34 | #include <media/v4l2-subdev.h> | 37 | #include <media/v4l2-subdev.h> |
35 | #include <media/videobuf2-dma-contig.h> | 38 | #include <media/videobuf2-dma-contig.h> |
36 | 39 | ||
@@ -1390,6 +1393,17 @@ static struct soc_camera_host_ops rcar_vin_host_ops = { | |||
1390 | .init_videobuf2 = rcar_vin_init_videobuf2, | 1393 | .init_videobuf2 = rcar_vin_init_videobuf2, |
1391 | }; | 1394 | }; |
1392 | 1395 | ||
1396 | #ifdef CONFIG_OF | ||
1397 | static struct of_device_id rcar_vin_of_table[] = { | ||
1398 | { .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 }, | ||
1399 | { .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 }, | ||
1400 | { .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 }, | ||
1401 | { .compatible = "renesas,vin-r8a7778", .data = (void *)RCAR_M1 }, | ||
1402 | { }, | ||
1403 | }; | ||
1404 | MODULE_DEVICE_TABLE(of, rcar_vin_of_table); | ||
1405 | #endif | ||
1406 | |||
1393 | static struct platform_device_id rcar_vin_id_table[] = { | 1407 | static struct platform_device_id rcar_vin_id_table[] = { |
1394 | { "r8a7791-vin", RCAR_GEN2 }, | 1408 | { "r8a7791-vin", RCAR_GEN2 }, |
1395 | { "r8a7790-vin", RCAR_GEN2 }, | 1409 | { "r8a7790-vin", RCAR_GEN2 }, |
@@ -1402,15 +1416,52 @@ MODULE_DEVICE_TABLE(platform, rcar_vin_id_table); | |||
1402 | 1416 | ||
1403 | static int rcar_vin_probe(struct platform_device *pdev) | 1417 | static int rcar_vin_probe(struct platform_device *pdev) |
1404 | { | 1418 | { |
1419 | const struct of_device_id *match = NULL; | ||
1405 | struct rcar_vin_priv *priv; | 1420 | struct rcar_vin_priv *priv; |
1406 | struct resource *mem; | 1421 | struct resource *mem; |
1407 | struct rcar_vin_platform_data *pdata; | 1422 | struct rcar_vin_platform_data *pdata; |
1423 | unsigned int pdata_flags; | ||
1408 | int irq, ret; | 1424 | int irq, ret; |
1409 | 1425 | ||
1410 | pdata = pdev->dev.platform_data; | 1426 | if (pdev->dev.of_node) { |
1411 | if (!pdata || !pdata->flags) { | 1427 | struct v4l2_of_endpoint ep; |
1412 | dev_err(&pdev->dev, "platform data not set\n"); | 1428 | struct device_node *np; |
1413 | return -EINVAL; | 1429 | |
1430 | match = of_match_device(of_match_ptr(rcar_vin_of_table), | ||
1431 | &pdev->dev); | ||
1432 | |||
1433 | np = of_graph_get_next_endpoint(pdev->dev.of_node, NULL); | ||
1434 | if (!np) { | ||
1435 | dev_err(&pdev->dev, "could not find endpoint\n"); | ||
1436 | return -EINVAL; | ||
1437 | } | ||
1438 | |||
1439 | ret = v4l2_of_parse_endpoint(np, &ep); | ||
1440 | if (ret) { | ||
1441 | dev_err(&pdev->dev, "could not parse endpoint\n"); | ||
1442 | return ret; | ||
1443 | } | ||
1444 | |||
1445 | if (ep.bus_type == V4L2_MBUS_BT656) | ||
1446 | pdata_flags = RCAR_VIN_BT656; | ||
1447 | else { | ||
1448 | pdata_flags = 0; | ||
1449 | if (ep.bus.parallel.flags & V4L2_MBUS_HSYNC_ACTIVE_LOW) | ||
1450 | pdata_flags |= RCAR_VIN_HSYNC_ACTIVE_LOW; | ||
1451 | if (ep.bus.parallel.flags & V4L2_MBUS_VSYNC_ACTIVE_LOW) | ||
1452 | pdata_flags |= RCAR_VIN_VSYNC_ACTIVE_LOW; | ||
1453 | } | ||
1454 | |||
1455 | of_node_put(np); | ||
1456 | |||
1457 | dev_dbg(&pdev->dev, "pdata_flags = %08x\n", pdata_flags); | ||
1458 | } else { | ||
1459 | pdata = pdev->dev.platform_data; | ||
1460 | if (!pdata || !pdata->flags) { | ||
1461 | dev_err(&pdev->dev, "platform data not set\n"); | ||
1462 | return -EINVAL; | ||
1463 | } | ||
1464 | pdata_flags = pdata->flags; | ||
1414 | } | 1465 | } |
1415 | 1466 | ||
1416 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1467 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -1441,12 +1492,18 @@ static int rcar_vin_probe(struct platform_device *pdev) | |||
1441 | 1492 | ||
1442 | priv->ici.priv = priv; | 1493 | priv->ici.priv = priv; |
1443 | priv->ici.v4l2_dev.dev = &pdev->dev; | 1494 | priv->ici.v4l2_dev.dev = &pdev->dev; |
1444 | priv->ici.nr = pdev->id; | ||
1445 | priv->ici.drv_name = dev_name(&pdev->dev); | 1495 | priv->ici.drv_name = dev_name(&pdev->dev); |
1446 | priv->ici.ops = &rcar_vin_host_ops; | 1496 | priv->ici.ops = &rcar_vin_host_ops; |
1447 | 1497 | ||
1448 | priv->pdata_flags = pdata->flags; | 1498 | priv->pdata_flags = pdata_flags; |
1449 | priv->chip = pdev->id_entry->driver_data; | 1499 | if (!match) { |
1500 | priv->ici.nr = pdev->id; | ||
1501 | priv->chip = pdev->id_entry->driver_data; | ||
1502 | } else { | ||
1503 | priv->ici.nr = of_alias_get_id(pdev->dev.of_node, "vin"); | ||
1504 | priv->chip = (enum chip_id)match->data; | ||
1505 | }; | ||
1506 | |||
1450 | spin_lock_init(&priv->lock); | 1507 | spin_lock_init(&priv->lock); |
1451 | INIT_LIST_HEAD(&priv->capture); | 1508 | INIT_LIST_HEAD(&priv->capture); |
1452 | 1509 | ||
@@ -1487,6 +1544,7 @@ static struct platform_driver rcar_vin_driver = { | |||
1487 | .driver = { | 1544 | .driver = { |
1488 | .name = DRV_NAME, | 1545 | .name = DRV_NAME, |
1489 | .owner = THIS_MODULE, | 1546 | .owner = THIS_MODULE, |
1547 | .of_match_table = of_match_ptr(rcar_vin_of_table), | ||
1490 | }, | 1548 | }, |
1491 | .id_table = rcar_vin_id_table, | 1549 | .id_table = rcar_vin_id_table, |
1492 | }; | 1550 | }; |