Re: iBook 2.2: Kernel 2.6.8 and beep (PC Speaker)?
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
--- 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;
}
--- 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: