diff options
author | Markus Pargmann <mpa@pengutronix.de> | 2013-08-19 11:05:55 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2013-08-20 06:02:00 -0400 |
commit | 741a509f34d8d702f70d0ad99b8152c57d76961e (patch) | |
tree | 19a6d0d87e3347331fd0e50cb3760c6eec91bd88 /sound/soc/soc-core.c | |
parent | d2a369cb53a3f3733800d5160d60f9a5271fe44c (diff) |
ASoC: core: Generic ac97 link reset functions
This patch adds generic ac97 reset functions using pincontrol and gpio
parsed from devicetree.
Signed-off-by: Markus Pargmann <mpa@pengutronix.de>
Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d82ee386eab5..b5c91f9aa160 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -30,9 +30,12 @@ | |||
30 | #include <linux/bitops.h> | 30 | #include <linux/bitops.h> |
31 | #include <linux/debugfs.h> | 31 | #include <linux/debugfs.h> |
32 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
33 | #include <linux/pinctrl/consumer.h> | ||
33 | #include <linux/ctype.h> | 34 | #include <linux/ctype.h> |
34 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
35 | #include <linux/of.h> | 36 | #include <linux/of.h> |
37 | #include <linux/gpio.h> | ||
38 | #include <linux/of_gpio.h> | ||
36 | #include <sound/ac97_codec.h> | 39 | #include <sound/ac97_codec.h> |
37 | #include <sound/core.h> | 40 | #include <sound/core.h> |
38 | #include <sound/jack.h> | 41 | #include <sound/jack.h> |
@@ -69,6 +72,16 @@ static int pmdown_time = 5000; | |||
69 | module_param(pmdown_time, int, 0); | 72 | module_param(pmdown_time, int, 0); |
70 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 73 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
71 | 74 | ||
75 | struct snd_ac97_reset_cfg { | ||
76 | struct pinctrl *pctl; | ||
77 | struct pinctrl_state *pstate_reset; | ||
78 | struct pinctrl_state *pstate_warm_reset; | ||
79 | struct pinctrl_state *pstate_run; | ||
80 | int gpio_sdata; | ||
81 | int gpio_sync; | ||
82 | int gpio_reset; | ||
83 | }; | ||
84 | |||
72 | /* returns the minimum number of bytes needed to represent | 85 | /* returns the minimum number of bytes needed to represent |
73 | * a particular given value */ | 86 | * a particular given value */ |
74 | static int min_bytes_needed(unsigned long val) | 87 | static int min_bytes_needed(unsigned long val) |
@@ -2080,6 +2093,117 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | |||
2080 | } | 2093 | } |
2081 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | 2094 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); |
2082 | 2095 | ||
2096 | static struct snd_ac97_reset_cfg snd_ac97_rst_cfg; | ||
2097 | |||
2098 | static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97) | ||
2099 | { | ||
2100 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
2101 | |||
2102 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_warm_reset); | ||
2103 | |||
2104 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 1); | ||
2105 | |||
2106 | udelay(10); | ||
2107 | |||
2108 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
2109 | |||
2110 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
2111 | msleep(2); | ||
2112 | } | ||
2113 | |||
2114 | static void snd_soc_ac97_reset(struct snd_ac97 *ac97) | ||
2115 | { | ||
2116 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
2117 | |||
2118 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_reset); | ||
2119 | |||
2120 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
2121 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sdata, 0); | ||
2122 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 0); | ||
2123 | |||
2124 | udelay(10); | ||
2125 | |||
2126 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 1); | ||
2127 | |||
2128 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
2129 | msleep(2); | ||
2130 | } | ||
2131 | |||
2132 | static int snd_soc_ac97_parse_pinctl(struct device *dev, | ||
2133 | struct snd_ac97_reset_cfg *cfg) | ||
2134 | { | ||
2135 | struct pinctrl *p; | ||
2136 | struct pinctrl_state *state; | ||
2137 | int gpio; | ||
2138 | int ret; | ||
2139 | |||
2140 | p = devm_pinctrl_get(dev); | ||
2141 | if (IS_ERR(p)) { | ||
2142 | dev_err(dev, "Failed to get pinctrl\n"); | ||
2143 | return PTR_RET(p); | ||
2144 | } | ||
2145 | cfg->pctl = p; | ||
2146 | |||
2147 | state = pinctrl_lookup_state(p, "ac97-reset"); | ||
2148 | if (IS_ERR(state)) { | ||
2149 | dev_err(dev, "Can't find pinctrl state ac97-reset\n"); | ||
2150 | return PTR_RET(state); | ||
2151 | } | ||
2152 | cfg->pstate_reset = state; | ||
2153 | |||
2154 | state = pinctrl_lookup_state(p, "ac97-warm-reset"); | ||
2155 | if (IS_ERR(state)) { | ||
2156 | dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n"); | ||
2157 | return PTR_RET(state); | ||
2158 | } | ||
2159 | cfg->pstate_warm_reset = state; | ||
2160 | |||
2161 | state = pinctrl_lookup_state(p, "ac97-running"); | ||
2162 | if (IS_ERR(state)) { | ||
2163 | dev_err(dev, "Can't find pinctrl state ac97-running\n"); | ||
2164 | return PTR_RET(state); | ||
2165 | } | ||
2166 | cfg->pstate_run = state; | ||
2167 | |||
2168 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 0); | ||
2169 | if (gpio < 0) { | ||
2170 | dev_err(dev, "Can't find ac97-sync gpio\n"); | ||
2171 | return gpio; | ||
2172 | } | ||
2173 | ret = devm_gpio_request(dev, gpio, "AC97 link sync"); | ||
2174 | if (ret) { | ||
2175 | dev_err(dev, "Failed requesting ac97-sync gpio\n"); | ||
2176 | return ret; | ||
2177 | } | ||
2178 | cfg->gpio_sync = gpio; | ||
2179 | |||
2180 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 1); | ||
2181 | if (gpio < 0) { | ||
2182 | dev_err(dev, "Can't find ac97-sdata gpio %d\n", gpio); | ||
2183 | return gpio; | ||
2184 | } | ||
2185 | ret = devm_gpio_request(dev, gpio, "AC97 link sdata"); | ||
2186 | if (ret) { | ||
2187 | dev_err(dev, "Failed requesting ac97-sdata gpio\n"); | ||
2188 | return ret; | ||
2189 | } | ||
2190 | cfg->gpio_sdata = gpio; | ||
2191 | |||
2192 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 2); | ||
2193 | if (gpio < 0) { | ||
2194 | dev_err(dev, "Can't find ac97-reset gpio\n"); | ||
2195 | return gpio; | ||
2196 | } | ||
2197 | ret = devm_gpio_request(dev, gpio, "AC97 link reset"); | ||
2198 | if (ret) { | ||
2199 | dev_err(dev, "Failed requesting ac97-reset gpio\n"); | ||
2200 | return ret; | ||
2201 | } | ||
2202 | cfg->gpio_reset = gpio; | ||
2203 | |||
2204 | return 0; | ||
2205 | } | ||
2206 | |||
2083 | struct snd_ac97_bus_ops *soc_ac97_ops; | 2207 | struct snd_ac97_bus_ops *soc_ac97_ops; |
2084 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | 2208 | EXPORT_SYMBOL_GPL(soc_ac97_ops); |
2085 | 2209 | ||
@@ -2098,6 +2222,35 @@ int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | |||
2098 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | 2222 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); |
2099 | 2223 | ||
2100 | /** | 2224 | /** |
2225 | * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions | ||
2226 | * | ||
2227 | * This function sets the reset and warm_reset properties of ops and parses | ||
2228 | * the device node of pdev to get pinctrl states and gpio numbers to use. | ||
2229 | */ | ||
2230 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | ||
2231 | struct platform_device *pdev) | ||
2232 | { | ||
2233 | struct device *dev = &pdev->dev; | ||
2234 | struct snd_ac97_reset_cfg cfg; | ||
2235 | int ret; | ||
2236 | |||
2237 | ret = snd_soc_ac97_parse_pinctl(dev, &cfg); | ||
2238 | if (ret) | ||
2239 | return ret; | ||
2240 | |||
2241 | ret = snd_soc_set_ac97_ops(ops); | ||
2242 | if (ret) | ||
2243 | return ret; | ||
2244 | |||
2245 | ops->warm_reset = snd_soc_ac97_warm_reset; | ||
2246 | ops->reset = snd_soc_ac97_reset; | ||
2247 | |||
2248 | snd_ac97_rst_cfg = cfg; | ||
2249 | return 0; | ||
2250 | } | ||
2251 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); | ||
2252 | |||
2253 | /** | ||
2101 | * snd_soc_free_ac97_codec - free AC97 codec device | 2254 | * snd_soc_free_ac97_codec - free AC97 codec device |
2102 | * @codec: audio codec | 2255 | * @codec: audio codec |
2103 | * | 2256 | * |