diff options
author | Stephen Warren <swarren@nvidia.com> | 2013-06-12 13:34:30 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-06-12 14:25:22 -0400 |
commit | dcad9f031240d59e9e1475a8e5b2cb427da94f6e (patch) | |
tree | 5bb28075e74375030c5fd2e89531f01660700047 | |
parent | 997b05203b0a710e11f9b2732bef2d2fdc1d824b (diff) |
ASoC: rt5640: add device tree support
Modify the RT5640 driver to parse platform data from device tree. Write
a DT binding document to describe those properties.
Slight re-ordering of rt5640_i2c_probe() to better fit the DT parsing.
Since ldo1_en is optional, guard usage of it with gpio_is_valid(), rather
than open-coding an if (gpio) check.
Signed-off-by: Stephen Warren <swarren@nvidia.com>
Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r-- | Documentation/devicetree/bindings/sound/rt5640.txt | 30 | ||||
-rw-r--r-- | sound/soc/codecs/rt5640.c | 48 |
2 files changed, 72 insertions, 6 deletions
diff --git a/Documentation/devicetree/bindings/sound/rt5640.txt b/Documentation/devicetree/bindings/sound/rt5640.txt new file mode 100644 index 000000000000..005bcb24d72d --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt5640.txt | |||
@@ -0,0 +1,30 @@ | |||
1 | RT5640 audio CODEC | ||
2 | |||
3 | This device supports I2C only. | ||
4 | |||
5 | Required properties: | ||
6 | |||
7 | - compatible : "realtek,rt5640". | ||
8 | |||
9 | - reg : The I2C address of the device. | ||
10 | |||
11 | - interrupts : The CODEC's interrupt output. | ||
12 | |||
13 | Optional properties: | ||
14 | |||
15 | - realtek,in1-differential | ||
16 | - realtek,in2-differential | ||
17 | Boolean. Indicate MIC1/2 input are differential, rather than single-ended. | ||
18 | |||
19 | - realtek,ldo1-en-gpios : The GPIO that controls the CODEC's LDO1_EN pin. | ||
20 | |||
21 | Example: | ||
22 | |||
23 | rt5640 { | ||
24 | compatible = "realtek,rt5640"; | ||
25 | reg = <0x1c>; | ||
26 | interrupt-parent = <&gpio>; | ||
27 | interrupts = <TEGRA_GPIO(W, 3) GPIO_ACTIVE_HIGH>; | ||
28 | realtek,ldo1-en-gpios = | ||
29 | <&gpio TEGRA_GPIO(V, 3) GPIO_ACTIVE_HIGH>; | ||
30 | }; | ||
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 288c17cd6023..8761552882a5 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
21 | #include <linux/of_gpio.h> | ||
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
22 | #include <linux/spi/spi.h> | 23 | #include <linux/spi/spi.h> |
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
@@ -1998,6 +1999,28 @@ static const struct i2c_device_id rt5640_i2c_id[] = { | |||
1998 | }; | 1999 | }; |
1999 | MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id); | 2000 | MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id); |
2000 | 2001 | ||
2002 | static int rt5640_parse_dt(struct rt5640_priv *rt5640, struct device_node *np) | ||
2003 | { | ||
2004 | rt5640->pdata.in1_diff = of_property_read_bool(np, | ||
2005 | "realtek,in1-differential"); | ||
2006 | rt5640->pdata.in2_diff = of_property_read_bool(np, | ||
2007 | "realtek,in2-differential"); | ||
2008 | |||
2009 | rt5640->pdata.ldo1_en = of_get_named_gpio(np, | ||
2010 | "realtek,ldo1-en-gpios", 0); | ||
2011 | /* | ||
2012 | * LDO1_EN is optional (it may be statically tied on the board). | ||
2013 | * -ENOENT means that the property doesn't exist, i.e. there is no | ||
2014 | * GPIO, so is not an error. Any other error code means the property | ||
2015 | * exists, but could not be parsed. | ||
2016 | */ | ||
2017 | if (!gpio_is_valid(rt5640->pdata.ldo1_en) && | ||
2018 | (rt5640->pdata.ldo1_en != -ENOENT)) | ||
2019 | return rt5640->pdata.ldo1_en; | ||
2020 | |||
2021 | return 0; | ||
2022 | } | ||
2023 | |||
2001 | static int rt5640_i2c_probe(struct i2c_client *i2c, | 2024 | static int rt5640_i2c_probe(struct i2c_client *i2c, |
2002 | const struct i2c_device_id *id) | 2025 | const struct i2c_device_id *id) |
2003 | { | 2026 | { |
@@ -2011,6 +2034,24 @@ static int rt5640_i2c_probe(struct i2c_client *i2c, | |||
2011 | GFP_KERNEL); | 2034 | GFP_KERNEL); |
2012 | if (NULL == rt5640) | 2035 | if (NULL == rt5640) |
2013 | return -ENOMEM; | 2036 | return -ENOMEM; |
2037 | i2c_set_clientdata(i2c, rt5640); | ||
2038 | |||
2039 | if (pdata) { | ||
2040 | rt5640->pdata = *pdata; | ||
2041 | /* | ||
2042 | * Translate zero'd out (default) pdata value to an invalid | ||
2043 | * GPIO ID. This makes the pdata and DT paths consistent in | ||
2044 | * terms of the value left in this field when no GPIO is | ||
2045 | * specified, but means we can't actually use GPIO 0. | ||
2046 | */ | ||
2047 | if (!rt5640->pdata.ldo1_en) | ||
2048 | rt5640->pdata.ldo1_en = -EINVAL; | ||
2049 | } else if (i2c->dev.of_node) { | ||
2050 | ret = rt5640_parse_dt(rt5640, i2c->dev.of_node); | ||
2051 | if (ret) | ||
2052 | return ret; | ||
2053 | } else | ||
2054 | rt5640->pdata.ldo1_en = -EINVAL; | ||
2014 | 2055 | ||
2015 | rt5640->regmap = devm_regmap_init_i2c(i2c, &rt5640_regmap); | 2056 | rt5640->regmap = devm_regmap_init_i2c(i2c, &rt5640_regmap); |
2016 | if (IS_ERR(rt5640->regmap)) { | 2057 | if (IS_ERR(rt5640->regmap)) { |
@@ -2020,12 +2061,7 @@ static int rt5640_i2c_probe(struct i2c_client *i2c, | |||
2020 | return ret; | 2061 | return ret; |
2021 | } | 2062 | } |
2022 | 2063 | ||
2023 | if (pdata) | 2064 | if (gpio_is_valid(rt5640->pdata.ldo1_en)) { |
2024 | rt5640->pdata = *pdata; | ||
2025 | |||
2026 | i2c_set_clientdata(i2c, rt5640); | ||
2027 | |||
2028 | if (rt5640->pdata.ldo1_en) { | ||
2029 | ret = devm_gpio_request_one(&i2c->dev, rt5640->pdata.ldo1_en, | 2065 | ret = devm_gpio_request_one(&i2c->dev, rt5640->pdata.ldo1_en, |
2030 | GPIOF_OUT_INIT_HIGH, | 2066 | GPIOF_OUT_INIT_HIGH, |
2031 | "RT5640 LDO1_EN"); | 2067 | "RT5640 LDO1_EN"); |