pandora: reserve CMA area for c64_tools
[pandora-kernel.git] / 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 <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);