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