aboutsummaryrefslogtreecommitdiff
path: root/sound/oss/via82cxxx_audio.c
diff options
context:
space:
mode:
authorAdrian Bunk <bunk@kernel.org>2008-02-06 01:36:36 -0800
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-06 10:41:02 -0800
commit83bad1d764b836a482b88e0a1f44d7a5c3e1fee0 (patch)
tree2fe0844d81a178ab51c22f41accef9b332ea86b6 /sound/oss/via82cxxx_audio.c
parentb4cf9c342a2887f425780c23ad2be3077949cee2 (diff)
scheduled OSS driver removal
This patch contains the scheduled removal of OSS drivers whose config options have been removed in 2.6.23. Signed-off-by: Adrian Bunk <bunk@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'sound/oss/via82cxxx_audio.c')
-rw-r--r--sound/oss/via82cxxx_audio.c3616
1 files changed, 0 insertions, 3616 deletions
diff --git a/sound/oss/via82cxxx_audio.c b/sound/oss/via82cxxx_audio.c
deleted file mode 100644
index f95aa094675..00000000000
--- a/sound/oss/via82cxxx_audio.c
+++ /dev/null
@@ -1,3616 +0,0 @@
-/*
- * Support for VIA 82Cxxx Audio Codecs
- * Copyright 1999,2000 Jeff Garzik
- *
- * Updated to support the VIA 8233/8235 audio subsystem
- * Alan Cox <alan@redhat.com> (C) Copyright 2002, 2003 Red Hat Inc
- *
- * Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2.
- * See the "COPYING" file distributed with this software for more info.
- * NO WARRANTY
- *
- * For a list of known bugs (errata) and documentation,
- * see via-audio.pdf in Documentation/DocBook.
- * If this documentation does not exist, run "make pdfdocs".
- */
-
-
-#define VIA_VERSION "1.9.1-ac4-2.5"
-
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/pci.h>
-#include <linux/poison.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/spinlock.h>
-#include <linux/sound.h>
-#include <linux/poll.h>
-#include <linux/soundcard.h>
-#include <linux/ac97_codec.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/dma-mapping.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-#include <linux/mutex.h>
-
-#include "sound_config.h"
-#include "dev_table.h"
-#include "mpu401.h"
-
-
-#undef VIA_DEBUG /* define to enable debugging output and checks */
-#ifdef VIA_DEBUG
-/* note: prints function name for you */
-#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
-#else
-#define DPRINTK(fmt, args...)
-#endif
-
-#undef VIA_NDEBUG /* define to disable lightweight runtime checks */
-#ifdef VIA_NDEBUG
-#define assert(expr)
-#else
-#define assert(expr) \
- if(!(expr)) { \
- printk( "Assertion failed! %s,%s,%s,line=%d\n", \
- #expr,__FILE__,__FUNCTION__,__LINE__); \
- }
-#endif
-
-#define VIA_SUPPORT_MMAP 1 /* buggy, for now... */
-
-#define MAX_CARDS 1
-
-#define VIA_CARD_NAME "VIA 82Cxxx Audio driver " VIA_VERSION
-#define VIA_MODULE_NAME "via82cxxx"
-#define PFX VIA_MODULE_NAME ": "
-
-#define VIA_COUNTER_LIMIT 100000
-
-/* size of DMA buffers */
-#define VIA_MAX_BUFFER_DMA_PAGES 32
-
-/* buffering default values in ms */
-#define VIA_DEFAULT_FRAG_TIME 20
-#define VIA_DEFAULT_BUFFER_TIME 500
-
-/* the hardware has a 256 fragment limit */
-#define VIA_MIN_FRAG_NUMBER 2
-#define VIA_MAX_FRAG_NUMBER 128
-
-#define VIA_MAX_FRAG_SIZE PAGE_SIZE
-#define VIA_MIN_FRAG_SIZE (VIA_MAX_BUFFER_DMA_PAGES * PAGE_SIZE / VIA_MAX_FRAG_NUMBER)
-
-
-/* 82C686 function 5 (audio codec) PCI configuration registers */
-#define VIA_ACLINK_STATUS 0x40
-#define VIA_ACLINK_CTRL 0x41
-#define VIA_FUNC_ENABLE 0x42
-#define VIA_PNP_CONTROL 0x43
-#define VIA_FM_NMI_CTRL 0x48
-
-/*
- * controller base 0 (scatter-gather) registers
- *
- * NOTE: Via datasheet lists first channel as "read"
- * channel and second channel as "write" channel.
- * I changed the naming of the constants to be more
- * clear than I felt the datasheet to be.
- */
-
-#define VIA_BASE0_PCM_OUT_CHAN 0x00 /* output PCM to user */
-#define VIA_BASE0_PCM_OUT_CHAN_STATUS 0x00
-#define VIA_BASE0_PCM_OUT_CHAN_CTRL 0x01
-#define VIA_BASE0_PCM_OUT_CHAN_TYPE 0x02
-
-#define VIA_BASE0_PCM_IN_CHAN 0x10 /* input PCM from user */
-#define VIA_BASE0_PCM_IN_CHAN_STATUS 0x10
-#define VIA_BASE0_PCM_IN_CHAN_CTRL 0x11
-#define VIA_BASE0_PCM_IN_CHAN_TYPE 0x12
-
-/* offsets from base */
-#define VIA_PCM_STATUS 0x00
-#define VIA_PCM_CONTROL 0x01
-#define VIA_PCM_TYPE 0x02
-#define VIA_PCM_LEFTVOL 0x02
-#define VIA_PCM_RIGHTVOL 0x03
-#define VIA_PCM_TABLE_ADDR 0x04
-#define VIA_PCM_STOPRATE 0x08 /* 8233+ */
-#define VIA_PCM_BLOCK_COUNT 0x0C
-
-/* XXX unused DMA channel for FM PCM data */
-#define VIA_BASE0_FM_OUT_CHAN 0x20
-#define VIA_BASE0_FM_OUT_CHAN_STATUS 0x20
-#define VIA_BASE0_FM_OUT_CHAN_CTRL 0x21
-#define VIA_BASE0_FM_OUT_CHAN_TYPE 0x22
-
-/* Six channel audio output on 8233 */
-#define VIA_BASE0_MULTI_OUT_CHAN 0x40
-#define VIA_BASE0_MULTI_OUT_CHAN_STATUS 0x40
-#define VIA_BASE0_MULTI_OUT_CHAN_CTRL 0x41
-#define VIA_BASE0_MULTI_OUT_CHAN_TYPE 0x42
-
-#define VIA_BASE0_AC97_CTRL 0x80
-#define VIA_BASE0_SGD_STATUS_SHADOW 0x84
-#define VIA_BASE0_GPI_INT_ENABLE 0x8C
-#define VIA_INTR_OUT ((1<<0) | (1<<4) | (1<<8))
-#define VIA_INTR_IN ((1<<1) | (1<<5) | (1<<9))
-#define VIA_INTR_FM ((1<<2) | (1<<6) | (1<<10))
-#define VIA_INTR_MASK (VIA_INTR_OUT | VIA_INTR_IN | VIA_INTR_FM)
-
-/* Newer VIA we need to monitor the low 3 bits of each channel. This
- mask covers the channels we don't yet use as well
- */
-
-#define VIA_NEW_INTR_MASK 0x77077777UL
-
-/* VIA_BASE0_AUDIO_xxx_CHAN_TYPE bits */
-#define VIA_IRQ_ON_FLAG (1<<0) /* int on each flagged scatter block */
-#define VIA_IRQ_ON_EOL (1<<1) /* int at end of scatter list */
-#define VIA_INT_SEL_PCI_LAST_LINE_READ (0) /* int at PCI read of last line */
-#define VIA_INT_SEL_LAST_SAMPLE_SENT (1<<2) /* int at last sample sent */
-#define VIA_INT_SEL_ONE_LINE_LEFT (1<<3) /* int at less than one line to send */
-#define VIA_PCM_FMT_STEREO (1<<4) /* PCM stereo format (bit clear == mono) */
-#define VIA_PCM_FMT_16BIT (1<<5) /* PCM 16-bit format (bit clear == 8-bit) */
-#define VIA_PCM_REC_FIFO (1<<6) /* PCM Recording FIFO */
-#define VIA_RESTART_SGD_ON_EOL (1<<7) /* restart scatter-gather at EOL */
-#define VIA_PCM_FMT_MASK (VIA_PCM_FMT_STEREO|VIA_PCM_FMT_16BIT)
-#define VIA_CHAN_TYPE_MASK (VIA_RESTART_SGD_ON_EOL | \
- VIA_IRQ_ON_FLAG | \
- VIA_IRQ_ON_EOL)
-#define VIA_CHAN_TYPE_INT_SELECT (VIA_INT_SEL_LAST_SAMPLE_SENT)
-
-/* PCI configuration register bits and masks */
-#define VIA_CR40_AC97_READY 0x01
-#define VIA_CR40_AC97_LOW_POWER 0x02
-#define VIA_CR40_SECONDARY_READY 0x04
-
-#define VIA_CR41_AC97_ENABLE 0x80 /* enable AC97 codec */
-#define VIA_CR41_AC97_RESET 0x40 /* clear bit to reset AC97 */
-#define VIA_CR41_AC97_WAKEUP 0x20 /* wake up from power-down mode */
-#define VIA_CR41_AC97_SDO 0x10 /* force Serial Data Out (SDO) high */
-#define VIA_CR41_VRA 0x08 /* enable variable sample rate */
-#define VIA_CR41_PCM_ENABLE 0x04 /* AC Link SGD Read Channel PCM Data Output */
-#define VIA_CR41_FM_PCM_ENABLE 0x02 /* AC Link FM Channel PCM Data Out */
-#define VIA_CR41_SB_PCM_ENABLE 0x01 /* AC Link SB PCM Data Output */
-#define VIA_CR41_BOOT_MASK (VIA_CR41_AC97_ENABLE | \
- VIA_CR41_AC97_WAKEUP | \
- VIA_CR41_AC97_SDO)
-#define VIA_CR41_RUN_MASK (VIA_CR41_AC97_ENABLE | \
- VIA_CR41_AC97_RESET | \
- VIA_CR41_VRA | \
- VIA_CR41_PCM_ENABLE)
-
-#define VIA_CR42_SB_ENABLE 0x01
-#define VIA_CR42_MIDI_ENABLE 0x02
-#define VIA_CR42_FM_ENABLE 0x04
-#define VIA_CR42_GAME_ENABLE 0x08
-#define VIA_CR42_MIDI_IRQMASK 0x40
-#define VIA_CR42_MIDI_PNP 0x80
-
-#define VIA_CR44_SECOND_CODEC_SUPPORT (1 << 6)
-#define VIA_CR44_AC_LINK_ACCESS (1 << 7)
-
-#define VIA_CR48_FM_TRAP_TO_NMI (1 << 2)
-
-/* controller base 0 register bitmasks */
-#define VIA_INT_DISABLE_MASK (~(0x01|0x02))
-#define VIA_SGD_STOPPED (1 << 2)
-#define VIA_SGD_PAUSED (1 << 6)
-#define VIA_SGD_ACTIVE (1 << 7)
-#define VIA_SGD_TERMINATE (1 << 6)
-#define VIA_SGD_FLAG (1 << 0)
-#define VIA_SGD_EOL (1 << 1)
-#define VIA_SGD_START (1 << 7)
-
-#define VIA_CR80_FIRST_CODEC 0
-#define VIA_CR80_SECOND_CODEC (1 << 30)
-#define VIA_CR80_FIRST_CODEC_VALID (1 << 25)
-#define VIA_CR80_VALID (1 << 25)
-#define VIA_CR80_SECOND_CODEC_VALID (1 << 27)
-#define VIA_CR80_BUSY (1 << 24)
-#define VIA_CR83_BUSY (1)
-#define VIA_CR83_FIRST_CODEC_VALID (1 << 1)
-#define VIA_CR80_READ (1 << 23)
-#define VIA_CR80_WRITE_MODE 0
-#define VIA_CR80_REG_IDX(idx) ((((idx) & 0xFF) >> 1) << 16)
-
-/* capabilities we announce */
-#ifdef VIA_SUPPORT_MMAP
-#define VIA_DSP_CAP (DSP_CAP_REVISION | DSP_CAP_DUPLEX | DSP_CAP_MMAP | \
- DSP_CAP_TRIGGER | DSP_CAP_REALTIME)
-#else
-#define VIA_DSP_CAP (DSP_CAP_REVISION | DSP_CAP_DUPLEX | \
- DSP_CAP_TRIGGER | DSP_CAP_REALTIME)
-#endif
-
-/* scatter-gather DMA table entry, exactly as passed to hardware */
-struct via_sgd_table {
- u32 addr;
- u32 count; /* includes additional VIA_xxx bits also */
-};
-
-#define VIA_EOL (1 << 31)
-#define VIA_FLAG (1 << 30)
-#define VIA_STOP (1 << 29)
-
-
-enum via_channel_states {
- sgd_stopped = 0,
- sgd_in_progress = 1,
-};
-
-
-struct via_buffer_pgtbl {
- dma_addr_t handle;
- void *cpuaddr;
-};
-
-
-struct via_channel {
- atomic_t n_frags;
- atomic_t hw_ptr;
- wait_queue_head_t wait;
-
- unsigned int sw_ptr;
- unsigned int slop_len;
- unsigned int n_irqs;
- int bytes;
-
- unsigned is_active : 1;
- unsigned is_record : 1;
- unsigned is_mapped : 1;
- unsigned is_enabled : 1;
- unsigned is_multi: 1; /* 8233 6 channel */
- u8 pcm_fmt; /* VIA_PCM_FMT_xxx */
- u8 channels; /* Channel count */
-
- unsigned rate; /* sample rate */
- unsigned int frag_size;
- unsigned int frag_number;
-
- unsigned char intmask;
-
- volatile struct via_sgd_table *sgtable;
- dma_addr_t sgt_handle;
-
- unsigned int page_number;
- struct via_buffer_pgtbl pgtbl[VIA_MAX_BUFFER_DMA_PAGES];
-
- long iobase;
-
- const char *name;
-};
-
-
-/* data stored for each chip */
-struct via_info {
- struct pci_dev *pdev;
- long baseaddr;
-
- struct ac97_codec *ac97;
- spinlock_t ac97_lock;
- spinlock_t lock;
- int card_num; /* unique card number, from 0 */
-
- int dev_dsp; /* /dev/dsp index from register_sound_dsp() */
-
- unsigned rev_h : 1;
- unsigned legacy: 1; /* Has legacy ports */
- unsigned intmask: 1; /* Needs int bits */
- unsigned sixchannel: 1; /* 8233/35 with 6 channel support */
- unsigned volume: 1;
-
- unsigned locked_rate : 1;
-
- int mixer_vol; /* 8233/35 volume - not yet implemented */
-
- struct mutex syscall_mutex;
- struct mutex open_mutex;
-
- /* The 8233/8235 have 4 DX audio channels, two record and
- one six channel out. We bind ch_in to DX 1, ch_out to multichannel
- and ch_fm to DX 2. DX 3 and REC0/REC1 are unused at the
- moment */
-
- struct via_channel ch_in;
- struct via_channel ch_out;
- struct via_channel ch_fm;
-
-#ifdef CONFIG_MIDI_VIA82CXXX
- void *midi_devc;
- struct address_info midi_info;
-#endif
-};
-
-
-/* number of cards, used for assigning unique numbers to cards */
-static unsigned via_num_cards;
-
-
-
-/****************************************************************
- *
- * prototypes
- *
- *
- */
-
-static int via_init_one (struct pci_dev *dev, const struct pci_device_id *id);
-static void __devexit via_remove_one (struct pci_dev *pdev);
-
-static ssize_t via_dsp_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos);
-static ssize_t via_dsp_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos);
-static unsigned int via_dsp_poll(struct file *file, struct poll_table_struct *wait);
-static int via_dsp_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
-static int via_dsp_open (struct inode *inode, struct file *file);
-static int via_dsp_release(struct inode *inode, struct file *file);
-static int via_dsp_mmap(struct file *file, struct vm_area_struct *vma);
-
-static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg);
-static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value);
-static u8 via_ac97_wait_idle (struct via_info *card);
-
-static void via_chan_free (struct via_info *card, struct via_channel *chan);
-static void via_chan_clear (struct via_info *card, struct via_channel *chan);
-static void via_chan_pcm_fmt (struct via_channel *chan, int reset);
-static void via_chan_buffer_free (struct via_info *card, struct via_channel *chan);
-
-
-/****************************************************************
- *
- * Various data the driver needs
- *
- *
- */
-
-
-static struct pci_device_id via_pci_tbl[] = {
- { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
- { PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8233_5,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1},
- { 0, }
-};
-MODULE_DEVICE_TABLE(pci,via_pci_tbl);
-
-
-static struct pci_driver via_driver = {
- .name = VIA_MODULE_NAME,
- .id_table = via_pci_tbl,
- .probe = via_init_one,
- .remove = __devexit_p(via_remove_one),
-};
-
-
-/****************************************************************
- *
- * Low-level base 0 register read/write helpers
- *
- *
- */
-
-/**
- * via_chan_stop - Terminate DMA on specified PCM channel
- * @iobase: PCI base address for SGD channel registers
- *
- * Terminate scatter-gather DMA operation for given
- * channel (derived from @iobase), if DMA is active.
- *
- * Note that @iobase is not the PCI base address,
- * but the PCI base address plus an offset to
- * one of three PCM channels supported by the chip.
- *
- */
-
-static inline void via_chan_stop (long iobase)
-{
- if (inb (iobase + VIA_PCM_STATUS) & VIA_SGD_ACTIVE)
- outb (VIA_SGD_TERMINATE, iobase + VIA_PCM_CONTROL);
-}
-
-
-/**
- * via_chan_status_clear - Clear status flags on specified DMA channel
- * @iobase: PCI base address for SGD channel registers
- *
- * Clear any pending status flags for the given
- * DMA channel (derived from @iobase), if any
- * flags are asserted.
- *
- * Note that @iobase is not the PCI base address,
- * but the PCI base address plus an offset to
- * one of three PCM channels supported by the chip.
- *
- */
-
-static inline void via_chan_status_clear (long iobase)
-{
- u8 tmp = inb (iobase + VIA_PCM_STATUS);
-
- if (tmp != 0)
- outb (tmp, iobase + VIA_PCM_STATUS);
-}
-
-
-/**
- * sg_begin - Begin recording or playback on a PCM channel
- * @chan: Channel for which DMA operation shall begin
- *
- * Start scatter-gather DMA for the given channel.
- *
- */
-
-static inline void sg_begin (struct via_channel *chan)
-{
- DPRINTK("Start with intmask %d\n", chan->intmask);
- DPRINTK("About to start from %d to %d\n",
- inl(chan->iobase + VIA_PCM_BLOCK_COUNT),
- inb(chan->iobase + VIA_PCM_STOPRATE + 3));
- outb (VIA_SGD_START|chan->intmask, chan->iobase + VIA_PCM_CONTROL);
- DPRINTK("Status is now %02X\n", inb(chan->iobase + VIA_PCM_STATUS));
- DPRINTK("Control is now %02X\n", inb(chan->iobase + VIA_PCM_CONTROL));
-}
-
-
-static int sg_active (long iobase)
-{
- u8 tmp = inb (iobase + VIA_PCM_STATUS);
- if ((tmp & VIA_SGD_STOPPED) || (tmp & VIA_SGD_PAUSED)) {
- printk(KERN_WARNING "via82cxxx warning: SG stopped or paused\n");
- return 0;
- }
- if (tmp & VIA_SGD_ACTIVE)
- return 1;
- return 0;
-}
-
-static int via_sg_offset(struct via_channel *chan)
-{
- return inl (chan->iobase + VIA_PCM_BLOCK_COUNT) & 0x00FFFFFF;
-}
-
-/****************************************************************
- *
- * Miscellaneous debris
- *
- *
- */
-
-
-/**
- * via_syscall_down - down the card-specific syscell semaphore
- * @card: Private info for specified board
- * @nonblock: boolean, non-zero if O_NONBLOCK is set
- *
- * Encapsulates standard method of acquiring the syscall sem.
- *
- * Returns negative errno on error, or zero for success.
- */
-
-static inline int via_syscall_down (struct via_info *card, int nonblock)
-{
- /* Thomas Sailer:
- * EAGAIN is supposed to be used if IO is pending,
- * not if there is contention on some internal
- * synchronization primitive which should be
- * held only for a short time anyway
- */
- nonblock = 0;
-
- if (nonblock) {
- if (!mutex_trylock(&card->syscall_mutex))
- return -EAGAIN;
- } else {
- if (mutex_lock_interruptible(&card->syscall_mutex))
- return -ERESTARTSYS;
- }
-
- return 0;
-}
-
-
-/**
- * via_stop_everything - Stop all audio operations
- * @card: Private info for specified board
- *
- * Stops all DMA operations and interrupts, and clear
- * any pending status bits resulting from those operations.
- */
-
-static void via_stop_everything (struct via_info *card)
-{
- u8 tmp, new_tmp;
-
- DPRINTK ("ENTER\n");
-
- assert (card != NULL);
-
- /*
- * terminate any existing operations on audio read/write channels
- */
- via_chan_stop (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
- via_chan_stop (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
- via_chan_stop (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
- if(card->sixchannel)
- via_chan_stop (card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN);
-
- /*
- * clear any existing stops / flags (sanity check mainly)
- */
- via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
- via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
- via_chan_status_clear (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
- if(card->sixchannel)
- via_chan_status_clear (card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN);
-
- /*
- * clear any enabled interrupt bits
- */
- tmp = inb (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
- new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
- if (tmp != new_tmp)
- outb (0, card->baseaddr + VIA_BASE0_PCM_OUT_CHAN_TYPE);
-
- tmp = inb (card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
- new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
- if (tmp != new_tmp)
- outb (0, card->baseaddr + VIA_BASE0_PCM_IN_CHAN_TYPE);
-
- tmp = inb (card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
- new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
- if (tmp != new_tmp)
- outb (0, card->baseaddr + VIA_BASE0_FM_OUT_CHAN_TYPE);
-
- if(card->sixchannel)
- {
- tmp = inb (card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN_TYPE);
- new_tmp = tmp & ~(VIA_IRQ_ON_FLAG|VIA_IRQ_ON_EOL|VIA_RESTART_SGD_ON_EOL);
- if (tmp != new_tmp)
- outb (0, card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN_TYPE);
- }
-
- udelay(10);
-
- /*
- * clear any existing flags
- */
- via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_OUT_CHAN);
- via_chan_status_clear (card->baseaddr + VIA_BASE0_PCM_IN_CHAN);
- via_chan_status_clear (card->baseaddr + VIA_BASE0_FM_OUT_CHAN);
-
- DPRINTK ("EXIT\n");
-}
-
-
-/**
- * via_set_rate - Set PCM rate for given channel
- * @ac97: Pointer to generic codec info struct
- * @chan: Private info for specified channel
- * @rate: Desired PCM sample rate, in Khz
- *
- * Sets the PCM sample rate for a channel.
- *
- * Values for @rate are clamped to a range of 4000 Khz through 48000 Khz,
- * due to hardware constraints.
- */
-
-static int via_set_rate (struct ac97_codec *ac97,
- struct via_channel *chan, unsigned rate)
-{
- struct via_info *card = ac97->private_data;
- int rate_reg;
- u32 dacp;
- u32 mast_vol, phone_vol, mono_vol, pcm_vol;
- u32 mute_vol = 0x8000; /* The mute volume? -- Seems to work! */
-
- DPRINTK ("ENTER, rate = %d\n", rate);
-
- if (chan->rate == rate)
- goto out;
- if (card->locked_rate) {
- chan->rate = 48000;
- goto out;
- }
-
- if (rate > 48000) rate = 48000;
- if (rate < 4000) rate = 4000;
-
- rate_reg = chan->is_record ? AC97_PCM_LR_ADC_RATE :
- AC97_PCM_FRONT_DAC_RATE;
-
- /* Save current state */
- dacp=via_ac97_read_reg(ac97, AC97_POWER_CONTROL);
- mast_vol = via_ac97_read_reg(ac97, AC97_MASTER_VOL_STEREO);
- mono_vol = via_ac97_read_reg(ac97, AC97_MASTER_VOL_MONO);
- phone_vol = via_ac97_read_reg(ac97, AC97_HEADPHONE_VOL);
- pcm_vol = via_ac97_read_reg(ac97, AC97_PCMOUT_VOL);
- /* Mute - largely reduces popping */
- via_ac97_write_reg(ac97, AC97_MASTER_VOL_STEREO, mute_vol);
- via_ac97_write_reg(ac97, AC97_MASTER_VOL_MONO, mute_vol);
- via_ac97_write_reg(ac97, AC97_HEADPHONE_VOL, mute_vol);
- via_ac97_write_reg(ac97, AC97_PCMOUT_VOL, mute_vol);
- /* Power down the DAC */
- via_ac97_write_reg(ac97, AC97_POWER_CONTROL, dacp|0x0200);
-
- /* Set new rate */
- via_ac97_write_reg (ac97, rate_reg, rate);
-
- /* Power DAC back up */
- via_ac97_write_reg(ac97, AC97_POWER_CONTROL, dacp);
- udelay (200); /* reduces popping */
-
- /* Restore volumes */
- via_ac97_write_reg(ac97, AC97_MASTER_VOL_STEREO, mast_vol);
- via_ac97_write_reg(ac97, AC97_MASTER_VOL_MONO, mono_vol);
- via_ac97_write_reg(ac97, AC97_HEADPHONE_VOL, phone_vol);
- via_ac97_write_reg(ac97, AC97_PCMOUT_VOL, pcm_vol);
-
- /* the hardware might return a value different than what we
- * passed to it, so read the rate value back from hardware
- * to see what we came up with
- */
- chan->rate = via_ac97_read_reg (ac97, rate_reg);
-
- if (chan->rate == 0) {
- card->locked_rate = 1;
- chan->rate = 48000;
- printk (KERN_WARNING PFX "Codec rate locked at 48Khz\n");
- }
-
-out:
- DPRINTK ("EXIT, returning rate %d Hz\n", chan->rate);
- return chan->rate;
-}
-
-
-/****************************************************************
- *
- * Channel-specific operations
- *
- *
- */
-
-
-/**
- * via_chan_init_defaults - Initialize a struct via_channel
- * @card: Private audio chip info
- * @chan: Channel to be initialized
- *
- * Zero @chan, and then set all static defaults for the structure.
- */
-
-static void via_chan_init_defaults (struct via_info *card, struct via_channel *chan)
-{
- memset (chan, 0, sizeof (*chan));
-
- if(card->intmask)
- chan->intmask = 0x23; /* Turn on the IRQ bits */
-
- if (chan == &card->ch_out) {
- chan->name = "PCM-OUT";
- if(card->sixchannel)
- {
- chan->iobase = card->baseaddr + VIA_BASE0_MULTI_OUT_CHAN;
- chan->is_multi = 1;
- DPRINTK("Using multichannel for pcm out\n");
- }
- else
- chan->iobase = card->baseaddr + VIA_BASE0_PCM_OUT_CHAN;
- } else if (chan == &card->ch_in) {
- chan->name = "PCM-IN";
- chan->iobase = card->baseaddr + VIA_BASE0_PCM_IN_CHAN;
- chan->is_record = 1;
- } else if (chan == &card->ch_fm) {
- chan->name = "PCM-OUT-FM";
- chan->iobase = card->baseaddr + VIA_BASE0_FM_OUT_CHAN;
- } else {
- BUG();
- }
-
- init_waitqueue_head (&chan->wait);
-
- chan->pcm_fmt = VIA_PCM_FMT_MASK;
- chan->is_enabled = 1;
-
- chan->frag_number = 0;
- chan->frag_size = 0;
- atomic_set(&chan->n_frags, 0);
- atomic_set (&chan->hw_ptr, 0);
-}
-
-/**
- * via_chan_init - Initialize PCM channel
- * @card: Private audio chip info
- * @chan: Channel to be initialized
- *
- * Performs some of the preparations necessary to begin
- * using a PCM channel.
- *
- * Currently the preparations consist of
- * setting the PCM channel to a known state.
- */
-
-
-static void via_chan_init (struct via_info *card, struct via_channel *chan)
-{
-
- DPRINTK ("ENTER\n");
-
- /* bzero channel structure, and init members to defaults */
- via_chan_init_defaults (card, chan);
-
- /* stop any existing channel output */
- via_chan_clear (card, chan);
- via_chan_status_clear (chan->iobase);
- via_chan_pcm_fmt (chan, 1);
-
- DPRINTK ("EXIT\n");
-}
-
-/**
- * via_chan_buffer_init - Initialize PCM channel buffer
- * @card: Private audio chip info
- * @chan: Channel to be initialized
- *
- * Performs some of the preparations necessary to begin
- * using a PCM channel.
- *
- * Currently the preparations include allocating the
- * scatter-gather DMA table and buffers,
- * and passing the
- * address of the DMA table to the hardware.
- *
- * Note that special care is taken when passing the
- * DMA table address to hardware, because it was found
- * during driver development that the hardware did not
- * always "take" the address.
- */
-
-static int via_chan_buffer_init (struct via_info *card, struct via_channel *chan)
-{
- int page, offset;
- int i;
-
- DPRINTK ("ENTER\n");
-
-
- chan->intmask = 0;
- if(card->intmask)
- chan->intmask = 0x23; /* Turn on the IRQ bits */
-
- if (chan->sgtable != NULL) {
- DPRINTK ("EXIT\n");
- return 0;
- }
-
- /* alloc DMA-able memory for scatter-gather table */
- chan->sgtable = pci_alloc_consistent (card->pdev,
- (sizeof (struct via_sgd_table) * chan->frag_number),
- &chan->sgt_handle);
- if (!chan->sgtable) {
- printk (KERN_ERR PFX "DMA table alloc fail, aborting\n");
- DPRINTK ("EXIT\n");
- return -ENOMEM;
- }
-
- memset ((void*)chan->sgtable, 0,
- (sizeof (struct via_sgd_table) * chan->frag_number));
-
- /* alloc DMA-able memory for scatter-gather buffers */
-
- chan->page_number = (chan->frag_number * chan->frag_size) / PAGE_SIZE +
- (((chan->frag_number * chan->frag_size) % PAGE_SIZE) ? 1 : 0);
-
- for (i = 0; i < chan->page_number; i++) {
- chan->pgtbl[i].cpuaddr = pci_alloc_consistent (card->pdev, PAGE_SIZE,
- &chan->pgtbl[i].handle);
-
- if (!chan->pgtbl[i].cpuaddr) {
- chan->page_number = i;
- goto err_out_nomem;
- }
-
-#ifndef VIA_NDEBUG
- memset (chan->pgtbl[i].cpuaddr, 0xBC, chan->frag_size);
-#endif
-
-#if 1
- DPRINTK ("dmabuf_pg #%d (h=%lx, v2p=%lx, a=%p)\n",
- i, (long)chan->pgtbl[i].handle,
- virt_to_phys(chan->pgtbl[i].cpuaddr),
- chan->pgtbl[i].cpuaddr);
-#endif
- }
-
- for (i = 0; i < chan->frag_number; i++) {
-
- page = i / (PAGE_SIZE / chan->frag_size);
- offset = (i % (PAGE_SIZE / chan->frag_size)) * chan->frag_size;
-
- chan->sgtable[i].count = cpu_to_le32 (chan->frag_size | VIA_FLAG);
- chan->sgtable[i].addr = cpu_to_le32 (chan->pgtbl[page].handle + offset);
-
-#if 1
- DPRINTK ("dmabuf #%d (32(h)=%lx)\n",
- i,
- (long)chan->sgtable[i].addr);
-#endif
- }
-
- /* overwrite the last buffer information */
- chan->sgtable[chan->frag_number - 1].count = cpu_to_le32 (chan->frag_size | VIA_EOL);
-
- /* set location of DMA-able scatter-gather info table */
- DPRINTK ("outl (0x%X, 0x%04lX)\n",
- chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR);
-
- via_ac97_wait_idle (card);
- outl (chan->sgt_handle, chan->iobase + VIA_PCM_TABLE_ADDR);
- udelay (20);
- via_ac97_wait_idle (card);
- /* load no rate adaption, stereo 16bit, set up ring slots */
- if(card->sixchannel)
- {
- if(!chan->is_multi)
- {
- outl (0xFFFFF | (0x3 << 20) | (chan->frag_number << 24), chan->iobase + VIA_PCM_STOPRATE);
- udelay (20);
- via_ac97_wait_idle (card);
- }
- }
-
- DPRINTK ("inl (0x%lX) = %x\n",
- chan->iobase + VIA_PCM_TABLE_ADDR,
- inl(chan->iobase + VIA_PCM_TABLE_ADDR));
-
- DPRINTK ("EXIT\n");
- return 0;
-
-err_out_nomem:
- printk (KERN_ERR PFX "DMA buffer alloc fail, aborting\n");
- via_chan_buffer_free (card, chan);
- DPRINTK ("EXIT\n");
- return -ENOMEM;
-}
-
-
-/**
- * via_chan_free - Release a PCM channel
- * @card: Private audio chip info
- * @chan: Channel to be released
- *
- * Performs all the functions necessary to clean up
- * an initialized channel.
- *
- * Currently these functions include disabled any
- * active DMA operations, setting the PCM channel
- * back to a known state, and releasing any allocated
- * sound buffers.
- */
-
-static void via_chan_free (struct via_info *card, struct via_channel *chan)
-{
- DPRINTK ("ENTER\n");
-
- spin_lock_irq (&card->lock);
-
- /* stop any existing channel output */
- via_chan_status_clear (chan->iobase);
- via_chan_stop (chan->iobase);
- via_chan_status_clear (chan->iobase);
-
- spin_unlock_irq (&card->lock);
-
- synchronize_irq(card->pdev->irq);
-
- DPRINTK ("EXIT\n");
-}
-
-static void via_chan_buffer_free (struct via_info *card, struct via_channel *chan)
-{
- int i;
-
- DPRINTK ("ENTER\n");
-
- /* zero location of DMA-able scatter-gather info table */
- via_ac97_wait_idle(card);
- outl (0, chan->iobase + VIA_PCM_TABLE_ADDR);
-
- for (i = 0; i < chan->page_number; i++)
- if (chan->pgtbl[i].cpuaddr) {
- pci_free_consistent (card->pdev, PAGE_SIZE,
- chan->pgtbl[i].cpuaddr,
- chan->pgtbl[i].handle);
- chan->pgtbl[i].cpuaddr = NULL;
- chan->pgtbl[i].handle = 0;
- }
-
- chan->page_number = 0;
-
- if (chan->sgtable) {
- pci_free_consistent (card->pdev,
- (sizeof (struct via_sgd_table) * chan->frag_number),
- (void*)chan->sgtable, chan->sgt_handle);
- chan->sgtable = NULL;
- }
-
- DPRINTK ("EXIT\n");
-}
-
-
-/**
- * via_chan_pcm_fmt - Update PCM channel settings
- * @chan: Channel to be updated
- * @reset: Boolean. If non-zero, channel will be reset
- * to 8-bit mono mode.
- *
- * Stores the settings of the current PCM format,
- * 8-bit or 16-bit, and mono/stereo, into the
- * hardware settings for the specified channel.
- * If @reset is non-zero, the channel is reset
- * to 8-bit mono mode. Otherwise, the channel
- * is set to the values stored in the channel
- * information struct @chan.
- */
-
-static void via_chan_pcm_fmt (struct via_channel *chan, int reset)
-{
- DPRINTK ("ENTER, pcm_fmt=0x%02X, reset=%s\n",
- chan->pcm_fmt, reset ? "yes" : "no");
-
- assert (chan != NULL);
-
- if (reset)
- {
- /* reset to 8-bit mono mode */
- chan->pcm_fmt = 0;
- chan->channels = 1;
- }
-
- /* enable interrupts on FLAG and EOL */
- chan->pcm_fmt |= VIA_CHAN_TYPE_MASK;
-
- /* if we are recording, enable recording fifo bit */
- if (chan->is_record)
- chan->pcm_fmt |= VIA_PCM_REC_FIFO;
- /* set interrupt select bits where applicable (PCM in & out channels) */
- if (!chan->is_record)
- chan->pcm_fmt |= VIA_CHAN_TYPE_INT_SELECT;
-
- DPRINTK("SET FMT - %02x %02x\n", chan->intmask , chan->is_multi);
-
- if(chan->intmask)
- {
- u32 m;
-
- /*
- * Channel 0x4 is up to 6 x 16bit and has to be
- * programmed differently
- */
-
- if(chan->is_multi)
- {
- u8 c = 0;
-
- /*
- * Load the type bit for num channels
- * and 8/16bit
- */
-
- if(chan->pcm_fmt & VIA_PCM_FMT_16BIT)
- c = 1 << 7;
- if(chan->pcm_fmt & VIA_PCM_FMT_STEREO)
- c |= (2<<4);
- else
- c |= (1<<4);
-
- outb(c, chan->iobase + VIA_PCM_TYPE);
-
- /*
- * Set the channel steering
- * Mono
- * Channel 0 to slot 3
- * Channel 0 to slot 4
- * Stereo
- * Channel 0 to slot 3
- * Channel 1 to slot 4
- */
-
- switch(chan->channels)
- {
- case 1:
- outl(0xFF000000 | (1<<0) | (1<<4) , chan->iobase + VIA_PCM_STOPRATE);
- break;
- case 2:
- outl(0xFF000000 | (1<<0) | (2<<4) , chan->iobase + VIA_PCM_STOPRATE);
- break;
- case 4:
- outl(0xFF000000 | (1<<0) | (2<<4) | (3<<8) | (4<<12), chan->iobase + VIA_PCM_STOPRATE);
- break;
- case 6:
- outl(0xFF000000 | (1<<0) | (2<<4) | (5<<8) | (6<<12) | (3<<16) | (4<<20), chan->iobase + VIA_PCM_STOPRATE);
- break;
- }
- }
- else
- {
- /*
- * New style, turn off channel volume
- * control, set bits in the right register
- */
- outb(0x0, chan->iobase + VIA_PCM_LEFTVOL);
- outb(0x0, chan->iobase + VIA_PCM_RIGHTVOL);
-
- m = inl(chan->iobase + VIA_PCM_STOPRATE);
- m &= ~(3<<20);
- if(chan->pcm_fmt & VIA_PCM_FMT_STEREO)
- m |= (1 << 20);
- if(chan->pcm_fmt & VIA_PCM_FMT_16BIT)
- m |= (1 << 21);
- outl(m, chan->iobase + VIA_PCM_STOPRATE);
- }
- }
- else
- outb (chan->pcm_fmt, chan->iobase + VIA_PCM_TYPE);
-
-
- DPRINTK ("EXIT, pcm_fmt = 0x%02X, reg = 0x%02X\n",
- chan->pcm_fmt,
- inb (chan->iobase + VIA_PCM_TYPE));
-}
-
-
-/**
- * via_chan_clear - Stop DMA channel operation, and reset pointers
- * @card: the chip to accessed
- * @chan: Channel to be cleared
- *
- * Call via_chan_stop to halt DMA operations, and then resets
- * all software pointers which track DMA operation.
- */
-
-static void via_chan_clear (struct via_info *card, struct via_channel *chan)
-{
- DPRINTK ("ENTER\n");
- via_chan_stop (chan->iobase);
- via_chan_buffer_free(card, chan);
- chan->is_active = 0;
- chan->is_mapped = 0;
- chan->is_enabled = 1;
- chan->slop_len = 0;
- chan->sw_ptr = 0;
- chan->n_irqs = 0;
- atomic_set (&chan->hw_ptr, 0);
- DPRINTK ("EXIT\n");
-}
-
-
-/**
- * via_chan_set_speed - Set PCM sample rate for given channel
- * @card: Private info for specified board
- * @chan: Channel whose sample rate will be adjusted
- * @val: New sample rate, in Khz
- *
- * Helper function for the %SNDCTL_DSP_SPEED ioctl. OSS semantics
- * demand that all audio operations halt (if they are not already
- * halted) when the %SNDCTL_DSP_SPEED is given.
- *
- * This function halts all audio operations for the given channel
- * @chan, and then calls via_set_rate to set the audio hardware
- * to the new rate.
- */
-
-static int via_chan_set_speed (struct via_info *card,
- struct via_channel *chan, int val)
-{
- DPRINTK ("ENTER, requested rate = %d\n", val);
-
- via_chan_clear (card, chan);
-
- val = via_set_rate (card->ac97, chan, val);
-
- DPRINTK ("EXIT, returning %d\n", val);
- return val;
-}
-
-
-/**
- * via_chan_set_fmt - Set PCM sample size for given channel
- * @card: Private info for specified board
- * @chan: Channel whose sample size will be adjusted
- * @val: New sample size, use the %AFMT_xxx constants
- *
- * Helper function for the %SNDCTL_DSP_SETFMT ioctl. OSS se