13 #include <linux/list.h>
14 #include <linux/module.h>
15 #include <linux/slab.h>
17 #include "../soundbus/soundbus.h"
23 #define MAX_CODECS_PER_BUS 2
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)
45 #define CC_LINEOUT_LABELLED_HEADPHONE (1<<7)
62 #define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0)
271 static struct layout layouts[] = {
277 .connections = onyx_connections_noheadphones,
281 .connections = topaz_input,
288 .connections = onyx_connections_reallineout,
295 .connections = topaz_input,
303 .connections = onyx_connections_noheadphones,
310 .connections = topaz_input,
318 .connections = onyx_connections_noheadphones,
322 .connections = topaz_input,
329 .connections = onyx_connections_noheadphones,
333 .connections = topaz_input,
340 .connections = onyx_connections_nomic,
347 .connections = topaz_input,
349 .busname =
"digital in", .pcmid = 1 },
354 .connections = tas_connections_nolineout,
361 .connections = tas_connections_nolineout,
368 .connections = tas_connections_noline,
375 .connections = tas_connections_nolineout,
382 .connections = onyx_connections_nomic,
386 .connections = topaz_input,
393 .connections = tas_connections_nolineout,
400 .connections = toonie_connections,
407 .connections = onyx_connections_noheadphones,
414 .connections = tas_connections_all,
420 .connections = tas_connections_nomic,
424 .connections = topaz_inout,
430 .connections = onyx_connections_noheadphones,
436 .connections = topaz_input,
442 .connections = onyx_connections_nomic,
448 .connections = topaz_input,
454 .connections = onyx_connections_noheadphones,
460 .connections = topaz_input,
466 .connections = onyx_connections_noheadphones,
470 .connections = topaz_output,
476 .connections = onyx_connections_noheadphones,
482 .connections = topaz_input,
488 .connections = tas_connections_nomic,
492 .connections = topaz_inout,
498 .connections = tas_connections_noline,
505 .connections = onyx_connections_noheadphones,
511 .connections = toonie_connections,
517 .connections = topaz_input,
521 .connections = onyx_connections_noheadphones,
528 .connections = tas_connections_noline,
535 .connections = tas_connections_all,
542 .connections = tas_connections_all,
548 static struct layout *find_layout_by_id(
unsigned int id)
553 while (l->
codecs[0].name) {
561 static struct layout *find_layout_by_device(
unsigned int id)
566 while (l->
codecs[0].name) {
574 static void use_layout(
struct layout *l)
580 request_module(
"snd-aoa-codec-%s", l->
codecs[i].name);
618 static int layouts_list_items;
623 #define control_info snd_ctl_boolean_mono_info
625 #define AMP_CONTROL(n, description) \
626 static int n##_control_get(struct snd_kcontrol *kcontrol, \
627 struct snd_ctl_elem_value *ucontrol) \
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); \
635 static int n##_control_put(struct snd_kcontrol *kcontrol, \
636 struct snd_ctl_elem_value *ucontrol) \
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]); \
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, \
658 static int detect_choice_get(
struct snd_kcontrol *kcontrol,
676 static int detect_choice_put(
struct snd_kcontrol *kcontrol,
696 .name =
"Headphone Detect Autoswitch",
699 .get = detect_choice_get,
700 .put = detect_choice_put,
706 .name =
"Line-Out Detect Autoswitch",
709 .get = detect_choice_get,
710 .put = detect_choice_put,
722 v = ldev->
gpio.methods->get_detect(&ldev->
gpio,
726 v = ldev->
gpio.methods->get_detect(&ldev->
gpio,
732 ucontrol->
value.integer.value[0] =
v;
738 .name =
"Headphone Detected",
747 .name =
"Line-Out Detected",
764 snprintf(propname,
sizeof(propname),
765 "platform-%s-codec-ref", codec->
name);
769 "required property %s not present\n", propname);
772 if (*ref != codec->
node->phandle) {
774 "%s doesn't match!\n", propname);
778 if (layouts_list_items != 1) {
780 "more than one soundbus, but no references.\n");
804 static int layout_found_codec(
struct aoa_codec *codec)
811 if (!ldev->
layout->codecs[i].name)
814 if (check_codec(codec,
816 &ldev->
layout->codecs[i]) == 0)
824 static void layout_remove_codec(
struct aoa_codec *codec)
836 static void layout_notify(
void *
data)
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);
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);
881 static void layout_attached_codec(
struct aoa_codec *codec)
885 int headphones, lineout;
892 headphones = codec->
gpio->methods->get_detect(codec->
gpio,
894 lineout = codec->
gpio->methods->get_detect(codec->
gpio,
897 if (codec->
gpio->methods->set_master) {
904 if (headphones <= 0 && lineout <= 0)
905 ldev->
gpio.methods->set_speakers(codec->
gpio, 1);
912 ldev->
gpio.methods->set_headphone(codec->
gpio, 1);
918 ->set_notify(&ldev->
gpio,
934 ldev->
gpio.methods->set_lineout(codec->
gpio, 1);
938 "Headphone Switch",
sizeof(ctl->
id.name));
943 ->set_notify(&ldev->
gpio,
952 "Headphone Detect Autoswitch",
953 sizeof(ctl->
id.name));
959 "Headphone Detected",
960 sizeof(ctl->
id.name));
975 .name =
"SoundByLayout",
977 .found_codec = layout_found_codec,
978 .remove_codec = layout_remove_codec,
979 .attached_codec = layout_attached_codec,
982 static int aoa_fabric_layout_probe(
struct soundbus_dev *sdev)
985 const unsigned int *
id;
1004 layout = find_layout_by_id(*
id);
1008 layout = find_layout_by_device(*
id);
1020 layout_device = ldev;
1032 "snd-aoa-fabric-layout: Using direct GPIOs\n");
1037 "snd-aoa-fabric-layout: Using PMF GPIOs\n");
1042 list_add(&ldev->
list, &layouts_list);
1043 layouts_list_items++;
1049 if (ldev->
layout->busname) {
1055 ldev->
gpio.methods->init(&ldev->
gpio);
1060 " another fabric is active!\n");
1070 ldev->
gpio.methods->exit(&ldev->
gpio);
1075 layouts_list_items--;
1079 layout_device =
NULL;
1083 static int aoa_fabric_layout_remove(
struct soundbus_dev *sdev)
1095 layouts_list_items--;
1096 of_node_put(ldev->
sound);
1098 ldev->
gpio.methods->set_notify(&ldev->
gpio,
1102 ldev->
gpio.methods->set_notify(&ldev->
gpio,
1107 ldev->
gpio.methods->exit(&ldev->
gpio);
1108 layout_device =
NULL;
1120 if (ldev->
gpio.methods && ldev->
gpio.methods->all_amps_off)
1121 ldev->
gpio.methods->all_amps_off(&ldev->
gpio);
1126 static int aoa_fabric_layout_resume(
struct soundbus_dev *sdev)
1130 if (ldev->
gpio.methods && ldev->
gpio.methods->all_amps_off)
1131 ldev->
gpio.methods->all_amps_restore(&ldev->
gpio);
1138 .name =
"snd_aoa_soundbus_drv",
1140 .probe = aoa_fabric_layout_probe,
1141 .remove = aoa_fabric_layout_remove,
1143 .suspend = aoa_fabric_layout_suspend,
1144 .resume = aoa_fabric_layout_resume,
1151 static int __init aoa_fabric_layout_init(
void)
1161 static void __exit aoa_fabric_layout_exit(
void)