1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Apple Onboard Audio driver -- layout/machine id fabric 4 * 5 * Copyright 2006-2008 Johannes Berg <johannes@sipsolutions.net> 6 * 7 * This fabric module looks for sound codecs based on the 8 * layout-id or device-id property in the device tree. 9 */ 10 #include <asm/prom.h> 11 #include <linux/list.h> 12 #include <linux/module.h> 13 #include <linux/slab.h> 14 #include "../aoa.h" 15 #include "../soundbus/soundbus.h" 16 17 MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); 18 MODULE_LICENSE("GPL"); 19 MODULE_DESCRIPTION("Layout-ID fabric for snd-aoa"); 20 21 #define MAX_CODECS_PER_BUS 2 22 23 /* These are the connections the layout fabric 24 * knows about. It doesn't really care about the 25 * input ones, but I thought I'd separate them 26 * to give them proper names. The thing is that 27 * Apple usually will distinguish the active output 28 * by GPIOs, while the active input is set directly 29 * on the codec. Hence we here tell the codec what 30 * we think is connected. This information is hard- 31 * coded below ... */ 32 #define CC_SPEAKERS (1<<0) 33 #define CC_HEADPHONE (1<<1) 34 #define CC_LINEOUT (1<<2) 35 #define CC_DIGITALOUT (1<<3) 36 #define CC_LINEIN (1<<4) 37 #define CC_MICROPHONE (1<<5) 38 #define CC_DIGITALIN (1<<6) 39 /* pretty bogus but users complain... 40 * This is a flag saying that the LINEOUT 41 * should be renamed to HEADPHONE. 42 * be careful with input detection! */ 43 #define CC_LINEOUT_LABELLED_HEADPHONE (1<<7) 44 45 struct codec_connection { 46 /* CC_ flags from above */ 47 int connected; 48 /* codec dependent bit to be set in the aoa_codec.connected field. 49 * This intentionally doesn't have any generic flags because the 50 * fabric has to know the codec anyway and all codecs might have 51 * different connectors */ 52 int codec_bit; 53 }; 54 55 struct codec_connect_info { 56 char *name; 57 struct codec_connection *connections; 58 }; 59 60 #define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0) 61 62 struct layout { 63 unsigned int layout_id, device_id; 64 struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; 65 int flags; 66 67 /* if busname is not assigned, we use 'Master' below, 68 * so that our layout table doesn't need to be filled 69 * too much. 70 * We only assign these two if we expect to find more 71 * than one soundbus, i.e. on those machines with 72 * multiple layout-ids */ 73 char *busname; 74 int pcmid; 75 }; 76 77 MODULE_ALIAS("sound-layout-36"); 78 MODULE_ALIAS("sound-layout-41"); 79 MODULE_ALIAS("sound-layout-45"); 80 MODULE_ALIAS("sound-layout-47"); 81 MODULE_ALIAS("sound-layout-48"); 82 MODULE_ALIAS("sound-layout-49"); 83 MODULE_ALIAS("sound-layout-50"); 84 MODULE_ALIAS("sound-layout-51"); 85 MODULE_ALIAS("sound-layout-56"); 86 MODULE_ALIAS("sound-layout-57"); 87 MODULE_ALIAS("sound-layout-58"); 88 MODULE_ALIAS("sound-layout-60"); 89 MODULE_ALIAS("sound-layout-61"); 90 MODULE_ALIAS("sound-layout-62"); 91 MODULE_ALIAS("sound-layout-64"); 92 MODULE_ALIAS("sound-layout-65"); 93 MODULE_ALIAS("sound-layout-66"); 94 MODULE_ALIAS("sound-layout-67"); 95 MODULE_ALIAS("sound-layout-68"); 96 MODULE_ALIAS("sound-layout-69"); 97 MODULE_ALIAS("sound-layout-70"); 98 MODULE_ALIAS("sound-layout-72"); 99 MODULE_ALIAS("sound-layout-76"); 100 MODULE_ALIAS("sound-layout-80"); 101 MODULE_ALIAS("sound-layout-82"); 102 MODULE_ALIAS("sound-layout-84"); 103 MODULE_ALIAS("sound-layout-86"); 104 MODULE_ALIAS("sound-layout-90"); 105 MODULE_ALIAS("sound-layout-92"); 106 MODULE_ALIAS("sound-layout-94"); 107 MODULE_ALIAS("sound-layout-96"); 108 MODULE_ALIAS("sound-layout-98"); 109 MODULE_ALIAS("sound-layout-100"); 110 111 MODULE_ALIAS("aoa-device-id-14"); 112 MODULE_ALIAS("aoa-device-id-22"); 113 MODULE_ALIAS("aoa-device-id-31"); 114 MODULE_ALIAS("aoa-device-id-35"); 115 MODULE_ALIAS("aoa-device-id-44"); 116 117 /* onyx with all but microphone connected */ 118 static struct codec_connection onyx_connections_nomic[] = { 119 { 120 .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, 121 .codec_bit = 0, 122 }, 123 { 124 .connected = CC_DIGITALOUT, 125 .codec_bit = 1, 126 }, 127 { 128 .connected = CC_LINEIN, 129 .codec_bit = 2, 130 }, 131 {} /* terminate array by .connected == 0 */ 132 }; 133 134 /* onyx on machines without headphone */ 135 static struct codec_connection onyx_connections_noheadphones[] = { 136 { 137 .connected = CC_SPEAKERS | CC_LINEOUT | 138 CC_LINEOUT_LABELLED_HEADPHONE, 139 .codec_bit = 0, 140 }, 141 { 142 .connected = CC_DIGITALOUT, 143 .codec_bit = 1, 144 }, 145 /* FIXME: are these correct? probably not for all the machines 146 * below ... If not this will need separating. */ 147 { 148 .connected = CC_LINEIN, 149 .codec_bit = 2, 150 }, 151 { 152 .connected = CC_MICROPHONE, 153 .codec_bit = 3, 154 }, 155 {} /* terminate array by .connected == 0 */ 156 }; 157 158 /* onyx on machines with real line-out */ 159 static struct codec_connection onyx_connections_reallineout[] = { 160 { 161 .connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE, 162 .codec_bit = 0, 163 }, 164 { 165 .connected = CC_DIGITALOUT, 166 .codec_bit = 1, 167 }, 168 { 169 .connected = CC_LINEIN, 170 .codec_bit = 2, 171 }, 172 {} /* terminate array by .connected == 0 */ 173 }; 174 175 /* tas on machines without line out */ 176 static struct codec_connection tas_connections_nolineout[] = { 177 { 178 .connected = CC_SPEAKERS | CC_HEADPHONE, 179 .codec_bit = 0, 180 }, 181 { 182 .connected = CC_LINEIN, 183 .codec_bit = 2, 184 }, 185 { 186 .connected = CC_MICROPHONE, 187 .codec_bit = 3, 188 }, 189 {} /* terminate array by .connected == 0 */ 190 }; 191 192 /* tas on machines with neither line out nor line in */ 193 static struct codec_connection tas_connections_noline[] = { 194 { 195 .connected = CC_SPEAKERS | CC_HEADPHONE, 196 .codec_bit = 0, 197 }, 198 { 199 .connected = CC_MICROPHONE, 200 .codec_bit = 3, 201 }, 202 {} /* terminate array by .connected == 0 */ 203 }; 204 205 /* tas on machines without microphone */ 206 static struct codec_connection tas_connections_nomic[] = { 207 { 208 .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, 209 .codec_bit = 0, 210 }, 211 { 212 .connected = CC_LINEIN, 213 .codec_bit = 2, 214 }, 215 {} /* terminate array by .connected == 0 */ 216 }; 217 218 /* tas on machines with everything connected */ 219 static struct codec_connection tas_connections_all[] = { 220 { 221 .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, 222 .codec_bit = 0, 223 }, 224 { 225 .connected = CC_LINEIN, 226 .codec_bit = 2, 227 }, 228 { 229 .connected = CC_MICROPHONE, 230 .codec_bit = 3, 231 }, 232 {} /* terminate array by .connected == 0 */ 233 }; 234 235 static struct codec_connection toonie_connections[] = { 236 { 237 .connected = CC_SPEAKERS | CC_HEADPHONE, 238 .codec_bit = 0, 239 }, 240 {} /* terminate array by .connected == 0 */ 241 }; 242 243 static struct codec_connection topaz_input[] = { 244 { 245 .connected = CC_DIGITALIN, 246 .codec_bit = 0, 247 }, 248 {} /* terminate array by .connected == 0 */ 249 }; 250 251 static struct codec_connection topaz_output[] = { 252 { 253 .connected = CC_DIGITALOUT, 254 .codec_bit = 1, 255 }, 256 {} /* terminate array by .connected == 0 */ 257 }; 258 259 static struct codec_connection topaz_inout[] = { 260 { 261 .connected = CC_DIGITALIN, 262 .codec_bit = 0, 263 }, 264 { 265 .connected = CC_DIGITALOUT, 266 .codec_bit = 1, 267 }, 268 {} /* terminate array by .connected == 0 */ 269 }; 270 271 static struct layout layouts[] = { 272 /* last PowerBooks (15" Oct 2005) */ 273 { .layout_id = 82, 274 .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, 275 .codecs[0] = { 276 .name = "onyx", 277 .connections = onyx_connections_noheadphones, 278 }, 279 .codecs[1] = { 280 .name = "topaz", 281 .connections = topaz_input, 282 }, 283 }, 284 /* PowerMac9,1 */ 285 { .layout_id = 60, 286 .codecs[0] = { 287 .name = "onyx", 288 .connections = onyx_connections_reallineout, 289 }, 290 }, 291 /* PowerMac9,1 */ 292 { .layout_id = 61, 293 .codecs[0] = { 294 .name = "topaz", 295 .connections = topaz_input, 296 }, 297 }, 298 /* PowerBook5,7 */ 299 { .layout_id = 64, 300 .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, 301 .codecs[0] = { 302 .name = "onyx", 303 .connections = onyx_connections_noheadphones, 304 }, 305 }, 306 /* PowerBook5,7 */ 307 { .layout_id = 65, 308 .codecs[0] = { 309 .name = "topaz", 310 .connections = topaz_input, 311 }, 312 }, 313 /* PowerBook5,9 [17" Oct 2005] */ 314 { .layout_id = 84, 315 .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, 316 .codecs[0] = { 317 .name = "onyx", 318 .connections = onyx_connections_noheadphones, 319 }, 320 .codecs[1] = { 321 .name = "topaz", 322 .connections = topaz_input, 323 }, 324 }, 325 /* PowerMac8,1 */ 326 { .layout_id = 45, 327 .codecs[0] = { 328 .name = "onyx", 329 .connections = onyx_connections_noheadphones, 330 }, 331 .codecs[1] = { 332 .name = "topaz", 333 .connections = topaz_input, 334 }, 335 }, 336 /* Quad PowerMac (analog in, analog/digital out) */ 337 { .layout_id = 68, 338 .codecs[0] = { 339 .name = "onyx", 340 .connections = onyx_connections_nomic, 341 }, 342 }, 343 /* Quad PowerMac (digital in) */ 344 { .layout_id = 69, 345 .codecs[0] = { 346 .name = "topaz", 347 .connections = topaz_input, 348 }, 349 .busname = "digital in", .pcmid = 1 }, 350 /* Early 2005 PowerBook (PowerBook 5,6) */ 351 { .layout_id = 70, 352 .codecs[0] = { 353 .name = "tas", 354 .connections = tas_connections_nolineout, 355 }, 356 }, 357 /* PowerBook 5,4 */ 358 { .layout_id = 51, 359 .codecs[0] = { 360 .name = "tas", 361 .connections = tas_connections_nolineout, 362 }, 363 }, 364 /* PowerBook6,1 */ 365 { .device_id = 31, 366 .codecs[0] = { 367 .name = "tas", 368 .connections = tas_connections_nolineout, 369 }, 370 }, 371 /* PowerBook6,5 */ 372 { .device_id = 44, 373 .codecs[0] = { 374 .name = "tas", 375 .connections = tas_connections_all, 376 }, 377 }, 378 /* PowerBook6,7 */ 379 { .layout_id = 80, 380 .codecs[0] = { 381 .name = "tas", 382 .connections = tas_connections_noline, 383 }, 384 }, 385 /* PowerBook6,8 */ 386 { .layout_id = 72, 387 .codecs[0] = { 388 .name = "tas", 389 .connections = tas_connections_nolineout, 390 }, 391 }, 392 /* PowerMac8,2 */ 393 { .layout_id = 86, 394 .codecs[0] = { 395 .name = "onyx", 396 .connections = onyx_connections_nomic, 397 }, 398 .codecs[1] = { 399 .name = "topaz", 400 .connections = topaz_input, 401 }, 402 }, 403 /* PowerBook6,7 */ 404 { .layout_id = 92, 405 .codecs[0] = { 406 .name = "tas", 407 .connections = tas_connections_nolineout, 408 }, 409 }, 410 /* PowerMac10,1 (Mac Mini) */ 411 { .layout_id = 58, 412 .codecs[0] = { 413 .name = "toonie", 414 .connections = toonie_connections, 415 }, 416 }, 417 { 418 .layout_id = 96, 419 .codecs[0] = { 420 .name = "onyx", 421 .connections = onyx_connections_noheadphones, 422 }, 423 }, 424 /* unknown, untested, but this comes from Apple */ 425 { .layout_id = 41, 426 .codecs[0] = { 427 .name = "tas", 428 .connections = tas_connections_all, 429 }, 430 }, 431 { .layout_id = 36, 432 .codecs[0] = { 433 .name = "tas", 434 .connections = tas_connections_nomic, 435 }, 436 .codecs[1] = { 437 .name = "topaz", 438 .connections = topaz_inout, 439 }, 440 }, 441 { .layout_id = 47, 442 .codecs[0] = { 443 .name = "onyx", 444 .connections = onyx_connections_noheadphones, 445 }, 446 }, 447 { .layout_id = 48, 448 .codecs[0] = { 449 .name = "topaz", 450 .connections = topaz_input, 451 }, 452 }, 453 { .layout_id = 49, 454 .codecs[0] = { 455 .name = "onyx", 456 .connections = onyx_connections_nomic, 457 }, 458 }, 459 { .layout_id = 50, 460 .codecs[0] = { 461 .name = "topaz", 462 .connections = topaz_input, 463 }, 464 }, 465 { .layout_id = 56, 466 .codecs[0] = { 467 .name = "onyx", 468 .connections = onyx_connections_noheadphones, 469 }, 470 }, 471 { .layout_id = 57, 472 .codecs[0] = { 473 .name = "topaz", 474 .connections = topaz_input, 475 }, 476 }, 477 { .layout_id = 62, 478 .codecs[0] = { 479 .name = "onyx", 480 .connections = onyx_connections_noheadphones, 481 }, 482 .codecs[1] = { 483 .name = "topaz", 484 .connections = topaz_output, 485 }, 486 }, 487 { .layout_id = 66, 488 .codecs[0] = { 489 .name = "onyx", 490 .connections = onyx_connections_noheadphones, 491 }, 492 }, 493 { .layout_id = 67, 494 .codecs[0] = { 495 .name = "topaz", 496 .connections = topaz_input, 497 }, 498 }, 499 { .layout_id = 76, 500 .codecs[0] = { 501 .name = "tas", 502 .connections = tas_connections_nomic, 503 }, 504 .codecs[1] = { 505 .name = "topaz", 506 .connections = topaz_inout, 507 }, 508 }, 509 { .layout_id = 90, 510 .codecs[0] = { 511 .name = "tas", 512 .connections = tas_connections_noline, 513 }, 514 }, 515 { .layout_id = 94, 516 .codecs[0] = { 517 .name = "onyx", 518 /* but it has an external mic?? how to select? */ 519 .connections = onyx_connections_noheadphones, 520 }, 521 }, 522 { .layout_id = 98, 523 .codecs[0] = { 524 .name = "toonie", 525 .connections = toonie_connections, 526 }, 527 }, 528 { .layout_id = 100, 529 .codecs[0] = { 530 .name = "topaz", 531 .connections = topaz_input, 532 }, 533 .codecs[1] = { 534 .name = "onyx", 535 .connections = onyx_connections_noheadphones, 536 }, 537 }, 538 /* PowerMac3,4 */ 539 { .device_id = 14, 540 .codecs[0] = { 541 .name = "tas", 542 .connections = tas_connections_noline, 543 }, 544 }, 545 /* PowerMac3,6 */ 546 { .device_id = 22, 547 .codecs[0] = { 548 .name = "tas", 549 .connections = tas_connections_all, 550 }, 551 }, 552 /* PowerBook5,2 */ 553 { .device_id = 35, 554 .codecs[0] = { 555 .name = "tas", 556 .connections = tas_connections_all, 557 }, 558 }, 559 {} 560 }; 561 562 static struct layout *find_layout_by_id(unsigned int id) 563 { 564 struct layout *l; 565 566 l = layouts; 567 while (l->codecs[0].name) { 568 if (l->layout_id == id) 569 return l; 570 l++; 571 } 572 return NULL; 573 } 574 575 static struct layout *find_layout_by_device(unsigned int id) 576 { 577 struct layout *l; 578 579 l = layouts; 580 while (l->codecs[0].name) { 581 if (l->device_id == id) 582 return l; 583 l++; 584 } 585 return NULL; 586 } 587 588 static void use_layout(struct layout *l) 589 { 590 int i; 591 592 for (i=0; i<MAX_CODECS_PER_BUS; i++) { 593 if (l->codecs[i].name) { 594 request_module("snd-aoa-codec-%s", l->codecs[i].name); 595 } 596 } 597 /* now we wait for the codecs to call us back */ 598 } 599 600 struct layout_dev; 601 602 struct layout_dev_ptr { 603 struct layout_dev *ptr; 604 }; 605 606 struct layout_dev { 607 struct list_head list; 608 struct soundbus_dev *sdev; 609 struct device_node *sound; 610 struct aoa_codec *codecs[MAX_CODECS_PER_BUS]; 611 struct layout *layout; 612 struct gpio_runtime gpio; 613 614 /* we need these for headphone/lineout detection */ 615 struct snd_kcontrol *headphone_ctrl; 616 struct snd_kcontrol *lineout_ctrl; 617 struct snd_kcontrol *speaker_ctrl; 618 struct snd_kcontrol *master_ctrl; 619 struct snd_kcontrol *headphone_detected_ctrl; 620 struct snd_kcontrol *lineout_detected_ctrl; 621 622 struct layout_dev_ptr selfptr_headphone; 623 struct layout_dev_ptr selfptr_lineout; 624 625 u32 have_lineout_detect:1, 626 have_headphone_detect:1, 627 switch_on_headphone:1, 628 switch_on_lineout:1; 629 }; 630 631 static LIST_HEAD(layouts_list); 632 static int layouts_list_items; 633 /* this can go away but only if we allow multiple cards, 634 * make the fabric handle all the card stuff, etc... */ 635 static struct layout_dev *layout_device; 636 637 #define control_info snd_ctl_boolean_mono_info 638 639 #define AMP_CONTROL(n, description) \ 640 static int n##_control_get(struct snd_kcontrol *kcontrol, \ 641 struct snd_ctl_elem_value *ucontrol) \ 642 { \ 643 struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ 644 if (gpio->methods && gpio->methods->get_##n) \ 645 ucontrol->value.integer.value[0] = \ 646 gpio->methods->get_##n(gpio); \ 647 return 0; \ 648 } \ 649 static int n##_control_put(struct snd_kcontrol *kcontrol, \ 650 struct snd_ctl_elem_value *ucontrol) \ 651 { \ 652 struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ 653 if (gpio->methods && gpio->methods->set_##n) \ 654 gpio->methods->set_##n(gpio, \ 655 !!ucontrol->value.integer.value[0]); \ 656 return 1; \ 657 } \ 658 static const struct snd_kcontrol_new n##_ctl = { \ 659 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 660 .name = description, \ 661 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 662 .info = control_info, \ 663 .get = n##_control_get, \ 664 .put = n##_control_put, \ 665 } 666 667 AMP_CONTROL(headphone, "Headphone Switch"); 668 AMP_CONTROL(speakers, "Speakers Switch"); 669 AMP_CONTROL(lineout, "Line-Out Switch"); 670 AMP_CONTROL(master, "Master Switch"); 671 672 static int detect_choice_get(struct snd_kcontrol *kcontrol, 673 struct snd_ctl_elem_value *ucontrol) 674 { 675 struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); 676 677 switch (kcontrol->private_value) { 678 case 0: 679 ucontrol->value.integer.value[0] = ldev->switch_on_headphone; 680 break; 681 case 1: 682 ucontrol->value.integer.value[0] = ldev->switch_on_lineout; 683 break; 684 default: 685 return -ENODEV; 686 } 687 return 0; 688 } 689 690 static int detect_choice_put(struct snd_kcontrol *kcontrol, 691 struct snd_ctl_elem_value *ucontrol) 692 { 693 struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); 694 695 switch (kcontrol->private_value) { 696 case 0: 697 ldev->switch_on_headphone = !!ucontrol->value.integer.value[0]; 698 break; 699 case 1: 700 ldev->switch_on_lineout = !!ucontrol->value.integer.value[0]; 701 break; 702 default: 703 return -ENODEV; 704 } 705 return 1; 706 } 707 708 static const struct snd_kcontrol_new headphone_detect_choice = { 709 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 710 .name = "Headphone Detect Autoswitch", 711 .info = control_info, 712 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 713 .get = detect_choice_get, 714 .put = detect_choice_put, 715 .private_value = 0, 716 }; 717 718 static const struct snd_kcontrol_new lineout_detect_choice = { 719 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 720 .name = "Line-Out Detect Autoswitch", 721 .info = control_info, 722 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 723 .get = detect_choice_get, 724 .put = detect_choice_put, 725 .private_value = 1, 726 }; 727 728 static int detected_get(struct snd_kcontrol *kcontrol, 729 struct snd_ctl_elem_value *ucontrol) 730 { 731 struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); 732 int v; 733 734 switch (kcontrol->private_value) { 735 case 0: 736 v = ldev->gpio.methods->get_detect(&ldev->gpio, 737 AOA_NOTIFY_HEADPHONE); 738 break; 739 case 1: 740 v = ldev->gpio.methods->get_detect(&ldev->gpio, 741 AOA_NOTIFY_LINE_OUT); 742 break; 743 default: 744 return -ENODEV; 745 } 746 ucontrol->value.integer.value[0] = v; 747 return 0; 748 } 749 750 static const struct snd_kcontrol_new headphone_detected = { 751 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 752 .name = "Headphone Detected", 753 .info = control_info, 754 .access = SNDRV_CTL_ELEM_ACCESS_READ, 755 .get = detected_get, 756 .private_value = 0, 757 }; 758 759 static const struct snd_kcontrol_new lineout_detected = { 760 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 761 .name = "Line-Out Detected", 762 .info = control_info, 763 .access = SNDRV_CTL_ELEM_ACCESS_READ, 764 .get = detected_get, 765 .private_value = 1, 766 }; 767 768 static int check_codec(struct aoa_codec *codec, 769 struct layout_dev *ldev, 770 struct codec_connect_info *cci) 771 { 772 const u32 *ref; 773 char propname[32]; 774 struct codec_connection *cc; 775 776 /* if the codec has a 'codec' node, we require a reference */ 777 if (of_node_name_eq(codec->node, "codec")) { 778 snprintf(propname, sizeof(propname), 779 "platform-%s-codec-ref", codec->name); 780 ref = of_get_property(ldev->sound, propname, NULL); 781 if (!ref) { 782 printk(KERN_INFO "snd-aoa-fabric-layout: " 783 "required property %s not present\n", propname); 784 return -ENODEV; 785 } 786 if (*ref != codec->node->phandle) { 787 printk(KERN_INFO "snd-aoa-fabric-layout: " 788 "%s doesn't match!\n", propname); 789 return -ENODEV; 790 } 791 } else { 792 if (layouts_list_items != 1) { 793 printk(KERN_INFO "snd-aoa-fabric-layout: " 794 "more than one soundbus, but no references.\n"); 795 return -ENODEV; 796 } 797 } 798 codec->soundbus_dev = ldev->sdev; 799 codec->gpio = &ldev->gpio; 800 801 cc = cci->connections; 802 if (!cc) 803 return -EINVAL; 804 805 printk(KERN_INFO "snd-aoa-fabric-layout: can use this codec\n"); 806 807 codec->connected = 0; 808 codec->fabric_data = cc; 809 810 while (cc->connected) { 811 codec->connected |= 1<<cc->codec_bit; 812 cc++; 813 } 814 815 return 0; 816 } 817 818 static int layout_found_codec(struct aoa_codec *codec) 819 { 820 struct layout_dev *ldev; 821 int i; 822 823 list_for_each_entry(ldev, &layouts_list, list) { 824 for (i=0; i<MAX_CODECS_PER_BUS; i++) { 825 if (!ldev->layout->codecs[i].name) 826 continue; 827 if (strcmp(ldev->layout->codecs[i].name, codec->name) == 0) { 828 if (check_codec(codec, 829 ldev, 830 &ldev->layout->codecs[i]) == 0) 831 return 0; 832 } 833 } 834 } 835 return -ENODEV; 836 } 837 838 static void layout_remove_codec(struct aoa_codec *codec) 839 { 840 int i; 841 /* here remove the codec from the layout dev's 842 * codec reference */ 843 844 codec->soundbus_dev = NULL; 845 codec->gpio = NULL; 846 for (i=0; i<MAX_CODECS_PER_BUS; i++) { 847 } 848 } 849 850 static void layout_notify(void *data) 851 { 852 struct layout_dev_ptr *dptr = data; 853 struct layout_dev *ldev; 854 int v, update; 855 struct snd_kcontrol *detected, *c; 856 struct snd_card *card = aoa_get_card(); 857 858 ldev = dptr->ptr; 859 if (data == &ldev->selfptr_headphone) { 860 v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_HEADPHONE); 861 detected = ldev->headphone_detected_ctrl; 862 update = ldev->switch_on_headphone; 863 if (update) { 864 ldev->gpio.methods->set_speakers(&ldev->gpio, !v); 865 ldev->gpio.methods->set_headphone(&ldev->gpio, v); 866 ldev->gpio.methods->set_lineout(&ldev->gpio, 0); 867 } 868 } else if (data == &ldev->selfptr_lineout) { 869 v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_LINE_OUT); 870 detected = ldev->lineout_detected_ctrl; 871 update = ldev->switch_on_lineout; 872 if (update) { 873 ldev->gpio.methods->set_speakers(&ldev->gpio, !v); 874 ldev->gpio.methods->set_headphone(&ldev->gpio, 0); 875 ldev->gpio.methods->set_lineout(&ldev->gpio, v); 876 } 877 } else 878 return; 879 880 if (detected) 881 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &detected->id); 882 if (update) { 883 c = ldev->headphone_ctrl; 884 if (c) 885 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); 886 c = ldev->speaker_ctrl; 887 if (c) 888 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); 889 c = ldev->lineout_ctrl; 890 if (c) 891 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); 892 } 893 } 894 895 static void layout_attached_codec(struct aoa_codec *codec) 896 { 897 struct codec_connection *cc; 898 struct snd_kcontrol *ctl; 899 int headphones, lineout; 900 struct layout_dev *ldev = layout_device; 901 902 /* need to add this codec to our codec array! */ 903 904 cc = codec->fabric_data; 905 906 headphones = codec->gpio->methods->get_detect(codec->gpio, 907 AOA_NOTIFY_HEADPHONE); 908 lineout = codec->gpio->methods->get_detect(codec->gpio, 909 AOA_NOTIFY_LINE_OUT); 910 911 if (codec->gpio->methods->set_master) { 912 ctl = snd_ctl_new1(&master_ctl, codec->gpio); 913 ldev->master_ctrl = ctl; 914 aoa_snd_ctl_add(ctl); 915 } 916 while (cc->connected) { 917 if (cc->connected & CC_SPEAKERS) { 918 if (headphones <= 0 && lineout <= 0) 919 ldev->gpio.methods->set_speakers(codec->gpio, 1); 920 ctl = snd_ctl_new1(&speakers_ctl, codec->gpio); 921 ldev->speaker_ctrl = ctl; 922 aoa_snd_ctl_add(ctl); 923 } 924 if (cc->connected & CC_HEADPHONE) { 925 if (headphones == 1) 926 ldev->gpio.methods->set_headphone(codec->gpio, 1); 927 ctl = snd_ctl_new1(&headphone_ctl, codec->gpio); 928 ldev->headphone_ctrl = ctl; 929 aoa_snd_ctl_add(ctl); 930 ldev->have_headphone_detect = 931 !ldev->gpio.methods 932 ->set_notify(&ldev->gpio, 933 AOA_NOTIFY_HEADPHONE, 934 layout_notify, 935 &ldev->selfptr_headphone); 936 if (ldev->have_headphone_detect) { 937 ctl = snd_ctl_new1(&headphone_detect_choice, 938 ldev); 939 aoa_snd_ctl_add(ctl); 940 ctl = snd_ctl_new1(&headphone_detected, 941 ldev); 942 ldev->headphone_detected_ctrl = ctl; 943 aoa_snd_ctl_add(ctl); 944 } 945 } 946 if (cc->connected & CC_LINEOUT) { 947 if (lineout == 1) 948 ldev->gpio.methods->set_lineout(codec->gpio, 1); 949 ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); 950 if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) 951 strlcpy(ctl->id.name, 952 "Headphone Switch", sizeof(ctl->id.name)); 953 ldev->lineout_ctrl = ctl; 954 aoa_snd_ctl_add(ctl); 955 ldev->have_lineout_detect = 956 !ldev->gpio.methods 957 ->set_notify(&ldev->gpio, 958 AOA_NOTIFY_LINE_OUT, 959 layout_notify, 960 &ldev->selfptr_lineout); 961 if (ldev->have_lineout_detect) { 962 ctl = snd_ctl_new1(&lineout_detect_choice, 963 ldev); 964 if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) 965 strlcpy(ctl->id.name, 966 "Headphone Detect Autoswitch", 967 sizeof(ctl->id.name)); 968 aoa_snd_ctl_add(ctl); 969 ctl = snd_ctl_new1(&lineout_detected, 970 ldev); 971 if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) 972 strlcpy(ctl->id.name, 973 "Headphone Detected", 974 sizeof(ctl->id.name)); 975 ldev->lineout_detected_ctrl = ctl; 976 aoa_snd_ctl_add(ctl); 977 } 978 } 979 cc++; 980 } 981 /* now update initial state */ 982 if (ldev->have_headphone_detect) 983 layout_notify(&ldev->selfptr_headphone); 984 if (ldev->have_lineout_detect) 985 layout_notify(&ldev->selfptr_lineout); 986 } 987 988 static struct aoa_fabric layout_fabric = { 989 .name = "SoundByLayout", 990 .owner = THIS_MODULE, 991 .found_codec = layout_found_codec, 992 .remove_codec = layout_remove_codec, 993 .attached_codec = layout_attached_codec, 994 }; 995 996 static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) 997 { 998 struct device_node *sound = NULL; 999 const unsigned int *id; 1000 struct layout *layout = NULL; 1001 struct layout_dev *ldev = NULL; 1002 int err; 1003 1004 /* hm, currently we can only have one ... */ 1005 if (layout_device) 1006 return -ENODEV; 1007 1008 /* by breaking out we keep a reference */ 1009 for_each_child_of_node(sdev->ofdev.dev.of_node, sound) { 1010 if (of_node_is_type(sound, "soundchip")) 1011 break; 1012 } 1013 if (!sound) 1014 return -ENODEV; 1015 1016 id = of_get_property(sound, "layout-id", NULL); 1017 if (id) { 1018 layout = find_layout_by_id(*id); 1019 } else { 1020 id = of_get_property(sound, "device-id", NULL); 1021 if (id) 1022 layout = find_layout_by_device(*id); 1023 } 1024 1025 if (!layout) { 1026 printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n"); 1027 goto outnodev; 1028 } 1029 1030 ldev = kzalloc(sizeof(struct layout_dev), GFP_KERNEL); 1031 if (!ldev) 1032 goto outnodev; 1033 1034 layout_device = ldev; 1035 ldev->sdev = sdev; 1036 ldev->sound = sound; 1037 ldev->layout = layout; 1038 ldev->gpio.node = sound->parent; 1039 switch (layout->layout_id) { 1040 case 0: /* anything with device_id, not layout_id */ 1041 case 41: /* that unknown machine no one seems to have */ 1042 case 51: /* PowerBook5,4 */ 1043 case 58: /* Mac Mini */ 1044 ldev->gpio.methods = ftr_gpio_methods; 1045 printk(KERN_DEBUG 1046 "snd-aoa-fabric-layout: Using direct GPIOs\n"); 1047 break; 1048 default: 1049 ldev->gpio.methods = pmf_gpio_methods; 1050 printk(KERN_DEBUG 1051 "snd-aoa-fabric-layout: Using PMF GPIOs\n"); 1052 } 1053 ldev->selfptr_headphone.ptr = ldev; 1054 ldev->selfptr_lineout.ptr = ldev; 1055 dev_set_drvdata(&sdev->ofdev.dev, ldev); 1056 list_add(&ldev->list, &layouts_list); 1057 layouts_list_items++; 1058 1059 /* assign these before registering ourselves, so 1060 * callbacks that are done during registration 1061 * already have the values */ 1062 sdev->pcmid = ldev->layout->pcmid; 1063 if (ldev->layout->busname) { 1064 sdev->pcmname = ldev->layout->busname; 1065 } else { 1066 sdev->pcmname = "Master"; 1067 } 1068 1069 ldev->gpio.methods->init(&ldev->gpio); 1070 1071 err = aoa_fabric_register(&layout_fabric, &sdev->ofdev.dev); 1072 if (err && err != -EALREADY) { 1073 printk(KERN_INFO "snd-aoa-fabric-layout: can't use," 1074 " another fabric is active!\n"); 1075 goto outlistdel; 1076 } 1077 1078 use_layout(layout); 1079 ldev->switch_on_headphone = 1; 1080 ldev->switch_on_lineout = 1; 1081 return 0; 1082 outlistdel: 1083 /* we won't be using these then... */ 1084 ldev->gpio.methods->exit(&ldev->gpio); 1085 /* reset if we didn't use it */ 1086 sdev->pcmname = NULL; 1087 sdev->pcmid = -1; 1088 list_del(&ldev->list); 1089 layouts_list_items--; 1090 kfree(ldev); 1091 outnodev: 1092 of_node_put(sound); 1093 layout_device = NULL; 1094 return -ENODEV; 1095 } 1096 1097 static int aoa_fabric_layout_remove(struct soundbus_dev *sdev) 1098 { 1099 struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); 1100 int i; 1101 1102 for (i=0; i<MAX_CODECS_PER_BUS; i++) { 1103 if (ldev->codecs[i]) { 1104 aoa_fabric_unlink_codec(ldev->codecs[i]); 1105 } 1106 ldev->codecs[i] = NULL; 1107 } 1108 list_del(&ldev->list); 1109 layouts_list_items--; 1110 of_node_put(ldev->sound); 1111 1112 ldev->gpio.methods->set_notify(&ldev->gpio, 1113 AOA_NOTIFY_HEADPHONE, 1114 NULL, 1115 NULL); 1116 ldev->gpio.methods->set_notify(&ldev->gpio, 1117 AOA_NOTIFY_LINE_OUT, 1118 NULL, 1119 NULL); 1120 1121 ldev->gpio.methods->exit(&ldev->gpio); 1122 layout_device = NULL; 1123 kfree(ldev); 1124 sdev->pcmid = -1; 1125 sdev->pcmname = NULL; 1126 return 0; 1127 } 1128 1129 #ifdef CONFIG_PM_SLEEP 1130 static int aoa_fabric_layout_suspend(struct device *dev) 1131 { 1132 struct layout_dev *ldev = dev_get_drvdata(dev); 1133 1134 if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) 1135 ldev->gpio.methods->all_amps_off(&ldev->gpio); 1136 1137 return 0; 1138 } 1139 1140 static int aoa_fabric_layout_resume(struct device *dev) 1141 { 1142 struct layout_dev *ldev = dev_get_drvdata(dev); 1143 1144 if (ldev->gpio.methods && ldev->gpio.methods->all_amps_restore) 1145 ldev->gpio.methods->all_amps_restore(&ldev->gpio); 1146 1147 return 0; 1148 } 1149 1150 static SIMPLE_DEV_PM_OPS(aoa_fabric_layout_pm_ops, 1151 aoa_fabric_layout_suspend, aoa_fabric_layout_resume); 1152 1153 #endif 1154 1155 static struct soundbus_driver aoa_soundbus_driver = { 1156 .name = "snd_aoa_soundbus_drv", 1157 .owner = THIS_MODULE, 1158 .probe = aoa_fabric_layout_probe, 1159 .remove = aoa_fabric_layout_remove, 1160 .driver = { 1161 .owner = THIS_MODULE, 1162 #ifdef CONFIG_PM_SLEEP 1163 .pm = &aoa_fabric_layout_pm_ops, 1164 #endif 1165 } 1166 }; 1167 1168 static int __init aoa_fabric_layout_init(void) 1169 { 1170 return soundbus_register_driver(&aoa_soundbus_driver); 1171 } 1172 1173 static void __exit aoa_fabric_layout_exit(void) 1174 { 1175 soundbus_unregister_driver(&aoa_soundbus_driver); 1176 aoa_fabric_unregister(&layout_fabric); 1177 } 1178 1179 module_init(aoa_fabric_layout_init); 1180 module_exit(aoa_fabric_layout_exit); 1181