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