X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=sound%2Fppc%2Fpmac.c;h=2498b75fb6e516449ab8d5e46ffc550dd9f7809a;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=95dfeef913f10d9cacdb64aaa9229bebdf482421;hpb=9213980e6a70d8473e0ffd4b39ab5b6caaba9ff5;p=linux-2.6.git diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c index 95dfeef91..2498b75fb 100644 --- a/sound/ppc/pmac.c +++ b/sound/ppc/pmac.c @@ -36,8 +36,6 @@ #include #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 @@ static int awacs_freqs[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 }; /* @@ -66,14 +64,14 @@ static int snd_pmac_dbdma_alloc(pmac_dbdma_t *rec, int size) 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); } @@ -86,7 +84,7 @@ static void snd_pmac_dbdma_free(pmac_dbdma_t *rec) * 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; @@ -202,8 +200,7 @@ inline static void snd_pmac_dma_run(pmac_stream_t *rec, int status) 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; @@ -226,15 +223,17 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr /* 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 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr 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,8 +263,7 @@ static int snd_pmac_pcm_prepare(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substr 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) { @@ -275,7 +273,7 @@ static int snd_pmac_pcm_trigger(pmac_t *chip, pmac_stream_t *rec, 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 @@ static int snd_pmac_pcm_trigger(pmac_t *chip, pmac_stream_t *rec, (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: @@ -316,11 +314,12 @@ static snd_pcm_uframes_t snd_pmac_pcm_pointer(pmac_t *chip, pmac_stream_t *rec, #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; @@ -381,7 +380,7 @@ static snd_pcm_uframes_t snd_pmac_capture_pointer(snd_pcm_substream_t *subs) */ 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; @@ -427,10 +426,10 @@ static snd_pcm_hardware_t snd_pmac_playback = .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, }; @@ -446,10 +445,10 @@ static snd_pcm_hardware_t snd_pmac_capture = .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, }; @@ -490,14 +489,12 @@ static int snd_pmac_pcm_open(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substream 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, @@ -554,6 +551,8 @@ static int snd_pmac_pcm_open(pmac_t *chip, pmac_stream_t *rec, snd_pcm_substream 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; } @@ -651,7 +650,7 @@ int __init snd_pmac_pcm_new(pmac_t *chip) 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; @@ -682,13 +681,42 @@ static void snd_pmac_dbdma_reset(pmac_t *chip) } +/* + * 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 +725,7 @@ snd_pmac_tx_intr(int irq, void *devid, struct pt_regs *regs) 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 +734,7 @@ snd_pmac_rx_intr(int irq, void *devid, struct pt_regs *regs) 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 +804,8 @@ static int snd_pmac_free(pmac_t *chip) 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); @@ -791,18 +821,18 @@ static int snd_pmac_free(pmac_t *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; } @@ -812,7 +842,7 @@ static int snd_pmac_free(pmac_t *chip) */ 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 +892,7 @@ static int __init snd_pmac_detect(pmac_t *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 */ @@ -896,7 +926,7 @@ static int __init snd_pmac_detect(pmac_t *chip) 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 */ @@ -920,18 +950,25 @@ static int __init snd_pmac_detect(pmac_t *chip) 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); @@ -1062,7 +1099,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) 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; @@ -1099,9 +1136,9 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) 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)) { @@ -1142,15 +1179,14 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) * 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; } } @@ -1199,7 +1235,7 @@ int __init snd_pmac_new(snd_card_t *card, pmac_t **chip_return) 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) @@ -1215,13 +1251,12 @@ static int snd_pmac_suspend(snd_card_t *card, unsigned int state) 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) @@ -1242,7 +1277,6 @@ static int snd_pmac_resume(snd_card_t *card, unsigned int state) if (chip->rx_irq >= 0) enable_irq(chip->rx_irq); - snd_power_change_state(card, SNDRV_CTL_POWER_D0); return 0; }