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 |
