static irqreturn_t snd_nm256_interrupt(int irq, void *dev_id, struct pt_regs *dummy) { nm256_t *chip = dev_id; u16 status; u8 cbyte; status = snd_nm256_readw(chip, NM_INT_REG); /* Not ours. */ if (status == 0) { snd_nm256_intr_check(chip); return IRQ_NONE; } chip->badintrcount = 0; /* Rather boring; check for individual interrupts and process them. */ spin_lock(&chip->reg_lock); if (status & NM_PLAYBACK_INT) { status &= ~NM_PLAYBACK_INT; NM_ACK_INT(chip, NM_PLAYBACK_INT); snd_nm256_playback_update(chip); } if (status & NM_RECORD_INT) { status &= ~NM_RECORD_INT; NM_ACK_INT(chip, NM_RECORD_INT); snd_nm256_capture_update(chip); } if (status & NM_MISC_INT_1) { status &= ~NM_MISC_INT_1; NM_ACK_INT(chip, NM_MISC_INT_1); snd_printd("NM256: Got misc interrupt #1\n"); snd_nm256_writew(chip, NM_INT_REG, 0x8000); cbyte = snd_nm256_readb(chip, 0x400); snd_nm256_writeb(chip, 0x400, cbyte | 2); } if (status & NM_MISC_INT_2) { status &= ~NM_MISC_INT_2; NM_ACK_INT(chip, NM_MISC_INT_2); snd_printd("NM256: Got misc interrupt #2\n"); cbyte = snd_nm256_readb(chip, 0x400); snd_nm256_writeb(chip, 0x400, cbyte & ~2); } /* Unknown interrupt. */ if (status) { snd_printd("NM256: Fire in the hole! Unknown status 0x%x\n", status); /* Pray. */ NM_ACK_INT(chip, status); } spin_unlock(&chip->reg_lock); return IRQ_HANDLED; }
/* initialize the ac97 into a known state */ static void snd_nm256_ac97_reset(struct snd_ac97 *ac97) { struct nm256 *chip = ac97->private_data; /* Reset the mixer. 'Tis magic! */ snd_nm256_writeb(chip, 0x6c0, 1); if (! chip->reset_workaround) { /* Dell latitude LS will lock up by this */ snd_nm256_writeb(chip, 0x6cc, 0x87); } if (! chip->reset_workaround_2) { /* Dell latitude CSx will lock up by this */ snd_nm256_writeb(chip, 0x6cc, 0x80); snd_nm256_writeb(chip, 0x6cc, 0x0); } if (! chip->in_resume) { int i; for (i = 0; i < ARRAY_SIZE(nm256_ac97_init_val); i++) { /* preload the cache, so as to avoid even a single * read of the mixer regs */ snd_nm256_ac97_write(ac97, nm256_ac97_init_val[i].reg, nm256_ac97_init_val[i].value); } } }
/* * set sample rate and format */ static void snd_nm256_set_format(struct nm256 *chip, struct nm256_stream *s, struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; int rate_index = snd_nm256_fixed_rate(runtime->rate); unsigned char ratebits = (rate_index << 4) & NM_RATE_MASK; s->shift = 0; if (snd_pcm_format_width(runtime->format) == 16) { ratebits |= NM_RATE_BITS_16; s->shift++; } if (runtime->channels > 1) { ratebits |= NM_RATE_STEREO; s->shift++; } runtime->rate = samplerates[rate_index]; switch (substream->stream) { case SNDRV_PCM_STREAM_PLAYBACK: snd_nm256_load_coefficient(chip, 0, rate_index); /* 0 = playback */ snd_nm256_writeb(chip, NM_PLAYBACK_REG_OFFSET + NM_RATE_REG_OFFSET, ratebits); break; case SNDRV_PCM_STREAM_CAPTURE: snd_nm256_load_coefficient(chip, 1, rate_index); /* 1 = record */ snd_nm256_writeb(chip, NM_RECORD_REG_OFFSET + NM_RATE_REG_OFFSET, ratebits); break; } }
static irqreturn_t snd_nm256_interrupt(int irq, void *dev_id) { struct nm256 *chip = dev_id; u16 status; u8 cbyte; status = snd_nm256_readw(chip, NM_INT_REG); if (status == 0) return snd_nm256_intr_check(chip); chip->badintrcount = 0; spin_lock(&chip->reg_lock); if (status & NM_PLAYBACK_INT) { status &= ~NM_PLAYBACK_INT; NM_ACK_INT(chip, NM_PLAYBACK_INT); snd_nm256_playback_update(chip); } if (status & NM_RECORD_INT) { status &= ~NM_RECORD_INT; NM_ACK_INT(chip, NM_RECORD_INT); snd_nm256_capture_update(chip); } if (status & NM_MISC_INT_1) { status &= ~NM_MISC_INT_1; NM_ACK_INT(chip, NM_MISC_INT_1); snd_printd("NM256: Got misc interrupt #1\n"); snd_nm256_writew(chip, NM_INT_REG, 0x8000); cbyte = snd_nm256_readb(chip, 0x400); snd_nm256_writeb(chip, 0x400, cbyte | 2); } if (status & NM_MISC_INT_2) { status &= ~NM_MISC_INT_2; NM_ACK_INT(chip, NM_MISC_INT_2); snd_printd("NM256: Got misc interrupt #2\n"); cbyte = snd_nm256_readb(chip, 0x400); snd_nm256_writeb(chip, 0x400, cbyte & ~2); } if (status) { snd_printd("NM256: Fire in the hole! Unknown status 0x%x\n", status); NM_ACK_INT(chip, status); } spin_unlock(&chip->reg_lock); return IRQ_HANDLED; }
/* initialize the ac97 into a known state */ static void snd_nm256_ac97_reset(ac97_t *ac97) { nm256_t *chip = ac97->private_data; /* Reset the mixer. 'Tis magic! */ snd_nm256_writeb(chip, 0x6c0, 1); if (! chip->reset_workaround) { /* Dell latitude LS will lock up by this */ snd_nm256_writeb(chip, 0x6cc, 0x87); } snd_nm256_writeb(chip, 0x6cc, 0x80); snd_nm256_writeb(chip, 0x6cc, 0x0); }
/* Stop the play engine. */ static void snd_nm256_playback_stop(struct nm256 *chip) { /* Shut off sound from both channels. */ snd_nm256_writew(chip, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT); /* Disable play engine. */ snd_nm256_writeb(chip, NM_PLAYBACK_ENABLE_REG, 0); }
static void snd_nm256_playback_stop(struct nm256 *chip) { snd_nm256_writew(chip, NM_AUDIO_MUTE_REG, NM_AUDIO_MUTE_LEFT | NM_AUDIO_MUTE_RIGHT); snd_nm256_writeb(chip, NM_PLAYBACK_ENABLE_REG, 0); }
static void snd_nm256_init_chip(struct nm256 *chip) { snd_nm256_writeb(chip, 0x0, 0x11); snd_nm256_writew(chip, 0x214, 0); }
/* * Initialize the hardware. */ static void snd_nm256_init_chip(struct nm256 *chip) { /* Reset everything. */ snd_nm256_writeb(chip, 0x0, 0x11); snd_nm256_writew(chip, 0x214, 0); /* stop sounds.. */ //snd_nm256_playback_stop(chip); //snd_nm256_capture_stop(chip); }
/* * Initialize the hardware. */ static void snd_nm256_init_chip(nm256_t *chip) { spin_lock_irq(&chip->reg_lock); /* Reset everything. */ snd_nm256_writeb(chip, 0x0, 0x11); snd_nm256_writew(chip, 0x214, 0); /* stop sounds.. */ //snd_nm256_playback_stop(chip); //snd_nm256_capture_stop(chip); spin_unlock_irq(&chip->reg_lock); }
static void snd_nm256_capture_start(nm256_t *chip, nm256_stream_t *s, snd_pcm_substream_t *substream) { /* program buffer pointers */ snd_nm256_writel(chip, NM_RBUFFER_START, s->buf); snd_nm256_writel(chip, NM_RBUFFER_END, s->buf + s->dma_size); snd_nm256_writel(chip, NM_RBUFFER_CURRP, s->buf); snd_nm256_capture_mark(chip, s); /* Enable playback engine and interrupts. */ snd_nm256_writeb(chip, NM_RECORD_ENABLE_REG, NM_RECORD_ENABLE_FLAG | NM_RECORD_FREERUN); }
static void snd_nm256_capture_start(struct nm256 *chip, struct nm256_stream *s, struct snd_pcm_substream *substream) { snd_nm256_writel(chip, NM_RBUFFER_START, s->buf); snd_nm256_writel(chip, NM_RBUFFER_END, s->buf + s->dma_size); snd_nm256_writel(chip, NM_RBUFFER_CURRP, s->buf); snd_nm256_capture_mark(chip, s); snd_nm256_writeb(chip, NM_RECORD_ENABLE_REG, NM_RECORD_ENABLE_FLAG | NM_RECORD_FREERUN); }
static void snd_nm256_playback_start(nm256_t *chip, nm256_stream_t *s, snd_pcm_substream_t *substream) { /* program buffer pointers */ snd_nm256_writel(chip, NM_PBUFFER_START, s->buf); snd_nm256_writel(chip, NM_PBUFFER_END, s->buf + s->dma_size - (1 << s->shift)); snd_nm256_writel(chip, NM_PBUFFER_CURRP, s->buf); snd_nm256_playback_mark(chip, s); /* Enable playback engine and interrupts. */ snd_nm256_writeb(chip, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN); /* Enable both channels. */ snd_nm256_writew(chip, NM_AUDIO_MUTE_REG, 0x0); }
static void snd_nm256_ac97_reset(struct snd_ac97 *ac97) { struct nm256 *chip = ac97->private_data; snd_nm256_writeb(chip, 0x6c0, 1); if (! chip->reset_workaround) { snd_nm256_writeb(chip, 0x6cc, 0x87); } if (! chip->reset_workaround_2) { snd_nm256_writeb(chip, 0x6cc, 0x80); snd_nm256_writeb(chip, 0x6cc, 0x0); } if (! chip->in_resume) { int i; for (i = 0; i < ARRAY_SIZE(nm256_ac97_init_val); i++) { snd_nm256_ac97_write(ac97, nm256_ac97_init_val[i].reg, nm256_ac97_init_val[i].value); } } }
static void snd_nm256_playback_start(struct nm256 *chip, struct nm256_stream *s, struct snd_pcm_substream *substream) { snd_nm256_writel(chip, NM_PBUFFER_START, s->buf); snd_nm256_writel(chip, NM_PBUFFER_END, s->buf + s->dma_size - (1 << s->shift)); snd_nm256_writel(chip, NM_PBUFFER_CURRP, s->buf); snd_nm256_playback_mark(chip, s); snd_nm256_writeb(chip, NM_PLAYBACK_ENABLE_REG, NM_PLAYBACK_ENABLE_FLAG | NM_PLAYBACK_FREERUN); snd_nm256_writew(chip, NM_AUDIO_MUTE_REG, 0x0); }
static void snd_nm256_capture_stop(struct nm256 *chip) { /* Disable recording engine. */ snd_nm256_writeb(chip, NM_RECORD_ENABLE_REG, 0); }
static void snd_nm256_capture_stop(struct nm256 *chip) { snd_nm256_writeb(chip, NM_RECORD_ENABLE_REG, 0); }