diff options
author | Hebbar, Gururaja <gururaja.hebbar@ti.com> | 2012-08-27 09:26:42 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-08-27 14:12:09 -0400 |
commit | 3e3b8c3415b15adb5a7ffcbfbeb360e7c9f5f4f7 (patch) | |
tree | 92c7bd6e3fe950d0aa521545d884bf19a55b663c | |
parent | 896f66b7de293644e65cf62600e4933af954dcf2 (diff) |
ASoC: Davinci: McASP: add device tree support for McASP
Add device tree probe for McASP driver.
Note:
DMA parameters are not populated from DT and will be done later.
Signed-off-by: Hebbar, Gururaja <gururaja.hebbar@ti.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt | 44 | ||||
-rw-r--r-- | sound/soc/davinci/davinci-mcasp.c | 124 |
2 files changed, 167 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt new file mode 100644 index 000000000000..e6148eca2942 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/davinci-mcasp-audio.txt | |||
@@ -0,0 +1,44 @@ | |||
1 | Texas Instruments McASP controller | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : | ||
5 | "ti,dm646x-mcasp-audio" : for DM646x platforms | ||
6 | "ti,da830-mcasp-audio" : for both DA830 & DA850 platforms | ||
7 | |||
8 | - reg : Should contain McASP registers offset and length | ||
9 | - interrupts : Interrupt number for McASP | ||
10 | - op-mode : I2S/DIT ops mode. | ||
11 | - tdm-slots : Slots for TDM operation. | ||
12 | - num-serializer : Serializers used by McASP. | ||
13 | - serial-dir : A list of serializer pin mode. The list number should be equal | ||
14 | to "num-serializer" parameter. Each entry is a number indication | ||
15 | serializer pin direction. (0 - INACTIVE, 1 - TX, 2 - RX) | ||
16 | |||
17 | |||
18 | Optional properties: | ||
19 | |||
20 | - ti,hwmods : Must be "mcasp<n>", n is controller instance starting 0 | ||
21 | - tx-num-evt : FIFO levels. | ||
22 | - rx-num-evt : FIFO levels. | ||
23 | - sram-size-playback : size of sram to be allocated during playback | ||
24 | - sram-size-capture : size of sram to be allocated during capture | ||
25 | |||
26 | Example: | ||
27 | |||
28 | mcasp0: mcasp0@1d00000 { | ||
29 | compatible = "ti,da830-mcasp-audio"; | ||
30 | #address-cells = <1>; | ||
31 | #size-cells = <0>; | ||
32 | reg = <0x100000 0x3000>; | ||
33 | interrupts = <82 83>; | ||
34 | op-mode = <0>; /* MCASP_IIS_MODE */ | ||
35 | tdm-slots = <2>; | ||
36 | num-serializer = <16>; | ||
37 | serial-dir = < | ||
38 | 0 0 0 0 /* 0: INACTIVE, 1: TX, 2: RX */ | ||
39 | 0 0 0 0 | ||
40 | 0 0 0 1 | ||
41 | 2 0 0 0 >; | ||
42 | tx-num-evt = <1>; | ||
43 | rx-num-evt = <1>; | ||
44 | }; | ||
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index 8f3c5a4cf537..7ecf19dfb07c 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -22,6 +22,9 @@ | |||
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/pm_runtime.h> | 24 | #include <linux/pm_runtime.h> |
25 | #include <linux/of.h> | ||
26 | #include <linux/of_platform.h> | ||
27 | #include <linux/of_device.h> | ||
25 | 28 | ||
26 | #include <sound/core.h> | 29 | #include <sound/core.h> |
27 | #include <sound/pcm.h> | 30 | #include <sound/pcm.h> |
@@ -856,6 +859,114 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | |||
856 | 859 | ||
857 | }; | 860 | }; |
858 | 861 | ||
862 | static const struct of_device_id mcasp_dt_ids[] = { | ||
863 | { | ||
864 | .compatible = "ti,dm646x-mcasp-audio", | ||
865 | .data = (void *)MCASP_VERSION_1, | ||
866 | }, | ||
867 | { | ||
868 | .compatible = "ti,da830-mcasp-audio", | ||
869 | .data = (void *)MCASP_VERSION_2, | ||
870 | }, | ||
871 | { /* sentinel */ } | ||
872 | }; | ||
873 | MODULE_DEVICE_TABLE(of, mcasp_dt_ids); | ||
874 | |||
875 | static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | ||
876 | struct platform_device *pdev) | ||
877 | { | ||
878 | struct device_node *np = pdev->dev.of_node; | ||
879 | struct snd_platform_data *pdata = NULL; | ||
880 | const struct of_device_id *match = | ||
881 | of_match_device(of_match_ptr(mcasp_dt_ids), &pdev->dev); | ||
882 | |||
883 | const u32 *of_serial_dir32; | ||
884 | u8 *of_serial_dir; | ||
885 | u32 val; | ||
886 | int i, ret = 0; | ||
887 | |||
888 | if (pdev->dev.platform_data) { | ||
889 | pdata = pdev->dev.platform_data; | ||
890 | return pdata; | ||
891 | } else if (match) { | ||
892 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
893 | if (!pdata) { | ||
894 | ret = -ENOMEM; | ||
895 | goto nodata; | ||
896 | } | ||
897 | } else { | ||
898 | /* control shouldn't reach here. something is wrong */ | ||
899 | ret = -EINVAL; | ||
900 | goto nodata; | ||
901 | } | ||
902 | |||
903 | if (match->data) | ||
904 | pdata->version = (u8)((int)match->data); | ||
905 | |||
906 | ret = of_property_read_u32(np, "op-mode", &val); | ||
907 | if (ret >= 0) | ||
908 | pdata->op_mode = val; | ||
909 | |||
910 | ret = of_property_read_u32(np, "tdm-slots", &val); | ||
911 | if (ret >= 0) | ||
912 | pdata->tdm_slots = val; | ||
913 | |||
914 | ret = of_property_read_u32(np, "num-serializer", &val); | ||
915 | if (ret >= 0) | ||
916 | pdata->num_serializer = val; | ||
917 | |||
918 | of_serial_dir32 = of_get_property(np, "serial-dir", &val); | ||
919 | val /= sizeof(u32); | ||
920 | if (val != pdata->num_serializer) { | ||
921 | dev_err(&pdev->dev, | ||
922 | "num-serializer(%d) != serial-dir size(%d)\n", | ||
923 | pdata->num_serializer, val); | ||
924 | ret = -EINVAL; | ||
925 | goto nodata; | ||
926 | } | ||
927 | |||
928 | if (of_serial_dir32) { | ||
929 | of_serial_dir = devm_kzalloc(&pdev->dev, | ||
930 | (sizeof(*of_serial_dir) * val), | ||
931 | GFP_KERNEL); | ||
932 | if (!of_serial_dir) { | ||
933 | ret = -ENOMEM; | ||
934 | goto nodata; | ||
935 | } | ||
936 | |||
937 | for (i = 0; i < pdata->num_serializer; i++) | ||
938 | of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); | ||
939 | |||
940 | pdata->serial_dir = of_serial_dir; | ||
941 | } | ||
942 | |||
943 | ret = of_property_read_u32(np, "tx-num-evt", &val); | ||
944 | if (ret >= 0) | ||
945 | pdata->txnumevt = val; | ||
946 | |||
947 | ret = of_property_read_u32(np, "rx-num-evt", &val); | ||
948 | if (ret >= 0) | ||
949 | pdata->rxnumevt = val; | ||
950 | |||
951 | ret = of_property_read_u32(np, "sram-size-playback", &val); | ||
952 | if (ret >= 0) | ||
953 | pdata->sram_size_playback = val; | ||
954 | |||
955 | ret = of_property_read_u32(np, "sram-size-capture", &val); | ||
956 | if (ret >= 0) | ||
957 | pdata->sram_size_capture = val; | ||
958 | |||
959 | return pdata; | ||
960 | |||
961 | nodata: | ||
962 | if (ret < 0) { | ||
963 | dev_err(&pdev->dev, "Error populating platform data, err %d\n", | ||
964 | ret); | ||
965 | pdata = NULL; | ||
966 | } | ||
967 | return pdata; | ||
968 | } | ||
969 | |||
859 | static int davinci_mcasp_probe(struct platform_device *pdev) | 970 | static int davinci_mcasp_probe(struct platform_device *pdev) |
860 | { | 971 | { |
861 | struct davinci_pcm_dma_params *dma_data; | 972 | struct davinci_pcm_dma_params *dma_data; |
@@ -864,11 +975,22 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
864 | struct davinci_audio_dev *dev; | 975 | struct davinci_audio_dev *dev; |
865 | int ret; | 976 | int ret; |
866 | 977 | ||
978 | if (!pdev->dev.platform_data && !pdev->dev.of_node) { | ||
979 | dev_err(&pdev->dev, "No platform data supplied\n"); | ||
980 | return -EINVAL; | ||
981 | } | ||
982 | |||
867 | dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), | 983 | dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), |
868 | GFP_KERNEL); | 984 | GFP_KERNEL); |
869 | if (!dev) | 985 | if (!dev) |
870 | return -ENOMEM; | 986 | return -ENOMEM; |
871 | 987 | ||
988 | pdata = davinci_mcasp_set_pdata_from_of(pdev); | ||
989 | if (!pdata) { | ||
990 | dev_err(&pdev->dev, "no platform data\n"); | ||
991 | return -EINVAL; | ||
992 | } | ||
993 | |||
872 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 994 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
873 | if (!mem) { | 995 | if (!mem) { |
874 | dev_err(&pdev->dev, "no mem resource?\n"); | 996 | dev_err(&pdev->dev, "no mem resource?\n"); |
@@ -882,7 +1004,6 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
882 | return -EBUSY; | 1004 | return -EBUSY; |
883 | } | 1005 | } |
884 | 1006 | ||
885 | pdata = pdev->dev.platform_data; | ||
886 | pm_runtime_enable(&pdev->dev); | 1007 | pm_runtime_enable(&pdev->dev); |
887 | 1008 | ||
888 | ret = pm_runtime_get_sync(&pdev->dev); | 1009 | ret = pm_runtime_get_sync(&pdev->dev); |
@@ -980,6 +1101,7 @@ static struct platform_driver davinci_mcasp_driver = { | |||
980 | .driver = { | 1101 | .driver = { |
981 | .name = "davinci-mcasp", | 1102 | .name = "davinci-mcasp", |
982 | .owner = THIS_MODULE, | 1103 | .owner = THIS_MODULE, |
1104 | .of_match_table = of_match_ptr(mcasp_dt_ids), | ||
983 | }, | 1105 | }, |
984 | }; | 1106 | }; |
985 | 1107 | ||