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