aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-jack.c
diff options
context:
space:
mode:
authorLopez Cruz, Misael <x0052729@ti.com>2009-03-03 16:25:04 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-03-04 09:47:38 -0500
commitec67624d33d5639bcc6ee6918cb1fc0bd1bac3a8 (patch)
tree301f1d4ae2f47cca1c7412ce49e7574de8b0dfd2 /sound/soc/soc-jack.c
parent5f2a9384a9291d898b4bf85c4fbf497eef582977 (diff)
ASoC: Add GPIO support for jack reporting interface
Add GPIO support to jack reporting framework in ASoC using gpiolib calls. The gpio support exports two new functions: snd_soc_jack_add_gpios and snd_soc_jack_free_gpios. Client drivers using gpio feature must pass an array of jack_gpio pins belonging to a specific jack to the snd_soc_jack_add_gpios function. The framework will request the gpios, set the data direction and request irq. The framework will update power status of related jack_pins when an event on the gpio pins comes according to the reporting bits defined for each gpio. All gpio resources allocated when adding jack_gpio pins can be released using snd_soc_jack_free_gpios function. Signed-off-by: Misael Lopez Cruz <x0052729@ti.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-jack.c')
-rw-r--r--sound/soc/soc-jack.c129
1 files changed, 129 insertions, 0 deletions
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index ab64a30bedde..bdf2484c2220 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -14,6 +14,10 @@
14#include <sound/jack.h> 14#include <sound/jack.h>
15#include <sound/soc.h> 15#include <sound/soc.h>
16#include <sound/soc-dapm.h> 16#include <sound/soc-dapm.h>
17#include <linux/gpio.h>
18#include <linux/interrupt.h>
19#include <linux/workqueue.h>
20#include <linux/delay.h>
17 21
18/** 22/**
19 * snd_soc_jack_new - Create a new jack 23 * snd_soc_jack_new - Create a new jack
@@ -136,3 +140,128 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
136 return 0; 140 return 0;
137} 141}
138EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins); 142EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins);
143
144#ifdef CONFIG_GPIOLIB
145/* gpio detect */
146void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
147{
148 struct snd_soc_jack *jack = gpio->jack;
149 int enable;
150 int report;
151
152 if (gpio->debounce_time > 0)
153 mdelay(gpio->debounce_time);
154
155 enable = gpio_get_value(gpio->gpio);
156 if (gpio->invert)
157 enable = !enable;
158
159 if (enable)
160 report = gpio->report;
161 else
162 report = 0;
163
164 snd_soc_jack_report(jack, report, gpio->report);
165}
166
167/* irq handler for gpio pin */
168static irqreturn_t gpio_handler(int irq, void *data)
169{
170 struct snd_soc_jack_gpio *gpio = data;
171
172 schedule_work(&gpio->work);
173
174 return IRQ_HANDLED;
175}
176
177/* gpio work */
178static void gpio_work(struct work_struct *work)
179{
180 struct snd_soc_jack_gpio *gpio;
181
182 gpio = container_of(work, struct snd_soc_jack_gpio, work);
183 snd_soc_jack_gpio_detect(gpio);
184}
185
186/**
187 * snd_soc_jack_add_gpios - Associate GPIO pins with an ASoC jack
188 *
189 * @jack: ASoC jack
190 * @count: number of pins
191 * @gpios: array of gpio pins
192 *
193 * This function will request gpio, set data direction and request irq
194 * for each gpio in the array.
195 */
196int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
197 struct snd_soc_jack_gpio *gpios)
198{
199 int i, ret;
200
201 for (i = 0; i < count; i++) {
202 if (!gpio_is_valid(gpios[i].gpio)) {
203 printk(KERN_ERR "Invalid gpio %d\n",
204 gpios[i].gpio);
205 ret = -EINVAL;
206 goto undo;
207 }
208 if (!gpios[i].name) {
209 printk(KERN_ERR "No name for gpio %d\n",
210 gpios[i].gpio);
211 ret = -EINVAL;
212 goto undo;
213 }
214
215 ret = gpio_request(gpios[i].gpio, gpios[i].name);
216 if (ret)
217 goto undo;
218
219 ret = gpio_direction_input(gpios[i].gpio);
220 if (ret)
221 goto err;
222
223 ret = request_irq(gpio_to_irq(gpios[i].gpio),
224 gpio_handler,
225 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
226 jack->card->dev->driver->name,
227 &gpios[i]);
228 if (ret)
229 goto err;
230
231 INIT_WORK(&gpios[i].work, gpio_work);
232 gpios[i].jack = jack;
233 }
234
235 return 0;
236
237err:
238 gpio_free(gpios[i].gpio);
239undo:
240 snd_soc_jack_free_gpios(jack, i, gpios);
241
242 return ret;
243}
244EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpios);
245
246/**
247 * snd_soc_jack_free_gpios - Release GPIO pins' resources of an ASoC jack
248 *
249 * @jack: ASoC jack
250 * @count: number of pins
251 * @gpios: array of gpio pins
252 *
253 * Release gpio and irq resources for gpio pins associated with an ASoC jack.
254 */
255void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
256 struct snd_soc_jack_gpio *gpios)
257{
258 int i;
259
260 for (i = 0; i < count; i++) {
261 free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]);
262 gpio_free(gpios[i].gpio);
263 gpios[i].jack = NULL;
264 }
265}
266EXPORT_SYMBOL_GPL(snd_soc_jack_free_gpios);
267#endif /* CONFIG_GPIOLIB */