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