diff options
author | Jarkko Nikula <jarkko.nikula@linux.intel.com> | 2014-05-26 07:34:37 -0400 |
---|---|---|
committer | Mark Brown <broonie@linaro.org> | 2014-05-26 10:26:00 -0400 |
commit | f025d3b9c64e1f7feb75a559d4a12f5f8c6a4a25 (patch) | |
tree | 819909f51afd408c50379e69c55d29337365d02c | |
parent | 50dfb69d1bb0062e2811547525c73e9a45a423e9 (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.h | 16 | ||||
-rw-r--r-- | sound/soc/soc-jack.c | 73 |
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 |
454 | int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, | 454 | int 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); |
456 | int snd_soc_jack_add_gpiods(struct device *gpiod_dev, | ||
457 | struct snd_soc_jack *jack, | ||
458 | int count, struct snd_soc_jack_gpio *gpios); | ||
456 | void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, | 459 | void 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 | ||
468 | int 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 | |||
465 | static inline void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, | 475 | static 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 | */ |
599 | struct snd_soc_jack_gpio { | 611 | struct 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: | |||
361 | EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpios); | 378 | EXPORT_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 | */ | ||
391 | int 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 | } | ||
402 | EXPORT_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 |