📄 azt3328.c
字号:
static int snd_azf3328_playback_prepare(snd_pcm_substream_t *substream){#if 0 azf3328_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; unsigned int size = snd_pcm_lib_buffer_bytes(substream); unsigned int count = snd_pcm_lib_period_bytes(substream);#endif snd_azf3328_dbgcallenter();#if 0 snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, 0);#endif snd_azf3328_dbgcallleave(); return 0;}static int snd_azf3328_capture_prepare(snd_pcm_substream_t * substream){#if 0 azf3328_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; unsigned int size = snd_pcm_lib_buffer_bytes(substream); unsigned int count = snd_pcm_lib_period_bytes(substream);#endif snd_azf3328_dbgcallenter();#if 0 snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); snd_azf3328_setdmaa(chip, runtime->dma_addr, count, size, 1);#endif snd_azf3328_dbgcallleave(); return 0;}static int snd_azf3328_playback_trigger(snd_pcm_substream_t * substream, int cmd){ azf3328_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; int result = 0; unsigned int status1; snd_azf3328_dbgcalls("snd_azf3328_playback_trigger cmd %d\n", cmd); switch (cmd) { case SNDRV_PCM_TRIGGER_START: snd_azf3328_dbgio(chip, "trigger1"); /* mute WaveOut */ snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); snd_azf3328_setfmt(chip, IDX_IO_PLAY_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); spin_lock(&chip->reg_lock); /* stop playback */ status1 = inw(chip->codec_port+IDX_IO_PLAY_FLAGS); status1 &= ~DMA_RESUME; outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); /* FIXME: clear interrupts or what??? */ outw(0xffff, chip->codec_port+IDX_IO_PLAY_IRQMASK); spin_unlock(&chip->reg_lock); snd_azf3328_setdmaa(chip, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream), 0); spin_lock(&chip->reg_lock);#ifdef WIN9X /* FIXME: enable playback/recording??? */ status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2; outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); /* start playback again */ /* FIXME: what is this value (0x0010)??? */ status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS);#else /* NT4 */ outw(0x00, chip->codec_port+IDX_IO_PLAY_FLAGS); outw(DMA_PLAY_SOMETHING1, chip->codec_port+IDX_IO_PLAY_FLAGS); outw(DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2, chip->codec_port+IDX_IO_PLAY_FLAGS); outw(DMA_RESUME|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port+IDX_IO_PLAY_FLAGS);#endif spin_unlock(&chip->reg_lock); /* now unmute WaveOut */ snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); snd_azf3328_dbgio(chip, "trigger2"); chip->is_playing = 1; break; case SNDRV_PCM_TRIGGER_STOP: /* mute WaveOut */ snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 1); spin_lock(&chip->reg_lock); /* stop playback */ status1 = inw(chip->codec_port+IDX_IO_PLAY_FLAGS); status1 &= ~DMA_RESUME; outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); status1 |= DMA_PLAY_SOMETHING1; outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); status1 &= ~DMA_PLAY_SOMETHING1; outw(status1, chip->codec_port+IDX_IO_PLAY_FLAGS); spin_unlock(&chip->reg_lock); /* now unmute WaveOut */ snd_azf3328_mixer_set_mute(chip, IDX_MIXER_WAVEOUT, 0); chip->is_playing = 0; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: snd_printk("FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_printk("FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); break; default: return -EINVAL; } snd_azf3328_dbgcallleave(); return result;}/* this is just analogous to playback; I'm not quite sure whether recording * should actually be triggered like that */static int snd_azf3328_capture_trigger(snd_pcm_substream_t * substream, int cmd){ azf3328_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; int result = 0; unsigned int status1; snd_azf3328_dbgcalls("snd_azf3328_capture_trigger cmd %d\n", cmd); switch (cmd) { case SNDRV_PCM_TRIGGER_START: snd_azf3328_dbgio(chip, "trigger1"); snd_azf3328_setfmt(chip, IDX_IO_REC_SOUNDFORMAT, runtime->rate, snd_pcm_format_width(runtime->format), runtime->channels); spin_lock(&chip->reg_lock); /* stop recording */ status1 = inw(chip->codec_port+IDX_IO_REC_FLAGS); status1 &= ~DMA_RESUME; outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); /* FIXME: clear interrupts or what??? */ outw(0xffff, chip->codec_port+IDX_IO_REC_IRQMASK); spin_unlock(&chip->reg_lock); snd_azf3328_setdmaa(chip, runtime->dma_addr, snd_pcm_lib_period_bytes(substream), snd_pcm_lib_buffer_bytes(substream), 1); spin_lock(&chip->reg_lock);#ifdef WIN9X /* FIXME: enable playback/recording??? */ status1 |= DMA_PLAY_SOMETHING1 | DMA_PLAY_SOMETHING2; outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); /* start playback again */ /* FIXME: what is this value (0x0010)??? */ status1 |= DMA_RESUME | DMA_EPILOGUE_SOMETHING; outw(status1, chip->codec_port+IDX_IO_REC_FLAGS);#else outw(0x00, chip->codec_port+IDX_IO_REC_FLAGS); outw(DMA_PLAY_SOMETHING1, chip->codec_port+IDX_IO_REC_FLAGS); outw(DMA_PLAY_SOMETHING1|DMA_PLAY_SOMETHING2, chip->codec_port+IDX_IO_REC_FLAGS); outw(DMA_RESUME|SOMETHING_ALMOST_ALWAYS_SET|DMA_EPILOGUE_SOMETHING|DMA_SOMETHING_ELSE, chip->codec_port+IDX_IO_REC_FLAGS);#endif spin_unlock(&chip->reg_lock); snd_azf3328_dbgio(chip, "trigger2"); chip->is_playing = 1; break; case SNDRV_PCM_TRIGGER_STOP: spin_lock(&chip->reg_lock); /* stop recording */ status1 = inw(chip->codec_port+IDX_IO_REC_FLAGS); status1 &= ~DMA_RESUME; outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); status1 |= DMA_PLAY_SOMETHING1; outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); status1 &= ~DMA_PLAY_SOMETHING1; outw(status1, chip->codec_port+IDX_IO_REC_FLAGS); spin_unlock(&chip->reg_lock); chip->is_playing = 0; break; case SNDRV_PCM_TRIGGER_PAUSE_PUSH: snd_printk("FIXME: SNDRV_PCM_TRIGGER_PAUSE_PUSH NIY!\n"); break; case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: snd_printk("FIXME: SNDRV_PCM_TRIGGER_PAUSE_RELEASE NIY!\n"); break; default: return -EINVAL; } snd_azf3328_dbgcallleave(); return result;}static snd_pcm_uframes_t snd_azf3328_playback_pointer(snd_pcm_substream_t * substream){ azf3328_t *chip = snd_pcm_substream_chip(substream); unsigned long bufptr, playptr; unsigned long result; snd_pcm_uframes_t frmres;#ifdef QUERY_HARDWARE bufptr = inl(chip->codec_port+IDX_IO_PLAY_DMA_START_1);#else bufptr = substream->runtime->dma_addr;#endif playptr = inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS); result = playptr - bufptr; frmres = bytes_to_frames( substream->runtime, result ); snd_azf3328_dbgplay("result %lx, playptr %lx (base %x), frames %ld\n", result, playptr, substream->runtime->dma_addr, frmres); return frmres;}static snd_pcm_uframes_t snd_azf3328_capture_pointer(snd_pcm_substream_t * substream){ azf3328_t *chip = snd_pcm_substream_chip(substream); unsigned long bufptr, recptr; unsigned long result; snd_pcm_uframes_t frmres;#ifdef QUERY_HARDWARE bufptr = inl(chip->codec_port+IDX_IO_REC_DMA_START_1);#else bufptr = substream->runtime->dma_addr;#endif recptr = inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS); result = recptr - bufptr; frmres = bytes_to_frames( substream->runtime, result ); snd_azf3328_dbgplay("result %lx, rec ptr %lx (base %x), frames %ld\n", result, recptr, substream->runtime->dma_addr, frmres); return frmres;}static irqreturn_t snd_azf3328_interrupt(int irq, void *dev_id, struct pt_regs *regs){ azf3328_t *chip = dev_id; unsigned int status, which; static unsigned long count; status = inw(chip->codec_port+IDX_IO_IRQSTATUS); /* fast path out, to ease interrupt sharing */ if (!(status & (IRQ_PLAYBACK|IRQ_RECORDING|IRQ_MPU401|IRQ_SOMEIRQ))) return IRQ_NONE; /* must be interrupt for another device */ snd_azf3328_dbgplay("Interrupt %ld!\nIDX_IO_PLAY_FLAGS %04x, IDX_IO_PLAY_IRQMASK %04x, IDX_IO_IRQSTATUS %04x\n", count, inw(chip->codec_port+IDX_IO_PLAY_FLAGS), inw(chip->codec_port+IDX_IO_PLAY_IRQMASK), inw(chip->codec_port+IDX_IO_IRQSTATUS)); if (status & IRQ_PLAYBACK) { spin_lock(&chip->reg_lock); which = inw(chip->codec_port+IDX_IO_PLAY_IRQMASK); if (which & IRQ_FINISHED_PLAYBUF_1) /* ack IRQ */ outw(which | IRQ_FINISHED_PLAYBUF_1, chip->codec_port+IDX_IO_PLAY_IRQMASK); if (which & IRQ_FINISHED_PLAYBUF_2) /* ack IRQ */ outw(which | IRQ_FINISHED_PLAYBUF_2, chip->codec_port+IDX_IO_PLAY_IRQMASK); if (which & IRQ_PLAY_SOMETHING) { snd_azf3328_dbgplay("azt3328: unknown play IRQ type occurred, please report!\n"); } if (chip->pcm && chip->playback_substream) { snd_azf3328_dbgplay("which %x, playptr %lx\n", which, inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); snd_pcm_period_elapsed(chip->playback_substream); snd_azf3328_dbgplay("period done, playptr %lx.\n", inl(chip->codec_port+IDX_IO_PLAY_DMA_CURRPOS)); } else snd_azf3328_dbgplay("azt3328: ouch, irq handler problem!\n"); spin_unlock(&chip->reg_lock); } if (status & IRQ_RECORDING) { spin_lock(&chip->reg_lock); which = inw(chip->codec_port+IDX_IO_REC_IRQMASK); if (which & IRQ_FINISHED_RECBUF_1) /* ack interrupt */ outw(which | IRQ_FINISHED_RECBUF_1, chip->codec_port+IDX_IO_REC_IRQMASK); if (which & IRQ_FINISHED_RECBUF_2) /* ack interrupt */ outw(which | IRQ_FINISHED_RECBUF_2, chip->codec_port+IDX_IO_REC_IRQMASK); if (which & IRQ_REC_SOMETHING) { snd_azf3328_dbgplay("azt3328: unknown rec IRQ type occurred, please report!\n"); } if (chip->pcm && chip->capture_substream) { snd_azf3328_dbgplay("which %x, recptr %lx\n", which, inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); spin_unlock(&chip->reg_lock); snd_pcm_period_elapsed(chip->capture_substream); spin_lock(&chip->reg_lock); snd_azf3328_dbgplay("period done, recptr %lx.\n", inl(chip->codec_port+IDX_IO_REC_DMA_CURRPOS)); } spin_unlock(&chip->reg_lock); } if (status & IRQ_MPU401) snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs); if (status & IRQ_SOMEIRQ) snd_azf3328_dbgplay("azt3328: unknown IRQ type occurred, please report!\n"); count++; return IRQ_HANDLED;}/*****************************************************************/static snd_pcm_hardware_t snd_azf3328_playback ={ /* FIXME!! Correct? */ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE, .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_KNOT, .rate_min = 5512, .rate_max = 64000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = 65536, .period_bytes_min = 64, .period_bytes_max = 65536, .periods_min = 1, .periods_max = 1024, /* FIXME: maybe that card actually has a FIFO? * Hmm, it seems newer revisions do have one, but we still don't know * its size... */ .fifo_size = 0,};static snd_pcm_hardware_t snd_azf3328_capture ={ /* FIXME */ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE, .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_KNOT, .rate_min = 5512, .rate_max = 64000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = 65536, .period_bytes_min = 64, .period_bytes_max = 65536, .periods_min = 1, .periods_max = 1024, .fifo_size = 0,};static unsigned int snd_azf3328_fixed_rates[] = { 5512, 6620, 8000, 9600, 11025, 16000, 22050, 32000, 44100, 48000, 64000};static snd_pcm_hw_constraint_list_t snd_azf3328_hw_constraints_rates = { .count = ARRAY_SIZE(snd_azf3328_fixed_rates), .list = snd_azf3328_fixed_rates, .mask = 0,};/*****************************************************************/static int snd_azf3328_playback_open(snd_pcm_substream_t * substream){ azf3328_t *chip = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; snd_azf3328_dbgcallenter(); chip->playback_substream = substream; runtime->hw = snd_azf3328_playback;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -