diff options
author | Josh Wu <josh.wu@atmel.com> | 2014-07-28 03:25:17 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-07-30 18:48:36 -0400 |
commit | 8ff19bc437f8d42d8a03dafe2bb28c5b3fc1bff1 (patch) | |
tree | 4701913487f39c3687b2f002e4c40a7e64b16463 | |
parent | 833e1063266ebbf75934f1171c6546cdf33e9848 (diff) |
[media] media: atmel-isi: add primary DT support
This patch add the DT support for Atmel ISI driver.
It use the same v4l2 DT interface that defined in video-interfaces.txt.
Signed-off-by: Josh Wu <josh.wu@atmel.com>
Cc: devicetree@vger.kernel.org
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
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/atmel-isi.txt | 51 | ||||
-rw-r--r-- | drivers/media/platform/soc_camera/atmel-isi.c | 65 |
2 files changed, 114 insertions, 2 deletions
diff --git a/Documentation/devicetree/bindings/media/atmel-isi.txt b/Documentation/devicetree/bindings/media/atmel-isi.txt new file mode 100644 index 000000000000..17e71b7b44c6 --- /dev/null +++ b/Documentation/devicetree/bindings/media/atmel-isi.txt | |||
@@ -0,0 +1,51 @@ | |||
1 | Atmel Image Sensor Interface (ISI) SoC Camera Subsystem | ||
2 | ---------------------------------------------- | ||
3 | |||
4 | Required properties: | ||
5 | - compatible: must be "atmel,at91sam9g45-isi" | ||
6 | - reg: physical base address and length of the registers set for the device; | ||
7 | - interrupts: should contain IRQ line for the ISI; | ||
8 | - clocks: list of clock specifiers, corresponding to entries in | ||
9 | the clock-names property; | ||
10 | - clock-names: must contain "isi_clk", which is the isi peripherial clock. | ||
11 | |||
12 | ISI supports a single port node with parallel bus. It should contain one | ||
13 | 'port' child node with child 'endpoint' node. Please refer to the bindings | ||
14 | defined in Documentation/devicetree/bindings/media/video-interfaces.txt. | ||
15 | |||
16 | Example: | ||
17 | isi: isi@f0034000 { | ||
18 | compatible = "atmel,at91sam9g45-isi"; | ||
19 | reg = <0xf0034000 0x4000>; | ||
20 | interrupts = <37 IRQ_TYPE_LEVEL_HIGH 5>; | ||
21 | |||
22 | clocks = <&isi_clk>; | ||
23 | clock-names = "isi_clk"; | ||
24 | |||
25 | pinctrl-names = "default"; | ||
26 | pinctrl-0 = <&pinctrl_isi>; | ||
27 | |||
28 | port { | ||
29 | #address-cells = <1>; | ||
30 | #size-cells = <0>; | ||
31 | |||
32 | isi_0: endpoint { | ||
33 | remote-endpoint = <&ov2640_0>; | ||
34 | bus-width = <8>; | ||
35 | }; | ||
36 | }; | ||
37 | }; | ||
38 | |||
39 | i2c1: i2c@f0018000 { | ||
40 | ov2640: camera@0x30 { | ||
41 | compatible = "omnivision,ov2640"; | ||
42 | reg = <0x30>; | ||
43 | |||
44 | port { | ||
45 | ov2640_0: endpoint { | ||
46 | remote-endpoint = <&isi_0>; | ||
47 | bus-width = <8>; | ||
48 | }; | ||
49 | }; | ||
50 | }; | ||
51 | }; | ||
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c index d32c53383565..3408b045b3f1 100644 --- a/drivers/media/platform/soc_camera/atmel-isi.c +++ b/drivers/media/platform/soc_camera/atmel-isi.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <media/atmel-isi.h> | 25 | #include <media/atmel-isi.h> |
26 | #include <media/soc_camera.h> | 26 | #include <media/soc_camera.h> |
27 | #include <media/soc_mediabus.h> | 27 | #include <media/soc_mediabus.h> |
28 | #include <media/v4l2-of.h> | ||
28 | #include <media/videobuf2-dma-contig.h> | 29 | #include <media/videobuf2-dma-contig.h> |
29 | 30 | ||
30 | #define MAX_BUFFER_NUM 32 | 31 | #define MAX_BUFFER_NUM 32 |
@@ -33,6 +34,7 @@ | |||
33 | #define VID_LIMIT_BYTES (16 * 1024 * 1024) | 34 | #define VID_LIMIT_BYTES (16 * 1024 * 1024) |
34 | #define MIN_FRAME_RATE 15 | 35 | #define MIN_FRAME_RATE 15 |
35 | #define FRAME_INTERVAL_MILLI_SEC (1000 / MIN_FRAME_RATE) | 36 | #define FRAME_INTERVAL_MILLI_SEC (1000 / MIN_FRAME_RATE) |
37 | #define ISI_DEFAULT_MCLK_FREQ 25000000 | ||
36 | 38 | ||
37 | /* Frame buffer descriptor */ | 39 | /* Frame buffer descriptor */ |
38 | struct fbd { | 40 | struct fbd { |
@@ -876,6 +878,51 @@ static int atmel_isi_remove(struct platform_device *pdev) | |||
876 | return 0; | 878 | return 0; |
877 | } | 879 | } |
878 | 880 | ||
881 | static int atmel_isi_probe_dt(struct atmel_isi *isi, | ||
882 | struct platform_device *pdev) | ||
883 | { | ||
884 | struct device_node *np= pdev->dev.of_node; | ||
885 | struct v4l2_of_endpoint ep; | ||
886 | int err; | ||
887 | |||
888 | /* Default settings for ISI */ | ||
889 | isi->pdata.full_mode = 1; | ||
890 | isi->pdata.mck_hz = ISI_DEFAULT_MCLK_FREQ; | ||
891 | isi->pdata.frate = ISI_CFG1_FRATE_CAPTURE_ALL; | ||
892 | |||
893 | np = of_graph_get_next_endpoint(np, NULL); | ||
894 | if (!np) { | ||
895 | dev_err(&pdev->dev, "Could not find the endpoint\n"); | ||
896 | return -EINVAL; | ||
897 | } | ||
898 | |||
899 | err = v4l2_of_parse_endpoint(np, &ep); | ||
900 | if (err) { | ||
901 | dev_err(&pdev->dev, "Could not parse the endpoint\n"); | ||
902 | goto err_probe_dt; | ||
903 | } | ||
904 | |||
905 | switch (ep.bus.parallel.bus_width) { | ||
906 | case 8: | ||
907 | isi->pdata.data_width_flags = ISI_DATAWIDTH_8; | ||
908 | break; | ||
909 | case 10: | ||
910 | isi->pdata.data_width_flags = | ||
911 | ISI_DATAWIDTH_8 | ISI_DATAWIDTH_10; | ||
912 | break; | ||
913 | default: | ||
914 | dev_err(&pdev->dev, "Unsupported bus width: %d\n", | ||
915 | ep.bus.parallel.bus_width); | ||
916 | err = -EINVAL; | ||
917 | goto err_probe_dt; | ||
918 | } | ||
919 | |||
920 | err_probe_dt: | ||
921 | of_node_put(np); | ||
922 | |||
923 | return err; | ||
924 | } | ||
925 | |||
879 | static int atmel_isi_probe(struct platform_device *pdev) | 926 | static int atmel_isi_probe(struct platform_device *pdev) |
880 | { | 927 | { |
881 | unsigned int irq; | 928 | unsigned int irq; |
@@ -887,7 +934,7 @@ static int atmel_isi_probe(struct platform_device *pdev) | |||
887 | struct isi_platform_data *pdata; | 934 | struct isi_platform_data *pdata; |
888 | 935 | ||
889 | pdata = dev->platform_data; | 936 | pdata = dev->platform_data; |
890 | if (!pdata || !pdata->data_width_flags) { | 937 | if ((!pdata || !pdata->data_width_flags) && !pdev->dev.of_node) { |
891 | dev_err(&pdev->dev, | 938 | dev_err(&pdev->dev, |
892 | "No config available for Atmel ISI\n"); | 939 | "No config available for Atmel ISI\n"); |
893 | return -EINVAL; | 940 | return -EINVAL; |
@@ -903,7 +950,14 @@ static int atmel_isi_probe(struct platform_device *pdev) | |||
903 | if (IS_ERR(isi->pclk)) | 950 | if (IS_ERR(isi->pclk)) |
904 | return PTR_ERR(isi->pclk); | 951 | return PTR_ERR(isi->pclk); |
905 | 952 | ||
906 | memcpy(&isi->pdata, pdata, sizeof(isi->pdata)); | 953 | if (pdata) { |
954 | memcpy(&isi->pdata, pdata, sizeof(isi->pdata)); | ||
955 | } else { | ||
956 | ret = atmel_isi_probe_dt(isi, pdev); | ||
957 | if (ret) | ||
958 | return ret; | ||
959 | } | ||
960 | |||
907 | isi->active = NULL; | 961 | isi->active = NULL; |
908 | spin_lock_init(&isi->lock); | 962 | spin_lock_init(&isi->lock); |
909 | INIT_LIST_HEAD(&isi->video_buffer_list); | 963 | INIT_LIST_HEAD(&isi->video_buffer_list); |
@@ -1005,11 +1059,18 @@ err_alloc_ctx: | |||
1005 | return ret; | 1059 | return ret; |
1006 | } | 1060 | } |
1007 | 1061 | ||
1062 | static const struct of_device_id atmel_isi_of_match[] = { | ||
1063 | { .compatible = "atmel,at91sam9g45-isi" }, | ||
1064 | { } | ||
1065 | }; | ||
1066 | MODULE_DEVICE_TABLE(of, atmel_isi_of_match); | ||
1067 | |||
1008 | static struct platform_driver atmel_isi_driver = { | 1068 | static struct platform_driver atmel_isi_driver = { |
1009 | .remove = atmel_isi_remove, | 1069 | .remove = atmel_isi_remove, |
1010 | .driver = { | 1070 | .driver = { |
1011 | .name = "atmel_isi", | 1071 | .name = "atmel_isi", |
1012 | .owner = THIS_MODULE, | 1072 | .owner = THIS_MODULE, |
1073 | .of_match_table = of_match_ptr(atmel_isi_of_match), | ||
1013 | }, | 1074 | }, |
1014 | }; | 1075 | }; |
1015 | 1076 | ||