diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2008-10-23 17:47:56 +0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2008-10-23 20:43:42 +0400 |
commit | 888dcb7cb26fb85dfe3486d28a2431d69d3e8148 (patch) | |
tree | aad6f0dba4bdb63bc72280ed51a79f7dea284278 /sound/aoa/fabrics/snd-aoa-fabric-layout.c | |
parent | 72474be62d6ec2e0337ff01ecbd737f9c5c242c7 (diff) | |
download | linux-888dcb7cb26fb85dfe3486d28a2431d69d3e8148.tar.xz |
ALSA: aoa: clean up file names
This cleans up the apple onboard audio driver filenames.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/aoa/fabrics/snd-aoa-fabric-layout.c')
-rw-r--r-- | sound/aoa/fabrics/snd-aoa-fabric-layout.c | 1120 |
1 files changed, 0 insertions, 1120 deletions
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c deleted file mode 100644 index dea7abb082cd..000000000000 --- a/sound/aoa/fabrics/snd-aoa-fabric-layout.c +++ /dev/null @@ -1,1120 +0,0 @@ -/* - * Apple Onboard Audio driver -- layout fabric - * - * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> - * - * GPL v2, can be found in COPYING. - * - * - * This fabric module looks for sound codecs - * based on the layout-id property in the device tree. - * - */ - -#include <asm/prom.h> -#include <linux/list.h> -#include <linux/module.h> -#include "../aoa.h" -#include "../soundbus/soundbus.h" - -MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Layout-ID fabric for snd-aoa"); - -#define MAX_CODECS_PER_BUS 2 - -/* These are the connections the layout fabric - * knows about. It doesn't really care about the - * input ones, but I thought I'd separate them - * to give them proper names. The thing is that - * Apple usually will distinguish the active output - * by GPIOs, while the active input is set directly - * on the codec. Hence we here tell the codec what - * we think is connected. This information is hard- - * coded below ... */ -#define CC_SPEAKERS (1<<0) -#define CC_HEADPHONE (1<<1) -#define CC_LINEOUT (1<<2) -#define CC_DIGITALOUT (1<<3) -#define CC_LINEIN (1<<4) -#define CC_MICROPHONE (1<<5) -#define CC_DIGITALIN (1<<6) -/* pretty bogus but users complain... - * This is a flag saying that the LINEOUT - * should be renamed to HEADPHONE. - * be careful with input detection! */ -#define CC_LINEOUT_LABELLED_HEADPHONE (1<<7) - -struct codec_connection { - /* CC_ flags from above */ - int connected; - /* codec dependent bit to be set in the aoa_codec.connected field. - * This intentionally doesn't have any generic flags because the - * fabric has to know the codec anyway and all codecs might have - * different connectors */ - int codec_bit; -}; - -struct codec_connect_info { - char *name; - struct codec_connection *connections; -}; - -#define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0) - -struct layout { - unsigned int layout_id; - struct codec_connect_info codecs[MAX_CODECS_PER_BUS]; - int flags; - - /* if busname is not assigned, we use 'Master' below, - * so that our layout table doesn't need to be filled - * too much. - * We only assign these two if we expect to find more - * than one soundbus, i.e. on those machines with - * multiple layout-ids */ - char *busname; - int pcmid; -}; - -MODULE_ALIAS("sound-layout-36"); -MODULE_ALIAS("sound-layout-41"); -MODULE_ALIAS("sound-layout-45"); -MODULE_ALIAS("sound-layout-47"); -MODULE_ALIAS("sound-layout-48"); -MODULE_ALIAS("sound-layout-49"); -MODULE_ALIAS("sound-layout-50"); -MODULE_ALIAS("sound-layout-51"); -MODULE_ALIAS("sound-layout-56"); -MODULE_ALIAS("sound-layout-57"); -MODULE_ALIAS("sound-layout-58"); -MODULE_ALIAS("sound-layout-60"); -MODULE_ALIAS("sound-layout-61"); -MODULE_ALIAS("sound-layout-62"); -MODULE_ALIAS("sound-layout-64"); -MODULE_ALIAS("sound-layout-65"); -MODULE_ALIAS("sound-layout-66"); -MODULE_ALIAS("sound-layout-67"); -MODULE_ALIAS("sound-layout-68"); -MODULE_ALIAS("sound-layout-69"); -MODULE_ALIAS("sound-layout-70"); -MODULE_ALIAS("sound-layout-72"); -MODULE_ALIAS("sound-layout-76"); -MODULE_ALIAS("sound-layout-80"); -MODULE_ALIAS("sound-layout-82"); -MODULE_ALIAS("sound-layout-84"); -MODULE_ALIAS("sound-layout-86"); -MODULE_ALIAS("sound-layout-90"); -MODULE_ALIAS("sound-layout-92"); -MODULE_ALIAS("sound-layout-94"); -MODULE_ALIAS("sound-layout-96"); -MODULE_ALIAS("sound-layout-98"); -MODULE_ALIAS("sound-layout-100"); - -/* onyx with all but microphone connected */ -static struct codec_connection onyx_connections_nomic[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, - .codec_bit = 0, - }, - { - .connected = CC_DIGITALOUT, - .codec_bit = 1, - }, - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* onyx on machines without headphone */ -static struct codec_connection onyx_connections_noheadphones[] = { - { - .connected = CC_SPEAKERS | CC_LINEOUT | - CC_LINEOUT_LABELLED_HEADPHONE, - .codec_bit = 0, - }, - { - .connected = CC_DIGITALOUT, - .codec_bit = 1, - }, - /* FIXME: are these correct? probably not for all the machines - * below ... If not this will need separating. */ - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - { - .connected = CC_MICROPHONE, - .codec_bit = 3, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* onyx on machines with real line-out */ -static struct codec_connection onyx_connections_reallineout[] = { - { - .connected = CC_SPEAKERS | CC_LINEOUT | CC_HEADPHONE, - .codec_bit = 0, - }, - { - .connected = CC_DIGITALOUT, - .codec_bit = 1, - }, - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* tas on machines without line out */ -static struct codec_connection tas_connections_nolineout[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE, - .codec_bit = 0, - }, - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - { - .connected = CC_MICROPHONE, - .codec_bit = 3, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* tas on machines with neither line out nor line in */ -static struct codec_connection tas_connections_noline[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE, - .codec_bit = 0, - }, - { - .connected = CC_MICROPHONE, - .codec_bit = 3, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* tas on machines without microphone */ -static struct codec_connection tas_connections_nomic[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, - .codec_bit = 0, - }, - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - {} /* terminate array by .connected == 0 */ -}; - -/* tas on machines with everything connected */ -static struct codec_connection tas_connections_all[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE | CC_LINEOUT, - .codec_bit = 0, - }, - { - .connected = CC_LINEIN, - .codec_bit = 2, - }, - { - .connected = CC_MICROPHONE, - .codec_bit = 3, - }, - {} /* terminate array by .connected == 0 */ -}; - -static struct codec_connection toonie_connections[] = { - { - .connected = CC_SPEAKERS | CC_HEADPHONE, - .codec_bit = 0, - }, - {} /* terminate array by .connected == 0 */ -}; - -static struct codec_connection topaz_input[] = { - { - .connected = CC_DIGITALIN, - .codec_bit = 0, - }, - {} /* terminate array by .connected == 0 */ -}; - -static struct codec_connection topaz_output[] = { - { - .connected = CC_DIGITALOUT, - .codec_bit = 1, - }, - {} /* terminate array by .connected == 0 */ -}; - -static struct codec_connection topaz_inout[] = { - { - .connected = CC_DIGITALIN, - .codec_bit = 0, - }, - { - .connected = CC_DIGITALOUT, - .codec_bit = 1, - }, - {} /* terminate array by .connected == 0 */ -}; - -static struct layout layouts[] = { - /* last PowerBooks (15" Oct 2005) */ - { .layout_id = 82, - .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* PowerMac9,1 */ - { .layout_id = 60, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_reallineout, - }, - }, - /* PowerMac9,1 */ - { .layout_id = 61, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* PowerBook5,7 */ - { .layout_id = 64, - .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - /* PowerBook5,7 */ - { .layout_id = 65, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* PowerBook5,9 [17" Oct 2005] */ - { .layout_id = 84, - .flags = LAYOUT_FLAG_COMBO_LINEOUT_SPDIF, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* PowerMac8,1 */ - { .layout_id = 45, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* Quad PowerMac (analog in, analog/digital out) */ - { .layout_id = 68, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_nomic, - }, - }, - /* Quad PowerMac (digital in) */ - { .layout_id = 69, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - .busname = "digital in", .pcmid = 1 }, - /* Early 2005 PowerBook (PowerBook 5,6) */ - { .layout_id = 70, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nolineout, - }, - }, - /* PowerBook 5,4 */ - { .layout_id = 51, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nolineout, - }, - }, - /* PowerBook6,7 */ - { .layout_id = 80, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_noline, - }, - }, - /* PowerBook6,8 */ - { .layout_id = 72, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nolineout, - }, - }, - /* PowerMac8,2 */ - { .layout_id = 86, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_nomic, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - /* PowerBook6,7 */ - { .layout_id = 92, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nolineout, - }, - }, - /* PowerMac10,1 (Mac Mini) */ - { .layout_id = 58, - .codecs[0] = { - .name = "toonie", - .connections = toonie_connections, - }, - }, - { - .layout_id = 96, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - /* unknown, untested, but this comes from Apple */ - { .layout_id = 41, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_all, - }, - }, - { .layout_id = 36, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nomic, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_inout, - }, - }, - { .layout_id = 47, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - { .layout_id = 48, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - { .layout_id = 49, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_nomic, - }, - }, - { .layout_id = 50, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - { .layout_id = 56, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - { .layout_id = 57, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - { .layout_id = 62, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_output, - }, - }, - { .layout_id = 66, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - { .layout_id = 67, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - }, - { .layout_id = 76, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_nomic, - }, - .codecs[1] = { - .name = "topaz", - .connections = topaz_inout, - }, - }, - { .layout_id = 90, - .codecs[0] = { - .name = "tas", - .connections = tas_connections_noline, - }, - }, - { .layout_id = 94, - .codecs[0] = { - .name = "onyx", - /* but it has an external mic?? how to select? */ - .connections = onyx_connections_noheadphones, - }, - }, - { .layout_id = 98, - .codecs[0] = { - .name = "toonie", - .connections = toonie_connections, - }, - }, - { .layout_id = 100, - .codecs[0] = { - .name = "topaz", - .connections = topaz_input, - }, - .codecs[1] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, - {} -}; - -static struct layout *find_layout_by_id(unsigned int id) -{ - struct layout *l; - - l = layouts; - while (l->layout_id) { - if (l->layout_id == id) - return l; - l++; - } - return NULL; -} - -static void use_layout(struct layout *l) -{ - int i; - - for (i=0; i<MAX_CODECS_PER_BUS; i++) { - if (l->codecs[i].name) { - request_module("snd-aoa-codec-%s", l->codecs[i].name); - } - } - /* now we wait for the codecs to call us back */ -} - -struct layout_dev; - -struct layout_dev_ptr { - struct layout_dev *ptr; -}; - -struct layout_dev { - struct list_head list; - struct soundbus_dev *sdev; - struct device_node *sound; - struct aoa_codec *codecs[MAX_CODECS_PER_BUS]; - struct layout *layout; - struct gpio_runtime gpio; - - /* we need these for headphone/lineout detection */ - struct snd_kcontrol *headphone_ctrl; - struct snd_kcontrol *lineout_ctrl; - struct snd_kcontrol *speaker_ctrl; - struct snd_kcontrol *headphone_detected_ctrl; - struct snd_kcontrol *lineout_detected_ctrl; - - struct layout_dev_ptr selfptr_headphone; - struct layout_dev_ptr selfptr_lineout; - - u32 have_lineout_detect:1, - have_headphone_detect:1, - switch_on_headphone:1, - switch_on_lineout:1; -}; - -static LIST_HEAD(layouts_list); -static int layouts_list_items; -/* this can go away but only if we allow multiple cards, - * make the fabric handle all the card stuff, etc... */ -static struct layout_dev *layout_device; - -#define control_info snd_ctl_boolean_mono_info - -#define AMP_CONTROL(n, description) \ -static int n##_control_get(struct snd_kcontrol *kcontrol, \ - struct snd_ctl_elem_value *ucontrol) \ -{ \ - struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ - if (gpio->methods && gpio->methods->get_##n) \ - ucontrol->value.integer.value[0] = \ - gpio->methods->get_##n(gpio); \ - return 0; \ -} \ -static int n##_control_put(struct snd_kcontrol *kcontrol, \ - struct snd_ctl_elem_value *ucontrol) \ -{ \ - struct gpio_runtime *gpio = snd_kcontrol_chip(kcontrol); \ - if (gpio->methods && gpio->methods->get_##n) \ - gpio->methods->set_##n(gpio, \ - !!ucontrol->value.integer.value[0]); \ - return 1; \ -} \ -static struct snd_kcontrol_new n##_ctl = { \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = description, \ - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \ - .info = control_info, \ - .get = n##_control_get, \ - .put = n##_control_put, \ -} - -AMP_CONTROL(headphone, "Headphone Switch"); -AMP_CONTROL(speakers, "Speakers Switch"); -AMP_CONTROL(lineout, "Line-Out Switch"); - -static int detect_choice_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); - - switch (kcontrol->private_value) { - case 0: - ucontrol->value.integer.value[0] = ldev->switch_on_headphone; - break; - case 1: - ucontrol->value.integer.value[0] = ldev->switch_on_lineout; - break; - default: - return -ENODEV; - } - return 0; -} - -static int detect_choice_put(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); - - switch (kcontrol->private_value) { - case 0: - ldev->switch_on_headphone = !!ucontrol->value.integer.value[0]; - break; - case 1: - ldev->switch_on_lineout = !!ucontrol->value.integer.value[0]; - break; - default: - return -ENODEV; - } - return 1; -} - -static struct snd_kcontrol_new headphone_detect_choice = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Detect Autoswitch", - .info = control_info, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .get = detect_choice_get, - .put = detect_choice_put, - .private_value = 0, -}; - -static struct snd_kcontrol_new lineout_detect_choice = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line-Out Detect Autoswitch", - .info = control_info, - .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, - .get = detect_choice_get, - .put = detect_choice_put, - .private_value = 1, -}; - -static int detected_get(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct layout_dev *ldev = snd_kcontrol_chip(kcontrol); - int v; - - switch (kcontrol->private_value) { - case 0: - v = ldev->gpio.methods->get_detect(&ldev->gpio, - AOA_NOTIFY_HEADPHONE); - break; - case 1: - v = ldev->gpio.methods->get_detect(&ldev->gpio, - AOA_NOTIFY_LINE_OUT); - break; - default: - return -ENODEV; - } - ucontrol->value.integer.value[0] = v; - return 0; -} - -static struct snd_kcontrol_new headphone_detected = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Headphone Detected", - .info = control_info, - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .get = detected_get, - .private_value = 0, -}; - -static struct snd_kcontrol_new lineout_detected = { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "Line-Out Detected", - .info = control_info, - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .get = detected_get, - .private_value = 1, -}; - -static int check_codec(struct aoa_codec *codec, - struct layout_dev *ldev, - struct codec_connect_info *cci) -{ - const u32 *ref; - char propname[32]; - struct codec_connection *cc; - - /* if the codec has a 'codec' node, we require a reference */ - if (codec->node && (strcmp(codec->node->name, "codec") == 0)) { - snprintf(propname, sizeof(propname), - "platform-%s-codec-ref", codec->name); - ref = of_get_property(ldev->sound, propname, NULL); - if (!ref) { - printk(KERN_INFO "snd-aoa-fabric-layout: " - "required property %s not present\n", propname); - return -ENODEV; - } - if (*ref != codec->node->linux_phandle) { - printk(KERN_INFO "snd-aoa-fabric-layout: " - "%s doesn't match!\n", propname); - return -ENODEV; - } - } else { - if (layouts_list_items != 1) { - printk(KERN_INFO "snd-aoa-fabric-layout: " - "more than one soundbus, but no references.\n"); - return -ENODEV; - } - } - codec->soundbus_dev = ldev->sdev; - codec->gpio = &ldev->gpio; - - cc = cci->connections; - if (!cc) - return -EINVAL; - - printk(KERN_INFO "snd-aoa-fabric-layout: can use this codec\n"); - - codec->connected = 0; - codec->fabric_data = cc; - - while (cc->connected) { - codec->connected |= 1<<cc->codec_bit; - cc++; - } - - return 0; -} - -static int layout_found_codec(struct aoa_codec *codec) -{ - struct layout_dev *ldev; - int i; - - list_for_each_entry(ldev, &layouts_list, list) { - for (i=0; i<MAX_CODECS_PER_BUS; i++) { - if (!ldev->layout->codecs[i].name) - continue; - if (strcmp(ldev->layout->codecs[i].name, codec->name) == 0) { - if (check_codec(codec, - ldev, - &ldev->layout->codecs[i]) == 0) - return 0; - } - } - } - return -ENODEV; -} - -static void layout_remove_codec(struct aoa_codec *codec) -{ - int i; - /* here remove the codec from the layout dev's - * codec reference */ - - codec->soundbus_dev = NULL; - codec->gpio = NULL; - for (i=0; i<MAX_CODECS_PER_BUS; i++) { - } -} - -static void layout_notify(void *data) -{ - struct layout_dev_ptr *dptr = data; - struct layout_dev *ldev; - int v, update; - struct snd_kcontrol *detected, *c; - struct snd_card *card = aoa_get_card(); - - ldev = dptr->ptr; - if (data == &ldev->selfptr_headphone) { - v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_HEADPHONE); - detected = ldev->headphone_detected_ctrl; - update = ldev->switch_on_headphone; - if (update) { - ldev->gpio.methods->set_speakers(&ldev->gpio, !v); - ldev->gpio.methods->set_headphone(&ldev->gpio, v); - ldev->gpio.methods->set_lineout(&ldev->gpio, 0); - } - } else if (data == &ldev->selfptr_lineout) { - v = ldev->gpio.methods->get_detect(&ldev->gpio, AOA_NOTIFY_LINE_OUT); - detected = ldev->lineout_detected_ctrl; - update = ldev->switch_on_lineout; - if (update) { - ldev->gpio.methods->set_speakers(&ldev->gpio, !v); - ldev->gpio.methods->set_headphone(&ldev->gpio, 0); - ldev->gpio.methods->set_lineout(&ldev->gpio, v); - } - } else - return; - - if (detected) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &detected->id); - if (update) { - c = ldev->headphone_ctrl; - if (c) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); - c = ldev->speaker_ctrl; - if (c) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); - c = ldev->lineout_ctrl; - if (c) - snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &c->id); - } -} - -static void layout_attached_codec(struct aoa_codec *codec) -{ - struct codec_connection *cc; - struct snd_kcontrol *ctl; - int headphones, lineout; - struct layout_dev *ldev = layout_device; - - /* need to add this codec to our codec array! */ - - cc = codec->fabric_data; - - headphones = codec->gpio->methods->get_detect(codec->gpio, - AOA_NOTIFY_HEADPHONE); - lineout = codec->gpio->methods->get_detect(codec->gpio, - AOA_NOTIFY_LINE_OUT); - - while (cc->connected) { - if (cc->connected & CC_SPEAKERS) { - if (headphones <= 0 && lineout <= 0) - ldev->gpio.methods->set_speakers(codec->gpio, 1); - ctl = snd_ctl_new1(&speakers_ctl, codec->gpio); - ldev->speaker_ctrl = ctl; - aoa_snd_ctl_add(ctl); - } - if (cc->connected & CC_HEADPHONE) { - if (headphones == 1) - ldev->gpio.methods->set_headphone(codec->gpio, 1); - ctl = snd_ctl_new1(&headphone_ctl, codec->gpio); - ldev->headphone_ctrl = ctl; - aoa_snd_ctl_add(ctl); - ldev->have_headphone_detect = - !ldev->gpio.methods - ->set_notify(&ldev->gpio, - AOA_NOTIFY_HEADPHONE, - layout_notify, - &ldev->selfptr_headphone); - if (ldev->have_headphone_detect) { - ctl = snd_ctl_new1(&headphone_detect_choice, - ldev); - aoa_snd_ctl_add(ctl); - ctl = snd_ctl_new1(&headphone_detected, - ldev); - ldev->headphone_detected_ctrl = ctl; - aoa_snd_ctl_add(ctl); - } - } - if (cc->connected & CC_LINEOUT) { - if (lineout == 1) - ldev->gpio.methods->set_lineout(codec->gpio, 1); - ctl = snd_ctl_new1(&lineout_ctl, codec->gpio); - if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) - strlcpy(ctl->id.name, - "Headphone Switch", sizeof(ctl->id.name)); - ldev->lineout_ctrl = ctl; - aoa_snd_ctl_add(ctl); - ldev->have_lineout_detect = - !ldev->gpio.methods - ->set_notify(&ldev->gpio, - AOA_NOTIFY_LINE_OUT, - layout_notify, - &ldev->selfptr_lineout); - if (ldev->have_lineout_detect) { - ctl = snd_ctl_new1(&lineout_detect_choice, - ldev); - if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) - strlcpy(ctl->id.name, - "Headphone Detect Autoswitch", - sizeof(ctl->id.name)); - aoa_snd_ctl_add(ctl); - ctl = snd_ctl_new1(&lineout_detected, - ldev); - if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE) - strlcpy(ctl->id.name, - "Headphone Detected", - sizeof(ctl->id.name)); - ldev->lineout_detected_ctrl = ctl; - aoa_snd_ctl_add(ctl); - } - } - cc++; - } - /* now update initial state */ - if (ldev->have_headphone_detect) - layout_notify(&ldev->selfptr_headphone); - if (ldev->have_lineout_detect) - layout_notify(&ldev->selfptr_lineout); -} - -static struct aoa_fabric layout_fabric = { - .name = "SoundByLayout", - .owner = THIS_MODULE, - .found_codec = layout_found_codec, - .remove_codec = layout_remove_codec, - .attached_codec = layout_attached_codec, -}; - -static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) -{ - struct device_node *sound = NULL; - const unsigned int *layout_id; - struct layout *layout; - struct layout_dev *ldev = NULL; - int err; - - /* hm, currently we can only have one ... */ - if (layout_device) - return -ENODEV; - - /* by breaking out we keep a reference */ - while ((sound = of_get_next_child(sdev->ofdev.node, sound))) { - if (sound->type && strcasecmp(sound->type, "soundchip") == 0) - break; - } - if (!sound) return -ENODEV; - - layout_id = of_get_property(sound, "layout-id", NULL); - if (!layout_id) - goto outnodev; - printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d\n", - *layout_id); - - layout = find_layout_by_id(*layout_id); - if (!layout) { - printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n"); - goto outnodev; - } - - ldev = kzalloc(sizeof(struct layout_dev), GFP_KERNEL); - if (!ldev) - goto outnodev; - - layout_device = ldev; - ldev->sdev = sdev; - ldev->sound = sound; - ldev->layout = layout; - ldev->gpio.node = sound->parent; - switch (layout->layout_id) { - case 41: /* that unknown machine no one seems to have */ - case 51: /* PowerBook5,4 */ - case 58: /* Mac Mini */ - ldev->gpio.methods = ftr_gpio_methods; - printk(KERN_DEBUG - "snd-aoa-fabric-layout: Using direct GPIOs\n"); - break; - default: - ldev->gpio.methods = pmf_gpio_methods; - printk(KERN_DEBUG - "snd-aoa-fabric-layout: Using PMF GPIOs\n"); - } - ldev->selfptr_headphone.ptr = ldev; - ldev->selfptr_lineout.ptr = ldev; - sdev->ofdev.dev.driver_data = ldev; - list_add(&ldev->list, &layouts_list); - layouts_list_items++; - - /* assign these before registering ourselves, so - * callbacks that are done during registration - * already have the values */ - sdev->pcmid = ldev->layout->pcmid; - if (ldev->layout->busname) { - sdev->pcmname = ldev->layout->busname; - } else { - sdev->pcmname = "Master"; - } - - ldev->gpio.methods->init(&ldev->gpio); - - err = aoa_fabric_register(&layout_fabric, &sdev->ofdev.dev); - if (err && err != -EALREADY) { - printk(KERN_INFO "snd-aoa-fabric-layout: can't use," - " another fabric is active!\n"); - goto outlistdel; - } - - use_layout(layout); - ldev->switch_on_headphone = 1; - ldev->switch_on_lineout = 1; - return 0; - outlistdel: - /* we won't be using these then... */ - ldev->gpio.methods->exit(&ldev->gpio); - /* reset if we didn't use it */ - sdev->pcmname = NULL; - sdev->pcmid = -1; - list_del(&ldev->list); - layouts_list_items--; - outnodev: - of_node_put(sound); - layout_device = NULL; - kfree(ldev); - return -ENODEV; -} - -static int aoa_fabric_layout_remove(struct soundbus_dev *sdev) -{ - struct layout_dev *ldev = sdev->ofdev.dev.driver_data; - int i; - - for (i=0; i<MAX_CODECS_PER_BUS; i++) { - if (ldev->codecs[i]) { - aoa_fabric_unlink_codec(ldev->codecs[i]); - } - ldev->codecs[i] = NULL; - } - list_del(&ldev->list); - layouts_list_items--; - of_node_put(ldev->sound); - - ldev->gpio.methods->set_notify(&ldev->gpio, - AOA_NOTIFY_HEADPHONE, - NULL, - NULL); - ldev->gpio.methods->set_notify(&ldev->gpio, - AOA_NOTIFY_LINE_OUT, - NULL, - NULL); - - ldev->gpio.methods->exit(&ldev->gpio); - layout_device = NULL; - kfree(ldev); - sdev->pcmid = -1; - sdev->pcmname = NULL; - return 0; -} - -#ifdef CONFIG_PM -static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t state) -{ - struct layout_dev *ldev = sdev->ofdev.dev.driver_data; - - if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) - ldev->gpio.methods->all_amps_off(&ldev->gpio); - - return 0; -} - -static int aoa_fabric_layout_resume(struct soundbus_dev *sdev) -{ - struct layout_dev *ldev = sdev->ofdev.dev.driver_data; - - if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) - ldev->gpio.methods->all_amps_restore(&ldev->gpio); - - return 0; -} -#endif - -static struct soundbus_driver aoa_soundbus_driver = { - .name = "snd_aoa_soundbus_drv", - .owner = THIS_MODULE, - .probe = aoa_fabric_layout_probe, - .remove = aoa_fabric_layout_remove, -#ifdef CONFIG_PM - .suspend = aoa_fabric_layout_suspend, - .resume = aoa_fabric_layout_resume, -#endif - .driver = { - .owner = THIS_MODULE, - } -}; - -static int __init aoa_fabric_layout_init(void) -{ - int err; - - err = soundbus_register_driver(&aoa_soundbus_driver); - if (err) - return err; - return 0; -} - -static void __exit aoa_fabric_layout_exit(void) -{ - soundbus_unregister_driver(&aoa_soundbus_driver); - aoa_fabric_unregister(&layout_fabric); -} - -module_init(aoa_fabric_layout_init); -module_exit(aoa_fabric_layout_exit); |