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