/* * PCM trigger/stop */ static int snd_pmac_pcm_trigger(struct snd_pmac *chip, struct pmac_stream *rec, struct snd_pcm_substream *subs, int cmd) { volatile struct dbdma_cmd __iomem *cp; int i, command; switch (cmd) { case SNDRV_PCM_TRIGGER_START: case SNDRV_PCM_TRIGGER_RESUME: if (rec->running) return -EBUSY; command = (subs->stream == SNDRV_PCM_STREAM_PLAYBACK ? OUTPUT_MORE : INPUT_MORE) + INTR_ALWAYS; 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++) out_le16(&cp->command, command); snd_pmac_dma_set_command(rec, &rec->cmd); (void)in_le32(&rec->dma->status); snd_pmac_dma_run(rec, RUN|WAKE); rec->running = 1; spin_unlock(&chip->reg_lock); break; case SNDRV_PCM_TRIGGER_STOP: case SNDRV_PCM_TRIGGER_SUSPEND: spin_lock(&chip->reg_lock); rec->running = 0; /*printk(KERN_DEBUG "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(&chip->reg_lock); break; default: return -EINVAL; } return 0; }
static int snd_pmac_beep_event(struct input_dev *dev, unsigned int type, unsigned int code, int hz) { struct snd_pmac *chip; struct pmac_beep *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 = input_get_drvdata(dev); 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; }