diff options
Diffstat (limited to 'sound/aoa/fabrics')
| -rw-r--r-- | sound/aoa/fabrics/Kconfig | 1 | ||||
| -rw-r--r-- | sound/aoa/fabrics/Makefile | 2 | ||||
| -rw-r--r-- | sound/aoa/fabrics/layout.c (renamed from sound/aoa/fabrics/snd-aoa-fabric-layout.c) | 173 |
3 files changed, 122 insertions, 54 deletions
diff --git a/sound/aoa/fabrics/Kconfig b/sound/aoa/fabrics/Kconfig index c3bc7705c86..3ca475a886b 100644 --- a/sound/aoa/fabrics/Kconfig +++ b/sound/aoa/fabrics/Kconfig @@ -1,6 +1,5 @@ config SND_AOA_FABRIC_LAYOUT tristate "layout-id fabric" - depends SND_AOA select SND_AOA_SOUNDBUS select SND_AOA_SOUNDBUS_I2S ---help--- diff --git a/sound/aoa/fabrics/Makefile b/sound/aoa/fabrics/Makefile index 55fc5e7e52c..da37c10eca5 100644 --- a/sound/aoa/fabrics/Makefile +++ b/sound/aoa/fabrics/Makefile @@ -1 +1,3 @@ +snd-aoa-fabric-layout-objs += layout.o + obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/layout.c index 04a7238e949..9dc5806d23d 100644 --- a/sound/aoa/fabrics/snd-aoa-fabric-layout.c +++ b/sound/aoa/fabrics/layout.c @@ -1,19 +1,18 @@ /* - * Apple Onboard Audio driver -- layout fabric + * Apple Onboard Audio driver -- layout/machine id fabric * - * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> + * Copyright 2006-2008 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. - * + * This fabric module looks for sound codecs based on the + * layout-id or device-id property in the device tree. */ - #include <asm/prom.h> #include <linux/list.h> #include <linux/module.h> +#include <linux/slab.h> #include "../aoa.h" #include "../soundbus/soundbus.h" @@ -63,10 +62,10 @@ struct codec_connect_info { #define LAYOUT_FLAG_COMBO_LINEOUT_SPDIF (1<<0) struct layout { - unsigned int layout_id; + unsigned int layout_id, device_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. @@ -77,23 +76,44 @@ struct layout { 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"); + +MODULE_ALIAS("aoa-device-id-14"); +MODULE_ALIAS("aoa-device-id-22"); +MODULE_ALIAS("aoa-device-id-35"); +MODULE_ALIAS("aoa-device-id-44"); /* onyx with all but microphone connected */ static struct codec_connection onyx_connections_nomic[] = { @@ -342,6 +362,13 @@ static struct layout layouts[] = { .connections = tas_connections_nolineout, }, }, + /* PowerBook6,5 */ + { .device_id = 44, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_all, + }, + }, /* PowerBook6,7 */ { .layout_id = 80, .codecs[0] = { @@ -381,6 +408,13 @@ static struct layout layouts[] = { .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] = { @@ -479,12 +513,6 @@ static struct layout layouts[] = { .connections = onyx_connections_noheadphones, }, }, - { .layout_id = 96, - .codecs[0] = { - .name = "onyx", - .connections = onyx_connections_noheadphones, - }, - }, { .layout_id = 98, .codecs[0] = { .name = "toonie", @@ -501,6 +529,27 @@ static struct layout layouts[] = { .connections = onyx_connections_noheadphones, }, }, + /* PowerMac3,4 */ + { .device_id = 14, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_noline, + }, + }, + /* PowerMac3,6 */ + { .device_id = 22, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_all, + }, + }, + /* PowerBook5,2 */ + { .device_id = 35, + .codecs[0] = { + .name = "tas", + .connections = tas_connections_all, + }, + }, {} }; @@ -509,7 +558,7 @@ static struct layout *find_layout_by_id(unsigned int id) struct layout *l; l = layouts; - while (l->layout_id) { + while (l->codecs[0].name) { if (l->layout_id == id) return l; l++; @@ -517,6 +566,19 @@ static struct layout *find_layout_by_id(unsigned int id) return NULL; } +static struct layout *find_layout_by_device(unsigned int id) +{ + struct layout *l; + + l = layouts; + while (l->codecs[0].name) { + if (l->device_id == id) + return l; + l++; + } + return NULL; +} + static void use_layout(struct layout *l) { int i; @@ -547,6 +609,7 @@ struct layout_dev { struct snd_kcontrol *headphone_ctrl; struct snd_kcontrol *lineout_ctrl; struct snd_kcontrol *speaker_ctrl; + struct snd_kcontrol *master_ctrl; struct snd_kcontrol *headphone_detected_ctrl; struct snd_kcontrol *lineout_detected_ctrl; @@ -565,15 +628,7 @@ static int layouts_list_items; * make the fabric handle all the card stuff, etc... */ static struct layout_dev *layout_device; -static int control_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - return 0; -} +#define control_info snd_ctl_boolean_mono_info #define AMP_CONTROL(n, description) \ static int n##_control_get(struct snd_kcontrol *kcontrol, \ @@ -589,9 +644,9 @@ 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) \ + if (gpio->methods && gpio->methods->set_##n) \ gpio->methods->set_##n(gpio, \ - ucontrol->value.integer.value[0]); \ + !!ucontrol->value.integer.value[0]); \ return 1; \ } \ static struct snd_kcontrol_new n##_ctl = { \ @@ -606,6 +661,7 @@ static struct snd_kcontrol_new n##_ctl = { \ AMP_CONTROL(headphone, "Headphone Switch"); AMP_CONTROL(speakers, "Speakers Switch"); AMP_CONTROL(lineout, "Line-Out Switch"); +AMP_CONTROL(master, "Master Switch"); static int detect_choice_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -707,7 +763,7 @@ static int check_codec(struct aoa_codec *codec, struct layout_dev *ldev, struct codec_connect_info *cci) { - u32 *ref; + const u32 *ref; char propname[32]; struct codec_connection *cc; @@ -715,13 +771,13 @@ static int check_codec(struct aoa_codec *codec, if (codec->node && (strcmp(codec->node->name, "codec") == 0)) { snprintf(propname, sizeof(propname), "platform-%s-codec-ref", codec->name); - ref = (u32*)get_property(ldev->sound, propname, NULL); + 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) { + if (*ref != codec->node->phandle) { printk(KERN_INFO "snd-aoa-fabric-layout: " "%s doesn't match!\n", propname); return -ENODEV; @@ -846,6 +902,11 @@ static void layout_attached_codec(struct aoa_codec *codec) lineout = codec->gpio->methods->get_detect(codec->gpio, AOA_NOTIFY_LINE_OUT); + if (codec->gpio->methods->set_master) { + ctl = snd_ctl_new1(&master_ctl, codec->gpio); + ldev->master_ctrl = ctl; + aoa_snd_ctl_add(ctl); + } while (cc->connected) { if (cc->connected & CC_SPEAKERS) { if (headphones <= 0 && lineout <= 0) @@ -929,8 +990,8 @@ static struct aoa_fabric layout_fabric = { static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) { struct device_node *sound = NULL; - unsigned int *layout_id; - struct layout *layout; + const unsigned int *id; + struct layout *layout = NULL; struct layout_dev *ldev = NULL; int err; @@ -939,20 +1000,24 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) return -ENODEV; /* by breaking out we keep a reference */ - while ((sound = of_get_next_child(sdev->ofdev.node, sound))) { + while ((sound = of_get_next_child(sdev->ofdev.dev.of_node, sound))) { if (sound->type && strcasecmp(sound->type, "soundchip") == 0) break; } - if (!sound) return -ENODEV; + if (!sound) + return -ENODEV; - layout_id = (unsigned int *) get_property(sound, "layout-id", NULL); - if (!layout_id) - goto outnodev; - printk(KERN_INFO "snd-aoa-fabric-layout: found bus with layout %d ", *layout_id); + id = of_get_property(sound, "layout-id", NULL); + if (id) { + layout = find_layout_by_id(*id); + } else { + id = of_get_property(sound, "device-id", NULL); + if (id) + layout = find_layout_by_device(*id); + } - layout = find_layout_by_id(*layout_id); if (!layout) { - printk("(no idea how to handle)\n"); + printk(KERN_ERR "snd-aoa-fabric-layout: unknown layout\n"); goto outnodev; } @@ -966,19 +1031,22 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) ldev->layout = layout; ldev->gpio.node = sound->parent; switch (layout->layout_id) { + case 0: /* anything with device_id, not 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; - - printk("(using)\n"); + dev_set_drvdata(&sdev->ofdev.dev, ldev); list_add(&ldev->list, &layouts_list); layouts_list_items++; @@ -994,7 +1062,7 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) ldev->gpio.methods->init(&ldev->gpio); - err = aoa_fabric_register(&layout_fabric); + 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"); @@ -1013,16 +1081,16 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev) sdev->pcmid = -1; list_del(&ldev->list); layouts_list_items--; + kfree(ldev); outnodev: - if (sound) of_node_put(sound); + of_node_put(sound); layout_device = NULL; - if (ldev) kfree(ldev); return -ENODEV; } static int aoa_fabric_layout_remove(struct soundbus_dev *sdev) { - struct layout_dev *ldev = sdev->ofdev.dev.driver_data; + struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); int i; for (i=0; i<MAX_CODECS_PER_BUS; i++) { @@ -1055,9 +1123,7 @@ static int aoa_fabric_layout_remove(struct soundbus_dev *sdev) #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; - - printk("aoa_fabric_layout_suspend()\n"); + struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) ldev->gpio.methods->all_amps_off(&ldev->gpio); @@ -1067,11 +1133,9 @@ static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t sta static int aoa_fabric_layout_resume(struct soundbus_dev *sdev) { - struct layout_dev *ldev = sdev->ofdev.dev.driver_data; + struct layout_dev *ldev = dev_get_drvdata(&sdev->ofdev.dev); - printk("aoa_fabric_layout_resume()\n"); - - if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) + if (ldev->gpio.methods && ldev->gpio.methods->all_amps_restore) ldev->gpio.methods->all_amps_restore(&ldev->gpio); return 0; @@ -1087,6 +1151,9 @@ static struct soundbus_driver aoa_soundbus_driver = { .suspend = aoa_fabric_layout_suspend, .resume = aoa_fabric_layout_resume, #endif + .driver = { + .owner = THIS_MODULE, + } }; static int __init aoa_fabric_layout_init(void) |
