#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);
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
};
/*
return -ENOMEM;
rec->size = size;
memset(rec->space, 0, sizeof(struct dbdma_cmd) * (size + 1));
- rec->cmds = (void*)DBDMA_ALIGN(rec->space);
+ rec->cmds = (void __iomem *)DBDMA_ALIGN(rec->space);
rec->addr = virt_to_bus(rec->cmds);
return 0;
}
static void snd_pmac_dbdma_free(pmac_dbdma_t *rec)
{
- if (rec && rec->space)
+ if (rec)
kfree(rec->space);
}
* 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;
static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substream_t *subs)
{
int i;
- volatile struct dbdma_cmd *cp;
- unsigned long flags;
+ volatile struct dbdma_cmd __iomem *cp;
snd_pcm_runtime_t *runtime = subs->runtime;
int rate_index;
long offset;
/* 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...
*/
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;
}
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;
+ volatile struct dbdma_cmd __iomem *cp;
int i, command;
switch (cmd) {
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++)
(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:
#if 1 /* hmm.. how can we get the current dma pointer?? */
int stat;
- volatile struct dbdma_cmd *cp = &rec->cmd.cmds[rec->cur_period];
+ volatile struct dbdma_cmd __iomem *cp = &rec->cmd.cmds[rec->cur_period];
stat = ld_le16(&cp->xfer_status);
if (stat & (ACTIVE|DEAD)) {
count = in_le16(&cp->res_count);
- count = rec->period_size - count;
+ if (count)
+ count = rec->period_size - count;
}
#endif
count += rec->cur_period * rec->period_size;
*/
static void snd_pmac_pcm_update(pmac_t *chip, pmac_stream_t *rec)
{
- volatile struct dbdma_cmd *cp;
+ volatile struct dbdma_cmd __iomem *cp;
int c;
int stat;
.rate_max = 44100,
.channels_min = 2,
.channels_max = 2,
- .buffer_bytes_max = 32768,
+ .buffer_bytes_max = 131072,
.period_bytes_min = 256,
.period_bytes_max = 16384,
- .periods_min = 1,
+ .periods_min = 3,
.periods_max = PMAC_MAX_FRAGS,
};
.rate_max = 44100,
.channels_min = 2,
.channels_max = 2,
- .buffer_bytes_max = 32768,
+ .buffer_bytes_max = 131072,
.period_bytes_min = 256,
.period_bytes_max = 16384,
- .periods_min = 1,
+ .periods_min = 3,
.periods_max = PMAC_MAX_FRAGS,
};
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,
if (chip->can_duplex)
snd_pcm_set_sync(subs);
+ /* constraints to fix choppy sound */
+ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
return 0;
}
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;
}
+/*
+ * 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;
}
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;
}
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);*/
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);
if (chip->latch_base)
iounmap(chip->latch_base);
if (chip->awacs)
- iounmap((void*)chip->awacs);
+ iounmap(chip->awacs);
if (chip->playback.dma)
- iounmap((void*)chip->playback.dma);
+ iounmap(chip->playback.dma);
if (chip->capture.dma)
- iounmap((void*)chip->capture.dma);
+ iounmap(chip->capture.dma);
if (chip->node) {
for (i = 0; i < 3; i++) {
if (chip->of_requested & (1 << i))
release_OF_resource(chip->node, i);
}
}
- snd_magic_kfree(chip);
+ kfree(chip);
return 0;
}
*/
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);
}
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 */
sound = sound->next;
if (! sound)
return -ENODEV;
- prop = (unsigned int *) get_property(sound, "sub-frame", 0);
+ prop = (unsigned int *) get_property(sound, "sub-frame", NULL);
if (prop && *prop < 16)
chip->subframe = *prop;
/* This should be verified on older screamers */
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 */
}
- prop = (unsigned int *)get_property(sound, "device-id", 0);
+ if (device_is_compatible(sound, "AOAKeylargo")) {
+ /* Seems to support the stock AWACS frequencies, but has
+ a snapper mixer */
+ chip->model = PMAC_SNAPPER;
+ // chip->can_byte_swap = 0; /* FIXME: check this */
+ chip->control_mask = MASK_IEPC | 0x11; /* disable IEE */
+ }
+ prop = (unsigned int *)get_property(sound, "device-id", NULL);
if (prop)
chip->device_id = *prop;
chip->has_iic = (find_devices("perch") != NULL);
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;
chip->of_requested |= (1 << i);
}
- chip->awacs = (volatile struct awacs_regs *) ioremap(np->addrs[0].address, 0x1000);
- chip->playback.dma = (volatile struct dbdma_regs *) ioremap(np->addrs[1].address, 0x100);
- chip->capture.dma = (volatile struct dbdma_regs *) ioremap(np->addrs[2].address, 0x100);
+ chip->awacs = ioremap(np->addrs[0].address, 0x1000);
+ chip->playback.dma = ioremap(np->addrs[1].address, 0x100);
+ chip->capture.dma = ioremap(np->addrs[2].address, 0x100);
if (chip->model <= PMAC_BURGUNDY) {
if (request_irq(np->intrs[0].line, snd_pmac_ctrl_intr, 0,
"PMac", (void*)chip)) {
* sound input. The 0x100 enables the SCSI bus
* terminator power.
*/
- chip->latch_base = (unsigned char *) ioremap (0xf301a000, 0x1000);
+ chip->latch_base = ioremap (0xf301a000, 0x1000);
in_8(chip->latch_base + 0x190);
} else if (chip->is_pbook_G3) {
struct device_node* mio;
for (mio = chip->node->parent; mio; mio = mio->parent) {
if (strcmp(mio->name, "mac-io") == 0
&& mio->n_addrs > 0) {
- chip->macio_base = (unsigned char *) ioremap
- (mio->addrs[0].address, 0x40);
+ chip->macio_base = ioremap(mio->addrs[0].address, 0x40);
break;
}
}
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)
if (chip->rx_irq >= 0)
disable_irq(chip->rx_irq);
snd_pmac_sound_feature(chip, 0);
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
return 0;
}
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)
if (chip->rx_irq >= 0)
enable_irq(chip->rx_irq);
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
return 0;
}