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