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