📄 ice1712.c
字号:
} if (status & ICE1712_IRQ_FM) outb(ICE1712_IRQ_FM, ICEREG(ice, IRQSTAT)); if (status & ICE1712_IRQ_PBKDS) { u32 idx; u16 pbkstatus; snd_pcm_substream_t *substream; pbkstatus = inw(ICEDS(ice, INTSTAT)); //printk("pbkstatus = 0x%x\n", pbkstatus); for (idx = 0; idx < 6; idx++) { if ((pbkstatus & (3 << (idx * 2))) == 0) continue; if ((substream = ice->playback_con_substream_ds[idx]) != NULL) snd_pcm_period_elapsed(substream); outw(3 << (idx * 2), ICEDS(ice, INTSTAT)); } outb(ICE1712_IRQ_PBKDS, ICEREG(ice, IRQSTAT)); } if (status & ICE1712_IRQ_CONCAP) { if (ice->capture_con_substream) snd_pcm_period_elapsed(ice->capture_con_substream); outb(ICE1712_IRQ_CONCAP, ICEREG(ice, IRQSTAT)); } if (status & ICE1712_IRQ_CONPBK) { if (ice->playback_con_substream) snd_pcm_period_elapsed(ice->playback_con_substream); outb(ICE1712_IRQ_CONPBK, ICEREG(ice, IRQSTAT)); } } return IRQ_RETVAL(handled);}/* * PCM part - misc */static int snd_ice1712_hw_params(snd_pcm_substream_t * substream, snd_pcm_hw_params_t * hw_params){ return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));}static int snd_ice1712_hw_free(snd_pcm_substream_t * substream){ return snd_pcm_lib_free_pages(substream);}/* * PCM part - consumer I/O */static int snd_ice1712_playback_trigger(snd_pcm_substream_t * substream, int cmd){ ice1712_t *ice = snd_pcm_substream_chip(substream); int result = 0; u32 tmp; spin_lock(&ice->reg_lock); tmp = snd_ice1712_read(ice, ICE1712_IREG_PBK_CTRL); if (cmd == SNDRV_PCM_TRIGGER_START) { tmp |= 1; } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { tmp &= ~1; } else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) { tmp |= 2; } else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) { tmp &= ~2; } else { result = -EINVAL; } snd_ice1712_write(ice, ICE1712_IREG_PBK_CTRL, tmp); spin_unlock(&ice->reg_lock); return result;}static int snd_ice1712_playback_ds_trigger(snd_pcm_substream_t * substream, int cmd){ ice1712_t *ice = snd_pcm_substream_chip(substream); int result = 0; u32 tmp; spin_lock(&ice->reg_lock); tmp = snd_ice1712_ds_read(ice, substream->number * 2, ICE1712_DSC_CONTROL); if (cmd == SNDRV_PCM_TRIGGER_START) { tmp |= 1; } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { tmp &= ~1; } else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_PUSH) { tmp |= 2; } else if (cmd == SNDRV_PCM_TRIGGER_PAUSE_RELEASE) { tmp &= ~2; } else { result = -EINVAL; } snd_ice1712_ds_write(ice, substream->number * 2, ICE1712_DSC_CONTROL, tmp); spin_unlock(&ice->reg_lock); return result;}static int snd_ice1712_capture_trigger(snd_pcm_substream_t * substream, int cmd){ ice1712_t *ice = snd_pcm_substream_chip(substream); int result = 0; u8 tmp; spin_lock(&ice->reg_lock); tmp = snd_ice1712_read(ice, ICE1712_IREG_CAP_CTRL); if (cmd == SNDRV_PCM_TRIGGER_START) { tmp |= 1; } else if (cmd == SNDRV_PCM_TRIGGER_STOP) { tmp &= ~1; } else { result = -EINVAL; } snd_ice1712_write(ice, ICE1712_IREG_CAP_CTRL, tmp); spin_unlock(&ice->reg_lock); return result;}static int snd_ice1712_playback_prepare(snd_pcm_substream_t * substream){ ice1712_t *ice = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; u32 period_size, buf_size, rate, tmp; period_size = (snd_pcm_lib_period_bytes(substream) >> 2) - 1; buf_size = snd_pcm_lib_buffer_bytes(substream) - 1; tmp = 0x0000; if (snd_pcm_format_width(runtime->format) == 16) tmp |= 0x10; if (runtime->channels == 2) tmp |= 0x08; rate = (runtime->rate * 8192) / 375; if (rate > 0x000fffff) rate = 0x000fffff; spin_lock_irq(&ice->reg_lock); outb(0, ice->ddma_port + 15); outb(ICE1712_DMA_MODE_WRITE | ICE1712_DMA_AUTOINIT, ice->ddma_port + 0x0b); outl(runtime->dma_addr, ice->ddma_port + 0); outw(buf_size, ice->ddma_port + 4); snd_ice1712_write(ice, ICE1712_IREG_PBK_RATE_LO, rate & 0xff); snd_ice1712_write(ice, ICE1712_IREG_PBK_RATE_MID, (rate >> 8) & 0xff); snd_ice1712_write(ice, ICE1712_IREG_PBK_RATE_HI, (rate >> 16) & 0xff); snd_ice1712_write(ice, ICE1712_IREG_PBK_CTRL, tmp); snd_ice1712_write(ice, ICE1712_IREG_PBK_COUNT_LO, period_size & 0xff); snd_ice1712_write(ice, ICE1712_IREG_PBK_COUNT_HI, period_size >> 8); snd_ice1712_write(ice, ICE1712_IREG_PBK_LEFT, 0); snd_ice1712_write(ice, ICE1712_IREG_PBK_RIGHT, 0); spin_unlock_irq(&ice->reg_lock); return 0;}static int snd_ice1712_playback_ds_prepare(snd_pcm_substream_t * substream){ ice1712_t *ice = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; u32 period_size, buf_size, rate, tmp, chn; period_size = snd_pcm_lib_period_bytes(substream) - 1; buf_size = snd_pcm_lib_buffer_bytes(substream) - 1; tmp = 0x0064; if (snd_pcm_format_width(runtime->format) == 16) tmp &= ~0x04; if (runtime->channels == 2) tmp |= 0x08; rate = (runtime->rate * 8192) / 375; if (rate > 0x000fffff) rate = 0x000fffff; ice->playback_con_active_buf[substream->number] = 0; ice->playback_con_virt_addr[substream->number] = runtime->dma_addr; chn = substream->number * 2; spin_lock_irq(&ice->reg_lock); snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR0, runtime->dma_addr); snd_ice1712_ds_write(ice, chn, ICE1712_DSC_COUNT0, period_size); snd_ice1712_ds_write(ice, chn, ICE1712_DSC_ADDR1, runtime->dma_addr + (runtime->periods > 1 ? period_size + 1 : 0)); snd_ice1712_ds_write(ice, chn, ICE1712_DSC_COUNT1, period_size); snd_ice1712_ds_write(ice, chn, ICE1712_DSC_RATE, rate); snd_ice1712_ds_write(ice, chn, ICE1712_DSC_VOLUME, 0); snd_ice1712_ds_write(ice, chn, ICE1712_DSC_CONTROL, tmp); if (runtime->channels == 2) { snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_RATE, rate); snd_ice1712_ds_write(ice, chn + 1, ICE1712_DSC_VOLUME, 0); } spin_unlock_irq(&ice->reg_lock); return 0;}static int snd_ice1712_capture_prepare(snd_pcm_substream_t * substream){ ice1712_t *ice = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; u32 period_size, buf_size; u8 tmp; period_size = (snd_pcm_lib_period_bytes(substream) >> 2) - 1; buf_size = snd_pcm_lib_buffer_bytes(substream) - 1; tmp = 0x06; if (snd_pcm_format_width(runtime->format) == 16) tmp &= ~0x04; if (runtime->channels == 2) tmp &= ~0x02; spin_lock_irq(&ice->reg_lock); outl(ice->capture_con_virt_addr = runtime->dma_addr, ICEREG(ice, CONCAP_ADDR)); outw(buf_size, ICEREG(ice, CONCAP_COUNT)); snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_HI, period_size >> 8); snd_ice1712_write(ice, ICE1712_IREG_CAP_COUNT_LO, period_size & 0xff); snd_ice1712_write(ice, ICE1712_IREG_CAP_CTRL, tmp); spin_unlock_irq(&ice->reg_lock); snd_ac97_set_rate(ice->ac97, AC97_PCM_LR_ADC_RATE, runtime->rate); return 0;}static snd_pcm_uframes_t snd_ice1712_playback_pointer(snd_pcm_substream_t * substream){ ice1712_t *ice = snd_pcm_substream_chip(substream); snd_pcm_runtime_t *runtime = substream->runtime; size_t ptr; if (!(snd_ice1712_read(ice, ICE1712_IREG_PBK_CTRL) & 1)) return 0; ptr = runtime->buffer_size - inw(ice->ddma_port + 4); if (ptr == runtime->buffer_size) ptr = 0; return bytes_to_frames(substream->runtime, ptr);}static snd_pcm_uframes_t snd_ice1712_playback_ds_pointer(snd_pcm_substream_t * substream){ ice1712_t *ice = snd_pcm_substream_chip(substream); u8 addr; size_t ptr; if (!(snd_ice1712_ds_read(ice, substream->number * 2, ICE1712_DSC_CONTROL) & 1)) return 0; if (ice->playback_con_active_buf[substream->number]) addr = ICE1712_DSC_ADDR1; else addr = ICE1712_DSC_ADDR0; ptr = snd_ice1712_ds_read(ice, substream->number * 2, addr) - ice->playback_con_virt_addr[substream->number]; if (ptr == substream->runtime->buffer_size) ptr = 0; return bytes_to_frames(substream->runtime, ptr);}static snd_pcm_uframes_t snd_ice1712_capture_pointer(snd_pcm_substream_t * substream){ ice1712_t *ice = snd_pcm_substream_chip(substream); size_t ptr; if (!(snd_ice1712_read(ice, ICE1712_IREG_CAP_CTRL) & 1)) return 0; ptr = inl(ICEREG(ice, CONCAP_ADDR)) - ice->capture_con_virt_addr; if (ptr == substream->runtime->buffer_size) ptr = 0; return bytes_to_frames(substream->runtime, ptr);}static snd_pcm_hardware_t snd_ice1712_playback ={ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, .rate_min = 4000, .rate_max = 48000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (64*1024), .period_bytes_min = 64, .period_bytes_max = (64*1024), .periods_min = 1, .periods_max = 1024, .fifo_size = 0,};static snd_pcm_hardware_t snd_ice1712_playback_ds ={ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE), .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, .rate_min = 4000, .rate_max = 48000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (128*1024), .period_bytes_min = 64, .period_bytes_max = (128*1024), .periods_min = 2, .periods_max = 2, .fifo_size = 0,};static snd_pcm_hardware_t snd_ice1712_capture ={ .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | SNDRV_PCM_INFO_MMAP_VALID), .formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE, .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000, .rate_min = 4000, .rate_max = 48000, .channels_min = 1, .channels_max = 2, .buffer_bytes_max = (64*1024), .period_bytes_min = 64, .period_bytes_max = (64*1024), .periods_min = 1, .periods_max = 1024, .fifo_size = 0,};static int snd_ice1712_playback_open(snd_pcm_substream_t * substream){ snd_pcm_runtime_t *runtime = substream->runtime; ice1712_t *ice = snd_pcm_substream_chip(substream); ice->playback_con_substream = substream; runtime->hw = snd_ice1712_playback; return 0;}static int snd_ice1712_playback_ds_open(snd_pcm_substream_t * substream){ snd_pcm_runtime_t *runtime = substream->runtime; ice1712_t *ice = snd_pcm_substream_chip(substream); u32 tmp; ice->playback_con_substream_ds[substream->number] = substream; runtime->hw = snd_ice1712_playback_ds; spin_lock_irq(&ice->reg_lock); tmp = inw(ICEDS(ice, INTMASK)) & ~(1 << (substream->number * 2)); outw(tmp, ICEDS(ice, INTMASK)); spin_unlock_irq(&ice->reg_lock); return 0;}static int snd_ice1712_capture_open(snd_pcm_substream_t * substream){ snd_pcm_runtime_t *runtime = substream->runtime; ice1712_t *ice = snd_pcm_substream_chip(substream); ice->capture_con_substream = substream; runtime->hw = snd_ice1712_capture; runtime->hw.rates = ice->ac97->rates[AC97_RATES_ADC]; if (!(runtime->hw.rates & SNDRV_PCM_RATE_8000)) runtime->hw.rate_min = 48000; return 0;}static int snd_ice1712_playback_close(snd_pcm_substream_t * substream){ ice1712_t *ice = snd_pcm_substream_chip(substream); ice->playback_con_substream = NULL; return 0;}static int snd_ice1712_playback_ds_close(snd_pcm_substream_t * substream){ ice1712_t *ice = snd_pcm_substream_chip(substream); u32 tmp; spin_lock_irq(&ice->reg_lock); tmp = inw(ICEDS(ice, INTMASK)) | (3 << (substream->number * 2)); outw(tmp, ICEDS(ice, INTMASK)); spin_unlock_irq(&ice->reg_lock); ice->playback_con_substream_ds[substream->number] = NULL; return 0;}static int snd_ice1712_capture_close(snd_pcm_substream_t * substream){ ice1712_t *ice = snd_pcm_substream_chip(substream); ice->capture_con_substream = NULL; return 0;}static snd_pcm_ops_t snd_ice1712_playback_ops = { .open = snd_ice1712_playback_open, .close = snd_ice1712_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_ice1712_hw_params, .hw_free = snd_ice1712_hw_free, .prepare = snd_ice1712_playback_prepare, .trigger = snd_ice1712_playback_trigger, .pointer = snd_ice1712_playback_pointer,};static snd_pcm_ops_t snd_ice1712_playback_ds_ops = { .open = snd_ice1712_playback_ds_open, .close = snd_ice1712_playback_ds_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_ice1712_hw_params, .hw_free = snd_ice1712_hw_free, .prepare = snd_ice1712_playback_ds_prepare, .trigger = snd_ice1712_playback_ds_trigger, .pointer = snd_ice1712_playback_ds_pointer,};static snd_pcm_ops_t snd_ice1712_capture_ops = { .open = snd_ice1712_capture_open, .close = snd_ice1712_capture_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_ice1712_hw_params, .hw_free = snd_ice1712_hw_free, .prepare = snd_ice1712_capture_prepare, .trigger = snd_ice1712_capture_trigger, .pointer = snd_ice1712_capture_pointer,};static void snd_ice1712_pcm_free(snd_pcm_t *pcm){ ice1712_t *ice = pcm->private_data; ice->pcm = NULL; snd_pcm_lib_preallocate_free_for_all(pcm);}static int __devinit snd_ice1712_pcm(ice1712_t * ice, int device, snd_pcm_t ** rpcm){ snd_pcm_t *pcm; int err; if (rpcm) *rpcm = NULL; err = snd_pcm_new(ice->card, "ICE1712 consumer", device, 1, 1, &pcm); if (err < 0) return err; snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_ice1712_playback_ops);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -