diff options
author | Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | 2013-01-10 03:34:08 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-01-13 18:27:18 -0500 |
commit | 9e7b6d60d880a463b17e4eae0d61c9f9a12f22bb (patch) | |
tree | 788a9c9851944719c757344f2c0d55455e16dba5 | |
parent | fd974e52dbbdb27910d40d8feea7000f26545683 (diff) |
ASoC: fsi: add device tree support
Support for loading the Renesas FSI driver via devicetree.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r-- | Documentation/devicetree/bindings/sound/renesas,fsi.txt | 26 | ||||
-rw-r--r-- | sound/soc/sh/fsi.c | 71 |
2 files changed, 89 insertions, 8 deletions
diff --git a/Documentation/devicetree/bindings/sound/renesas,fsi.txt b/Documentation/devicetree/bindings/sound/renesas,fsi.txt new file mode 100644 index 000000000000..c5be003f413e --- /dev/null +++ b/Documentation/devicetree/bindings/sound/renesas,fsi.txt | |||
@@ -0,0 +1,26 @@ | |||
1 | Renesas FSI | ||
2 | |||
3 | Required properties: | ||
4 | - compatible : "renesas,sh_fsi2" or "renesas,sh_fsi" | ||
5 | - reg : Should contain the register physical address and length | ||
6 | - interrupts : Should contain FSI interrupt | ||
7 | |||
8 | - fsia,spdif-connection : FSI is connected by S/PDFI | ||
9 | - fsia,stream-mode-support : FSI supports 16bit stream mode. | ||
10 | - fsia,use-internal-clock : FSI uses internal clock when master mode. | ||
11 | |||
12 | - fsib,spdif-connection : same as fsia | ||
13 | - fsib,stream-mode-support : same as fsia | ||
14 | - fsib,use-internal-clock : same as fsia | ||
15 | |||
16 | Example: | ||
17 | |||
18 | sh_fsi2: sh_fsi2@0xec230000 { | ||
19 | compatible = "renesas,sh_fsi2"; | ||
20 | reg = <0xec230000 0x400>; | ||
21 | interrupts = <0 146 0x4>; | ||
22 | |||
23 | fsia,spdif-connection; | ||
24 | fsia,stream-mode-support; | ||
25 | fsia,use-internal-clock; | ||
26 | }; | ||
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c index ef34ef8e92ed..91576120cd47 100644 --- a/sound/soc/sh/fsi.c +++ b/sound/soc/sh/fsi.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/dma-mapping.h> | 16 | #include <linux/dma-mapping.h> |
17 | #include <linux/pm_runtime.h> | 17 | #include <linux/pm_runtime.h> |
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/of.h> | ||
20 | #include <linux/of_device.h> | ||
19 | #include <linux/scatterlist.h> | 21 | #include <linux/scatterlist.h> |
20 | #include <linux/sh_dma.h> | 22 | #include <linux/sh_dma.h> |
21 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
@@ -297,7 +299,7 @@ struct fsi_master { | |||
297 | int irq; | 299 | int irq; |
298 | struct fsi_priv fsia; | 300 | struct fsi_priv fsia; |
299 | struct fsi_priv fsib; | 301 | struct fsi_priv fsib; |
300 | struct fsi_core *core; | 302 | const struct fsi_core *core; |
301 | spinlock_t lock; | 303 | spinlock_t lock; |
302 | }; | 304 | }; |
303 | 305 | ||
@@ -1887,6 +1889,33 @@ static struct snd_soc_platform_driver fsi_soc_platform = { | |||
1887 | /* | 1889 | /* |
1888 | * platform function | 1890 | * platform function |
1889 | */ | 1891 | */ |
1892 | static void fsi_of_parse(char *name, | ||
1893 | struct device_node *np, | ||
1894 | struct sh_fsi_port_info *info, | ||
1895 | struct device *dev) | ||
1896 | { | ||
1897 | int i; | ||
1898 | char prop[128]; | ||
1899 | unsigned long flags = 0; | ||
1900 | struct { | ||
1901 | char *name; | ||
1902 | unsigned int val; | ||
1903 | } of_parse_property[] = { | ||
1904 | { "spdif-connection", SH_FSI_FMT_SPDIF }, | ||
1905 | { "stream-mode-support", SH_FSI_ENABLE_STREAM_MODE }, | ||
1906 | { "use-internal-clock", SH_FSI_CLK_CPG }, | ||
1907 | }; | ||
1908 | |||
1909 | for (i = 0; i < ARRAY_SIZE(of_parse_property); i++) { | ||
1910 | sprintf(prop, "%s,%s", name, of_parse_property[i].name); | ||
1911 | if (of_get_property(np, prop, NULL)) | ||
1912 | flags |= of_parse_property[i].val; | ||
1913 | } | ||
1914 | info->flags = flags; | ||
1915 | |||
1916 | dev_dbg(dev, "%s flags : %lx\n", name, info->flags); | ||
1917 | } | ||
1918 | |||
1890 | static void fsi_port_info_init(struct fsi_priv *fsi, | 1919 | static void fsi_port_info_init(struct fsi_priv *fsi, |
1891 | struct sh_fsi_port_info *info) | 1920 | struct sh_fsi_port_info *info) |
1892 | { | 1921 | { |
@@ -1914,22 +1943,40 @@ static void fsi_handler_init(struct fsi_priv *fsi, | |||
1914 | } | 1943 | } |
1915 | } | 1944 | } |
1916 | 1945 | ||
1946 | static struct of_device_id fsi_of_match[]; | ||
1917 | static int fsi_probe(struct platform_device *pdev) | 1947 | static int fsi_probe(struct platform_device *pdev) |
1918 | { | 1948 | { |
1919 | struct fsi_master *master; | 1949 | struct fsi_master *master; |
1920 | const struct platform_device_id *id_entry; | 1950 | struct device_node *np = pdev->dev.of_node; |
1921 | struct sh_fsi_platform_info info; | 1951 | struct sh_fsi_platform_info info; |
1952 | const struct fsi_core *core; | ||
1922 | struct fsi_priv *fsi; | 1953 | struct fsi_priv *fsi; |
1923 | struct resource *res; | 1954 | struct resource *res; |
1924 | unsigned int irq; | 1955 | unsigned int irq; |
1925 | int ret; | 1956 | int ret; |
1926 | 1957 | ||
1927 | memset(&info, 0, sizeof(info)); | 1958 | memset(&info, 0, sizeof(info)); |
1928 | if (pdev->dev.platform_data) | ||
1929 | memcpy(&info, pdev->dev.platform_data, sizeof(info)); | ||
1930 | 1959 | ||
1931 | id_entry = pdev->id_entry; | 1960 | core = NULL; |
1932 | if (!id_entry) { | 1961 | if (np) { |
1962 | const struct of_device_id *of_id; | ||
1963 | |||
1964 | of_id = of_match_device(fsi_of_match, &pdev->dev); | ||
1965 | if (of_id) { | ||
1966 | core = of_id->data; | ||
1967 | fsi_of_parse("fsia", np, &info.port_a, &pdev->dev); | ||
1968 | fsi_of_parse("fsib", np, &info.port_b, &pdev->dev); | ||
1969 | } | ||
1970 | } else { | ||
1971 | const struct platform_device_id *id_entry = pdev->id_entry; | ||
1972 | if (id_entry) | ||
1973 | core = (struct fsi_core *)id_entry->driver_data; | ||
1974 | |||
1975 | if (pdev->dev.platform_data) | ||
1976 | memcpy(&info, pdev->dev.platform_data, sizeof(info)); | ||
1977 | } | ||
1978 | |||
1979 | if (!core) { | ||
1933 | dev_err(&pdev->dev, "unknown fsi device\n"); | 1980 | dev_err(&pdev->dev, "unknown fsi device\n"); |
1934 | return -ENODEV; | 1981 | return -ENODEV; |
1935 | } | 1982 | } |
@@ -1956,7 +2003,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
1956 | 2003 | ||
1957 | /* master setting */ | 2004 | /* master setting */ |
1958 | master->irq = irq; | 2005 | master->irq = irq; |
1959 | master->core = (struct fsi_core *)id_entry->driver_data; | 2006 | master->core = core; |
1960 | spin_lock_init(&master->lock); | 2007 | spin_lock_init(&master->lock); |
1961 | 2008 | ||
1962 | /* FSI A setting */ | 2009 | /* FSI A setting */ |
@@ -1987,7 +2034,7 @@ static int fsi_probe(struct platform_device *pdev) | |||
1987 | dev_set_drvdata(&pdev->dev, master); | 2034 | dev_set_drvdata(&pdev->dev, master); |
1988 | 2035 | ||
1989 | ret = devm_request_irq(&pdev->dev, irq, &fsi_interrupt, 0, | 2036 | ret = devm_request_irq(&pdev->dev, irq, &fsi_interrupt, 0, |
1990 | id_entry->name, master); | 2037 | dev_name(&pdev->dev), master); |
1991 | if (ret) { | 2038 | if (ret) { |
1992 | dev_err(&pdev->dev, "irq request err\n"); | 2039 | dev_err(&pdev->dev, "irq request err\n"); |
1993 | goto exit_fsib; | 2040 | goto exit_fsib; |
@@ -2113,6 +2160,13 @@ static struct fsi_core fsi2_core = { | |||
2113 | .b_mclk = B_MST_CTLR, | 2160 | .b_mclk = B_MST_CTLR, |
2114 | }; | 2161 | }; |
2115 | 2162 | ||
2163 | static struct of_device_id fsi_of_match[] __devinitconst = { | ||
2164 | { .compatible = "renesas,sh_fsi", .data = &fsi1_core}, | ||
2165 | { .compatible = "renesas,sh_fsi2", .data = &fsi2_core}, | ||
2166 | {}, | ||
2167 | }; | ||
2168 | MODULE_DEVICE_TABLE(of, fsi_of_match); | ||
2169 | |||
2116 | static struct platform_device_id fsi_id_table[] = { | 2170 | static struct platform_device_id fsi_id_table[] = { |
2117 | { "sh_fsi", (kernel_ulong_t)&fsi1_core }, | 2171 | { "sh_fsi", (kernel_ulong_t)&fsi1_core }, |
2118 | { "sh_fsi2", (kernel_ulong_t)&fsi2_core }, | 2172 | { "sh_fsi2", (kernel_ulong_t)&fsi2_core }, |
@@ -2124,6 +2178,7 @@ static struct platform_driver fsi_driver = { | |||
2124 | .driver = { | 2178 | .driver = { |
2125 | .name = "fsi-pcm-audio", | 2179 | .name = "fsi-pcm-audio", |
2126 | .pm = &fsi_pm_ops, | 2180 | .pm = &fsi_pm_ops, |
2181 | .of_match_table = fsi_of_match, | ||
2127 | }, | 2182 | }, |
2128 | .probe = fsi_probe, | 2183 | .probe = fsi_probe, |
2129 | .remove = fsi_remove, | 2184 | .remove = fsi_remove, |