1 /* 2 * soc-jack.c -- ALSA SoC jack handling 3 * 4 * Copyright 2008 Wolfson Microelectronics PLC. 5 * 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License as published by the 10 * Free Software Foundation; either version 2 of the License, or (at your 11 * option) any later version. 12 */ 13 14 #include <sound/jack.h> 15 #include <sound/soc.h> 16 #include <linux/gpio.h> 17 #include <linux/gpio/consumer.h> 18 #include <linux/interrupt.h> 19 #include <linux/workqueue.h> 20 #include <linux/delay.h> 21 #include <linux/export.h> 22 #include <linux/suspend.h> 23 #include <trace/events/asoc.h> 24 25 struct jack_gpio_tbl { 26 int count; 27 struct snd_soc_jack *jack; 28 struct snd_soc_jack_gpio *gpios; 29 }; 30 31 /** 32 * snd_soc_codec_set_jack - configure codec jack. 33 * @codec: CODEC 34 * @jack: structure to use for the jack 35 * @data: can be used if codec driver need extra data for configuring jack 36 * 37 * Configures and enables jack detection function. 38 */ 39 int snd_soc_codec_set_jack(struct snd_soc_codec *codec, 40 struct snd_soc_jack *jack, void *data) 41 { 42 if (codec->driver->set_jack) 43 return codec->driver->set_jack(codec, jack, data); 44 else 45 return -ENOTSUPP; 46 } 47 EXPORT_SYMBOL_GPL(snd_soc_codec_set_jack); 48 49 /** 50 * snd_soc_component_set_jack - configure component jack. 51 * @component: COMPONENTs 52 * @jack: structure to use for the jack 53 * @data: can be used if codec driver need extra data for configuring jack 54 * 55 * Configures and enables jack detection function. 56 */ 57 int snd_soc_component_set_jack(struct snd_soc_component *component, 58 struct snd_soc_jack *jack, void *data) 59 { 60 /* will be removed */ 61 if (component->set_jack) 62 return component->set_jack(component, jack, data); 63 64 if (component->driver->set_jack) 65 return component->driver->set_jack(component, jack, data); 66 67 return -ENOTSUPP; 68 } 69 EXPORT_SYMBOL_GPL(snd_soc_component_set_jack); 70 71 /** 72 * snd_soc_card_jack_new - Create a new jack 73 * @card: ASoC card 74 * @id: an identifying string for this jack 75 * @type: a bitmask of enum snd_jack_type values that can be detected by 76 * this jack 77 * @jack: structure to use for the jack 78 * @pins: Array of jack pins to be added to the jack or NULL 79 * @num_pins: Number of elements in the @pins array 80 * 81 * Creates a new jack object. 82 * 83 * Returns zero if successful, or a negative error code on failure. 84 * On success jack will be initialised. 85 */ 86 int snd_soc_card_jack_new(struct snd_soc_card *card, const char *id, int type, 87 struct snd_soc_jack *jack, struct snd_soc_jack_pin *pins, 88 unsigned int num_pins) 89 { 90 int ret; 91 92 mutex_init(&jack->mutex); 93 jack->card = card; 94 INIT_LIST_HEAD(&jack->pins); 95 INIT_LIST_HEAD(&jack->jack_zones); 96 BLOCKING_INIT_NOTIFIER_HEAD(&jack->notifier); 97 98 ret = snd_jack_new(card->snd_card, id, type, &jack->jack, false, false); 99 if (ret) 100 return ret; 101 102 if (num_pins) 103 return snd_soc_jack_add_pins(jack, num_pins, pins); 104 105 return 0; 106 } 107 EXPORT_SYMBOL_GPL(snd_soc_card_jack_new); 108 109 /** 110 * snd_soc_jack_report - Report the current status for a jack 111 * 112 * @jack: the jack 113 * @status: a bitmask of enum snd_jack_type values that are currently detected. 114 * @mask: a bitmask of enum snd_jack_type values that being reported. 115 * 116 * If configured using snd_soc_jack_add_pins() then the associated 117 * DAPM pins will be enabled or disabled as appropriate and DAPM 118 * synchronised. 119 * 120 * Note: This function uses mutexes and should be called from a 121 * context which can sleep (such as a workqueue). 122 */ 123 void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) 124 { 125 struct snd_soc_dapm_context *dapm; 126 struct snd_soc_jack_pin *pin; 127 unsigned int sync = 0; 128 int enable; 129 130 trace_snd_soc_jack_report(jack, mask, status); 131 132 if (!jack) 133 return; 134 135 dapm = &jack->card->dapm; 136 137 mutex_lock(&jack->mutex); 138 139 jack->status &= ~mask; 140 jack->status |= status & mask; 141 142 trace_snd_soc_jack_notify(jack, status); 143 144 list_for_each_entry(pin, &jack->pins, list) { 145 enable = pin->mask & jack->status; 146 147 if (pin->invert) 148 enable = !enable; 149 150 if (enable) 151 snd_soc_dapm_enable_pin(dapm, pin->pin); 152 else 153 snd_soc_dapm_disable_pin(dapm, pin->pin); 154 155 /* we need to sync for this case only */ 156 sync = 1; 157 } 158 159 /* Report before the DAPM sync to help users updating micbias status */ 160 blocking_notifier_call_chain(&jack->notifier, jack->status, jack); 161 162 if (sync) 163 snd_soc_dapm_sync(dapm); 164 165 snd_jack_report(jack->jack, jack->status); 166 167 mutex_unlock(&jack->mutex); 168 } 169 EXPORT_SYMBOL_GPL(snd_soc_jack_report); 170 171 /** 172 * snd_soc_jack_add_zones - Associate voltage zones with jack 173 * 174 * @jack: ASoC jack 175 * @count: Number of zones 176 * @zones: Array of zones 177 * 178 * After this function has been called the zones specified in the 179 * array will be associated with the jack. 180 */ 181 int snd_soc_jack_add_zones(struct snd_soc_jack *jack, int count, 182 struct snd_soc_jack_zone *zones) 183 { 184 int i; 185 186 for (i = 0; i < count; i++) { 187 INIT_LIST_HEAD(&zones[i].list); 188 list_add(&(zones[i].list), &jack->jack_zones); 189 } 190 return 0; 191 } 192 EXPORT_SYMBOL_GPL(snd_soc_jack_add_zones); 193 194 /** 195 * snd_soc_jack_get_type - Based on the mic bias value, this function returns 196 * the type of jack from the zones declared in the jack type 197 * 198 * @jack: ASoC jack 199 * @micbias_voltage: mic bias voltage at adc channel when jack is plugged in 200 * 201 * Based on the mic bias value passed, this function helps identify 202 * the type of jack from the already declared jack zones 203 */ 204 int snd_soc_jack_get_type(struct snd_soc_jack *jack, int micbias_voltage) 205 { 206 struct snd_soc_jack_zone *zone; 207 208 list_for_each_entry(zone, &jack->jack_zones, list) { 209 if (micbias_voltage >= zone->min_mv && 210 micbias_voltage < zone->max_mv) 211 return zone->jack_type; 212 } 213 return 0; 214 } 215 EXPORT_SYMBOL_GPL(snd_soc_jack_get_type); 216 217 /** 218 * snd_soc_jack_add_pins - Associate DAPM pins with an ASoC jack 219 * 220 * @jack: ASoC jack 221 * @count: Number of pins 222 * @pins: Array of pins 223 * 224 * After this function has been called the DAPM pins specified in the 225 * pins array will have their status updated to reflect the current 226 * state of the jack whenever the jack status is updated. 227 */ 228 int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count, 229 struct snd_soc_jack_pin *pins) 230 { 231 int i; 232 233 for (i = 0; i < count; i++) { 234 if (!pins[i].pin) { 235 dev_err(jack->card->dev, "ASoC: No name for pin %d\n", 236 i); 237 return -EINVAL; 238 } 239 if (!pins[i].mask) { 240 dev_err(jack->card->dev, "ASoC: No mask for pin %d" 241 " (%s)\n", i, pins[i].pin); 242 return -EINVAL; 243 } 244 245 INIT_LIST_HEAD(&pins[i].list); 246 list_add(&(pins[i].list), &jack->pins); 247 snd_jack_add_new_kctl(jack->jack, pins[i].pin, pins[i].mask); 248 } 249 250 /* Update to reflect the last reported status; canned jack 251 * implementations are likely to set their state before the 252 * card has an opportunity to associate pins. 253 */ 254 snd_soc_jack_report(jack, 0, 0); 255 256 return 0; 257 } 258 EXPORT_SYMBOL_GPL(snd_soc_jack_add_pins); 259 260 /** 261 * snd_soc_jack_notifier_register - Register a notifier for jack status 262 * 263 * @jack: ASoC jack 264 * @nb: Notifier block to register 265 * 266 * Register for notification of the current status of the jack. Note 267 * that it is not possible to report additional jack events in the 268 * callback from the notifier, this is intended to support 269 * applications such as enabling electrical detection only when a 270 * mechanical detection event has occurred. 271 */ 272 void snd_soc_jack_notifier_register(struct snd_soc_jack *jack, 273 struct notifier_block *nb) 274 { 275 blocking_notifier_chain_register(&jack->notifier, nb); 276 } 277 EXPORT_SYMBOL_GPL(snd_soc_jack_notifier_register); 278 279 /** 280 * snd_soc_jack_notifier_unregister - Unregister a notifier for jack status 281 * 282 * @jack: ASoC jack 283 * @nb: Notifier block to unregister 284 * 285 * Stop notifying for status changes. 286 */ 287 void snd_soc_jack_notifier_unregister(struct snd_soc_jack *jack, 288 struct notifier_block *nb) 289 { 290 blocking_notifier_chain_unregister(&jack->notifier, nb); 291 } 292 EXPORT_SYMBOL_GPL(snd_soc_jack_notifier_unregister); 293 294 #ifdef CONFIG_GPIOLIB 295 /* gpio detect */ 296 static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio) 297 { 298 struct snd_soc_jack *jack = gpio->jack; 299 int enable; 300 int report; 301 302 enable = gpiod_get_value_cansleep(gpio->desc); 303 if (gpio->invert) 304 enable = !enable; 305 306 if (enable) 307 report = gpio->report; 308 else 309 report = 0; 310 311 if (gpio->jack_status_check) 312 report = gpio->jack_status_check(gpio->data); 313 314 snd_soc_jack_report(jack, report, gpio->report); 315 } 316 317 /* irq handler for gpio pin */ 318 static irqreturn_t gpio_handler(int irq, void *data) 319 { 320 struct snd_soc_jack_gpio *gpio = data; 321 struct device *dev = gpio->jack->card->dev; 322 323 trace_snd_soc_jack_irq(gpio->name); 324 325 if (device_may_wakeup(dev)) 326 pm_wakeup_event(dev, gpio->debounce_time + 50); 327 328 queue_delayed_work(system_power_efficient_wq, &gpio->work, 329 msecs_to_jiffies(gpio->debounce_time)); 330 331 return IRQ_HANDLED; 332 } 333 334 /* gpio work */ 335 static void gpio_work(struct work_struct *work) 336 { 337 struct snd_soc_jack_gpio *gpio; 338 339 gpio = container_of(work, struct snd_soc_jack_gpio, work.work); 340 snd_soc_jack_gpio_detect(gpio); 341 } 342 343 static int snd_soc_jack_pm_notifier(struct notifier_block *nb, 344 unsigned long action, void *data) 345 { 346 struct snd_soc_jack_gpio *gpio = 347 container_of(nb, struct snd_soc_jack_gpio, pm_notifier); 348 349 switch (action) { 350 case PM_POST_SUSPEND: 351 case PM_POST_HIBERNATION: 352 case PM_POST_RESTORE: 353 /* 354 * Use workqueue so we do not have to care about running 355 * concurrently with work triggered by the interrupt handler. 356 */ 357 queue_delayed_work(system_power_efficient_wq, &gpio->work, 0); 358 break; 359 } 360 361 return NOTIFY_DONE; 362 } 363 364 static void jack_free_gpios(struct snd_soc_jack *jack, int count, 365 struct snd_soc_jack_gpio *gpios) 366 { 367 int i; 368 369 for (i = 0; i < count; i++) { 370 gpiod_unexport(gpios[i].desc); 371 unregister_pm_notifier(&gpios[i].pm_notifier); 372 free_irq(gpiod_to_irq(gpios[i].desc), &gpios[i]); 373 cancel_delayed_work_sync(&gpios[i].work); 374 gpiod_put(gpios[i].desc); 375 gpios[i].jack = NULL; 376 } 377 } 378 379 static void jack_devres_free_gpios(struct device *dev, void *res) 380 { 381 struct jack_gpio_tbl *tbl = res; 382 383 jack_free_gpios(tbl->jack, tbl->count, tbl->gpios); 384 } 385 386 /** 387 * snd_soc_jack_add_gpios - Associate GPIO pins with an ASoC jack 388 * 389 * @jack: ASoC jack 390 * @count: number of pins 391 * @gpios: array of gpio pins 392 * 393 * This function will request gpio, set data direction and request irq 394 * for each gpio in the array. 395 */ 396 int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count, 397 struct snd_soc_jack_gpio *gpios) 398 { 399 int i, ret; 400 struct jack_gpio_tbl *tbl; 401 402 tbl = devres_alloc(jack_devres_free_gpios, sizeof(*tbl), GFP_KERNEL); 403 if (!tbl) 404 return -ENOMEM; 405 tbl->jack = jack; 406 tbl->count = count; 407 tbl->gpios = gpios; 408 409 for (i = 0; i < count; i++) { 410 if (!gpios[i].name) { 411 dev_err(jack->card->dev, 412 "ASoC: No name for gpio at index %d\n", i); 413 ret = -EINVAL; 414 goto undo; 415 } 416 417 if (gpios[i].desc) { 418 /* Already have a GPIO descriptor. */ 419 goto got_gpio; 420 } else if (gpios[i].gpiod_dev) { 421 /* Get a GPIO descriptor */ 422 gpios[i].desc = gpiod_get_index(gpios[i].gpiod_dev, 423 gpios[i].name, 424 gpios[i].idx, GPIOD_IN); 425 if (IS_ERR(gpios[i].desc)) { 426 ret = PTR_ERR(gpios[i].desc); 427 dev_err(gpios[i].gpiod_dev, 428 "ASoC: Cannot get gpio at index %d: %d", 429 i, ret); 430 goto undo; 431 } 432 } else { 433 /* legacy GPIO number */ 434 if (!gpio_is_valid(gpios[i].gpio)) { 435 dev_err(jack->card->dev, 436 "ASoC: Invalid gpio %d\n", 437 gpios[i].gpio); 438 ret = -EINVAL; 439 goto undo; 440 } 441 442 ret = gpio_request_one(gpios[i].gpio, GPIOF_IN, 443 gpios[i].name); 444 if (ret) 445 goto undo; 446 447 gpios[i].desc = gpio_to_desc(gpios[i].gpio); 448 } 449 got_gpio: 450 INIT_DELAYED_WORK(&gpios[i].work, gpio_work); 451 gpios[i].jack = jack; 452 453 ret = request_any_context_irq(gpiod_to_irq(gpios[i].desc), 454 gpio_handler, 455 IRQF_TRIGGER_RISING | 456 IRQF_TRIGGER_FALLING, 457 gpios[i].name, 458 &gpios[i]); 459 if (ret < 0) 460 goto err; 461 462 if (gpios[i].wake) { 463 ret = irq_set_irq_wake(gpiod_to_irq(gpios[i].desc), 1); 464 if (ret != 0) 465 dev_err(jack->card->dev, 466 "ASoC: Failed to mark GPIO at index %d as wake source: %d\n", 467 i, ret); 468 } 469 470 /* 471 * Register PM notifier so we do not miss state transitions 472 * happening while system is asleep. 473 */ 474 gpios[i].pm_notifier.notifier_call = snd_soc_jack_pm_notifier; 475 register_pm_notifier(&gpios[i].pm_notifier); 476 477 /* Expose GPIO value over sysfs for diagnostic purposes */ 478 gpiod_export(gpios[i].desc, false); 479 480 /* Update initial jack status */ 481 schedule_delayed_work(&gpios[i].work, 482 msecs_to_jiffies(gpios[i].debounce_time)); 483 } 484 485 devres_add(jack->card->dev, tbl); 486 return 0; 487 488 err: 489 gpio_free(gpios[i].gpio); 490 undo: 491 jack_free_gpios(jack, i, gpios); 492 devres_free(tbl); 493 494 return ret; 495 } 496 EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpios); 497 498 /** 499 * snd_soc_jack_add_gpiods - Associate GPIO descriptor pins with an ASoC jack 500 * 501 * @gpiod_dev: GPIO consumer device 502 * @jack: ASoC jack 503 * @count: number of pins 504 * @gpios: array of gpio pins 505 * 506 * This function will request gpio, set data direction and request irq 507 * for each gpio in the array. 508 */ 509 int snd_soc_jack_add_gpiods(struct device *gpiod_dev, 510 struct snd_soc_jack *jack, 511 int count, struct snd_soc_jack_gpio *gpios) 512 { 513 int i; 514 515 for (i = 0; i < count; i++) 516 gpios[i].gpiod_dev = gpiod_dev; 517 518 return snd_soc_jack_add_gpios(jack, count, gpios); 519 } 520 EXPORT_SYMBOL_GPL(snd_soc_jack_add_gpiods); 521 522 /** 523 * snd_soc_jack_free_gpios - Release GPIO pins' resources of an ASoC jack 524 * 525 * @jack: ASoC jack 526 * @count: number of pins 527 * @gpios: array of gpio pins 528 * 529 * Release gpio and irq resources for gpio pins associated with an ASoC jack. 530 */ 531 void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count, 532 struct snd_soc_jack_gpio *gpios) 533 { 534 jack_free_gpios(jack, count, gpios); 535 devres_destroy(jack->card->dev, jack_devres_free_gpios, NULL, NULL); 536 } 537 EXPORT_SYMBOL_GPL(snd_soc_jack_free_gpios); 538 #endif /* CONFIG_GPIOLIB */ 539