diff options
Diffstat (limited to 'sound/oss/ymfpci.c')
-rw-r--r-- | sound/oss/ymfpci.c | 2692 |
1 files changed, 0 insertions, 2692 deletions
diff --git a/sound/oss/ymfpci.c b/sound/oss/ymfpci.c deleted file mode 100644 index 6e22472df95..00000000000 --- a/sound/oss/ymfpci.c +++ /dev/null @@ -1,2692 +0,0 @@ -/* - * Copyright 1999 Jaroslav Kysela <perex@suse.cz> - * Copyright 2000 Alan Cox <alan@redhat.com> - * Copyright 2001 Kai Germaschewski <kai@tp1.ruhr-uni-bochum.de> - * Copyright 2002 Pete Zaitcev <zaitcev@yahoo.com> - * - * Yamaha YMF7xx driver. - * - * This code is a result of high-speed collision - * between ymfpci.c of ALSA and cs46xx.c of Linux. - * -- Pete Zaitcev <zaitcev@yahoo.com>; 2000/09/18 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * TODO: - * - Use P44Slot for 44.1 playback (beware of idle buzzing in P44Slot). - * - 96KHz playback for DVD - use pitch of 2.0. - * - Retain DMA buffer on close, do not wait the end of frame. - * - Resolve XXX tagged questions. - * - Cannot play 5133Hz. - * - 2001/01/07 Consider if we can remove voice_lock, like so: - * : Allocate/deallocate voices in open/close under semafore. - * : We access voices in interrupt, that only for pcms that open. - * voice_lock around playback_prepare closes interrupts for insane duration. - * - Revisit the way voice_alloc is done - too confusing, overcomplicated. - * Should support various channel types, however. - * - Remove prog_dmabuf from read/write, leave it in open. - * - 2001/01/07 Replace the OPL3 part of CONFIG_SOUND_YMFPCI_LEGACY code with - * native synthesizer through a playback slot. - * - 2001/11/29 ac97_save_state - * Talk to Kai to remove ac97_save_state before it's too late! - * - Second AC97 - * - Restore S/PDIF - Toshibas have it. - * - * Kai used pci_alloc_consistent for DMA buffer, which sounds a little - * unconventional. However, given how small our fragments can be, - * a little uncached access is perhaps better than endless flushing. - * On i386 and other I/O-coherent architectures pci_alloc_consistent - * is entirely harmless. - */ - -#include <linux/config.h> -#include <linux/module.h> -#include <linux/init.h> -#include <linux/interrupt.h> -#include <linux/ioport.h> -#include <linux/delay.h> -#include <linux/pci.h> -#include <linux/slab.h> -#include <linux/poll.h> -#include <linux/soundcard.h> -#include <linux/ac97_codec.h> -#include <linux/sound.h> - -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/uaccess.h> - -#ifdef CONFIG_SOUND_YMFPCI_LEGACY -# include "sound_config.h" -# include "mpu401.h" -#endif -#include "ymfpci.h" - -/* - * I do not believe in debug levels as I never can guess what - * part of the code is going to be problematic in the future. - * Don't forget to run your klogd with -c 8. - * - * Example (do not remove): - * #define YMFDBG(fmt, arg...) do{ printk(KERN_DEBUG fmt, ##arg); }while(0) - */ -#define YMFDBGW(fmt, arg...) /* */ /* write counts */ -#define YMFDBGI(fmt, arg...) /* */ /* interrupts */ -#define YMFDBGX(fmt, arg...) /* */ /* ioctl */ - -static int ymf_playback_trigger(ymfpci_t *unit, struct ymf_pcm *ypcm, int cmd); -static void ymf_capture_trigger(ymfpci_t *unit, struct ymf_pcm *ypcm, int cmd); -static void ymfpci_voice_free(ymfpci_t *unit, ymfpci_voice_t *pvoice); -static int ymf_capture_alloc(struct ymf_unit *unit, int *pbank); -static int ymf_playback_prepare(struct ymf_state *state); -static int ymf_capture_prepare(struct ymf_state *state); -static struct ymf_state *ymf_state_alloc(ymfpci_t *unit); - -static void ymfpci_aclink_reset(struct pci_dev * pci); -static void ymfpci_disable_dsp(ymfpci_t *unit); -static void ymfpci_download_image(ymfpci_t *codec); -static void ymf_memload(ymfpci_t *unit); - -static DEFINE_SPINLOCK(ymf_devs_lock); -static LIST_HEAD(ymf_devs); - -/* - * constants - */ - -static struct pci_device_id ymf_id_tbl[] = { -#define DEV(dev, data) \ - { PCI_VENDOR_ID_YAMAHA, dev, PCI_ANY_ID, PCI_ANY_ID, 0, 0, \ - (unsigned long)data } - DEV (PCI_DEVICE_ID_YAMAHA_724, "YMF724"), - DEV (PCI_DEVICE_ID_YAMAHA_724F, "YMF724F"), - DEV (PCI_DEVICE_ID_YAMAHA_740, "YMF740"), - DEV (PCI_DEVICE_ID_YAMAHA_740C, "YMF740C"), - DEV (PCI_DEVICE_ID_YAMAHA_744, "YMF744"), - DEV (PCI_DEVICE_ID_YAMAHA_754, "YMF754"), -#undef DEV - { } -}; -MODULE_DEVICE_TABLE(pci, ymf_id_tbl); - -/* - * common I/O routines - */ - -static inline void ymfpci_writeb(ymfpci_t *codec, u32 offset, u8 val) -{ - writeb(val, codec->reg_area_virt + offset); -} - -static inline u16 ymfpci_readw(ymfpci_t *codec, u32 offset) -{ - return readw(codec->reg_area_virt + offset); -} - -static inline void ymfpci_writew(ymfpci_t *codec, u32 offset, u16 val) -{ - writew(val, codec->reg_area_virt + offset); -} - -static inline u32 ymfpci_readl(ymfpci_t *codec, u32 offset) -{ - return readl(codec->reg_area_virt + offset); -} - -static inline void ymfpci_writel(ymfpci_t *codec, u32 offset, u32 val) -{ - writel(val, codec->reg_area_virt + offset); -} - -static int ymfpci_codec_ready(ymfpci_t *codec, int secondary, int sched) -{ - signed long end_time; - u32 reg = secondary ? YDSXGR_SECSTATUSADR : YDSXGR_PRISTATUSADR; - - end_time = jiffies + 3 * (HZ / 4); - do { - if ((ymfpci_readw(codec, reg) & 0x8000) == 0) - return 0; - if (sched) { - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); - } - } while (end_time - (signed long)jiffies >= 0); - printk(KERN_ERR "ymfpci_codec_ready: codec %i is not ready [0x%x]\n", - secondary, ymfpci_readw(codec, reg)); - return -EBUSY; -} - -static void ymfpci_codec_write(struct ac97_codec *dev, u8 reg, u16 val) -{ - ymfpci_t *codec = dev->private_data; - u32 cmd; - - spin_lock(&codec->ac97_lock); - /* XXX Do make use of dev->id */ - ymfpci_codec_ready(codec, 0, 0); - cmd = ((YDSXG_AC97WRITECMD | reg) << 16) | val; - ymfpci_writel(codec, YDSXGR_AC97CMDDATA, cmd); - spin_unlock(&codec->ac97_lock); -} - -static u16 _ymfpci_codec_read(ymfpci_t *unit, u8 reg) -{ - int i; - - if (ymfpci_codec_ready(unit, 0, 0)) - return ~0; - ymfpci_writew(unit, YDSXGR_AC97CMDADR, YDSXG_AC97READCMD | reg); - if (ymfpci_codec_ready(unit, 0, 0)) - return ~0; - if (unit->pci->device == PCI_DEVICE_ID_YAMAHA_744 && unit->rev < 2) { - for (i = 0; i < 600; i++) - ymfpci_readw(unit, YDSXGR_PRISTATUSDATA); - } - return ymfpci_readw(unit, YDSXGR_PRISTATUSDATA); -} - -static u16 ymfpci_codec_read(struct ac97_codec *dev, u8 reg) -{ - ymfpci_t *unit = dev->private_data; - u16 ret; - - spin_lock(&unit->ac97_lock); - ret = _ymfpci_codec_read(unit, reg); - spin_unlock(&unit->ac97_lock); - - return ret; -} - -/* - * Misc routines - */ - -/* - * Calculate the actual sampling rate relatetively to the base clock (48kHz). - */ -static u32 ymfpci_calc_delta(u32 rate) -{ - switch (rate) { - case 8000: return 0x02aaab00; - case 11025: return 0x03accd00; - case 16000: return 0x05555500; - case 22050: return 0x07599a00; - case 32000: return 0x0aaaab00; - case 44100: return 0x0eb33300; - default: return ((rate << 16) / 48000) << 12; - } -} - -static u32 def_rate[8] = { - 100, 2000, 8000, 11025, 16000, 22050, 32000, 48000 -}; - -static u32 ymfpci_calc_lpfK(u32 rate) -{ - u32 i; - static u32 val[8] = { - 0x00570000, 0x06AA0000, 0x18B20000, 0x20930000, - 0x2B9A0000, 0x35A10000, 0x3EAA0000, 0x40000000 - }; - - if (rate == 44100) - return 0x40000000; /* FIXME: What's the right value? */ - for (i = 0; i < 8; i++) - if (rate <= def_rate[i]) - return val[i]; - return val[0]; -} - -static u32 ymfpci_calc_lpfQ(u32 rate) -{ - u32 i; - static u32 val[8] = { - 0x35280000, 0x34A70000, 0x32020000, 0x31770000, - 0x31390000, 0x31C90000, 0x33D00000, 0x40000000 - }; - - if (rate == 44100) - return 0x370A0000; - for (i = 0; i < 8; i++) - if (rate <= def_rate[i]) - return val[i]; - return val[0]; -} - -static u32 ymf_calc_lend(u32 rate) -{ - return (rate * YMF_SAMPF) / 48000; -} - -/* - * We ever allow only a few formats, but let's be generic, for smaller surprise. - */ -static int ymf_pcm_format_width(int format) -{ - static int mask16 = AFMT_S16_LE|AFMT_S16_BE|AFMT_U16_LE|AFMT_U16_BE; - - if ((format & (format-1)) != 0) { - printk(KERN_ERR "ymfpci: format 0x%x is not a power of 2\n", format); - return 8; - } - - if (format == AFMT_IMA_ADPCM) return 4; - if ((format & mask16) != 0) return 16; - return 8; -} - -static void ymf_pcm_update_shift(struct ymf_pcm_format *f) -{ - f->shift = 0; - if (f->voices == 2) - f->shift++; - if (ymf_pcm_format_width(f->format) == 16) - f->shift++; -} - -/* Are you sure 32K is not too much? See if mpg123 skips on loaded systems. */ -#define DMABUF_DEFAULTORDER (15-PAGE_SHIFT) -#define DMABUF_MINORDER 1 - -/* - * Allocate DMA buffer - */ -static int alloc_dmabuf(ymfpci_t *unit, struct ymf_dmabuf *dmabuf) -{ - void *rawbuf = NULL; - dma_addr_t dma_addr; - int order; - struct page *map, *mapend; - - /* alloc as big a chunk as we can */ - for (order = DMABUF_DEFAULTORDER; order >= DMABUF_MINORDER; order--) { - rawbuf = pci_alloc_consistent(unit->pci, PAGE_SIZE << order, &dma_addr); - if (rawbuf) - break; - } - if (!rawbuf) - return -ENOMEM; - -#if 0 - printk(KERN_DEBUG "ymfpci: allocated %ld (order = %d) bytes at %p\n", - PAGE_SIZE << order, order, rawbuf); -#endif - - dmabuf->ready = dmabuf->mapped = 0; - dmabuf->rawbuf = rawbuf; - dmabuf->dma_addr = dma_addr; - dmabuf->buforder = order; - - /* now mark the pages as reserved; otherwise remap_pfn_range doesn't do what we want */ - mapend = virt_to_page(rawbuf + (PAGE_SIZE << order) - 1); - for (map = virt_to_page(rawbuf); map <= mapend; map++) - set_bit(PG_reserved, &map->flags); - - return 0; -} - -/* - * Free DMA buffer - */ -static void dealloc_dmabuf(ymfpci_t *unit, struct ymf_dmabuf *dmabuf) -{ - struct page *map, *mapend; - - if (dmabuf->rawbuf) { - /* undo marking the pages as reserved */ - mapend = virt_to_page(dmabuf->rawbuf + (PAGE_SIZE << dmabuf->buforder) - 1); - for (map = virt_to_page(dmabuf->rawbuf); map <= mapend; map++) - clear_bit(PG_reserved, &map->flags); - - pci_free_consistent(unit->pci, PAGE_SIZE << dmabuf->buforder, - dmabuf->rawbuf, dmabuf->dma_addr); - } - dmabuf->rawbuf = NULL; - dmabuf->mapped = dmabuf->ready = 0; -} - -static int prog_dmabuf(struct ymf_state *state, int rec) -{ - struct ymf_dmabuf *dmabuf; - int w_16; - unsigned bufsize; - unsigned long flags; - int redzone, redfrags; - int ret; - - w_16 = ymf_pcm_format_width(state->format.format) == 16; - dmabuf = rec ? &state->rpcm.dmabuf : &state->wpcm.dmabuf; - - spin_lock_irqsave(&state->unit->reg_lock, flags); - dmabuf->hwptr = dmabuf->swptr = 0; - dmabuf->total_bytes = 0; - dmabuf->count = 0; - spin_unlock_irqrestore(&state->unit->reg_lock, flags); - - /* allocate DMA buffer if not allocated yet */ - if (!dmabuf->rawbuf) - if ((ret = alloc_dmabuf(state->unit, dmabuf))) - return ret; - - /* - * Create fake fragment sizes and numbers for OSS ioctls. - * Import what Doom might have set with SNDCTL_DSP_SETFRAGMENT. - */ - bufsize = PAGE_SIZE << dmabuf->buforder; - /* By default we give 4 big buffers. */ - dmabuf->fragshift = (dmabuf->buforder + PAGE_SHIFT - 2); - if (dmabuf->ossfragshift > 3 && - dmabuf->ossfragshift < dmabuf->fragshift) { - /* If OSS set smaller fragments, give more smaller buffers. */ - dmabuf->fragshift = dmabuf->ossfragshift; - } - dmabuf->fragsize = 1 << dmabuf->fragshift; - - dmabuf->numfrag = bufsize >> dmabuf->fragshift; - dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift; - - if (dmabuf->ossmaxfrags >= 2) { - redzone = ymf_calc_lend(state->format.rate); - redzone <<= state->format.shift; - redzone *= 3; - redfrags = (redzone + dmabuf->fragsize-1) >> dmabuf->fragshift; - - if (dmabuf->ossmaxfrags + redfrags < dmabuf->numfrag) { - dmabuf->numfrag = dmabuf->ossmaxfrags + redfrags; - dmabuf->dmasize = dmabuf->numfrag << dmabuf->fragshift; - } - } - - memset(dmabuf->rawbuf, w_16 ? 0 : 0x80, dmabuf->dmasize); - - /* - * Now set up the ring - */ - - /* XXX ret = rec? cap_pre(): pbk_pre(); */ - spin_lock_irqsave(&state->unit->voice_lock, flags); - if (rec) { - if ((ret = ymf_capture_prepare(state)) != 0) { - spin_unlock_irqrestore(&state->unit->voice_lock, flags); - return ret; - } - } else { - if ((ret = ymf_playback_prepare(state)) != 0) { - spin_unlock_irqrestore(&state->unit->voice_lock, flags); - return ret; - } - } - spin_unlock_irqrestore(&state->unit->voice_lock, flags); - - /* set the ready flag for the dma buffer (this comment is not stupid) */ - dmabuf->ready = 1; - -#if 0 - printk(KERN_DEBUG "prog_dmabuf: rate %d format 0x%x," - " numfrag %d fragsize %d dmasize %d\n", - state->format.rate, state->format.format, dmabuf->numfrag, - dmabuf->fragsize, dmabuf->dmasize); -#endif - - return 0; -} - -static void ymf_start_dac(struct ymf_state *state) -{ - ymf_playback_trigger(state->unit, &state->wpcm, 1); -} - -// static void ymf_start_adc(struct ymf_state *state) -// { -// ymf_capture_trigger(state->unit, &state->rpcm, 1); -// } - -/* - * Wait until output is drained. - * This does not kill the hardware for the sake of ioctls. - */ -static void ymf_wait_dac(struct ymf_state *state) -{ - struct ymf_unit *unit = state->unit; - struct ymf_pcm *ypcm = &state->wpcm; - DECLARE_WAITQUEUE(waita, current); - unsigned long flags; - - add_wait_queue(&ypcm->dmabuf.wait, &waita); - - spin_lock_irqsave(&unit->reg_lock, flags); - if (ypcm->dmabuf.count != 0 && !ypcm->running) { - ymf_playback_trigger(unit, ypcm, 1); - } - -#if 0 - if (file->f_flags & O_NONBLOCK) { - /* - * XXX Our mistake is to attach DMA buffer to state - * rather than to some per-device structure. - * Cannot skip waiting, can only make it shorter. - */ - } -#endif - - set_current_state(TASK_UNINTERRUPTIBLE); - while (ypcm->running) { - spin_unlock_irqrestore(&unit->reg_lock, flags); - schedule(); - spin_lock_irqsave(&unit->reg_lock, flags); - set_current_state(TASK_UNINTERRUPTIBLE); - } - spin_unlock_irqrestore(&unit->reg_lock, flags); - - set_current_state(TASK_RUNNING); - remove_wait_queue(&ypcm->dmabuf.wait, &waita); - - /* - * This function may take up to 4 seconds to reach this point - * (32K circular buffer, 8000 Hz). User notices. - */ -} - -/* Can just stop, without wait. Or can we? */ -static void ymf_stop_adc(struct ymf_state *state) -{ - struct ymf_unit *unit = state->unit; - unsigned long flags; - - spin_lock_irqsave(&unit->reg_lock, flags); - ymf_capture_trigger(unit, &state->rpcm, 0); - spin_unlock_irqrestore(&unit->reg_lock, flags); -} - -/* - * Hardware start management - */ - -static void ymfpci_hw_start(ymfpci_t *unit) -{ - unsigned long flags; - - spin_lock_irqsave(&unit->reg_lock, flags); - if (unit->start_count++ == 0) { - ymfpci_writel(unit, YDSXGR_MODE, - ymfpci_readl(unit, YDSXGR_MODE) | 3); - unit->active_bank = ymfpci_readl(unit, YDSXGR_CTRLSELECT) & 1; - } - spin_unlock_irqrestore(&unit->reg_lock, flags); -} - -static void ymfpci_hw_stop(ymfpci_t *unit) -{ - unsigned long flags; - long timeout = 1000; - - spin_lock_irqsave(&unit->reg_lock, flags); - if (--unit->start_count == 0) { - ymfpci_writel(unit, YDSXGR_MODE, - ymfpci_readl(unit, YDSXGR_MODE) & ~3); - while (timeout-- > 0) { - if ((ymfpci_readl(unit, YDSXGR_STATUS) & 2) == 0) - break; - } - } - spin_unlock_irqrestore(&unit->reg_lock, flags); -} - -/* - * Playback voice management - */ - -static int voice_alloc(ymfpci_t *codec, ymfpci_voice_type_t type, int pair, ymfpci_voice_t *rvoice[]) -{ - ymfpci_voice_t *voice, *voice2; - int idx; - - for (idx = 0; idx < YDSXG_PLAYBACK_VOICES; idx += pair ? 2 : 1) { - voice = &codec->voices[idx]; - voice2 = pair ? &codec->voices[idx+1] : NULL; - if (voice->use || (voice2 && voice2->use)) - continue; - voice->use = 1; - if (voice2) - voice2->use = 1; - switch (type) { - case YMFPCI_PCM: - voice->pcm = 1; - if (voice2) - voice2->pcm = 1; - break; - case YMFPCI_SYNTH: - voice->synth = 1; - break; - case YMFPCI_MIDI: - voice->midi = 1; - break; - } - ymfpci_hw_start(codec); - rvoice[0] = voice; - if (voice2) { - ymfpci_hw_start(codec); - rvoice[1] = voice2; - } - return 0; - } - return -EBUSY; /* Your audio channel is open by someone else. */ -} - -static void ymfpci_voice_free(ymfpci_t *unit, ymfpci_voice_t *pvoice) -{ - ymfpci_hw_stop(unit); - pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; - pvoice->ypcm = NULL; -} - -/* - */ - -static void ymf_pcm_interrupt(ymfpci_t *codec, ymfpci_voice_t *voice) -{ - struct ymf_pcm *ypcm; - int redzone; - int pos, delta, swptr; - int played, distance; - struct ymf_state *state; - struct ymf_dmabuf *dmabuf; - char silence; - - if ((ypcm = voice->ypcm) == NULL) { - return; - } - if ((state = ypcm->state) == NULL) { - ypcm->running = 0; // lock it - return; - } - dmabuf = &ypcm->dmabuf; - spin_lock(&codec->reg_lock); - if (ypcm->running) { - YMFDBGI("ymfpci: %d, intr bank %d count %d start 0x%x:%x\n", - voice->number, codec->active_bank, dmabuf->count, - le32_to_cpu(voice->bank[0].start), - le32_to_cpu(voice->bank[1].start)); - silence = (ymf_pcm_format_width(state->format.format) == 16) ? - 0 : 0x80; - /* We need actual left-hand-side redzone size here. */ - redzone = ymf_calc_lend(state->format.rate); - redzone <<= (state->format.shift + 1); - swptr = dmabuf->swptr; - - pos = le32_to_cpu(voice->bank[codec->active_bank].start); - pos <<= state->format.shift; - if (pos < 0 || pos >= dmabuf->dmasize) { /* ucode bug */ - printk(KERN_ERR "ymfpci%d: runaway voice %d: hwptr %d=>%d dmasize %d\n", - codec->dev_audio, voice->number, - dmabuf->hwptr, pos, dmabuf->dmasize); - pos = 0; - } - if (pos < dmabuf->hwptr) { - delta = dmabuf->dmasize - dmabuf->hwptr; - memset(dmabuf->rawbuf + dmabuf->hwptr, silence, delta); - delta += pos; - memset(dmabuf->rawbuf, silence, pos); - } else { - delta = pos - dmabuf->hwptr; - memset(dmabuf->rawbuf + dmabuf->hwptr, silence, delta); - } - dmabuf->hwptr = pos; - - if (dmabuf->count == 0) { - printk(KERN_ERR "ymfpci%d: %d: strain: hwptr %d\n", - codec->dev_audio, voice->number, dmabuf->hwptr); - ymf_playback_trigger(codec, ypcm, 0); - } - - if (swptr <= pos) { - distance = pos - swptr; - } else { - distance = dmabuf->dmasize - (swptr - pos); - } - if (distance < redzone) { - /* - * hwptr inside redzone => DMA ran out of samples. - */ - if (delta < dmabuf->count) { - /* - * Lost interrupt or other screwage. - */ - printk(KERN_ERR "ymfpci%d: %d: lost: delta %d" - " hwptr %d swptr %d distance %d count %d\n", - codec->dev_audio, voice->number, delta, - dmabuf->hwptr, swptr, distance, dmabuf->count); - } else { - /* - * Normal end of DMA. - */ - YMFDBGI("ymfpci%d: %d: done: delta %d" - " hwptr %d swptr %d distance %d count %d\n", - codec->dev_audio, voice->number, delta, - dmabuf->hwptr, swptr, distance, dmabuf->count); - } - played = dmabuf->count; - if (ypcm->running) { - ymf_playback_trigger(codec, ypcm, 0); - } - } else { - /* - * hwptr is chipping away towards a remote swptr. - * Calculate other distance and apply it to count. - */ - if (swptr >= pos) { - distance = swptr - pos; - } else { - distance = dmabuf->dmasize - (pos - swptr); - } - if (distance < dmabuf->count) { - played = dmabuf->count - distance; - } else { - played = 0; - } - } - - dmabuf->total_bytes += played; - dmabuf->count -= played; - if (dmabuf->count < dmabuf->dmasize / 2) { - wake_up(&dmabuf->wait); - } - } - spin_unlock(&codec->reg_lock); -} - -static void ymf_cap_interrupt(ymfpci_t *unit, struct ymf_capture *cap) -{ - struct ymf_pcm *ypcm; - int redzone; - struct ymf_state *state; - struct ymf_dmabuf *dmabuf; - int pos, delta; - int cnt; - - if ((ypcm = cap->ypcm) == NULL) { - return; - } - if ((state = ypcm->state) == NULL) { - ypcm->running = 0; // lock it - return; - } - dmabuf = &ypcm->dmabuf; - spin_lock(&unit->reg_lock); - if (ypcm->running) { - redzone = ymf_calc_lend(state->format.rate); - redzone <<= (state->format.shift + 1); - - pos = le32_to_cpu(cap->bank[unit->active_bank].start); - // pos <<= state->format.shift; - if (pos < 0 || pos >= dmabuf->dmasize) { /* ucode bug */ - printk(KERN_ERR "ymfpci%d: runaway capture %d: hwptr %d=>%d dmasize %d\n", - unit->dev_audio, ypcm->capture_bank_number, - dmabuf->hwptr, pos, dmabuf->dmasize); - pos = 0; - } - if (pos < dmabuf->hwptr) { - delta = dmabuf->dmasize - dmabuf->hwptr; - delta += pos; - } else { - delta = pos - dmabuf->hwptr; - } - dmabuf->hwptr = pos; - - cnt = dmabuf->count; - cnt += delta; - if (cnt + redzone > dmabuf->dmasize) { - /* Overflow - bump swptr */ - dmabuf->count = dmabuf->dmasize - redzone; - dmabuf->swptr = dmabuf->hwptr + redzone; - if (dmabuf->swptr >= dmabuf->dmasize) { - dmabuf->swptr -= dmabuf->dmasize; - } - } else { - dmabuf->count = cnt; - } - - dmabuf->total_bytes += delta; - if (dmabuf->count) { /* && is_sleeping XXX */ - wake_up(&dmabuf->wait); - } - } - spin_unlock(&unit->reg_lock); -} - -static int ymf_playback_trigger(ymfpci_t *codec, struct ymf_pcm *ypcm, int cmd) -{ - - if (ypcm->voices[0] == NULL) { - return -EINVAL; - } - if (cmd != 0) { - codec->ctrl_playback[ypcm->voices[0]->number + 1] = - cpu_to_le32(ypcm->voices[0]->bank_ba); - if (ypcm->voices[1] != NULL) - codec->ctrl_playback[ypcm->voices[1]->number + 1] = - cpu_to_le32(ypcm->voices[1]->bank_ba); - ypcm->running = 1; - } else { - codec->ctrl_playback[ypcm->voices[0]->number + 1] = 0; - if (ypcm->voices[1] != NULL) - codec->ctrl_playback[ypcm->voices[1]->number + 1] = 0; - ypcm->running = 0; - } - return 0; -} - -static void ymf_capture_trigger(ymfpci_t *codec, struct ymf_pcm *ypcm, int cmd) -{ - u32 tmp; - - if (cmd != 0) { - tmp = ymfpci_readl(codec, YDSXGR_MAPOFREC) | (1 << ypcm->capture_bank_number); - ymfpci_writel(codec, YDSXGR_MAPOFREC, tmp); - ypcm->running = 1; - } else { - tmp = ymfpci_readl(codec, YDSXGR_MAPOFREC) & ~(1 << ypcm->capture_bank_number); - ymfpci_writel(codec, YDSXGR_MAPOFREC, tmp); - ypcm->running = 0; - } -} - -static int ymfpci_pcm_voice_alloc(struct ymf_pcm *ypcm, int voices) -{ - struct ymf_unit *unit; - int err; - - unit = ypcm->state->unit; - if (ypcm->voices[1] != NULL && voices < 2) { - ymfpci_voice_free(unit, ypcm->voices[1]); - ypcm->voices[1] = NULL; - } - if (voices == 1 && ypcm->voices[0] != NULL) - return 0; /* already allocated */ - if (voices == 2 && ypcm->voices[0] != NULL && ypcm->voices[1] != NULL) - return 0; /* already allocated */ - if (voices > 1) { - if (ypcm->voices[0] != NULL && ypcm->voices[1] == NULL) { - ymfpci_voice_free(unit, ypcm->voices[0]); - ypcm->voices[0] = NULL; - } - if ((err = voice_alloc(unit, YMFPCI_PCM, 1, ypcm->voices)) < 0) - return err; - ypcm->voices[0]->ypcm = ypcm; - ypcm->voices[1]->ypcm = ypcm; - } else { - if ((err = voice_alloc(unit, YMFPCI_PCM, 0, ypcm->voices)) < 0) - return err; - ypcm->voices[0]->ypcm = ypcm; - } - return 0; -} - -static void ymf_pcm_init_voice(ymfpci_voice_t *voice, int stereo, - int rate, int w_16, unsigned long addr, unsigned int end, int spdif) -{ - u32 format; - u32 delta = ymfpci_calc_delta(rate); - u32 lpfQ = ymfpci_calc_lpfQ(rate); - u32 lpfK = ymfpci_calc_lpfK(rate); - ymfpci_playback_bank_t *bank; - int nbank; - - /* - * The gain is a floating point number. According to the manual, - * bit 31 indicates a sign bit, bit 30 indicates an integer part, - * and bits [29:15] indicate a decimal fraction part. Thus, - * for a gain of 1.0 the constant of 0x40000000 is loaded. - */ - unsigned default_gain = cpu_to_le32(0x40000000); - - format = (stereo ? 0x00010000 : 0) | (w_16 ? 0 : 0x80000000); - if (stereo) - end >>= 1; - if (w_16) - end >>= 1; - for (nbank = 0; nbank < 2; nbank++) { - bank = &voice->bank[nbank]; - bank->format = cpu_to_le32(format); - bank->loop_default = 0; /* 0-loops forever, otherwise count */ - bank->base = cpu_to_le32(addr); - bank->loop_start = 0; - bank->loop_end = cpu_to_le32(end); - bank->loop_frac = 0; - bank->eg_gain_end = default_gain; - bank->lpfQ = cpu_to_le32(lpfQ); - bank->status = 0; - bank->num_of_frames = 0; - bank->loop_count = 0; - bank->start = 0; - bank->start_frac = 0; - bank->delta = - bank->delta_end = cpu_to_le32(delta); - bank->lpfK = - bank->lpfK_end = cpu_to_le32(lpfK); - bank->eg_gain = default_gain; - bank->lpfD1 = - bank->lpfD2 = 0; - - bank->left_gain = - bank->right_gain = - bank->left_gain_end = - bank->right_gain_end = - bank->eff1_gain = - bank->eff2_gain = - bank->eff3_gain = - bank->eff1_gain_end = - bank->eff2_gain_end = - bank->eff3_gain_end = 0; - - if (!stereo) { - if (!spdif) { - bank->left_gain = - bank->right_gain = - bank->left_gain_end = - bank->right_gain_end = default_gain; - } else { - bank->eff2_gain = - bank->eff2_gain_end = - bank->eff3_gain = - bank->eff3_gain_end = default_gain; - } - } else { - if (!spdif) { - if ((voice->number & 1) == 0) { - bank->left_gain = - bank->left_gain_end = default_gain; - } else { - bank->format |= cpu_to_le32(1); - bank->right_gain = - bank->right_gain_end = default_gain; - } - } else { - if ((voice->number & 1) == 0) { - bank->eff2_gain = - bank->eff2_gain_end = default_gain; - } else { - bank->format |= cpu_to_le32(1); - bank->eff3_gain = - bank->eff3_gain_end = default_gain; - } - } - } - } -} - -/* - * XXX Capture channel allocation is entirely fake at the moment. - * We use only one channel and mark it busy as required. - */ -static int ymf_capture_alloc(struct ymf_unit *unit, int *pbank) -{ - struct ymf_capture *cap; - int cbank; - - cbank = 1; /* Only ADC slot is used for now. */ - cap = &unit->capture[cbank]; - if (cap->use) - return -EBUSY; - cap->use = 1; - *pbank = cbank; - return 0; -} - -static int ymf_playback_prepare(struct ymf_state *state) -{ - struct ymf_pcm *ypcm = &state->wpcm; - int err, nvoice; - - if ((err = ymfpci_pcm_voice_alloc(ypcm, state->format.voices)) < 0) { - /* Somebody started 32 mpg123's in parallel? */ - printk(KERN_INFO "ymfpci%d: cannot allocate voice\n", - state->unit->dev_audio); - return err; - } - - for (nvoice = 0; nvoice < state->format.voices; nvoice++) { - ymf_pcm_init_voice(ypcm->voices[nvoice], - state->format.voices == 2, state->format.rate, - ymf_pcm_format_width(state->format.format) == 16, - ypcm->dmabuf.dma_addr, ypcm->dmabuf.dmasize, - ypcm->spdif); - } - return 0; -} - -static int ymf_capture_prepare(struct ymf_state *state) -{ - ymfpci_t *unit = state->unit; - struct ymf_pcm *ypcm = &state->rpcm; - ymfpci_capture_bank_t * bank; - /* XXX This is confusing, gotta rename one of them banks... */ - int nbank; /* flip-flop bank */ - int cbank; /* input [super-]bank */ - struct ymf_capture *cap; - u32 rate, format; - - if (ypcm->capture_bank_number == -1) { - if (ymf_capture_alloc(unit, &cbank) != 0) - return -EBUSY; - - ypcm->capture_bank_number = cbank; - - cap = &unit->capture[cbank]; - cap->bank = unit->bank_capture[cbank][0]; - cap->ypcm = ypcm; - ymfpci_hw_start(unit); - } - - // ypcm->frag_size = snd_pcm_lib_transfer_fragment(substream); - // frag_size is replaced with nonfragged byte-aligned rolling buffer - rate = ((48000 * 4096) / state->format.rate) - 1; - format = 0; - if (state->format.voices == 2) - format |= 2; - if (ymf_pcm_format_width(state->format.format) == 8) - format |= 1; - switch (ypcm->capture_bank_number) { - case 0: - ymfpci_writel(unit, YDSXGR_RECFORMAT, format); - ymfpci_writel(unit, YDSXGR_RECSLOTSR, rate); - break; - case 1: - ymfpci_writel(unit, YDSXGR_ADCFORMAT, format); - ymfpci_writel(unit, YDSXGR_ADCSLOTSR, rate); - break; - } - for (nbank = 0; nbank < 2; nbank++) { - bank = unit->bank_capture[ypcm->capture_bank_number][nbank]; - bank->base = cpu_to_le32(ypcm->dmabuf.dma_addr); - // bank->loop_end = ypcm->dmabuf.dmasize >> state->format.shift; - bank->loop_end = cpu_to_le32(ypcm->dmabuf.dmasize); - bank->start = 0; - bank->num_of_loops = 0; - } -#if 0 /* s/pdif */ - if (state->digital.dig_valid) - /*state->digital.type == SND_PCM_DIG_AES_IEC958*/ - ymfpci_writew(codec, YDSXGR_SPDIFOUTSTATUS, - state->digital.dig_status[0] | (state->digital.dig_status[1] << 8)); -#endif - return 0; -} - -static irqreturn_t ymf_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - ymfpci_t *codec = dev_id; - u32 status, nvoice, mode; - struct ymf_voice *voice; - struct ymf_capture *cap; - - status = ymfpci_readl(codec, YDSXGR_STATUS); - if (status & 0x80000000) { - codec->active_bank = ymfpci_readl(codec, YDSXGR_CTRLSELECT) & 1; - spin_lock(&codec->voice_lock); - for (nvoice = 0; nvoice < YDSXG_PLAYBACK_VOICES; nvoice++) { - voice = &codec->voices[nvoice]; - if (voice->use) - ymf_pcm_interrupt(codec, voice); - } - for (nvoice = 0; nvoice < YDSXG_CAPTURE_VOICES; nvoice++) { - cap = &codec->capture[nvoice]; - if (cap->use) - ymf_cap_interrupt(codec, cap); - } - spin_unlock(&codec->voice_lock); - spin_lock(&codec->reg_lock); - ymfpci_writel(codec, YDSXGR_STATUS, 0x80000000); - mode = ymfpci_readl(codec, YDSXGR_MODE) | 2; - ymfpci_writel(codec, YDSXGR_MODE, mode); - spin_unlock(&codec->reg_lock); - } - - status = ymfpci_readl(codec, YDSXGR_INTFLAG); - if (status & 1) { - /* timer handler */ - ymfpci_writel(codec, YDSXGR_INTFLAG, ~0); - } - return IRQ_HANDLED; -} - -static void ymf_pcm_free_substream(struct ymf_pcm *ypcm) -{ - unsigned long flags; - struct ymf_unit *unit; - - unit = ypcm->state->unit; - - if (ypcm->type == PLAYBACK_VOICE) { - spin_lock_irqsave(&unit->voice_lock, flags); - if (ypcm->voices[1]) - ymfpci_voice_free(unit, ypcm->voices[1]); - if (ypcm->voices[0]) - ymfpci_voice_free(unit, ypcm->voices[0]); - spin_unlock_irqrestore(&unit->voice_lock, flags); - } else { - if (ypcm->capture_bank_number != -1) { - unit->capture[ypcm->capture_bank_number].use = 0; - ypcm->capture_bank_number = -1; - ymfpci_hw_stop(unit); - } - } -} - -static struct ymf_state *ymf_state_alloc(ymfpci_t *unit) -{ - struct ymf_pcm *ypcm; - struct ymf_state *state; - - if ((state = kmalloc(sizeof(struct ymf_state), GFP_KERNEL)) == NULL) { - goto out0; - } - memset(state, 0, sizeof(struct ymf_state)); - - ypcm = &state->wpcm; - ypcm->state = state; - ypcm->type = PLAYBACK_VOICE; - ypcm->capture_bank_number = -1; - init_waitqueue_head(&ypcm->dmabuf.wait); - - ypcm = &state->rpcm; - ypcm->state = state; - ypcm->type = CAPTURE_AC97; - ypcm->capture_bank_number = -1; - init_waitqueue_head(&ypcm->dmabuf.wait); - - state->unit = unit; - - state->format.format = AFMT_U8; - state->format.rate = 8000; - state->format.voices = 1; - ymf_pcm_update_shift(&state->format); - - return state; - -out0: - return NULL; -} - -/* AES/IEC958 channel status bits */ -#define SND_PCM_AES0_PROFESSIONAL (1<<0) /* 0 = consumer, 1 = professional */ -#define SND_PCM_AES0_NONAUDIO (1<<1) /* 0 = audio, 1 = non-audio */ -#define SND_PCM_AES0_PRO_EMPHASIS (7<<2) /* mask - emphasis */ -#define SND_PCM_AES0_PRO_EMPHASIS_NOTID (0<<2) /* emphasis not indicated */ -#define SND_PCM_AES0_PRO_EMPHASIS_NONE (1<<2) /* none emphasis */ -#define SND_PCM_AES0_PRO_EMPHASIS_5015 (3<<2) /* 50/15us emphasis */ -#define SND_PCM_AES0_PRO_EMPHASIS_CCITT (7<<2) /* CCITT J.17 emphasis */ -#define SND_PCM_AES0_PRO_FREQ_UNLOCKED (1<<5) /* source sample frequency: 0 = locked, 1 = unlocked */ -#define SND_PCM_AES0_PRO_FS (3<<6) /* mask - sample frequency */ -#define SND_PCM_AES0_PRO_FS_NOTID (0<<6) /* fs not indicated */ -#define SND_PCM_AES0_PRO_FS_44100 (1<<6) /* 44.1kHz */ -#define SND_PCM_AES0_PRO_FS_48000 (2<<6) /* 48kHz */ -#define SND_PCM_AES0_PRO_FS_32000 (3<<6) /* 32kHz */ -#define SND_PCM_AES0_CON_NOT_COPYRIGHT (1<<2) /* 0 = copyright, 1 = not copyright */ -#define SND_PCM_AES0_CON_EMPHASIS (7<<3) /* mask - emphasis */ -#define SND_PCM_AES0_CON_EMPHASIS_NONE (0<<3) /* none emphasis */ -#define SND_PCM_AES0_CON_EMPHASIS_5015 (1<<3) /* 50/15us emphasis */ -#define SND_PCM_AES0_CON_MODE (3<<6) /* mask - mode */ -#define SND_PCM_AES1_PRO_MODE (15<<0) /* mask - channel mode */ -#define SND_PCM_AES1_PRO_MODE_NOTID (0<<0) /* not indicated */ -#define SND_PCM_AES1_ |