Commit b75550e1 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt Committed by Linus Torvalds

[PATCH] pmac: sound support for latest laptops

This patch hacks the current Alsa snd-powermac driver to add support for
recent machine models with the tas3004 chip, that is basically new laptop
models.  The Mac Mini is _NOT_ yet supported by this patch (soon soon ...).
 The G5s (iMac or Desktop) will need the rewritten sound driver on which
I'm working on (I _might_ get a hack for analog only on some G5s on the
current driver, but no promise).
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 16b81757
...@@ -881,6 +881,7 @@ static int __init snd_pmac_detect(pmac_t *chip) ...@@ -881,6 +881,7 @@ static int __init snd_pmac_detect(pmac_t *chip)
{ {
struct device_node *sound; struct device_node *sound;
unsigned int *prop, l; unsigned int *prop, l;
u32 layout_id = 0;
if (_machine != _MACH_Pmac) if (_machine != _MACH_Pmac)
return -ENODEV; return -ENODEV;
...@@ -929,6 +930,9 @@ static int __init snd_pmac_detect(pmac_t *chip) ...@@ -929,6 +930,9 @@ static int __init snd_pmac_detect(pmac_t *chip)
prop = (unsigned int *) get_property(sound, "sub-frame", NULL); prop = (unsigned int *) get_property(sound, "sub-frame", NULL);
if (prop && *prop < 16) if (prop && *prop < 16)
chip->subframe = *prop; chip->subframe = *prop;
prop = (unsigned int *) get_property(sound, "layout-id", NULL);
if (prop)
layout_id = *prop;
/* This should be verified on older screamers */ /* This should be verified on older screamers */
if (device_is_compatible(sound, "screamer")) { if (device_is_compatible(sound, "screamer")) {
chip->model = PMAC_SCREAMER; chip->model = PMAC_SCREAMER;
...@@ -961,12 +965,22 @@ static int __init snd_pmac_detect(pmac_t *chip) ...@@ -961,12 +965,22 @@ static int __init snd_pmac_detect(pmac_t *chip)
chip->freq_table = tumbler_freqs; chip->freq_table = tumbler_freqs;
chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
} }
if (device_is_compatible(sound, "AOAKeylargo")) { if (device_is_compatible(sound, "AOAKeylargo") ||
/* Seems to support the stock AWACS frequencies, but has device_is_compatible(sound, "AOAbase")) {
a snapper mixer */ /* For now, only support very basic TAS3004 based machines with
* single frequency until proper i2s control is implemented
*/
switch(layout_id) {
case 0x48:
case 0x46:
case 0x33:
case 0x29:
chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
chip->model = PMAC_SNAPPER; chip->model = PMAC_SNAPPER;
// chip->can_byte_swap = 0; /* FIXME: check this */ chip->can_byte_swap = 0; /* FIXME: check this */
chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
break;
}
} }
prop = (unsigned int *)get_property(sound, "device-id", NULL); prop = (unsigned int *)get_property(sound, "device-id", NULL);
if (prop) if (prop)
......
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#include <asm/irq.h> #include <asm/irq.h>
#ifdef CONFIG_PPC_HAS_FEATURE_CALLS #ifdef CONFIG_PPC_HAS_FEATURE_CALLS
#include <asm/pmac_feature.h> #include <asm/pmac_feature.h>
#else
#error old crap
#endif #endif
#include "pmac.h" #include "pmac.h"
#include "tumbler_volume.h" #include "tumbler_volume.h"
...@@ -950,10 +952,10 @@ static struct device_node *find_compatible_audio_device(const char *name) ...@@ -950,10 +952,10 @@ static struct device_node *find_compatible_audio_device(const char *name)
} }
/* find an audio device and get its address */ /* find an audio device and get its address */
static unsigned long tumbler_find_device(const char *device, pmac_gpio_t *gp, int is_compatible) static long tumbler_find_device(const char *device, pmac_gpio_t *gp, int is_compatible)
{ {
struct device_node *node; struct device_node *node;
u32 *base; u32 *base, addr;
if (is_compatible) if (is_compatible)
node = find_compatible_audio_device(device); node = find_compatible_audio_device(device);
...@@ -966,21 +968,31 @@ static unsigned long tumbler_find_device(const char *device, pmac_gpio_t *gp, in ...@@ -966,21 +968,31 @@ static unsigned long tumbler_find_device(const char *device, pmac_gpio_t *gp, in
base = (u32 *)get_property(node, "AAPL,address", NULL); base = (u32 *)get_property(node, "AAPL,address", NULL);
if (! base) { if (! base) {
base = (u32 *)get_property(node, "reg", NULL);
if (!base) {
snd_printd("cannot find address for device %s\n", device); snd_printd("cannot find address for device %s\n", device);
return -ENODEV; return -ENODEV;
} }
/* this only work if PPC_HAS_FEATURE_CALLS is set as we
* are only getting the low part of the address
*/
addr = *base;
if (addr < 0x50)
addr += 0x50;
} else
addr = *base;
#ifdef CONFIG_PPC_HAS_FEATURE_CALLS #ifdef CONFIG_PPC_HAS_FEATURE_CALLS
gp->addr = (*base) & 0x0000ffff; gp->addr = addr & 0x0000ffff;
#else #else
gp->addr = ioremap((unsigned long)(*base), 1); gp->addr = ioremap((unsigned long)addr, 1);
#endif #endif
/* Try to find the active state, default to 0 ! */
base = (u32 *)get_property(node, "audio-gpio-active-state", NULL); base = (u32 *)get_property(node, "audio-gpio-active-state", NULL);
if (base) if (base)
gp->active_state = *base; gp->active_state = *base;
else else
gp->active_state = 1; gp->active_state = 0;
return (node->n_intrs > 0) ? node->intrs[0].line : 0; return (node->n_intrs > 0) ? node->intrs[0].line : 0;
} }
...@@ -1039,10 +1051,15 @@ static int __init tumbler_init(pmac_t *chip) ...@@ -1039,10 +1051,15 @@ static int __init tumbler_init(pmac_t *chip)
pmac_tumbler_t *mix = chip->mixer_data; pmac_tumbler_t *mix = chip->mixer_data;
snd_assert(mix, return -EINVAL); snd_assert(mix, return -EINVAL);
tumbler_find_device("audio-hw-reset", &mix->audio_reset, 0); if (tumbler_find_device("audio-hw-reset", &mix->audio_reset, 0) < 0)
tumbler_find_device("amp-mute", &mix->amp_mute, 0); tumbler_find_device("hw-reset", &mix->audio_reset, 1);
tumbler_find_device("headphone-mute", &mix->hp_mute, 0); if (tumbler_find_device("amp-mute", &mix->amp_mute, 0) < 0)
tumbler_find_device("amp-mute", &mix->amp_mute, 1);
if (tumbler_find_device("headphone-mute", &mix->hp_mute, 0) < 0)
tumbler_find_device("headphone-mute", &mix->hp_mute, 1);
irq = tumbler_find_device("headphone-detect", &mix->hp_detect, 0); irq = tumbler_find_device("headphone-detect", &mix->hp_detect, 0);
if (irq < 0)
irq = tumbler_find_device("headphone-detect", &mix->hp_detect, 1);
if (irq < 0) if (irq < 0)
irq = tumbler_find_device("keywest-gpio15", &mix->hp_detect, 1); irq = tumbler_find_device("keywest-gpio15", &mix->hp_detect, 1);
...@@ -1108,10 +1125,14 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) ...@@ -1108,10 +1125,14 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
/* set up TAS */ /* set up TAS */
tas_node = find_devices("deq"); tas_node = find_devices("deq");
if (tas_node == NULL)
tas_node = find_devices("codec");
if (tas_node == NULL) if (tas_node == NULL)
return -ENODEV; return -ENODEV;
paddr = (u32 *)get_property(tas_node, "i2c-address", NULL); paddr = (u32 *)get_property(tas_node, "i2c-address", NULL);
if (paddr == NULL)
paddr = (u32 *)get_property(tas_node, "reg", NULL);
if (paddr) if (paddr)
mix->i2c.addr = (*paddr) >> 1; mix->i2c.addr = (*paddr) >> 1;
else else
...@@ -1156,7 +1177,6 @@ int __init snd_pmac_tumbler_init(pmac_t *chip) ...@@ -1156,7 +1177,6 @@ int __init snd_pmac_tumbler_init(pmac_t *chip)
if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0)
return err; return err;
#ifdef CONFIG_PMAC_PBOOK #ifdef CONFIG_PMAC_PBOOK
chip->resume = tumbler_resume; chip->resume = tumbler_resume;
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment