[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: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
16b817579f
Коммит
b75550e1bc
|
@ -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)
|
||||||
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)
|
||||||
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
|
||||||
chip->model = PMAC_SNAPPER;
|
* single frequency until proper i2s control is implemented
|
||||||
// chip->can_byte_swap = 0; /* FIXME: check this */
|
*/
|
||||||
chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
|
switch(layout_id) {
|
||||||
|
case 0x48:
|
||||||
|
case 0x46:
|
||||||
|
case 0x33:
|
||||||
|
case 0x29:
|
||||||
|
chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
|
||||||
|
chip->model = PMAC_SNAPPER;
|
||||||
|
chip->can_byte_swap = 0; /* FIXME: check this */
|
||||||
|
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 @@
|
||||||
#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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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
|
||||||
|
|
||||||
base = (u32 *)get_property(node, "AAPL,address", NULL);
|
base = (u32 *)get_property(node, "AAPL,address", NULL);
|
||||||
if (! base) {
|
if (! base) {
|
||||||
snd_printd("cannot find address for device %s\n", device);
|
base = (u32 *)get_property(node, "reg", NULL);
|
||||||
return -ENODEV;
|
if (!base) {
|
||||||
}
|
snd_printd("cannot find address for device %s\n", device);
|
||||||
|
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)
|
||||||
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)
|
||||||
|
|
||||||
/* 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)
|
||||||
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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче