Sven Luther <[EMAIL PROTECTED]> wrote: Hi Sven,
>> Use filterdiff (patchutils) to filter the changes made to sound/ppc/*, >> and here's your diff. > > I am over busy with other stuff right now, but would you care to do this and > send me the patch (or fill a bug report) ? Here it is. beep.patch contains everything related to the beep support. chips.patch contains the other changes to the files in sound/ppc, which are bugfixes and new features for the awacs, daca, tumbler and burgundy chips. The changes in chips.patch are minimal, you could apply them too without any problem. I didn't try to build with the patches applied (lacking time), but reading the diff there's nothing that should break. JB. -- Julien BLACHE - Debian & GNU/Linux Developer - <[EMAIL PROTECTED]> Public key available on <http://www.jblache.org> - KeyID: F5D6 5169 GPG Fingerprint : 935A 79F1 C8B3 3521 FD62 7CC7 CD61 4FD7 F5D6 5169
--- linux-2.5-plain/sound/ppc/beep.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-sound-plain/sound/ppc/beep.c 2004-08-26 21:17:10.000000000 +0200 @@ -0,0 +1,262 @@ +/* + * Beep using pcm + * + * Copyright (c) by Takashi Iwai <[EMAIL PROTECTED]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <sound/driver.h> +#include <asm/io.h> +#include <asm/irq.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/input.h> +#include <sound/core.h> +#include <sound/control.h> +#include "pmac.h" + +struct snd_pmac_beep { + int running; /* boolean */ + int volume; /* mixer volume: 0-100 */ + int volume_play; /* currently playing volume */ + int hz; + int nsamples; + short *buf; /* allocated wave buffer */ + unsigned long addr; /* physical address of buffer */ + struct input_dev dev; +}; + +/* + * stop beep if running + */ +void snd_pmac_beep_stop(pmac_t *chip) +{ + pmac_beep_t *beep = chip->beep; + if (beep && beep->running) { + beep->running = 0; + snd_pmac_beep_dma_stop(chip); + } +} + +/* + * Stuff for outputting a beep. The values range from -327 to +327 + * so we can multiply by an amplitude in the range 0..100 to get a + * signed short value to put in the output buffer. + */ +static short beep_wform[256] = { + 0, 40, 79, 117, 153, 187, 218, 245, + 269, 288, 304, 316, 323, 327, 327, 324, + 318, 310, 299, 288, 275, 262, 249, 236, + 224, 213, 204, 196, 190, 186, 183, 182, + 182, 183, 186, 189, 192, 196, 200, 203, + 206, 208, 209, 209, 209, 207, 204, 201, + 197, 193, 188, 183, 179, 174, 170, 166, + 163, 161, 160, 159, 159, 160, 161, 162, + 164, 166, 168, 169, 171, 171, 171, 170, + 169, 167, 163, 159, 155, 150, 144, 139, + 133, 128, 122, 117, 113, 110, 107, 105, + 103, 103, 103, 103, 104, 104, 105, 105, + 105, 103, 101, 97, 92, 86, 78, 68, + 58, 45, 32, 18, 3, -11, -26, -41, + -55, -68, -79, -88, -95, -100, -102, -102, + -99, -93, -85, -75, -62, -48, -33, -16, + 0, 16, 33, 48, 62, 75, 85, 93, + 99, 102, 102, 100, 95, 88, 79, 68, + 55, 41, 26, 11, -3, -18, -32, -45, + -58, -68, -78, -86, -92, -97, -101, -103, + -105, -105, -105, -104, -104, -103, -103, -103, + -103, -105, -107, -110, -113, -117, -122, -128, + -133, -139, -144, -150, -155, -159, -163, -167, + -169, -170, -171, -171, -171, -169, -168, -166, + -164, -162, -161, -160, -159, -159, -160, -161, + -163, -166, -170, -174, -179, -183, -188, -193, + -197, -201, -204, -207, -209, -209, -209, -208, + -206, -203, -200, -196, -192, -189, -186, -183, + -182, -182, -183, -186, -190, -196, -204, -213, + -224, -236, -249, -262, -275, -288, -299, -310, + -318, -324, -327, -327, -323, -316, -304, -288, + -269, -245, -218, -187, -153, -117, -79, -40, +}; + +#define BEEP_SRATE 22050 /* 22050 Hz sample rate */ +#define BEEP_BUFLEN 512 +#define BEEP_VOLUME 15 /* 0 - 100 */ + +static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, unsigned int code, int hz) +{ + pmac_t *chip; + pmac_beep_t *beep; + unsigned long flags; + int beep_speed = 0; + int srate; + int period, ncycles, nsamples; + int i, j, f; + short *p; + + if (type != EV_SND) + return -1; + + switch (code) { + case SND_BELL: if (hz) hz = 1000; + case SND_TONE: break; + default: return -1; + } + + chip = dev->private; + if (! chip || (beep = chip->beep) == NULL) + return -1; + + if (! hz) { + spin_lock_irqsave(&chip->reg_lock, flags); + if (beep->running) + snd_pmac_beep_stop(chip); + spin_unlock_irqrestore(&chip->reg_lock, flags); + return 0; + } + + beep_speed = snd_pmac_rate_index(chip, &chip->playback, BEEP_SRATE); + srate = chip->freq_table[beep_speed]; + + if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) + hz = 1000; + + spin_lock_irqsave(&chip->reg_lock, flags); + if (chip->playback.running || chip->capture.running || beep->running) { + spin_unlock_irqrestore(&chip->reg_lock, flags); + return 0; + } + beep->running = 1; + spin_unlock_irqrestore(&chip->reg_lock, flags); + + if (hz == beep->hz && beep->volume == beep->volume_play) { + nsamples = beep->nsamples; + } else { + period = srate * 256 / hz; /* fixed point */ + ncycles = BEEP_BUFLEN * 256 / period; + nsamples = (period * ncycles) >> 8; + f = ncycles * 65536 / nsamples; + j = 0; + p = beep->buf; + for (i = 0; i < nsamples; ++i, p += 2) { + p[0] = p[1] = beep_wform[j >> 8] * beep->volume; + j = (j + f) & 0xffff; + } + beep->hz = hz; + beep->volume_play = beep->volume; + beep->nsamples = nsamples; + } + + spin_lock_irqsave(&chip->reg_lock, flags); + snd_pmac_beep_dma_start(chip, beep->nsamples * 4, beep->addr, beep_speed); + spin_unlock_irqrestore(&chip->reg_lock, flags); + return 0; +} + +/* + * beep volume mixer + */ + +#define chip_t pmac_t + +static int snd_pmac_info_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 1; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 100; + return 0; +} + +static int snd_pmac_get_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + pmac_t *chip = snd_kcontrol_chip(kcontrol); + snd_assert(chip->beep, return -ENXIO); + ucontrol->value.integer.value[0] = chip->beep->volume; + return 0; +} + +static int snd_pmac_put_beep(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) +{ + pmac_t *chip = snd_kcontrol_chip(kcontrol); + int oval; + snd_assert(chip->beep, return -ENXIO); + oval = chip->beep->volume; + chip->beep->volume = ucontrol->value.integer.value[0]; + return oval != chip->beep->volume; +} + +static snd_kcontrol_new_t snd_pmac_beep_mixer = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Beep Playback Volume", + .info = snd_pmac_info_beep, + .get = snd_pmac_get_beep, + .put = snd_pmac_put_beep, +}; + +/* Initialize beep stuff */ +int __init snd_pmac_attach_beep(pmac_t *chip) +{ + pmac_beep_t *beep; + int err; + + beep = kmalloc(sizeof(*beep), GFP_KERNEL); + if (! beep) + return -ENOMEM; + + memset(beep, 0, sizeof(*beep)); + beep->buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL); + if (! beep->buf) { + kfree(beep); + return -ENOMEM; + } + beep->addr = virt_to_bus(beep->buf); + + beep->dev.evbit[0] = BIT(EV_SND); + beep->dev.sndbit[0] = BIT(SND_BELL) | BIT(SND_TONE); + beep->dev.event = snd_pmac_beep_event; + beep->dev.private = chip; + + /* FIXME: set more better values */ + beep->dev.name = "PowerMac Beep"; + beep->dev.phys = "powermac/beep"; + beep->dev.id.bustype = BUS_ADB; + beep->dev.id.vendor = 0x001f; + beep->dev.id.product = 0x0001; + beep->dev.id.version = 0x0100; + + beep->volume = BEEP_VOLUME; + beep->running = 0; + if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_beep_mixer, chip))) < 0) { + kfree(beep->buf); + kfree(beep); + return err; + } + + chip->beep = beep; + input_register_device(&beep->dev); + + return 0; +} + +void snd_pmac_detach_beep(pmac_t *chip) +{ + if (chip->beep) { + input_unregister_device(&chip->beep->dev); + kfree(chip->beep->buf); + kfree(chip->beep); + chip->beep = NULL; + } +} --- linux-2.5-plain/sound/ppc/Kconfig 2004-08-26 21:01:50.000000000 +0200 +++ linux-sound-plain/sound/ppc/Kconfig 2004-08-26 21:16:11.000000000 +0200 @@ -6,9 +6,12 @@ comment "ALSA PowerMac requires I2C" depends on SND && I2C=n +comment "ALSA PowerMac requires INPUT" + depends on SND && INPUT=n + config SND_POWERMAC tristate "PowerMac (AWACS, DACA, Burgundy, Tumbler, Keywest)" - depends on SND && I2C + depends on SND && I2C && INPUT select SND_PCM endmenu --- linux-2.5-plain/sound/ppc/Makefile 2004-08-26 21:01:48.000000000 +0200 +++ linux-sound-plain/sound/ppc/Makefile 2004-08-26 21:16:09.000000000 +0200 @@ -3,7 +3,7 @@ # Copyright (c) 2001 by Jaroslav Kysela <[EMAIL PROTECTED]> # -snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o +snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o # Toplevel Module Dependency obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o --- linux-2.5-plain/sound/ppc/pmac.c 2004-08-26 21:05:32.000000000 +0200 +++ linux-sound-plain/sound/ppc/pmac.c 2004-08-26 21:20:59.000000000 +0200 @@ -36,8 +36,6 @@ #include <asm/feature.h> #endif -#define chip_t pmac_t - #if defined(CONFIG_PM) && defined(CONFIG_PMAC_PBOOK) static int snd_pmac_register_sleep_notifier(pmac_t *chip); @@ -52,8 +50,8 @@ 44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350 }; /* fixed frequency table for tumbler */ -static int tumbler_freqs[2] = { - 48000, 44100 +static int tumbler_freqs[1] = { + 44100 }; /* @@ -86,7 +84,7 @@ * look up frequency table */ -static unsigned int snd_pmac_rate_index(pmac_t *chip, pmac_stream_t *rec, unsigned int rate) +unsigned int snd_pmac_rate_index(pmac_t *chip, pmac_stream_t *rec, unsigned int rate) { int i, ok, found; @@ -203,7 +201,6 @@ { int i; volatile struct dbdma_cmd *cp; - unsigned long flags; snd_pcm_runtime_t *runtime = subs->runtime; int rate_index; long offset; @@ -226,15 +223,17 @@ /* We really want to execute a DMA stop command, after the AWACS * is initialized. * For reasons I don't understand, it stops the hissing noise - * common to many PowerBook G3 systems (like mine :-). + * common to many PowerBook G3 systems and random noise otherwise + * captured on iBook2's about every third time. -ReneR */ - spin_lock_irqsave(&chip->reg_lock, flags); + spin_lock_irq(&chip->reg_lock); snd_pmac_dma_stop(rec); - if (rec->stream == SNDRV_PCM_STREAM_PLAYBACK) { - st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP); - snd_pmac_dma_set_command(rec, &chip->extra_dma); - snd_pmac_dma_run(rec, RUN); - } + st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP); + snd_pmac_dma_set_command(rec, &chip->extra_dma); + snd_pmac_dma_run(rec, RUN); + spin_unlock_irq(&chip->reg_lock); + mdelay(5); + spin_lock_irq(&chip->reg_lock); /* continuous DMA memory type doesn't provide the physical address, * so we need to resolve the address here... */ @@ -252,7 +251,7 @@ snd_pmac_dma_stop(rec); snd_pmac_dma_set_command(rec, &rec->cmd); - spin_unlock_irqrestore(&chip->reg_lock, flags); + spin_unlock_irq(&chip->reg_lock); return 0; } @@ -264,7 +263,6 @@ static int snd_pmac_pcm_trigger(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substream_t *subs, int cmd) { - unsigned long flags; volatile struct dbdma_cmd *cp; int i, command; @@ -275,7 +273,7 @@ return -EBUSY; command = (subs->stream == SNDRV_PCM_STREAM_PLAYBACK ? OUTPUT_MORE : INPUT_MORE) + INTR_ALWAYS; - spin_lock_irqsave(&chip->reg_lock, flags); + spin_lock(&chip->reg_lock); snd_pmac_beep_stop(chip); snd_pmac_pcm_set_format(chip); for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) @@ -284,18 +282,18 @@ (void)in_le32(&rec->dma->status); snd_pmac_dma_run(rec, RUN|WAKE); rec->running = 1; - spin_unlock_irqrestore(&chip->reg_lock, flags); + spin_unlock(&chip->reg_lock); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: - spin_lock_irqsave(&chip->reg_lock, flags); + spin_lock(&chip->reg_lock); rec->running = 0; /*printk("stopped!!\n");*/ snd_pmac_dma_stop(rec); for (i = 0, cp = rec->cmd.cmds; i < rec->nperiods; i++, cp++) out_le16(&cp->command, DBDMA_STOP); - spin_unlock_irqrestore(&chip->reg_lock, flags); + spin_unlock(&chip->reg_lock); break; default: @@ -490,14 +488,12 @@ snd_pcm_runtime_t *runtime = subs->runtime; int i, j, fflags; static int typical_freqs[] = { - 48000, 44100, 22050, 11025, 0, }; static int typical_freq_flags[] = { - SNDRV_PCM_RATE_48000, SNDRV_PCM_RATE_44100, SNDRV_PCM_RATE_22050, SNDRV_PCM_RATE_11025, @@ -651,7 +647,7 @@ pcm->private_data = chip; pcm->private_free = pmac_pcm_free; - pcm->info_flags = 0; + pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; strcpy(pcm->name, chip->card->shortname); chip->pcm = pcm; @@ -683,12 +679,41 @@ /* + * handling beep + */ +void snd_pmac_beep_dma_start(pmac_t *chip, int bytes, unsigned long addr, int speed) +{ + pmac_stream_t *rec = &chip->playback; + + snd_pmac_dma_stop(rec); + st_le16(&chip->extra_dma.cmds->req_count, bytes); + st_le16(&chip->extra_dma.cmds->xfer_status, 0); + st_le32(&chip->extra_dma.cmds->cmd_dep, chip->extra_dma.addr); + st_le32(&chip->extra_dma.cmds->phy_addr, addr); + st_le16(&chip->extra_dma.cmds->command, OUTPUT_MORE + BR_ALWAYS); + out_le32(&chip->awacs->control, + (in_le32(&chip->awacs->control) & ~0x1f00) + | (speed << 8)); + out_le32(&chip->awacs->byteswap, 0); + snd_pmac_dma_set_command(rec, &chip->extra_dma); + snd_pmac_dma_run(rec, RUN); +} + +void snd_pmac_beep_dma_stop(pmac_t *chip) +{ + snd_pmac_dma_stop(&chip->playback); + st_le16(&chip->extra_dma.cmds->command, DBDMA_STOP); + snd_pmac_pcm_set_format(chip); /* reset format */ +} + + +/* * interrupt handlers */ static irqreturn_t snd_pmac_tx_intr(int irq, void *devid, struct pt_regs *regs) { - pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE); + pmac_t *chip = devid; snd_pmac_pcm_update(chip, &chip->playback); return IRQ_HANDLED; } @@ -697,7 +722,7 @@ static irqreturn_t snd_pmac_rx_intr(int irq, void *devid, struct pt_regs *regs) { - pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE); + pmac_t *chip = devid; snd_pmac_pcm_update(chip, &chip->capture); return IRQ_HANDLED; } @@ -706,7 +731,7 @@ static irqreturn_t snd_pmac_ctrl_intr(int irq, void *devid, struct pt_regs *regs) { - pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE); + pmac_t *chip = devid; int ctrl = in_le32(&chip->awacs->control); /*printk("pmac: control interrupt.. 0x%x\n", ctrl);*/ @@ -776,6 +801,8 @@ if (chip->mixer_free) chip->mixer_free(chip); + snd_pmac_detach_beep(chip); + /* release resources */ if (chip->irq >= 0) free_irq(chip->irq, (void*)chip); @@ -802,7 +829,7 @@ release_OF_resource(chip->node, i); } } - snd_magic_kfree(chip); + kfree(chip); return 0; } @@ -812,7 +839,7 @@ */ static int snd_pmac_dev_free(snd_device_t *device) { - pmac_t *chip = snd_magic_cast(pmac_t, device->device_data, return -ENXIO); + pmac_t *chip = device->device_data; return snd_pmac_free(chip); } @@ -862,7 +889,7 @@ chip->can_byte_swap = 1; chip->can_duplex = 1; chip->can_capture = 1; - chip->num_freqs = 8; + chip->num_freqs = ARRAY_SIZE(awacs_freqs); chip->freq_table = awacs_freqs; chip->control_mask = MASK_IEPC | MASK_IEE | 0x11; /* default */ @@ -920,14 +947,14 @@ chip->can_capture = 0; /* no capture */ chip->can_duplex = 0; // chip->can_byte_swap = 0; /* FIXME: check this */ - chip->num_freqs = 2; + chip->num_freqs = ARRAY_SIZE(tumbler_freqs); chip->freq_table = tumbler_freqs; chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ } if (device_is_compatible(sound, "snapper")) { chip->model = PMAC_SNAPPER; // chip->can_byte_swap = 0; /* FIXME: check this */ - chip->num_freqs = 2; + chip->num_freqs = ARRAY_SIZE(tumbler_freqs); chip->freq_table = tumbler_freqs; chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */ } @@ -1069,7 +1096,7 @@ snd_runtime_check(chip_return, return -EINVAL); *chip_return = NULL; - chip = snd_magic_kcalloc(pmac_t, 0, GFP_KERNEL); + chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); if (chip == NULL) return -ENOMEM; chip->card = card; @@ -1206,7 +1233,7 @@ static int snd_pmac_suspend(snd_card_t *card, unsigned int state) { - pmac_t *chip = snd_magic_cast(pmac_t, card->pm_private_data, return -EINVAL); + pmac_t *chip = card->pm_private_data; unsigned long flags; if (chip->suspend) @@ -1228,7 +1255,7 @@ static int snd_pmac_resume(snd_card_t *card, unsigned int state) { - pmac_t *chip = snd_magic_cast(pmac_t, card->pm_private_data, return -EINVAL); + pmac_t *chip = card->pm_private_data; snd_pmac_sound_feature(chip, 1); if (chip->resume) --- linux-2.5-plain/sound/ppc/pmac.h 2004-08-26 21:03:12.000000000 +0200 +++ linux-sound-plain/sound/ppc/pmac.h 2004-08-26 21:18:00.000000000 +0200 @@ -84,7 +84,7 @@ snd_pcm_substream_t *substream; - unsigned int cur_freqs; /* currently available frequences */ + unsigned int cur_freqs; /* currently available frequencies */ unsigned int cur_formats; /* currently available formats */ }; @@ -155,6 +155,7 @@ void (*mixer_free)(pmac_t *); snd_kcontrol_t *master_sw_ctl; snd_kcontrol_t *speaker_sw_ctl; + snd_kcontrol_t *drc_sw_ctl; /* only used for tumbler -ReneR */ snd_kcontrol_t *hp_detect_ctl; /* lowlevel callbacks */ @@ -173,6 +174,12 @@ int snd_pmac_new(snd_card_t *card, pmac_t **chip_return); int snd_pmac_pcm_new(pmac_t *chip); int snd_pmac_attach_beep(pmac_t *chip); +void snd_pmac_detach_beep(pmac_t *chip); +void snd_pmac_beep_stop(pmac_t *chip); +unsigned int snd_pmac_rate_index(pmac_t *chip, pmac_stream_t *rec, unsigned int rate); + +void snd_pmac_beep_dma_start(pmac_t *chip, int bytes, unsigned long addr, int speed); +void snd_pmac_beep_dma_stop(pmac_t *chip); /* initialize mixer */ int snd_pmac_awacs_init(pmac_t *chip); @@ -206,9 +213,4 @@ schedule_timeout(((msec) * HZ + 999) / 1000);\ } while (0) -#ifndef PMAC_SUPPORT_PCM_BEEP -#define snd_pmac_attach_beep(chip) 0 -#define snd_pmac_beep_stop(chip) /**/ -#endif - #endif /* __PMAC_H */ --- linux-2.5-plain/sound/ppc/powermac.c 2004-08-26 21:05:28.000000000 +0200 +++ linux-sound-plain/sound/ppc/powermac.c 2004-08-26 21:20:52.000000000 +0200 @@ -30,31 +30,19 @@ #define CHIP_NAME "PMac" MODULE_DESCRIPTION("PowerMac"); -MODULE_CLASSES("{sound}"); -MODULE_DEVICES("{{Apple,PowerMac}}"); +MODULE_SUPPORTED_DEVICE("{{Apple,PowerMac}}"); MODULE_LICENSE("GPL"); static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ -/* static int enable = 1; */ -#ifdef PMAC_SUPPORT_PCM_BEEP static int enable_beep = 1; -#endif module_param(index, int, 0444); MODULE_PARM_DESC(index, "Index value for " CHIP_NAME " soundchip."); -MODULE_PARM_SYNTAX(index, SNDRV_INDEX_DESC); module_param(id, charp, 0444); MODULE_PARM_DESC(id, "ID string for " CHIP_NAME " soundchip."); -MODULE_PARM_SYNTAX(id, SNDRV_ID_DESC); -/* module_param(enable, bool, 0444); - MODULE_PARM_DESC(enable, "Enable this soundchip."); - MODULE_PARM_SYNTAX(enable, SNDRV_ENABLE_DESC); */ -#ifdef PMAC_SUPPORT_PCM_BEEP module_param(enable_beep, bool, 0444); MODULE_PARM_DESC(enable_beep, "Enable beep using PCM."); -MODULE_PARM_SYNTAX(enable_beep, SNDRV_ENABLED "," SNDRV_BOOLEAN_TRUE_DESC); -#endif /* @@ -133,10 +121,8 @@ goto __error; chip->initialized = 1; -#ifdef PMAC_SUPPORT_PCM_BEEP if (enable_beep) snd_pmac_attach_beep(chip); -#endif if ((err = snd_card_register(card)) < 0) goto __error; @@ -151,18 +137,14 @@ /* - * MODULE sutff + * MODULE stuff */ static int __init alsa_card_pmac_init(void) { int err; - if ((err = snd_pmac_probe()) < 0) { -#ifdef MODULE - printk(KERN_ERR "no PMac soundchip found\n"); -#endif + if ((err = snd_pmac_probe()) < 0) return err; - } return 0; }
--- linux-2.5-plain/sound/ppc/awacs.c 2004-08-26 21:02:24.000000000 +0200 +++ linux-sound-plain/sound/ppc/awacs.c 2004-08-26 21:16:57.000000000 +0200 @@ -29,8 +29,6 @@ #include <sound/core.h> #include "pmac.h" -#define chip_t pmac_t - #ifdef CONFIG_ADB_CUDA #define PMAC_AMP_AVAIL @@ -574,11 +572,22 @@ AWACS_VOLUME("Master Playback Volume", 2, 6, 1), AWACS_SWITCH("Master Capture Switch", 1, SHIFT_LOOPTHRU, 0), AWACS_VOLUME("Capture Volume", 0, 4, 0), - AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0), AWACS_SWITCH("CD Capture Switch", 0, SHIFT_MUX_CD, 0), +}; + +/* FIXME: is this correct order? + * screamer (powerbook G3 pismo) seems to have different bits... + */ +static snd_kcontrol_new_t snd_pmac_awacs_mixers2[] __initdata = { + AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_LINE, 0), AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_MIC, 0), }; +static snd_kcontrol_new_t snd_pmac_screamer_mixers2[] __initdata = { + AWACS_SWITCH("Line Capture Switch", 0, SHIFT_MUX_MIC, 0), + AWACS_SWITCH("Mic Capture Switch", 0, SHIFT_MUX_LINE, 0), +}; + static snd_kcontrol_new_t snd_pmac_awacs_master_sw __initdata = AWACS_SWITCH("Master Playback Switch", 1, SHIFT_HDMUTE, 1); @@ -602,8 +611,6 @@ AWACS_SWITCH("PC Speaker Playback Switch", 1, SHIFT_SPKMUTE, 1); -#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t)) - /* * add new mixer elements to the card */ @@ -818,9 +825,17 @@ */ strcpy(chip->card->mixername, "PowerMac AWACS"); - if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_mixers), + if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers), snd_pmac_awacs_mixers)) < 0) return err; + if (chip->model == PMAC_SCREAMER) + err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mixers2), + snd_pmac_screamer_mixers2); + else + err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mixers2), + snd_pmac_awacs_mixers2); + if (err < 0) + return err; chip->master_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_master_sw, chip); if ((err = snd_ctl_add(chip->card, chip->master_sw_ctl)) < 0) return err; @@ -832,7 +847,7 @@ * screamer registers. * in this case, it seems the route C is not used. */ - if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_amp_vol), + if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_amp_vol), snd_pmac_awacs_amp_vol)) < 0) return err; /* overwrite */ @@ -846,7 +861,7 @@ #endif /* PMAC_AMP_AVAIL */ { /* route A = headphone, route C = speaker */ - if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_speaker_vol), + if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_speaker_vol), snd_pmac_awacs_speaker_vol)) < 0) return err; chip->speaker_sw_ctl = snd_ctl_new1(&snd_pmac_awacs_speaker_sw, chip); @@ -855,11 +870,11 @@ } if (chip->model == PMAC_SCREAMER) { - if ((err = build_mixers(chip, num_controls(snd_pmac_screamer_mic_boost), + if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_screamer_mic_boost), snd_pmac_screamer_mic_boost)) < 0) return err; } else { - if ((err = build_mixers(chip, num_controls(snd_pmac_awacs_mic_boost), + if ((err = build_mixers(chip, ARRAY_SIZE(snd_pmac_awacs_mic_boost), snd_pmac_awacs_mic_boost)) < 0) return err; } --- linux-2.5-plain/sound/ppc/burgundy.c 2004-08-26 21:01:31.000000000 +0200 +++ linux-sound-plain/sound/ppc/burgundy.c 2004-08-26 21:15:31.000000000 +0200 @@ -28,8 +28,6 @@ #include "pmac.h" #include "burgundy.h" -#define chip_t pmac_t - /* Waits for busy flag to clear */ inline static void @@ -324,8 +322,6 @@ static snd_kcontrol_new_t snd_pmac_burgundy_speaker_sw __initdata = BURGUNDY_OUTPUT_SWITCH("PC Speaker Playback Switch", 0, BURGUNDY_OUTPUT_INTERN, 0, 0); -#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t)) - #ifdef PMAC_SUPPORT_AUTOMUTE /* @@ -420,7 +416,7 @@ */ strcpy(chip->card->mixername, "PowerMac Burgundy"); - for (i = 0; i < num_controls(snd_pmac_burgundy_mixers); i++) { + for (i = 0; i < ARRAY_SIZE(snd_pmac_burgundy_mixers); i++) { if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_pmac_burgundy_mixers[i], chip))) < 0) return err; } --- linux-2.5-plain/sound/ppc/daca.c 2004-08-26 21:01:02.000000000 +0200 +++ linux-sound-plain/sound/ppc/daca.c 2004-08-26 21:14:44.000000000 +0200 @@ -28,8 +28,6 @@ #include <sound/core.h> #include "pmac.h" -#define chip_t pmac_t - /* i2c address */ #define DACA_I2C_ADDR 0x4d @@ -217,8 +215,6 @@ }, }; -#define num_controls(ary) (sizeof(ary) / sizeof(snd_kcontrol_new_t)) - #ifdef CONFIG_PMAC_PBOOK static void daca_resume(pmac_t *chip) @@ -272,7 +268,7 @@ */ strcpy(chip->card->mixername, "PowerMac DACA"); - for (i = 0; i < num_controls(daca_mixers); i++) { + for (i = 0; i < ARRAY_SIZE(daca_mixers); i++) { if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&daca_mixers[i], chip))) < 0) return err; } --- linux-2.5-plain/sound/ppc/tumbler.c 2004-08-26 21:00:41.000000000 +0200 +++ linux-sound-plain/sound/ppc/tumbler.c 2004-08-26 21:14:00.000000000 +0200 @@ -16,6 +16,11 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Rene Rebe <[EMAIL PROTECTED]>: + * * update from shadow registers on wakeup and headphone plug + * * automatically toggle DRC on headphone plug + * */ @@ -36,8 +41,6 @@ #include "pmac.h" #include "tumbler_volume.h" -#define chip_t pmac_t - /* i2c address for tumbler */ #define TAS_I2C_ADDR 0x34 @@ -759,12 +762,6 @@ DEFINE_MONO("Tone Control - Treble", treble), DEFINE_MONO("PCM Playback Volume", pcm), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DRC Switch", - .info = snd_pmac_boolean_mono_info, - .get = tumbler_get_drc_switch, - .put = tumbler_put_drc_switch - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DRC Range", .info = tumbler_info_drc_value, .get = tumbler_get_drc_value, @@ -791,12 +788,6 @@ DEFINE_SNAPPER_MONO("Tone Control - Bass", bass), DEFINE_SNAPPER_MONO("Tone Control - Treble", treble), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - .name = "DRC Switch", - .info = snd_pmac_boolean_mono_info, - .get = tumbler_get_drc_switch, - .put = tumbler_put_drc_switch - }, - { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DRC Range", .info = tumbler_info_drc_value, .get = tumbler_get_drc_value, @@ -826,6 +817,14 @@ .put = tumbler_put_mute_switch, .private_value = TUMBLER_MUTE_AMP, }; +static snd_kcontrol_new_t tumbler_drc_sw __initdata = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "DRC Switch", + .info = snd_pmac_boolean_mono_info, + .get = tumbler_get_drc_switch, + .put = tumbler_put_drc_switch +}; + #ifdef PMAC_SUPPORT_AUTOMUTE /* @@ -847,6 +846,29 @@ } } +static struct work_struct device_change; + +static void +device_change_handler(void *self) +{ + pmac_t *chip = (pmac_t*) self; + pmac_tumbler_t *mix; + + if (!chip) + return; + + mix = chip->mixer_data; + + /* first set the DRC so the speaker do not explode -ReneR */ + if (chip->model == PMAC_TUMBLER) + tumbler_set_drc(mix); + else + snapper_set_drc(mix); + + /* reset the master volume so the correct amplification is applied */ + tumbler_set_master_volume(mix); +} + static void tumbler_update_automute(pmac_t *chip, int do_notify) { if (chip->auto_mute) { @@ -856,14 +878,25 @@ /* mute speaker */ check_mute(chip, &mix->amp_mute, 1, do_notify, chip->speaker_sw_ctl); check_mute(chip, &mix->hp_mute, 0, do_notify, chip->master_sw_ctl); + mix->drc_enable = 0; + } else { /* unmute speaker */ check_mute(chip, &mix->amp_mute, 0, do_notify, chip->speaker_sw_ctl); check_mute(chip, &mix->hp_mute, 1, do_notify, chip->master_sw_ctl); + mix->drc_enable = 1; } - if (do_notify) + if (do_notify) { snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hp_detect_ctl->id); + snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, + &chip->drc_sw_ctl->id); + } + + /* finally we need to schedule an update of the mixer values + (master and DRC are enough for now) -ReneR */ + schedule_work(&device_change); + } } #endif /* PMAC_SUPPORT_AUTOMUTE */ @@ -872,7 +905,7 @@ /* interrupt - headphone plug changed */ static irqreturn_t headphone_intr(int irq, void *devid, struct pt_regs *regs) { - pmac_t *chip = snd_magic_cast(pmac_t, devid, return IRQ_NONE); + pmac_t *chip = devid; if (chip->update_automute && chip->initialized) { chip->update_automute(chip, 1); return IRQ_HANDLED; @@ -1114,11 +1147,17 @@ chip->speaker_sw_ctl = snd_ctl_new1(&tumbler_speaker_sw, chip); if ((err = snd_ctl_add(chip->card, chip->speaker_sw_ctl)) < 0) return err; + chip->drc_sw_ctl = snd_ctl_new1(&tumbler_drc_sw, chip); + if ((err = snd_ctl_add(chip->card, chip->drc_sw_ctl)) < 0) + return err; + #ifdef CONFIG_PMAC_PBOOK chip->resume = tumbler_resume; #endif + INIT_WORK(&device_change, device_change_handler, (void *)chip); + #ifdef PMAC_SUPPORT_AUTOMUTE if (mix->headphone_irq >=0 && (err = snd_pmac_add_automute(chip)) < 0) return err;