Re: iBook 2.2: Kernel 2.6.8 and beep (PC Speaker)?
Package: kernel-source-2.6.8
Thanks Julien. I now forward this to the kernel-source-2.6.8 package in order
to not lose it in my mail archive.
Friendly,
Sven Luther
On Wed, Sep 08, 2004 at 11:44:56AM +0200, Julien BLACHE wrote:
> Sven Luther <sven.luther@wanadoo.fr> 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 - <jblache@debian.org>
>
> Public key available on <http://www.jblache.org> - KeyID: F5D6 5169
> GPG Fingerprint : 935A 79F1 C8B3 3521 FD62 7CC7 CD61 4FD7 F5D6 5169
>
Content-Description: Beep support for PowerMac
> --- 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 <tiwai@suse.de>
> + *
> + * 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 <perex@suse.cz>
> #
>
> -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;
>
> }
Content-Description: hardware support updates for awacs, daca, tumbler, burgundy
> --- 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 <rene.rebe@gmx.net>:
> + * * 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;
Reply to: