aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJarkko Nikula <jarkko.nikula@linux.intel.com>2014-05-26 07:34:37 -0400
committerMark Brown <broonie@linaro.org>2014-05-26 10:26:00 -0400
commitf025d3b9c64e1f7feb75a559d4a12f5f8c6a4a25 (patch)
tree819909f51afd408c50379e69c55d29337365d02c
parent50dfb69d1bb0062e2811547525c73e9a45a423e9 (diff)
ASoC: jack: Add support for GPIO descriptor defined jack pins
Allow jack GPIO pins be defined also using GPIO descriptor-based interface in addition to legacy GPIO numbers. This is done by adding two new fields to struct snd_soc_jack_gpio: idx and gpiod_dev. Legacy GPIO numbers are used only when GPIO consumer device gpiod_dev is NULL and otherwise idx is the descriptor index within the GPIO consumer device. New function snd_soc_jack_add_gpiods() is added for typical cases where all GPIO descriptor jack pins belong to same GPIO consumer device. For other cases the caller must set the gpiod_dev in struct snd_soc_jack_gpio before calling snd_soc_jack_add_gpios(). Signed-off-by: Jarkko Nikula <jarkko.nikula@linux.intel.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--include/sound/soc.h16
-rw-r--r--sound/soc/soc-jack.c73
2 files changed, 72 insertions, 17 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index c6bd40f2c40b..61bea882a74b 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -453,6 +453,9 @@ int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage);
453#ifdef CONFIG_GPIOLIB 453#ifdef CONFIG_GPIOLIB
454int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, 454int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
455 struct snd_soc_jack_gpio *gpios); 455 struct snd_soc_jack_gpio *gpios);
456int snd_soc_jack_add_gpiods(struct device *gpiod_dev,
457 struct snd_soc_jack *jack,
458 int count, struct snd_soc_jack_gpio *gpios);
456void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, 459void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
457 struct snd_soc_jack_gpio *gpios); 460 struct snd_soc_jack_gpio *gpios);
458#else 461#else
@@ -462,6 +465,13 @@ static inline int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
462 return 0; 465 return 0;
463} 466}
464 467
468int snd_soc_jack_add_gpiods(struct device *gpiod_dev,
469 struct snd_soc_jack *jack,
470 int count, struct snd_soc_jack_gpio *gpios)
471{
472 return 0;
473}
474
465static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, 475static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
466 struct snd_soc_jack_gpio *gpios) 476 struct snd_soc_jack_gpio *gpios)
467{ 477{
@@ -586,7 +596,9 @@ struct snd_soc_jack_zone {
586/** 596/**
587 * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection 597 * struct snd_soc_jack_gpio - Describes a gpio pin for jack detection
588 * 598 *
589 * @gpio: gpio number 599 * @gpio: legacy gpio number
600 * @idx: gpio descriptor index within the GPIO consumer device
601 * @gpiod_dev GPIO consumer device
590 * @name: gpio name 602 * @name: gpio name
591 * @report: value to report when jack detected 603 * @report: value to report when jack detected
592 * @invert: report presence in low state 604 * @invert: report presence in low state
@@ -598,6 +610,8 @@ struct snd_soc_jack_zone {
598 */ 610 */
599struct snd_soc_jack_gpio { 611struct snd_soc_jack_gpio {
600 unsigned int gpio; 612 unsigned int gpio;
613 unsigned int idx;
614 struct device *gpiod_dev;
601 const char *name; 615 const char *name;
602 int report; 616 int report;
603 int invert; 617 int invert;
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 7203842fea66..d0d98810af91 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -298,24 +298,41 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
298 int i, ret; 298 int i, ret;
299 299
300 for (i = 0; i < count; i++) { 300 for (i = 0; i < count; i++) {
301 if (!gpio_is_valid(gpios[i].gpio)) {
302 dev_err(jack->codec->dev, "ASoC: Invalid gpio %d\n",
303 gpios[i].gpio);
304 ret = -EINVAL;
305 goto undo;
306 }
307 if (!gpios[i].name) { 301 if (!gpios[i].name) {
308 dev_err(jack->codec->dev, "ASoC: No name for gpio %d\n", 302 dev_err(jack->codec->dev,
309 gpios[i].gpio); 303 "ASoC: No name for gpio at index %d\n", i);
310 ret = -EINVAL; 304 ret = -EINVAL;
311 goto undo; 305 goto undo;
312 } 306 }
313 307
314 ret = gpio_request(gpios[i].gpio, gpios[i].name); 308 if (gpios[i].gpiod_dev) {
315 if (ret) 309 /* GPIO descriptor */
316 goto undo; 310 gpios[i].desc = gpiod_get_index(gpios[i].gpiod_dev,
317 311 gpios[i].name,
318 gpios[i].desc = gpio_to_desc(gpios[i].gpio); 312 gpios[i].idx);
313 if (IS_ERR(gpios[i].desc)) {
314 ret = PTR_ERR(gpios[i].desc);
315 dev_err(gpios[i].gpiod_dev,
316 "ASoC: Cannot get gpio at index %d: %d",
317 i, ret);
318 goto undo;
319 }
320 } else {
321 /* legacy GPIO number */
322 if (!gpio_is_valid(gpios[i].gpio)) {
323 dev_err(jack->codec->dev,
324 "ASoC: Invalid gpio %d\n",
325 gpios[i].gpio);
326 ret = -EINVAL;
327 goto undo;
328 }
329
330 ret = gpio_request(gpios[i].gpio, gpios[i].name);
331 if (ret)
332 goto undo;
333
334 gpios[i].desc = gpio_to_desc(gpios[i].gpio);
335 }
319 336
320 ret = gpiod_direction_input(gpios[i].desc); 337 ret = gpiod_direction_input(gpios[i].desc);
321 if (ret) 338 if (ret)
@@ -336,9 +353,9 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
336 if (gpios[i].wake) { 353 if (gpios[i].wake) {
337 ret = irq_set_irq_wake(gpiod_to_irq(gpios[i].desc), 1); 354 ret = irq_set_irq_wake(gpiod_to_irq(gpios[i].desc), 1);
338 if (ret != 0) 355 if (ret != 0)
339 dev_err(jack->codec->dev, "ASoC: " 356 dev_err(jack->codec->dev,
340 "Failed to mark GPIO %d as wake source: %d\n", 357 "ASoC: Failed to mark GPIO at index %d as wake source: %d\n",
341 gpios[i].gpio, ret); 358 i, ret);
342 } 359 }
343 360
344 /* Expose GPIO value over sysfs for diagnostic purposes */ 361 /* Expose GPIO value over sysfs for diagnostic purposes */
@@ -361,6 +378,30 @@ undo:
361EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpios); 378EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpios);
362 379
363/** 380/**
381 * snd_soc_jack_add_gpiods - Associate GPIO descriptor pins with an ASoC jack
382 *
383 * @gpiod_dev: GPIO consumer device
384 * @jack: ASoC jack
385 * @count: number of pins
386 * @gpios: array of gpio pins
387 *
388 * This function will request gpio, set data direction and request irq
389 * for each gpio in the array.
390 */
391int snd_soc_jack_add_gpiods(struct device *gpiod_dev,
392 struct snd_soc_jack *jack,
393 int count, struct snd_soc_jack_gpio *gpios)
394{
395 int i;
396
397 for (i = 0; i < count; i++)
398 gpios[i].gpiod_dev = gpiod_dev;
399
400 return snd_soc_jack_add_gpios(jack, count, gpios);
401}
402EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpiods);
403
404/**
364 * snd_soc_jack_free_gpios - Release GPIO pins' resources of an ASoC jack 405 * snd_soc_jack_free_gpios - Release GPIO pins' resources of an ASoC jack
365 * 406 *
366 * @jack: ASoC jack 407 * @jack: ASoC jack