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-35"); 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,7 */ 365 { .layout_id = 80, 366 .codecs[0] = { 367 .name = "tas", 368 .connections = tas_connections_noline, 369 }, 370 }, 371 /* PowerBook6,8 */ 372 { .layout_id = 72, 373 .codecs[0] = { 374 .name = "tas", 375 .connections = tas_connections_nolineout, 376 }, 377 }, 378 /* PowerMac8,2 */ 379 { .layout_id = 86, 380 .codecs[0] = { 381 .name = "onyx", 382 .connections = onyx_connections_nomic, 383 }, 384 .codecs[1] = { 385 .name = "topaz", 386 .connections = topaz_input, 387 }, 388 }, 389 /* PowerBook6,7 */ 390 { .layout_id = 92, 391 .codecs[0] = { 392 .name = "tas", 393 .connections = tas_connections_nolineout, 394 }, 395 }, 396 /* PowerMac10,1 (Mac Mini) */ 397 { .layout_id = 58, 398 .codecs[0] = { 399 .name = "toonie", 400 .connections = toonie_connections, 401 }, 402 }, 403 { 404 .layout_id = 96, 405 .codecs[0] = { 406 .name = "onyx", 407 .connections = onyx_connections_noheadphones, 408 }, 409 }, 410 /* unknown, untested, but this comes from Apple */ 411 { .layout_id = 41, 412 .codecs[0] = { 413 .name = "tas", 414 .connections = tas_connections_all, 415 }, 416 }, 417 { .layout_id = 36, 418 .codecs[0] = { 419 .name = "tas", 420 .connections = tas_connections_nomic, 421 }, 422 .codecs[1] = { 423 .name = "topaz", 424 .connections = topaz_inout, 425 }, 426 }, 427 { .layout_id = 47, 428 .codecs[0] = { 429 .name = "onyx", 430 .connections = onyx_connections_noheadphones, 431 }, 432 }, 433 { .layout_id = 48, 434 .codecs[0] = { 435 .name = "topaz", 436 .connections = topaz_input, 437 }, 438 }, 439 { .layout_id = 49, 440 .codecs[0] = { 441 .name = "onyx", 442 .connections = onyx_connections_nomic, 443 }, 444 }, 445 { .layout_id = 50, 446 .codecs[0] = { 447 .name = "topaz", 448 .connections = topaz_input, 449 }, 450 }, 451 { .layout_id = 56, 452 .codecs[0] = { 453 .name = "onyx", 454 .connections = onyx_connections_noheadphones, 455 }, 456 }, 457 { .layout_id = 57, 458 .codecs[0] = { 459 .name = "topaz", 460 .connections = topaz_input, 461 }, 462 }, 463 { .layout_id = 62, 464 .codecs[0] = { 465 .name = "onyx", 466 .connections = onyx_connections_noheadphones, 467 }, 468 .codecs[1] = { 469 .name = "topaz", 470 .connections = topaz_output, 471 }, 472 }, 473 { .layout_id = 66, 474 .codecs[0] = { 475 .name = "onyx", 476 .connections = onyx_connections_noheadphones, 477 }, 478 }, 479 { .layout_id = 67, 480 .codecs[0] = { 481 .name = "topaz", 482 .connections = topaz_input, 483 }, 484 }, 485 { .layout_id = 76, 486 .codecs[0] = { 487 .name = "tas", 488 .connections = tas_connections_nomic, 489 }, 490 .codecs[1] = { 491 .name = "topaz", 492 .connections = topaz_inout, 493 }, 494 }, 495 { .layout_id = 90, 496 .codecs[0] = { 497 .name = "tas", 498 .connections = tas_connections_noline, 499 }, 500 }, 501 { .layout_id = 94, 502 .codecs[0] = { 503 .name = "onyx", 504 /* but it has an external mic?? how to select? */ 505 .connections = onyx_connections_noheadphones, 506 }, 507 }, 508 { .layout_id = 98, 509 .codecs[0] = { 510 .name = "toonie", 511 .connections = toonie_connections, 512 }, 513 }, 514 { .layout_id = 100, 515 .codecs[0] = { 516 .name = "topaz", 517 .connections = topaz_input, 518 }, 519 .codecs[1] = { 520 .name = "onyx", 521 .connections = onyx_connections_noheadphones, 522 }, 523 }, 524 /* PowerMac3,4 */ 525 { .device_id = 14, 526 .codecs[0] = { 527 .name = "tas", 528 .connections = tas_connections_noline, 529 }, 530 }, 531 /* PowerMac3,6 */ 532 { .device_id = 22, 533 .codecs[0] = { 534 .name = "tas", 535 .connections = tas_connections_all, 536 }, 537 }, 538 /* PowerBook5,2 */ 539 { .device_id = 35, 540 .codecs[0] = { 541 .name = "tas", 542 .connections = tas_connections_all, 543 }, 544 }, 545 {} 546 }; 547 548 static struct layout *find_layout_by_id(unsigned int id) 549 { 550 struct layout *l; 551 552 l = layouts; 553 while (l->codecs[0].name) { 554 if (l->layout_id == id) 555 return l; 556 l++; 557 } 558 return NULL; 559 } 560 561 static struct layout *find_layout_by_device(unsigned int id) 562 { 563 struct layout *l; 564 565 l = layouts; 566 while (l->codecs[0].name) { 567 if (l->device_id == id) 568 return l; 569 l++; 570 } 571 return NULL; 572 } 573 574 static void use_layout(struct layout *l) 575 { 576 int i; 577 578 for (i=0; i<MAX_CODECS_PER_BUS; i++) { 579 if (l->codecs[i].name) { 580 request_module("snd-aoa-codec-%s", l->codecs[i].name); 581 } 582 } 583 /* now we wait for the codecs to call us back */ 584 } 585 586 struct layout_dev; 587 588 struct layout_dev_ptr { 589 struct layout_dev *ptr; 590 }; 591 592 struct layout_dev { 593 struct list_head list; 594 struct soundbus_dev *sdev; 595 struct device_node *sound; 596 struct aoa_codec *codecs[MAX_CODECS_PER_BUS]; 597 struct layout *layout; 598 struct gpio_runtime gpio; 599 600 /* we need these for headphone/lineout detection */ 601 struct snd_kcontrol *headphone_ctrl; 602 struct snd_kcontrol *lineout_ctrl; 603 struct snd_kcontrol *speaker_ctrl; 604 struct snd_kcontrol *master_ctrl; 605 struct snd_kcontrol *headphone_detected_ctrl; 606 struct snd_kcontrol *lineout_detected_ctrl; 607 608 struct layout_dev_ptr selfptr_headphone; 609 struct layout_dev_ptr selfptr_lineout; 610 611 u32 have_lineout_detect:1, 612 have_headphone_detect:1, 613 switch_on_headphone:1, 614 switch_on_lineout:1; 615 }; 616 617 static LIST_HEAD(layouts_list); 618 static int layouts_list_items; 619 /* this can go away but only if we allow multiple cards, 620 * make the fabric handle all the card stuff, etc... */ 621 static struct layout_dev *layout_device; 622 623 #define control_info snd_ctl_boolean_mono_info 624 625 #define AMP_CONTROL(n, description) \ 626 static int n##_control_get(struct snd_kcontrol *kcontrol, \ 627 struct snd_ctl_elem_value *ucontrol) \ 628 { \ 629 struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ 630 if (gpio->methods && gpio->methods->get_##n) \ 631 ucontrol->value.integer.value[0] = \ 632 gpio->methods->get_##n(gpio); \ 633 return 0; \ 634 } \ 635 static int n##_control_put(struct snd_kcontrol *kcontrol, \ 636 struct snd_ctl_elem_value *ucontrol) \ 637 { \ 638 struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ 639 if (gpio->methods && gpio->methods->get_##n) \ 640 gpio->methods->set_##n(gpio, \ 641 !!ucontrol->value.integer.value[0]); \ 642 return 1; \ 643 } \ 644 static struct snd_kcontrol_new n##_ctl = { \ 645 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 646 .name = description, \ 647 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ 648 .info = control_info, \ 649 .get = n##_control_get, \ 650 .put = n##_control_put, \ 651 } 652 653 AMP_CONTROL(headphone, "Headphone Switch"); 654 AMP_CONTROL(speakers, "Speakers Switch"); 655 AMP_CONTROL(lineout, "Line-Out Switch"); 656 AMP_CONTROL(master, "Master Switch"); 657 658 static int detect_choice_get(struct snd_kcontrol *kcontrol, 659 struct snd_ctl_elem_value *ucontrol) 660 { 661 struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); 662 663 switch (kcontrol->private_value) { 664 case 0: 665 ucontrol->value.integer.value[0] = ldev->switch_on_headphone; 666 break; 667 case 1: 668 ucontrol->value.integer.value[0] = ldev->switch_on_lineout; 669 break; 670 default: 671 return -ENODEV; 672 } 673 return 0; 674 } 675 676 static int detect_choice_put(struct snd_kcontrol *kcontrol, 677 struct snd_ctl_elem_value *ucontrol) 678 { 679 struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); 680 681 switch (kcontrol->private_value) { 682 case 0: 683 ldev->switch_on_headphone = !!ucontrol->value.integer.value[0]; 684 break; 685 case 1: 686 ldev->switch_on_lineout = !!ucontrol->value.integer.value[0]; 687 break; 688 default: 689 return -ENODEV; 690 } 691 return 1; 692 } 693 694 static struct snd_kcontrol_new headphone_detect_choice = { 695 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 696 .name = "Headphone Detect Autoswitch", 697 .info = control_info, 698 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 699 .get = detect_choice_get, 700 .put = detect_choice_put, 701 .private_value = 0, 702 }; 703 704 static struct snd_kcontrol_new lineout_detect_choice = { 705 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 706 .name = "Line-Out Detect Autoswitch", 707 .info = control_info, 708 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, 709 .get = detect_choice_get, 710 .put = detect_choice_put, 711 .private_value = 1, 712 }; 713 714 static int detected_get(struct snd_kcontrol *kcontrol, 715 struct snd_ctl_elem_value *ucontrol) 716 { 717 struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); 718 int v; 719 720 switch (kcontrol->private_value) { 721 case 0: 722 v = ldev->gpio.methods->get_detect(&ldev->gpio, 723 AOA_NOTIFY_HEADPHONE); 724 break; 725 case 1: 726 v = ldev->gpio.methods->get_detect(&ldev->gpio, 727 AOA_NOTIFY_LINE_OUT); 728 break; 729 default: 730 return -ENODEV; 731 } 732 ucontrol->value.integer.value[0] = v; 733 return 0; 734 } 735 736 static struct snd_kcontrol_new headphone_detected = { 737 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 738 .name = "Headphone Detected", 739 .info = control_info, 740 .access = SNDRV_CTL_ELEM_ACCESS_READ, 741 .get = detected_get, 742 .private_value = 0, 743 }; 744 745 static struct snd_kcontrol_new lineout_detected = { 746 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 747 .name = "Line-Out Detected", 748 .info = control_info, 749 .access = SNDRV_CTL_ELEM_ACCESS_READ, 750 .get = detected_get, 751 .private_value = 1, 752 }; 753 754 static int check_codec(struct aoa_codec *codec, 755 struct layout_dev *ldev, 756 struct codec_connect_info *cci) 757 { 758 const u32 *ref; 759 char propname[32]; 760 struct codec_connection *cc; 761 762 /* if the codec has a 'codec' node, we require a reference */ 763 if (codec->node && (strcmp(codec->node->name, "codec") == 0)) { 764 snprintf(propname, sizeof(propname), 765 "platform-%s-codec-ref", codec->name); 766 ref = of_get_property(ldev->sound, propname, NULL); 767 if (!ref) { 768 printk(KERN_INFO "snd-aoa-fabric-layout: " 769 "required property %s not present\n", propname); 770 return -ENODEV; 771 } 772 if (*ref != codec->node->phandle) { 773 printk(KERN_INFO "snd-aoa-fabric-layout: " 774 "%s doesn't match!\n", propname); 775 return -ENODEV; 776 } 777 } else { 778 if (layouts_list_items != 1) { 779 printk(KERN_INFO "snd-aoa-fabric-layout: " 780 "more than one soundbus, but no references.\n"); 781 return -ENODEV; 782 } 783 } 784 codec->soundbus_dev = ldev->sdev; 785 codec->gpio = &ldev->gpio; 786 787 cc = cci->connections; 788 if (!cc) 789 return -EINVAL; 790 791 printk(KERN_INFO "snd-aoa-fabric-layout: can use this codec\n"); 792 793 codec->connected = 0; 794 codec->fabric_data = cc; 795 796 while (cc->connected) { 797 codec->connected |= 1<<cc->codec_bit; 798 cc++; 799 } 800 801 return 0; 802 } 803 804 static int layout_found_codec(struct aoa_codec *codec) 805 { 806 struct layout_dev *ldev; 807 int i; 808 809 list_for_each_entry(ldev, &layouts_list, list) { 810 for (i=0; i<MAX_CODECS_PER_BUS; i++) { 811 if (!ldev->layout->codecs[i].name) 812 continue; 813 if (strcmp(ldev->layout->codecs[i].name, codec->name) == 0) { 814 if (check_codec(codec, 815 ldev, 816 &ldev->layout->codecs[i]) == 0) 817 return 0; 818 } 819 } 820 } 821 return -ENODEV; 822 } 823 824 static void layout_remove_codec(struct aoa_codec *codec) 825 { 826 int i; 827 /* here remove the codec from the layout dev's 828 * codec reference */ 829 830 codec->soundbus_dev = NULL; 831 codec->gpio = NULL; 832 for (i=0; i<MAX_CODECS_PER_BUS; i++) { 833 } 834 } 835 836 static void layout_notify(void *data) 837 { 838 struct layout_dev_ptr *dptr = data; 839 struct layout_dev *ldev; 840 int v, update; 841 struct snd_kcontrol *detected, *c; 842 struct snd_card *card = aoa_get_card(); 843 844 ldev = dptr->ptr; 845 if (data == &ldev->selfptr_headphone) { 846 v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_HEADPHONE); 847 detected = ldev->headphone_detected_ctrl; 848 update = ldev->switch_on_headphone; 849 if (update) { 850 ldev->gpio.methods->set_speakers(&ldev->gpio, !v); 851 ldev->gpio.methods->set_headphone(&ldev->gpio, v); 852 ldev->gpio.methods->set_lineout(&ldev->gpio, 0); 853 } 854 } else if (data == &ldev->selfptr_lineout) { 855 v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_LINE_OUT); 856 detected = ldev->lineout_detected_ctrl; 857 update = ldev->switch_on_lineout; 858 if (update) { 859 ldev->gpio.methods->set_speakers(&ldev->gpio, !v); 860 ldev->gpio.methods->set_headphone(&ldev->gpio, 0); 861 ldev->gpio.methods->set_lineout(&ldev->gpio, v); 862 } 863 } else 864 return; 865 866 if (detected) 867 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &detected->id); 868 if (update) { 869 c = ldev->headphone_ctrl; 870 if (c) 871 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); 872 c = ldev->speaker_ctrl; 873 if (c) 874 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); 875 c = ldev->lineout_ctrl; 876 if (c) 877 snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); 878 } 879 } 880 881 static void layout_attached_codec(struct aoa_codec *codec) 882 { 883 struct codec_connection *cc; 884 struct snd_kcontrol *ctl; 885 int headphones, lineout; 886 struct layout_dev *ldev = layout_device; 887 888 /* need to add this codec to our codec array! */ 889 890 cc = codec->fabric_data; 891 892 headphones = codec->gpio->methods->get_detect(codec->gpio, 893 AOA_NOTIFY_HEADPHONE); 894 lineout = codec->gpio->methods->get_detect(codec->gpio, 895 AOA_NOTIFY_LINE_OUT); 896 897 if (codec->gpio->methods->set_master) { 898 ctl = snd_ctl_new1(&master_ctl, codec->gpio); 899 ldev->master_ctrl = ctl; 900 aoa_snd_ctl_add(ctl); 901 } 902 while (cc->connected) { 903 if (cc->connected & CC_SPEAKERS) { 904 if (headphones <= 0 && lineout <= 0) 905 ldev->gpio.methods->set_speakers(codec->gpio, 1); 906 ctl = snd_ctl_new1(&speakers_ctl, codec->gpio); 907 ldev->speaker_ctrl = ctl; 908 aoa_snd_ctl_add(ctl); 909 } 910 if (cc->connected & CC_HEADPHONE) { 911 if (headphones == 1) 912 ldev->gpio.methods->set_headphone(codec->gpio, 1); 913 ctl = snd_ctl_new1(&headphone_ctl, codec->gpio); 914 ldev->headphone_ctrl = ctl; 915 aoa_snd_ctl_add(ctl); 916 ldev->have_headphone_detect = 917 !ldev->gpio.methods 918 ->set_notify(&ldev->gpio, 919 AOA_NOTIFY_HEADPHONE, 920 layout_notify, 921 &ldev->selfptr_headphone); 922 if (ldev->have_headphone_detect) { 923 ctl = snd_ctl_new1(&headphone_detect_choice, 924 ldev); 925 aoa_snd_ctl_add(ctl); 926 ctl = snd_ctl_new1(&headphone_detected, 927 ldev); 928 ldev->headphone_detected_ctrl = ctl; 929 aoa_snd_ctl_add(ctl); 930 } 931 } 932 if (cc->connected & CC_LINEOUT) { 933 if (lineout == 1) 934 ldev->gpio.methods->set_lineout(codec->gpio, 1); 935 ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); 936 if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) 937 strlcpy(ctl->id.name, 938 "Headphone Switch", sizeof(ctl->id.name)); 939 ldev->lineout_ctrl = ctl; 940 aoa_snd_ctl_add(ctl); 941 ldev->have_lineout_detect = 942 !ldev->gpio.methods 943 ->set_notify(&ldev->gpio, 944 AOA_NOTIFY_LINE_OUT, 945 layout_notify, 946 &ldev->selfptr_lineout); 947 if (ldev->have_lineout_detect) { 948 ctl = snd_ctl_new1(&lineout_detect_choice, 949 ldev); 950 if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) 951 strlcpy(ctl->id.name, 952 "Headphone Detect Autoswitch", 953 sizeof(ctl->id.name)); 954 aoa_snd_ctl_add(ctl); 955 ctl = snd_ctl_new1(&lineout_detected, 956 ldev); 957 if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) 958 strlcpy(ctl->id.name, 959 "Headphone Detected", 960 sizeof(ctl->id.name)); 961 ldev->lineout_detected_ctrl = ctl; 962 aoa_snd_ctl_add(ctl); 963 } 964 } 965 cc++; 966 } 967 /* now update initial state */ 968 if (ldev->have_headphone_detect) 969 layout_notify(&ldev->selfptr_headphone); 970 if (ldev->have_lineout_detect) 971 layout_notify(&ldev->selfptr_lineout); 972 } 973 974 static struct aoa_fabric layout_fabric = { 975 .name = "SoundByLayout", 976 .owner = THIS_MODULE, 977 .found_codec = layout_found_codec, 978 .remove_codec = layout_remove_codec, 979 .attached_codec = layout_attached_codec, 980 }; 981 982 static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) 983 { 984 struct device_node *sound = NULL; 985 const unsigned int *id; 986 struct layout *layout = NULL; 987 struct layout_dev *ldev = NULL; 988 int err; 989 990 /* hm, currently we can only have one ... */ 991 if (layout_device) 992 return -ENODEV; 993 994 /* by breaking out we keep a reference */ 995 while ((sound = of_get_next_child(sdev->ofdev.dev.of_node, sound))) { 996 if (sound->type && strcasecmp(sound->type, "soundchip") == 0) 997 break; 998 } 999 if (!sound) 1000 return -ENODEV; 1001 1002 id = of_get_property(sound, "layout-id", NULL); 1003 if (id) { 1004 layout = find_layout_by_id(*id); 1005 } else { 1006 id = of_get_property(sound, "device-id", NULL); 1007 if (id) 1008 layout = find_layout_by_device(*id); 1009 } 1010 1011 if (!layout) { 1012 printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n"); 1013 goto outnodev; 1014 } 1015 1016 ldev = kzalloc(sizeof(struct layout_dev), GFP_KERNEL); 1017 if (!ldev) 1018 goto outnodev; 1019 1020 layout_device = ldev; 1021 ldev->sdev = sdev; 1022 ldev->sound = sound; 1023 ldev->layout = layout; 1024 ldev->gpio.node = sound->parent; 1025 switch (layout->layout_id) { 1026 case 0: /* anything with device_id, not layout_id */ 1027 case 41: /* that unknown machine no one seems to have */ 1028 case 51: /* PowerBook5,4 */ 1029 case 58: /* Mac Mini */ 1030 ldev->gpio.methods = ftr_gpio_methods; 1031 printk(KERN_DEBUG 1032 "snd-aoa-fabric-layout: Using direct GPIOs\n"); 1033 break; 1034 default: 1035 ldev->gpio.methods = pmf_gpio_methods; 1036 printk(KERN_DEBUG 1037 "snd-aoa-fabric-layout: Using PMF GPIOs\n"); 1038 } 1039 ldev->selfptr_headphone.ptr = ldev; 1040 ldev->selfptr_lineout.ptr = ldev; 1041 dev_set_drvdata(&sdev->ofdev.dev, ldev); 1042 list_add(&ldev->list, &layouts_list); 1043 layouts_list_items++; 1044 1045 /* assign these before registering ourselves, so 1046 * callbacks that are done during registration 1047 * already have the values */ 1048 sdev->pcmid = ldev->layout->pcmid; 1049 if (ldev->layout->busname) { 1050 sdev->pcmname = ldev->layout->busname; 1051 } else { 1052 sdev->pcmname = "Master"; 1053 } 1054 1055 ldev->gpio.methods->init(&ldev->gpio); 1056 1057 err = aoa_fabric_register(&layout_fabric, &sdev->ofdev.dev); 1058 if (err && err != -EALREADY) { 1059 printk(KERN_INFO "snd-aoa-fabric-layout: can't use," 1060 " another fabric is active!\n"); 1061 goto outlistdel; 1062 } 1063 1064 use_layout(layout); 1065 ldev->switch_on_headphone = 1; 1066 ldev->switch_on_lineout = 1; 1067 return 0; 1068 outlistdel: 1069 /* we won't be using these then... */ 1070 ldev->gpio.methods->exit(&ldev->gpio); 1071 /* reset if we didn't use it */ 1072 sdev->pcmname = NULL; 1073 sdev->pcmid = -1; 1074 list_del(&ldev->list); 1075 layouts_list_items--; 1076 kfree(ldev); 1077 outnodev: 1078 of_node_put(sound); 1079 layout_device = NULL; 1080 return -ENODEV; 1081 } 1082 1083 static int aoa_fabric_layout_remove(struct soundbus_dev *sdev) 1084 { 1085 struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); 1086 int i; 1087 1088 for (i=0; i<MAX_CODECS_PER_BUS; i++) { 1089 if (ldev->codecs[i]) { 1090 aoa_fabric_unlink_codec(ldev->codecs[i]); 1091 } 1092 ldev->codecs[i] = NULL; 1093 } 1094 list_del(&ldev->list); 1095 layouts_list_items--; 1096 of_node_put(ldev->sound); 1097 1098 ldev->gpio.methods->set_notify(&ldev->gpio, 1099 AOA_NOTIFY_HEADPHONE, 1100 NULL, 1101 NULL); 1102 ldev->gpio.methods->set_notify(&ldev->gpio, 1103 AOA_NOTIFY_LINE_OUT, 1104 NULL, 1105 NULL); 1106 1107 ldev->gpio.methods->exit(&ldev->gpio); 1108 layout_device = NULL; 1109 kfree(ldev); 1110 sdev->pcmid = -1; 1111 sdev->pcmname = NULL; 1112 return 0; 1113 } 1114 1115 #ifdef CONFIG_PM 1116 static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state) 1117 { 1118 struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); 1119 1120 if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) 1121 ldev->gpio.methods->all_amps_off(&ldev->gpio); 1122 1123 return 0; 1124 } 1125 1126 static int aoa_fabric_layout_resume(struct soundbus_dev *sdev) 1127 { 1128 struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); 1129 1130 if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) 1131 ldev->gpio.methods->all_amps_restore(&ldev->gpio); 1132 1133 return 0; 1134 } 1135 #endif 1136 1137 static struct soundbus_driver aoa_soundbus_driver = { 1138 .name = "snd_aoa_soundbus_drv", 1139 .owner = THIS_MODULE, 1140 .probe = aoa_fabric_layout_probe, 1141 .remove = aoa_fabric_layout_remove, 1142 #ifdef CONFIG_PM 1143 .suspend = aoa_fabric_layout_suspend, 1144 .resume = aoa_fabric_layout_resume, 1145 #endif 1146 .driver = { 1147 .owner = THIS_MODULE, 1148 } 1149 }; 1150 1151 static int __init aoa_fabric_layout_init(void) 1152 { 1153 int err; 1154 1155 err = soundbus_register_driver(&aoa_soundbus_driver); 1156 if (err) 1157 return err; 1158 return 0; 1159 } 1160 1161 static void __exit aoa_fabric_layout_exit(void) 1162 { 1163 soundbus_unregister_driver(&aoa_soundbus_driver); 1164 aoa_fabric_unregister(&layout_fabric); 1165 } 1166 1167 module_init(aoa_fabric_layout_init); 1168 module_exit(aoa_fabric_layout_exit); 1169