1 /* 2 * soc-dapm.c -- ALSA SoC Dynamic Audio Power Management 3 * 4 * Copyright 2005 Wolfson Microelectronics PLC. 5 * Author: Liam Girdwood <lrg@slimlogic.co.uk> 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation; either version 2 of the License, or (at your 10 * option) any later version. 11 * 12 * Features: 13 * o Changes power status of internal codec blocks depending on the 14 * dynamic configuration of codec internal audio paths and active 15 * DAC's/ADC's. 16 * o Platform power domain - can support external components i.e. amps and 17 * mic/meadphone insertion events. 18 * o Automatic Mic Bias support 19 * o Jack insertion power event initiation - e.g. hp insertion will enable 20 * sinks, dacs, etc 21 * o Delayed powerdown of audio susbsystem to reduce pops between a quick 22 * device reopen. 23 * 24 * Todo: 25 * o DAPM power change sequencing - allow for configurable per 26 * codec sequences. 27 * o Support for analogue bias optimisation. 28 * o Support for reduced codec oversampling rates. 29 * o Support for reduced codec bias currents. 30 */ 31 32 #include <linux/module.h> 33 #include <linux/moduleparam.h> 34 #include <linux/init.h> 35 #include <linux/delay.h> 36 #include <linux/pm.h> 37 #include <linux/bitops.h> 38 #include <linux/platform_device.h> 39 #include <linux/jiffies.h> 40 #include <sound/core.h> 41 #include <sound/pcm.h> 42 #include <sound/pcm_params.h> 43 #include <sound/soc-dapm.h> 44 #include <sound/initval.h> 45 46 /* debug */ 47 #ifdef DEBUG 48 #define dump_dapm(codec, action) dbg_dump_dapm(codec, action) 49 #else 50 #define dump_dapm(codec, action) 51 #endif 52 53 /* dapm power sequences - make this per codec in the future */ 54 static int dapm_up_seq[] = { 55 snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic, 56 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_dac, 57 snd_soc_dapm_mixer, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_pga, 58 snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post 59 }; 60 61 static int dapm_down_seq[] = { 62 snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, 63 snd_soc_dapm_pga, snd_soc_dapm_mixer_named_ctl, snd_soc_dapm_mixer, 64 snd_soc_dapm_dac, snd_soc_dapm_mic, snd_soc_dapm_micbias, 65 snd_soc_dapm_mux, snd_soc_dapm_value_mux, snd_soc_dapm_post 66 }; 67 68 static int dapm_status = 1; 69 module_param(dapm_status, int, 0); 70 MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries"); 71 72 static void pop_wait(u32 pop_time) 73 { 74 if (pop_time) 75 schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time)); 76 } 77 78 static void pop_dbg(u32 pop_time, const char *fmt, ...) 79 { 80 va_list args; 81 82 va_start(args, fmt); 83 84 if (pop_time) { 85 vprintk(fmt, args); 86 pop_wait(pop_time); 87 } 88 89 va_end(args); 90 } 91 92 /* create a new dapm widget */ 93 static inline struct snd_soc_dapm_widget *dapm_cnew_widget( 94 const struct snd_soc_dapm_widget *_widget) 95 { 96 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL); 97 } 98 99 /* set up initial codec paths */ 100 static void dapm_set_path_status(struct snd_soc_dapm_widget *w, 101 struct snd_soc_dapm_path *p, int i) 102 { 103 switch (w->id) { 104 case snd_soc_dapm_switch: 105 case snd_soc_dapm_mixer: 106 case snd_soc_dapm_mixer_named_ctl: { 107 int val; 108 struct soc_mixer_control *mc = (struct soc_mixer_control *) 109 w->kcontrols[i].private_value; 110 unsigned int reg = mc->reg; 111 unsigned int shift = mc->shift; 112 int max = mc->max; 113 unsigned int mask = (1 << fls(max)) - 1; 114 unsigned int invert = mc->invert; 115 116 val = snd_soc_read(w->codec, reg); 117 val = (val >> shift) & mask; 118 119 if ((invert && !val) || (!invert && val)) 120 p->connect = 1; 121 else 122 p->connect = 0; 123 } 124 break; 125 case snd_soc_dapm_mux: { 126 struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value; 127 int val, item, bitmask; 128 129 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) 130 ; 131 val = snd_soc_read(w->codec, e->reg); 132 item = (val >> e->shift_l) & (bitmask - 1); 133 134 p->connect = 0; 135 for (i = 0; i < e->max; i++) { 136 if (!(strcmp(p->name, e->texts[i])) && item == i) 137 p->connect = 1; 138 } 139 } 140 break; 141 case snd_soc_dapm_value_mux: { 142 struct soc_enum *e = (struct soc_enum *) 143 w->kcontrols[i].private_value; 144 int val, item; 145 146 val = snd_soc_read(w->codec, e->reg); 147 val = (val >> e->shift_l) & e->mask; 148 for (item = 0; item < e->max; item++) { 149 if (val == e->values[item]) 150 break; 151 } 152 153 p->connect = 0; 154 for (i = 0; i < e->max; i++) { 155 if (!(strcmp(p->name, e->texts[i])) && item == i) 156 p->connect = 1; 157 } 158 } 159 break; 160 /* does not effect routing - always connected */ 161 case snd_soc_dapm_pga: 162 case snd_soc_dapm_output: 163 case snd_soc_dapm_adc: 164 case snd_soc_dapm_input: 165 case snd_soc_dapm_dac: 166 case snd_soc_dapm_micbias: 167 case snd_soc_dapm_vmid: 168 p->connect = 1; 169 break; 170 /* does effect routing - dynamically connected */ 171 case snd_soc_dapm_hp: 172 case snd_soc_dapm_mic: 173 case snd_soc_dapm_spk: 174 case snd_soc_dapm_line: 175 case snd_soc_dapm_pre: 176 case snd_soc_dapm_post: 177 p->connect = 0; 178 break; 179 } 180 } 181 182 /* connect mux widget to it's interconnecting audio paths */ 183 static int dapm_connect_mux(struct snd_soc_codec *codec, 184 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, 185 struct snd_soc_dapm_path *path, const char *control_name, 186 const struct snd_kcontrol_new *kcontrol) 187 { 188 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 189 int i; 190 191 for (i = 0; i < e->max; i++) { 192 if (!(strcmp(control_name, e->texts[i]))) { 193 list_add(&path->list, &codec->dapm_paths); 194 list_add(&path->list_sink, &dest->sources); 195 list_add(&path->list_source, &src->sinks); 196 path->name = (char*)e->texts[i]; 197 dapm_set_path_status(dest, path, 0); 198 return 0; 199 } 200 } 201 202 return -ENODEV; 203 } 204 205 /* connect mixer widget to it's interconnecting audio paths */ 206 static int dapm_connect_mixer(struct snd_soc_codec *codec, 207 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest, 208 struct snd_soc_dapm_path *path, const char *control_name) 209 { 210 int i; 211 212 /* search for mixer kcontrol */ 213 for (i = 0; i < dest->num_kcontrols; i++) { 214 if (!strcmp(control_name, dest->kcontrols[i].name)) { 215 list_add(&path->list, &codec->dapm_paths); 216 list_add(&path->list_sink, &dest->sources); 217 list_add(&path->list_source, &src->sinks); 218 path->name = dest->kcontrols[i].name; 219 dapm_set_path_status(dest, path, i); 220 return 0; 221 } 222 } 223 return -ENODEV; 224 } 225 226 /* update dapm codec register bits */ 227 static int dapm_update_bits(struct snd_soc_dapm_widget *widget) 228 { 229 int change, power; 230 unsigned short old, new; 231 struct snd_soc_codec *codec = widget->codec; 232 233 /* check for valid widgets */ 234 if (widget->reg < 0 || widget->id == snd_soc_dapm_input || 235 widget->id == snd_soc_dapm_output || 236 widget->id == snd_soc_dapm_hp || 237 widget->id == snd_soc_dapm_mic || 238 widget->id == snd_soc_dapm_line || 239 widget->id == snd_soc_dapm_spk) 240 return 0; 241 242 power = widget->power; 243 if (widget->invert) 244 power = (power ? 0:1); 245 246 old = snd_soc_read(codec, widget->reg); 247 new = (old & ~(0x1 << widget->shift)) | (power << widget->shift); 248 249 change = old != new; 250 if (change) { 251 pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n", 252 widget->name, widget->power ? "on" : "off", 253 codec->pop_time); 254 snd_soc_write(codec, widget->reg, new); 255 pop_wait(codec->pop_time); 256 } 257 pr_debug("reg %x old %x new %x change %d\n", widget->reg, 258 old, new, change); 259 return change; 260 } 261 262 /* ramps the volume up or down to minimise pops before or after a 263 * DAPM power event */ 264 static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power) 265 { 266 const struct snd_kcontrol_new *k = widget->kcontrols; 267 268 if (widget->muted && !power) 269 return 0; 270 if (!widget->muted && power) 271 return 0; 272 273 if (widget->num_kcontrols && k) { 274 struct soc_mixer_control *mc = 275 (struct soc_mixer_control *)k->private_value; 276 unsigned int reg = mc->reg; 277 unsigned int shift = mc->shift; 278 int max = mc->max; 279 unsigned int mask = (1 << fls(max)) - 1; 280 unsigned int invert = mc->invert; 281 282 if (power) { 283 int i; 284 /* power up has happended, increase volume to last level */ 285 if (invert) { 286 for (i = max; i > widget->saved_value; i--) 287 snd_soc_update_bits(widget->codec, reg, mask, i); 288 } else { 289 for (i = 0; i < widget->saved_value; i++) 290 snd_soc_update_bits(widget->codec, reg, mask, i); 291 } 292 widget->muted = 0; 293 } else { 294 /* power down is about to occur, decrease volume to mute */ 295 int val = snd_soc_read(widget->codec, reg); 296 int i = widget->saved_value = (val >> shift) & mask; 297 if (invert) { 298 for (; i < mask; i++) 299 snd_soc_update_bits(widget->codec, reg, mask, i); 300 } else { 301 for (; i > 0; i--) 302 snd_soc_update_bits(widget->codec, reg, mask, i); 303 } 304 widget->muted = 1; 305 } 306 } 307 return 0; 308 } 309 310 /* create new dapm mixer control */ 311 static int dapm_new_mixer(struct snd_soc_codec *codec, 312 struct snd_soc_dapm_widget *w) 313 { 314 int i, ret = 0; 315 size_t name_len; 316 struct snd_soc_dapm_path *path; 317 318 /* add kcontrol */ 319 for (i = 0; i < w->num_kcontrols; i++) { 320 321 /* match name */ 322 list_for_each_entry(path, &w->sources, list_sink) { 323 324 /* mixer/mux paths name must match control name */ 325 if (path->name != (char*)w->kcontrols[i].name) 326 continue; 327 328 /* add dapm control with long name. 329 * for dapm_mixer this is the concatenation of the 330 * mixer and kcontrol name. 331 * for dapm_mixer_named_ctl this is simply the 332 * kcontrol name. 333 */ 334 name_len = strlen(w->kcontrols[i].name) + 1; 335 if (w->id != snd_soc_dapm_mixer_named_ctl) 336 name_len += 1 + strlen(w->name); 337 338 path->long_name = kmalloc(name_len, GFP_KERNEL); 339 340 if (path->long_name == NULL) 341 return -ENOMEM; 342 343 switch (w->id) { 344 default: 345 snprintf(path->long_name, name_len, "%s %s", 346 w->name, w->kcontrols[i].name); 347 break; 348 case snd_soc_dapm_mixer_named_ctl: 349 snprintf(path->long_name, name_len, "%s", 350 w->kcontrols[i].name); 351 break; 352 } 353 354 path->long_name[name_len - 1] = '\0'; 355 356 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w, 357 path->long_name); 358 ret = snd_ctl_add(codec->card, path->kcontrol); 359 if (ret < 0) { 360 printk(KERN_ERR "asoc: failed to add dapm kcontrol %s\n", 361 path->long_name); 362 kfree(path->long_name); 363 path->long_name = NULL; 364 return ret; 365 } 366 } 367 } 368 return ret; 369 } 370 371 /* create new dapm mux control */ 372 static int dapm_new_mux(struct snd_soc_codec *codec, 373 struct snd_soc_dapm_widget *w) 374 { 375 struct snd_soc_dapm_path *path = NULL; 376 struct snd_kcontrol *kcontrol; 377 int ret = 0; 378 379 if (!w->num_kcontrols) { 380 printk(KERN_ERR "asoc: mux %s has no controls\n", w->name); 381 return -EINVAL; 382 } 383 384 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); 385 ret = snd_ctl_add(codec->card, kcontrol); 386 if (ret < 0) 387 goto err; 388 389 list_for_each_entry(path, &w->sources, list_sink) 390 path->kcontrol = kcontrol; 391 392 return ret; 393 394 err: 395 printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name); 396 return ret; 397 } 398 399 /* create new dapm volume control */ 400 static int dapm_new_pga(struct snd_soc_codec *codec, 401 struct snd_soc_dapm_widget *w) 402 { 403 struct snd_kcontrol *kcontrol; 404 int ret = 0; 405 406 if (!w->num_kcontrols) 407 return -EINVAL; 408 409 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name); 410 ret = snd_ctl_add(codec->card, kcontrol); 411 if (ret < 0) { 412 printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name); 413 return ret; 414 } 415 416 return ret; 417 } 418 419 /* reset 'walked' bit for each dapm path */ 420 static inline void dapm_clear_walk(struct snd_soc_codec *codec) 421 { 422 struct snd_soc_dapm_path *p; 423 424 list_for_each_entry(p, &codec->dapm_paths, list) 425 p->walked = 0; 426 } 427 428 /* 429 * Recursively check for a completed path to an active or physically connected 430 * output widget. Returns number of complete paths. 431 */ 432 static int is_connected_output_ep(struct snd_soc_dapm_widget *widget) 433 { 434 struct snd_soc_dapm_path *path; 435 int con = 0; 436 437 if (widget->id == snd_soc_dapm_adc && widget->active) 438 return 1; 439 440 if (widget->connected) { 441 /* connected pin ? */ 442 if (widget->id == snd_soc_dapm_output && !widget->ext) 443 return 1; 444 445 /* connected jack or spk ? */ 446 if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk || 447 widget->id == snd_soc_dapm_line) 448 return 1; 449 } 450 451 list_for_each_entry(path, &widget->sinks, list_source) { 452 if (path->walked) 453 continue; 454 455 if (path->sink && path->connect) { 456 path->walked = 1; 457 con += is_connected_output_ep(path->sink); 458 } 459 } 460 461 return con; 462 } 463 464 /* 465 * Recursively check for a completed path to an active or physically connected 466 * input widget. Returns number of complete paths. 467 */ 468 static int is_connected_input_ep(struct snd_soc_dapm_widget *widget) 469 { 470 struct snd_soc_dapm_path *path; 471 int con = 0; 472 473 /* active stream ? */ 474 if (widget->id == snd_soc_dapm_dac && widget->active) 475 return 1; 476 477 if (widget->connected) { 478 /* connected pin ? */ 479 if (widget->id == snd_soc_dapm_input && !widget->ext) 480 return 1; 481 482 /* connected VMID/Bias for lower pops */ 483 if (widget->id == snd_soc_dapm_vmid) 484 return 1; 485 486 /* connected jack ? */ 487 if (widget->id == snd_soc_dapm_mic || widget->id == snd_soc_dapm_line) 488 return 1; 489 } 490 491 list_for_each_entry(path, &widget->sources, list_sink) { 492 if (path->walked) 493 continue; 494 495 if (path->source && path->connect) { 496 path->walked = 1; 497 con += is_connected_input_ep(path->source); 498 } 499 } 500 501 return con; 502 } 503 504 /* 505 * Handler for generic register modifier widget. 506 */ 507 int dapm_reg_event(struct snd_soc_dapm_widget *w, 508 struct snd_kcontrol *kcontrol, int event) 509 { 510 unsigned int val; 511 512 if (SND_SOC_DAPM_EVENT_ON(event)) 513 val = w->on_val; 514 else 515 val = w->off_val; 516 517 snd_soc_update_bits(w->codec, -(w->reg + 1), 518 w->mask << w->shift, val << w->shift); 519 520 return 0; 521 } 522 EXPORT_SYMBOL_GPL(dapm_reg_event); 523 524 /* 525 * Scan a single DAPM widget for a complete audio path and update the 526 * power status appropriately. 527 */ 528 static int dapm_power_widget(struct snd_soc_codec *codec, int event, 529 struct snd_soc_dapm_widget *w) 530 { 531 int in, out, power_change, power, ret; 532 533 /* vmid - no action */ 534 if (w->id == snd_soc_dapm_vmid) 535 return 0; 536 537 /* active ADC */ 538 if (w->id == snd_soc_dapm_adc && w->active) { 539 in = is_connected_input_ep(w); 540 dapm_clear_walk(w->codec); 541 w->power = (in != 0) ? 1 : 0; 542 dapm_update_bits(w); 543 return 0; 544 } 545 546 /* active DAC */ 547 if (w->id == snd_soc_dapm_dac && w->active) { 548 out = is_connected_output_ep(w); 549 dapm_clear_walk(w->codec); 550 w->power = (out != 0) ? 1 : 0; 551 dapm_update_bits(w); 552 return 0; 553 } 554 555 /* pre and post event widgets */ 556 if (w->id == snd_soc_dapm_pre) { 557 if (!w->event) 558 return 0; 559 560 if (event == SND_SOC_DAPM_STREAM_START) { 561 ret = w->event(w, 562 NULL, SND_SOC_DAPM_PRE_PMU); 563 if (ret < 0) 564 return ret; 565 } else if (event == SND_SOC_DAPM_STREAM_STOP) { 566 ret = w->event(w, 567 NULL, SND_SOC_DAPM_PRE_PMD); 568 if (ret < 0) 569 return ret; 570 } 571 return 0; 572 } 573 if (w->id == snd_soc_dapm_post) { 574 if (!w->event) 575 return 0; 576 577 if (event == SND_SOC_DAPM_STREAM_START) { 578 ret = w->event(w, 579 NULL, SND_SOC_DAPM_POST_PMU); 580 if (ret < 0) 581 return ret; 582 } else if (event == SND_SOC_DAPM_STREAM_STOP) { 583 ret = w->event(w, 584 NULL, SND_SOC_DAPM_POST_PMD); 585 if (ret < 0) 586 return ret; 587 } 588 return 0; 589 } 590 591 /* all other widgets */ 592 in = is_connected_input_ep(w); 593 dapm_clear_walk(w->codec); 594 out = is_connected_output_ep(w); 595 dapm_clear_walk(w->codec); 596 power = (out != 0 && in != 0) ? 1 : 0; 597 power_change = (w->power == power) ? 0 : 1; 598 w->power = power; 599 600 if (!power_change) 601 return 0; 602 603 /* call any power change event handlers */ 604 if (w->event) 605 pr_debug("power %s event for %s flags %x\n", 606 w->power ? "on" : "off", 607 w->name, w->event_flags); 608 609 /* power up pre event */ 610 if (power && w->event && 611 (w->event_flags & SND_SOC_DAPM_PRE_PMU)) { 612 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMU); 613 if (ret < 0) 614 return ret; 615 } 616 617 /* power down pre event */ 618 if (!power && w->event && 619 (w->event_flags & SND_SOC_DAPM_PRE_PMD)) { 620 ret = w->event(w, NULL, SND_SOC_DAPM_PRE_PMD); 621 if (ret < 0) 622 return ret; 623 } 624 625 /* Lower PGA volume to reduce pops */ 626 if (w->id == snd_soc_dapm_pga && !power) 627 dapm_set_pga(w, power); 628 629 dapm_update_bits(w); 630 631 /* Raise PGA volume to reduce pops */ 632 if (w->id == snd_soc_dapm_pga && power) 633 dapm_set_pga(w, power); 634 635 /* power up post event */ 636 if (power && w->event && 637 (w->event_flags & SND_SOC_DAPM_POST_PMU)) { 638 ret = w->event(w, 639 NULL, SND_SOC_DAPM_POST_PMU); 640 if (ret < 0) 641 return ret; 642 } 643 644 /* power down post event */ 645 if (!power && w->event && 646 (w->event_flags & SND_SOC_DAPM_POST_PMD)) { 647 ret = w->event(w, NULL, SND_SOC_DAPM_POST_PMD); 648 if (ret < 0) 649 return ret; 650 } 651 652 return 0; 653 } 654 655 /* 656 * Scan each dapm widget for complete audio path. 657 * A complete path is a route that has valid endpoints i.e.:- 658 * 659 * o DAC to output pin. 660 * o Input Pin to ADC. 661 * o Input pin to Output pin (bypass, sidetone) 662 * o DAC to ADC (loopback). 663 */ 664 static int dapm_power_widgets(struct snd_soc_codec *codec, int event) 665 { 666 struct snd_soc_dapm_widget *w; 667 int i, c = 1, *seq = NULL, ret = 0; 668 669 /* do we have a sequenced stream event */ 670 if (event == SND_SOC_DAPM_STREAM_START) { 671 c = ARRAY_SIZE(dapm_up_seq); 672 seq = dapm_up_seq; 673 } else if (event == SND_SOC_DAPM_STREAM_STOP) { 674 c = ARRAY_SIZE(dapm_down_seq); 675 seq = dapm_down_seq; 676 } 677 678 for (i = 0; i < c; i++) { 679 list_for_each_entry(w, &codec->dapm_widgets, list) { 680 681 /* is widget in stream order */ 682 if (seq && seq[i] && w->id != seq[i]) 683 continue; 684 685 ret = dapm_power_widget(codec, event, w); 686 if (ret != 0) 687 return ret; 688 } 689 } 690 691 return 0; 692 } 693 694 #ifdef DEBUG 695 static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action) 696 { 697 struct snd_soc_dapm_widget *w; 698 struct snd_soc_dapm_path *p = NULL; 699 int in, out; 700 701 printk("DAPM %s %s\n", codec->name, action); 702 703 list_for_each_entry(w, &codec->dapm_widgets, list) { 704 705 /* only display widgets that effect routing */ 706 switch (w->id) { 707 case snd_soc_dapm_pre: 708 case snd_soc_dapm_post: 709 case snd_soc_dapm_vmid: 710 continue; 711 case snd_soc_dapm_mux: 712 case snd_soc_dapm_value_mux: 713 case snd_soc_dapm_output: 714 case snd_soc_dapm_input: 715 case snd_soc_dapm_switch: 716 case snd_soc_dapm_hp: 717 case snd_soc_dapm_mic: 718 case snd_soc_dapm_spk: 719 case snd_soc_dapm_line: 720 case snd_soc_dapm_micbias: 721 case snd_soc_dapm_dac: 722 case snd_soc_dapm_adc: 723 case snd_soc_dapm_pga: 724 case snd_soc_dapm_mixer: 725 case snd_soc_dapm_mixer_named_ctl: 726 if (w->name) { 727 in = is_connected_input_ep(w); 728 dapm_clear_walk(w->codec); 729 out = is_connected_output_ep(w); 730 dapm_clear_walk(w->codec); 731 printk("%s: %s in %d out %d\n", w->name, 732 w->power ? "On":"Off",in, out); 733 734 list_for_each_entry(p, &w->sources, list_sink) { 735 if (p->connect) 736 printk(" in %s %s\n", p->name ? p->name : "static", 737 p->source->name); 738 } 739 list_for_each_entry(p, &w->sinks, list_source) { 740 if (p->connect) 741 printk(" out %s %s\n", p->name ? p->name : "static", 742 p->sink->name); 743 } 744 } 745 break; 746 } 747 } 748 } 749 #endif 750 751 /* test and update the power status of a mux widget */ 752 static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 753 struct snd_kcontrol *kcontrol, int mask, 754 int mux, int val, struct soc_enum *e) 755 { 756 struct snd_soc_dapm_path *path; 757 int found = 0; 758 759 if (widget->id != snd_soc_dapm_mux && 760 widget->id != snd_soc_dapm_value_mux) 761 return -ENODEV; 762 763 if (!snd_soc_test_bits(widget->codec, e->reg, mask, val)) 764 return 0; 765 766 /* find dapm widget path assoc with kcontrol */ 767 list_for_each_entry(path, &widget->codec->dapm_paths, list) { 768 if (path->kcontrol != kcontrol) 769 continue; 770 771 if (!path->name || !e->texts[mux]) 772 continue; 773 774 found = 1; 775 /* we now need to match the string in the enum to the path */ 776 if (!(strcmp(path->name, e->texts[mux]))) 777 path->connect = 1; /* new connection */ 778 else 779 path->connect = 0; /* old connection must be powered down */ 780 } 781 782 if (found) { 783 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP); 784 dump_dapm(widget->codec, "mux power update"); 785 } 786 787 return 0; 788 } 789 790 /* test and update the power status of a mixer or switch widget */ 791 static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget, 792 struct snd_kcontrol *kcontrol, int reg, 793 int val_mask, int val, int invert) 794 { 795 struct snd_soc_dapm_path *path; 796 int found = 0; 797 798 if (widget->id != snd_soc_dapm_mixer && 799 widget->id != snd_soc_dapm_mixer_named_ctl && 800 widget->id != snd_soc_dapm_switch) 801 return -ENODEV; 802 803 if (!snd_soc_test_bits(widget->codec, reg, val_mask, val)) 804 return 0; 805 806 /* find dapm widget path assoc with kcontrol */ 807 list_for_each_entry(path, &widget->codec->dapm_paths, list) { 808 if (path->kcontrol != kcontrol) 809 continue; 810 811 /* found, now check type */ 812 found = 1; 813 if (val) 814 /* new connection */ 815 path->connect = invert ? 0:1; 816 else 817 /* old connection must be powered down */ 818 path->connect = invert ? 1:0; 819 break; 820 } 821 822 if (found) { 823 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP); 824 dump_dapm(widget->codec, "mixer power update"); 825 } 826 827 return 0; 828 } 829 830 /* show dapm widget status in sys fs */ 831 static ssize_t dapm_widget_show(struct device *dev, 832 struct device_attribute *attr, char *buf) 833 { 834 struct snd_soc_device *devdata = dev_get_drvdata(dev); 835 struct snd_soc_codec *codec = devdata->card->codec; 836 struct snd_soc_dapm_widget *w; 837 int count = 0; 838 char *state = "not set"; 839 840 list_for_each_entry(w, &codec->dapm_widgets, list) { 841 842 /* only display widgets that burnm power */ 843 switch (w->id) { 844 case snd_soc_dapm_hp: 845 case snd_soc_dapm_mic: 846 case snd_soc_dapm_spk: 847 case snd_soc_dapm_line: 848 case snd_soc_dapm_micbias: 849 case snd_soc_dapm_dac: 850 case snd_soc_dapm_adc: 851 case snd_soc_dapm_pga: 852 case snd_soc_dapm_mixer: 853 case snd_soc_dapm_mixer_named_ctl: 854 if (w->name) 855 count += sprintf(buf + count, "%s: %s\n", 856 w->name, w->power ? "On":"Off"); 857 break; 858 default: 859 break; 860 } 861 } 862 863 switch (codec->bias_level) { 864 case SND_SOC_BIAS_ON: 865 state = "On"; 866 break; 867 case SND_SOC_BIAS_PREPARE: 868 state = "Prepare"; 869 break; 870 case SND_SOC_BIAS_STANDBY: 871 state = "Standby"; 872 break; 873 case SND_SOC_BIAS_OFF: 874 state = "Off"; 875 break; 876 } 877 count += sprintf(buf + count, "PM State: %s\n", state); 878 879 return count; 880 } 881 882 static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL); 883 884 int snd_soc_dapm_sys_add(struct device *dev) 885 { 886 if (!dapm_status) 887 return 0; 888 return device_create_file(dev, &dev_attr_dapm_widget); 889 } 890 891 static void snd_soc_dapm_sys_remove(struct device *dev) 892 { 893 if (dapm_status) { 894 device_remove_file(dev, &dev_attr_dapm_widget); 895 } 896 } 897 898 /* free all dapm widgets and resources */ 899 static void dapm_free_widgets(struct snd_soc_codec *codec) 900 { 901 struct snd_soc_dapm_widget *w, *next_w; 902 struct snd_soc_dapm_path *p, *next_p; 903 904 list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) { 905 list_del(&w->list); 906 kfree(w); 907 } 908 909 list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) { 910 list_del(&p->list); 911 kfree(p->long_name); 912 kfree(p); 913 } 914 } 915 916 static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec, 917 const char *pin, int status) 918 { 919 struct snd_soc_dapm_widget *w; 920 921 list_for_each_entry(w, &codec->dapm_widgets, list) { 922 if (!strcmp(w->name, pin)) { 923 pr_debug("dapm: %s: pin %s\n", codec->name, pin); 924 w->connected = status; 925 return 0; 926 } 927 } 928 929 pr_err("dapm: %s: configuring unknown pin %s\n", codec->name, pin); 930 return -EINVAL; 931 } 932 933 /** 934 * snd_soc_dapm_sync - scan and power dapm paths 935 * @codec: audio codec 936 * 937 * Walks all dapm audio paths and powers widgets according to their 938 * stream or path usage. 939 * 940 * Returns 0 for success. 941 */ 942 int snd_soc_dapm_sync(struct snd_soc_codec *codec) 943 { 944 int ret = dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP); 945 dump_dapm(codec, "sync"); 946 return ret; 947 } 948 EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); 949 950 static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, 951 const char *sink, const char *control, const char *source) 952 { 953 struct snd_soc_dapm_path *path; 954 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 955 int ret = 0; 956 957 /* find src and dest widgets */ 958 list_for_each_entry(w, &codec->dapm_widgets, list) { 959 960 if (!wsink && !(strcmp(w->name, sink))) { 961 wsink = w; 962 continue; 963 } 964 if (!wsource && !(strcmp(w->name, source))) { 965 wsource = w; 966 } 967 } 968 969 if (wsource == NULL || wsink == NULL) 970 return -ENODEV; 971 972 path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL); 973 if (!path) 974 return -ENOMEM; 975 976 path->source = wsource; 977 path->sink = wsink; 978 INIT_LIST_HEAD(&path->list); 979 INIT_LIST_HEAD(&path->list_source); 980 INIT_LIST_HEAD(&path->list_sink); 981 982 /* check for external widgets */ 983 if (wsink->id == snd_soc_dapm_input) { 984 if (wsource->id == snd_soc_dapm_micbias || 985 wsource->id == snd_soc_dapm_mic || 986 wsink->id == snd_soc_dapm_line || 987 wsink->id == snd_soc_dapm_output) 988 wsink->ext = 1; 989 } 990 if (wsource->id == snd_soc_dapm_output) { 991 if (wsink->id == snd_soc_dapm_spk || 992 wsink->id == snd_soc_dapm_hp || 993 wsink->id == snd_soc_dapm_line || 994 wsink->id == snd_soc_dapm_input) 995 wsource->ext = 1; 996 } 997 998 /* connect static paths */ 999 if (control == NULL) { 1000 list_add(&path->list, &codec->dapm_paths); 1001 list_add(&path->list_sink, &wsink->sources); 1002 list_add(&path->list_source, &wsource->sinks); 1003 path->connect = 1; 1004 return 0; 1005 } 1006 1007 /* connect dynamic paths */ 1008 switch(wsink->id) { 1009 case snd_soc_dapm_adc: 1010 case snd_soc_dapm_dac: 1011 case snd_soc_dapm_pga: 1012 case snd_soc_dapm_input: 1013 case snd_soc_dapm_output: 1014 case snd_soc_dapm_micbias: 1015 case snd_soc_dapm_vmid: 1016 case snd_soc_dapm_pre: 1017 case snd_soc_dapm_post: 1018 list_add(&path->list, &codec->dapm_paths); 1019 list_add(&path->list_sink, &wsink->sources); 1020 list_add(&path->list_source, &wsource->sinks); 1021 path->connect = 1; 1022 return 0; 1023 case snd_soc_dapm_mux: 1024 case snd_soc_dapm_value_mux: 1025 ret = dapm_connect_mux(codec, wsource, wsink, path, control, 1026 &wsink->kcontrols[0]); 1027 if (ret != 0) 1028 goto err; 1029 break; 1030 case snd_soc_dapm_switch: 1031 case snd_soc_dapm_mixer: 1032 case snd_soc_dapm_mixer_named_ctl: 1033 ret = dapm_connect_mixer(codec, wsource, wsink, path, control); 1034 if (ret != 0) 1035 goto err; 1036 break; 1037 case snd_soc_dapm_hp: 1038 case snd_soc_dapm_mic: 1039 case snd_soc_dapm_line: 1040 case snd_soc_dapm_spk: 1041 list_add(&path->list, &codec->dapm_paths); 1042 list_add(&path->list_sink, &wsink->sources); 1043 list_add(&path->list_source, &wsource->sinks); 1044 path->connect = 0; 1045 return 0; 1046 } 1047 return 0; 1048 1049 err: 1050 printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source, 1051 control, sink); 1052 kfree(path); 1053 return ret; 1054 } 1055 1056 /** 1057 * snd_soc_dapm_add_routes - Add routes between DAPM widgets 1058 * @codec: codec 1059 * @route: audio routes 1060 * @num: number of routes 1061 * 1062 * Connects 2 dapm widgets together via a named audio path. The sink is 1063 * the widget receiving the audio signal, whilst the source is the sender 1064 * of the audio signal. 1065 * 1066 * Returns 0 for success else error. On error all resources can be freed 1067 * with a call to snd_soc_card_free(). 1068 */ 1069 int snd_soc_dapm_add_routes(struct snd_soc_codec *codec, 1070 const struct snd_soc_dapm_route *route, int num) 1071 { 1072 int i, ret; 1073 1074 for (i = 0; i < num; i++) { 1075 ret = snd_soc_dapm_add_route(codec, route->sink, 1076 route->control, route->source); 1077 if (ret < 0) { 1078 printk(KERN_ERR "Failed to add route %s->%s\n", 1079 route->source, 1080 route->sink); 1081 return ret; 1082 } 1083 route++; 1084 } 1085 1086 return 0; 1087 } 1088 EXPORT_SYMBOL_GPL(snd_soc_dapm_add_routes); 1089 1090 /** 1091 * snd_soc_dapm_new_widgets - add new dapm widgets 1092 * @codec: audio codec 1093 * 1094 * Checks the codec for any new dapm widgets and creates them if found. 1095 * 1096 * Returns 0 for success. 1097 */ 1098 int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec) 1099 { 1100 struct snd_soc_dapm_widget *w; 1101 1102 list_for_each_entry(w, &codec->dapm_widgets, list) 1103 { 1104 if (w->new) 1105 continue; 1106 1107 switch(w->id) { 1108 case snd_soc_dapm_switch: 1109 case snd_soc_dapm_mixer: 1110 case snd_soc_dapm_mixer_named_ctl: 1111 dapm_new_mixer(codec, w); 1112 break; 1113 case snd_soc_dapm_mux: 1114 case snd_soc_dapm_value_mux: 1115 dapm_new_mux(codec, w); 1116 break; 1117 case snd_soc_dapm_adc: 1118 case snd_soc_dapm_dac: 1119 case snd_soc_dapm_pga: 1120 dapm_new_pga(codec, w); 1121 break; 1122 case snd_soc_dapm_input: 1123 case snd_soc_dapm_output: 1124 case snd_soc_dapm_micbias: 1125 case snd_soc_dapm_spk: 1126 case snd_soc_dapm_hp: 1127 case snd_soc_dapm_mic: 1128 case snd_soc_dapm_line: 1129 case snd_soc_dapm_vmid: 1130 case snd_soc_dapm_pre: 1131 case snd_soc_dapm_post: 1132 break; 1133 } 1134 w->new = 1; 1135 } 1136 1137 dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP); 1138 return 0; 1139 } 1140 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets); 1141 1142 /** 1143 * snd_soc_dapm_get_volsw - dapm mixer get callback 1144 * @kcontrol: mixer control 1145 * @ucontrol: control element information 1146 * 1147 * Callback to get the value of a dapm mixer control. 1148 * 1149 * Returns 0 for success. 1150 */ 1151 int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, 1152 struct snd_ctl_elem_value *ucontrol) 1153 { 1154 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1155 struct soc_mixer_control *mc = 1156 (struct soc_mixer_control *)kcontrol->private_value; 1157 unsigned int reg = mc->reg; 1158 unsigned int shift = mc->shift; 1159 unsigned int rshift = mc->rshift; 1160 int max = mc->max; 1161 unsigned int invert = mc->invert; 1162 unsigned int mask = (1 << fls(max)) - 1; 1163 1164 /* return the saved value if we are powered down */ 1165 if (widget->id == snd_soc_dapm_pga && !widget->power) { 1166 ucontrol->value.integer.value[0] = widget->saved_value; 1167 return 0; 1168 } 1169 1170 ucontrol->value.integer.value[0] = 1171 (snd_soc_read(widget->codec, reg) >> shift) & mask; 1172 if (shift != rshift) 1173 ucontrol->value.integer.value[1] = 1174 (snd_soc_read(widget->codec, reg) >> rshift) & mask; 1175 if (invert) { 1176 ucontrol->value.integer.value[0] = 1177 max - ucontrol->value.integer.value[0]; 1178 if (shift != rshift) 1179 ucontrol->value.integer.value[1] = 1180 max - ucontrol->value.integer.value[1]; 1181 } 1182 1183 return 0; 1184 } 1185 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw); 1186 1187 /** 1188 * snd_soc_dapm_put_volsw - dapm mixer set callback 1189 * @kcontrol: mixer control 1190 * @ucontrol: control element information 1191 * 1192 * Callback to set the value of a dapm mixer control. 1193 * 1194 * Returns 0 for success. 1195 */ 1196 int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, 1197 struct snd_ctl_elem_value *ucontrol) 1198 { 1199 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1200 struct soc_mixer_control *mc = 1201 (struct soc_mixer_control *)kcontrol->private_value; 1202 unsigned int reg = mc->reg; 1203 unsigned int shift = mc->shift; 1204 unsigned int rshift = mc->rshift; 1205 int max = mc->max; 1206 unsigned int mask = (1 << fls(max)) - 1; 1207 unsigned int invert = mc->invert; 1208 unsigned short val, val2, val_mask; 1209 int ret; 1210 1211 val = (ucontrol->value.integer.value[0] & mask); 1212 1213 if (invert) 1214 val = max - val; 1215 val_mask = mask << shift; 1216 val = val << shift; 1217 if (shift != rshift) { 1218 val2 = (ucontrol->value.integer.value[1] & mask); 1219 if (invert) 1220 val2 = max - val2; 1221 val_mask |= mask << rshift; 1222 val |= val2 << rshift; 1223 } 1224 1225 mutex_lock(&widget->codec->mutex); 1226 widget->value = val; 1227 1228 /* save volume value if the widget is powered down */ 1229 if (widget->id == snd_soc_dapm_pga && !widget->power) { 1230 widget->saved_value = val; 1231 mutex_unlock(&widget->codec->mutex); 1232 return 1; 1233 } 1234 1235 dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert); 1236 if (widget->event) { 1237 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1238 ret = widget->event(widget, kcontrol, 1239 SND_SOC_DAPM_PRE_REG); 1240 if (ret < 0) { 1241 ret = 1; 1242 goto out; 1243 } 1244 } 1245 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); 1246 if (widget->event_flags & SND_SOC_DAPM_POST_REG) 1247 ret = widget->event(widget, kcontrol, 1248 SND_SOC_DAPM_POST_REG); 1249 } else 1250 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val); 1251 1252 out: 1253 mutex_unlock(&widget->codec->mutex); 1254 return ret; 1255 } 1256 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw); 1257 1258 /** 1259 * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback 1260 * @kcontrol: mixer control 1261 * @ucontrol: control element information 1262 * 1263 * Callback to get the value of a dapm enumerated double mixer control. 1264 * 1265 * Returns 0 for success. 1266 */ 1267 int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol, 1268 struct snd_ctl_elem_value *ucontrol) 1269 { 1270 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1271 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1272 unsigned short val, bitmask; 1273 1274 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) 1275 ; 1276 val = snd_soc_read(widget->codec, e->reg); 1277 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1); 1278 if (e->shift_l != e->shift_r) 1279 ucontrol->value.enumerated.item[1] = 1280 (val >> e->shift_r) & (bitmask - 1); 1281 1282 return 0; 1283 } 1284 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double); 1285 1286 /** 1287 * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback 1288 * @kcontrol: mixer control 1289 * @ucontrol: control element information 1290 * 1291 * Callback to set the value of a dapm enumerated double mixer control. 1292 * 1293 * Returns 0 for success. 1294 */ 1295 int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, 1296 struct snd_ctl_elem_value *ucontrol) 1297 { 1298 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1299 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1300 unsigned short val, mux; 1301 unsigned short mask, bitmask; 1302 int ret = 0; 1303 1304 for (bitmask = 1; bitmask < e->max; bitmask <<= 1) 1305 ; 1306 if (ucontrol->value.enumerated.item[0] > e->max - 1) 1307 return -EINVAL; 1308 mux = ucontrol->value.enumerated.item[0]; 1309 val = mux << e->shift_l; 1310 mask = (bitmask - 1) << e->shift_l; 1311 if (e->shift_l != e->shift_r) { 1312 if (ucontrol->value.enumerated.item[1] > e->max - 1) 1313 return -EINVAL; 1314 val |= ucontrol->value.enumerated.item[1] << e->shift_r; 1315 mask |= (bitmask - 1) << e->shift_r; 1316 } 1317 1318 mutex_lock(&widget->codec->mutex); 1319 widget->value = val; 1320 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); 1321 if (widget->event) { 1322 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1323 ret = widget->event(widget, 1324 kcontrol, SND_SOC_DAPM_PRE_REG); 1325 if (ret < 0) 1326 goto out; 1327 } 1328 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1329 if (widget->event_flags & SND_SOC_DAPM_POST_REG) 1330 ret = widget->event(widget, 1331 kcontrol, SND_SOC_DAPM_POST_REG); 1332 } else 1333 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1334 1335 out: 1336 mutex_unlock(&widget->codec->mutex); 1337 return ret; 1338 } 1339 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); 1340 1341 /** 1342 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get 1343 * callback 1344 * @kcontrol: mixer control 1345 * @ucontrol: control element information 1346 * 1347 * Callback to get the value of a dapm semi enumerated double mixer control. 1348 * 1349 * Semi enumerated mixer: the enumerated items are referred as values. Can be 1350 * used for handling bitfield coded enumeration for example. 1351 * 1352 * Returns 0 for success. 1353 */ 1354 int snd_soc_dapm_get_value_enum_double(struct snd_kcontrol *kcontrol, 1355 struct snd_ctl_elem_value *ucontrol) 1356 { 1357 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1358 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1359 unsigned short reg_val, val, mux; 1360 1361 reg_val = snd_soc_read(widget->codec, e->reg); 1362 val = (reg_val >> e->shift_l) & e->mask; 1363 for (mux = 0; mux < e->max; mux++) { 1364 if (val == e->values[mux]) 1365 break; 1366 } 1367 ucontrol->value.enumerated.item[0] = mux; 1368 if (e->shift_l != e->shift_r) { 1369 val = (reg_val >> e->shift_r) & e->mask; 1370 for (mux = 0; mux < e->max; mux++) { 1371 if (val == e->values[mux]) 1372 break; 1373 } 1374 ucontrol->value.enumerated.item[1] = mux; 1375 } 1376 1377 return 0; 1378 } 1379 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double); 1380 1381 /** 1382 * snd_soc_dapm_put_value_enum_double - dapm semi enumerated double mixer set 1383 * callback 1384 * @kcontrol: mixer control 1385 * @ucontrol: control element information 1386 * 1387 * Callback to set the value of a dapm semi enumerated double mixer control. 1388 * 1389 * Semi enumerated mixer: the enumerated items are referred as values. Can be 1390 * used for handling bitfield coded enumeration for example. 1391 * 1392 * Returns 0 for success. 1393 */ 1394 int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol, 1395 struct snd_ctl_elem_value *ucontrol) 1396 { 1397 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1398 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1399 unsigned short val, mux; 1400 unsigned short mask; 1401 int ret = 0; 1402 1403 if (ucontrol->value.enumerated.item[0] > e->max - 1) 1404 return -EINVAL; 1405 mux = ucontrol->value.enumerated.item[0]; 1406 val = e->values[ucontrol->value.enumerated.item[0]] << e->shift_l; 1407 mask = e->mask << e->shift_l; 1408 if (e->shift_l != e->shift_r) { 1409 if (ucontrol->value.enumerated.item[1] > e->max - 1) 1410 return -EINVAL; 1411 val |= e->values[ucontrol->value.enumerated.item[1]] << e->shift_r; 1412 mask |= e->mask << e->shift_r; 1413 } 1414 1415 mutex_lock(&widget->codec->mutex); 1416 widget->value = val; 1417 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); 1418 if (widget->event) { 1419 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1420 ret = widget->event(widget, 1421 kcontrol, SND_SOC_DAPM_PRE_REG); 1422 if (ret < 0) 1423 goto out; 1424 } 1425 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1426 if (widget->event_flags & SND_SOC_DAPM_POST_REG) 1427 ret = widget->event(widget, 1428 kcontrol, SND_SOC_DAPM_POST_REG); 1429 } else 1430 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1431 1432 out: 1433 mutex_unlock(&widget->codec->mutex); 1434 return ret; 1435 } 1436 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double); 1437 1438 /** 1439 * snd_soc_dapm_info_pin_switch - Info for a pin switch 1440 * 1441 * @kcontrol: mixer control 1442 * @uinfo: control element information 1443 * 1444 * Callback to provide information about a pin switch control. 1445 */ 1446 int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol, 1447 struct snd_ctl_elem_info *uinfo) 1448 { 1449 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; 1450 uinfo->count = 1; 1451 uinfo->value.integer.min = 0; 1452 uinfo->value.integer.max = 1; 1453 1454 return 0; 1455 } 1456 EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch); 1457 1458 /** 1459 * snd_soc_dapm_get_pin_switch - Get information for a pin switch 1460 * 1461 * @kcontrol: mixer control 1462 * @ucontrol: Value 1463 */ 1464 int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol, 1465 struct snd_ctl_elem_value *ucontrol) 1466 { 1467 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1468 const char *pin = (const char *)kcontrol->private_value; 1469 1470 mutex_lock(&codec->mutex); 1471 1472 ucontrol->value.integer.value[0] = 1473 snd_soc_dapm_get_pin_status(codec, pin); 1474 1475 mutex_unlock(&codec->mutex); 1476 1477 return 0; 1478 } 1479 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch); 1480 1481 /** 1482 * snd_soc_dapm_put_pin_switch - Set information for a pin switch 1483 * 1484 * @kcontrol: mixer control 1485 * @ucontrol: Value 1486 */ 1487 int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol, 1488 struct snd_ctl_elem_value *ucontrol) 1489 { 1490 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 1491 const char *pin = (const char *)kcontrol->private_value; 1492 1493 mutex_lock(&codec->mutex); 1494 1495 if (ucontrol->value.integer.value[0]) 1496 snd_soc_dapm_enable_pin(codec, pin); 1497 else 1498 snd_soc_dapm_disable_pin(codec, pin); 1499 1500 snd_soc_dapm_sync(codec); 1501 1502 mutex_unlock(&codec->mutex); 1503 1504 return 0; 1505 } 1506 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch); 1507 1508 /** 1509 * snd_soc_dapm_new_control - create new dapm control 1510 * @codec: audio codec 1511 * @widget: widget template 1512 * 1513 * Creates a new dapm control based upon the template. 1514 * 1515 * Returns 0 for success else error. 1516 */ 1517 int snd_soc_dapm_new_control(struct snd_soc_codec *codec, 1518 const struct snd_soc_dapm_widget *widget) 1519 { 1520 struct snd_soc_dapm_widget *w; 1521 1522 if ((w = dapm_cnew_widget(widget)) == NULL) 1523 return -ENOMEM; 1524 1525 w->codec = codec; 1526 INIT_LIST_HEAD(&w->sources); 1527 INIT_LIST_HEAD(&w->sinks); 1528 INIT_LIST_HEAD(&w->list); 1529 list_add(&w->list, &codec->dapm_widgets); 1530 1531 /* machine layer set ups unconnected pins and insertions */ 1532 w->connected = 1; 1533 return 0; 1534 } 1535 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control); 1536 1537 /** 1538 * snd_soc_dapm_new_controls - create new dapm controls 1539 * @codec: audio codec 1540 * @widget: widget array 1541 * @num: number of widgets 1542 * 1543 * Creates new DAPM controls based upon the templates. 1544 * 1545 * Returns 0 for success else error. 1546 */ 1547 int snd_soc_dapm_new_controls(struct snd_soc_codec *codec, 1548 const struct snd_soc_dapm_widget *widget, 1549 int num) 1550 { 1551 int i, ret; 1552 1553 for (i = 0; i < num; i++) { 1554 ret = snd_soc_dapm_new_control(codec, widget); 1555 if (ret < 0) { 1556 printk(KERN_ERR 1557 "ASoC: Failed to create DAPM control %s: %d\n", 1558 widget->name, ret); 1559 return ret; 1560 } 1561 widget++; 1562 } 1563 return 0; 1564 } 1565 EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls); 1566 1567 1568 /** 1569 * snd_soc_dapm_stream_event - send a stream event to the dapm core 1570 * @codec: audio codec 1571 * @stream: stream name 1572 * @event: stream event 1573 * 1574 * Sends a stream event to the dapm core. The core then makes any 1575 * necessary widget power changes. 1576 * 1577 * Returns 0 for success else error. 1578 */ 1579 int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, 1580 char *stream, int event) 1581 { 1582 struct snd_soc_dapm_widget *w; 1583 1584 if (stream == NULL) 1585 return 0; 1586 1587 mutex_lock(&codec->mutex); 1588 list_for_each_entry(w, &codec->dapm_widgets, list) 1589 { 1590 if (!w->sname) 1591 continue; 1592 pr_debug("widget %s\n %s stream %s event %d\n", 1593 w->name, w->sname, stream, event); 1594 if (strstr(w->sname, stream)) { 1595 switch(event) { 1596 case SND_SOC_DAPM_STREAM_START: 1597 w->active = 1; 1598 break; 1599 case SND_SOC_DAPM_STREAM_STOP: 1600 w->active = 0; 1601 break; 1602 case SND_SOC_DAPM_STREAM_SUSPEND: 1603 if (w->active) 1604 w->suspend = 1; 1605 w->active = 0; 1606 break; 1607 case SND_SOC_DAPM_STREAM_RESUME: 1608 if (w->suspend) { 1609 w->active = 1; 1610 w->suspend = 0; 1611 } 1612 break; 1613 case SND_SOC_DAPM_STREAM_PAUSE_PUSH: 1614 break; 1615 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE: 1616 break; 1617 } 1618 } 1619 } 1620 mutex_unlock(&codec->mutex); 1621 1622 dapm_power_widgets(codec, event); 1623 dump_dapm(codec, __func__); 1624 return 0; 1625 } 1626 EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event); 1627 1628 /** 1629 * snd_soc_dapm_set_bias_level - set the bias level for the system 1630 * @socdev: audio device 1631 * @level: level to configure 1632 * 1633 * Configure the bias (power) levels for the SoC audio device. 1634 * 1635 * Returns 0 for success else error. 1636 */ 1637 int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev, 1638 enum snd_soc_bias_level level) 1639 { 1640 struct snd_soc_card *card = socdev->card; 1641 struct snd_soc_codec *codec = socdev->card->codec; 1642 int ret = 0; 1643 1644 if (card->set_bias_level) 1645 ret = card->set_bias_level(card, level); 1646 if (ret == 0 && codec->set_bias_level) 1647 ret = codec->set_bias_level(codec, level); 1648 1649 return ret; 1650 } 1651 1652 /** 1653 * snd_soc_dapm_enable_pin - enable pin. 1654 * @codec: SoC codec 1655 * @pin: pin name 1656 * 1657 * Enables input/output pin and it's parents or children widgets iff there is 1658 * a valid audio route and active audio stream. 1659 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 1660 * do any widget power switching. 1661 */ 1662 int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin) 1663 { 1664 return snd_soc_dapm_set_pin(codec, pin, 1); 1665 } 1666 EXPORT_SYMBOL_GPL(snd_soc_dapm_enable_pin); 1667 1668 /** 1669 * snd_soc_dapm_disable_pin - disable pin. 1670 * @codec: SoC codec 1671 * @pin: pin name 1672 * 1673 * Disables input/output pin and it's parents or children widgets. 1674 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 1675 * do any widget power switching. 1676 */ 1677 int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin) 1678 { 1679 return snd_soc_dapm_set_pin(codec, pin, 0); 1680 } 1681 EXPORT_SYMBOL_GPL(snd_soc_dapm_disable_pin); 1682 1683 /** 1684 * snd_soc_dapm_nc_pin - permanently disable pin. 1685 * @codec: SoC codec 1686 * @pin: pin name 1687 * 1688 * Marks the specified pin as being not connected, disabling it along 1689 * any parent or child widgets. At present this is identical to 1690 * snd_soc_dapm_disable_pin() but in future it will be extended to do 1691 * additional things such as disabling controls which only affect 1692 * paths through the pin. 1693 * 1694 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to 1695 * do any widget power switching. 1696 */ 1697 int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin) 1698 { 1699 return snd_soc_dapm_set_pin(codec, pin, 0); 1700 } 1701 EXPORT_SYMBOL_GPL(snd_soc_dapm_nc_pin); 1702 1703 /** 1704 * snd_soc_dapm_get_pin_status - get audio pin status 1705 * @codec: audio codec 1706 * @pin: audio signal pin endpoint (or start point) 1707 * 1708 * Get audio pin status - connected or disconnected. 1709 * 1710 * Returns 1 for connected otherwise 0. 1711 */ 1712 int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin) 1713 { 1714 struct snd_soc_dapm_widget *w; 1715 1716 list_for_each_entry(w, &codec->dapm_widgets, list) { 1717 if (!strcmp(w->name, pin)) 1718 return w->connected; 1719 } 1720 1721 return 0; 1722 } 1723 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status); 1724 1725 /** 1726 * snd_soc_dapm_free - free dapm resources 1727 * @socdev: SoC device 1728 * 1729 * Free all dapm widgets and resources. 1730 */ 1731 void snd_soc_dapm_free(struct snd_soc_device *socdev) 1732 { 1733 struct snd_soc_codec *codec = socdev->card->codec; 1734 1735 snd_soc_dapm_sys_remove(socdev->dev); 1736 dapm_free_widgets(codec); 1737 } 1738 EXPORT_SYMBOL_GPL(snd_soc_dapm_free); 1739 1740 /* Module information */ 1741 MODULE_AUTHOR("Liam Girdwood, lrg@slimlogic.co.uk"); 1742 MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC"); 1743 MODULE_LICENSE("GPL"); 1744