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