/*
- * Copyright 2001 Randolph Chung <tausq@debian.org>
+ * Copyright 2001-2004 Randolph Chung <tausq@debian.org>
*
* Analog Devices 1889 PCI audio driver (AD1819 AC97-compatible codec)
*
*
* $Id: ad1889.c,v 1.3 2002/10/19 21:31:44 grundler Exp $
*/
-#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/ioport.h>
#include <linux/ac97_codec.h>
#include <linux/sound.h>
#include <linux/interrupt.h>
+#include <linux/mutex.h>
#include <asm/delay.h>
#include <asm/io.h>
#define AD1889_WRITEL(dev,reg,val) writel((val), dev->regbase + reg)
//now 100ms
+/* #define WAIT_10MS() schedule_timeout(HZ/10) */
#define WAIT_10MS() do { int __i; for (__i = 0; __i < 100; __i++) udelay(1000); } while(0)
/* currently only support a single device */
/************************* helper routines ***************************** */
static inline void ad1889_set_wav_rate(ad1889_dev_t *dev, int rate)
{
+ struct ac97_codec *ac97_codec = dev->ac97_codec;
+
+ DBG("Setting WAV rate to %d\n", rate);
dev->state[AD_WAV_STATE].dmabuf.rate = rate;
- AD1889_WRITEW(dev, AD_DSWAS, rate);
-}
+ AD1889_WRITEW(dev, AD_DS_WAS, rate);
-static inline void ad1889_set_adc_rate(ad1889_dev_t *dev, int rate)
-{
- dev->state[AD_ADC_STATE].dmabuf.rate = rate;
- AD1889_WRITEW(dev, AD_DSRES, rate);
+ /* Cycle the DAC to enable the new rate */
+ ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0x0200);
+ WAIT_10MS();
+ ac97_codec->codec_write(dev->ac97_codec, AC97_POWER_CONTROL, 0);
}
static inline void ad1889_set_wav_fmt(ad1889_dev_t *dev, int fmt)
{
u16 tmp;
- tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
- if (fmt == AFMT_S16_LE) {
+ DBG("Setting WAV format to 0x%x\n", fmt);
+
+ tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
+ if (fmt & AFMT_S16_LE) {
//tmp |= 0x0100; /* set WA16 */
tmp |= 0x0300; /* set WA16 stereo */
- } else if (fmt == AFMT_U8) {
+ } else if (fmt & AFMT_U8) {
tmp &= ~0x0100; /* clear WA16 */
}
- AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
+ AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
}
static inline void ad1889_set_adc_fmt(ad1889_dev_t *dev, int fmt)
{
u16 tmp;
- tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
- if (fmt == AFMT_S16_LE) {
+ DBG("Setting ADC format to 0x%x\n", fmt);
+
+ tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
+ if (fmt & AFMT_S16_LE) {
tmp |= 0x0100; /* set WA16 */
- } else if (fmt == AFMT_U8) {
+ } else if (fmt & AFMT_U8) {
tmp &= ~0x0100; /* clear WA16 */
}
- AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
}
static void ad1889_start_wav(ad1889_state_t *state)
dmabuf->dma_len = cnt;
dmabuf->ready = 1;
+ DBG("Starting playback at 0x%p for %ld bytes\n", dmabuf->rawbuf +
+ dmabuf->rd_ptr, dmabuf->dma_len);
+
/* load up the current register set */
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVCC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVICC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVCA, dmabuf->dma_handle);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCC, cnt);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVICC, cnt);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVCA, dmabuf->dma_handle);
/* TODO: for now we load the base registers with the same thing */
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVBC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVIBC, cnt);
- AD1889_WRITEL(ad1889_dev, AD_DMAWAVBA, dmabuf->dma_handle);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBC, cnt);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVIBC, cnt);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_WAVBA, dmabuf->dma_handle);
/* and we're off to the races... */
- AD1889_WRITEL(ad1889_dev, AD_DMACHSS, 0x8);
- tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+ AD1889_WRITEL(ad1889_dev, AD_DMA_CHSS, 0x8);
+ tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
tmp |= 0x0400; /* set WAEN */
- AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
- (void) AD1889_READW(ad1889_dev, AD_DSWSMC); /* flush posted PCI write */
+ AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
+ (void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
dmabuf->enable |= DAC_RUNNING;
u16 tmp;
unsigned long cnt = dmabuf->dma_len;
- tmp = AD1889_READW(ad1889_dev, AD_DSWSMC);
+ tmp = AD1889_READW(ad1889_dev, AD_DS_WSMC);
tmp &= ~0x0400; /* clear WAEN */
- AD1889_WRITEW(ad1889_dev, AD_DSWSMC, tmp);
- (void) AD1889_READW(ad1889_dev, AD_DSWSMC); /* flush posted PCI write */
+ AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, tmp);
+ (void) AD1889_READW(ad1889_dev, AD_DS_WSMC); /* flush posted PCI write */
pci_unmap_single(ad1889_dev->pci, dmabuf->dma_handle,
cnt, PCI_DMA_TODEVICE);
spin_lock_irqsave(&state->card->lock, flags);
- tmp = AD1889_READW(ad1889_dev, AD_DSRAMC);
+ tmp = AD1889_READW(ad1889_dev, AD_DS_RAMC);
if (start) {
state->dmabuf.enable |= ADC_RUNNING;
tmp |= 0x0004; /* set ADEN */
state->dmabuf.enable &= ~ADC_RUNNING;
tmp &= ~0x0004; /* clear ADEN */
}
- AD1889_WRITEW(ad1889_dev, AD_DSRAMC, tmp);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, tmp);
spin_unlock_irqrestore(&state->card->lock, flags);
}
for (i = 0; i < AD_MAX_STATES; i++) {
dev->state[i].card = dev;
- init_MUTEX(&dev->state[i].sem);
+ mutex_init(&dev->state[i].mutex);
init_waitqueue_head(&dev->state[i].dmabuf.wait);
}
dmabuf->dma_handle = 0;
dmabuf->rd_ptr = dmabuf->wr_ptr = dmabuf->dma_len = 0UL;
dmabuf->ready = 0;
- dmabuf->rate = 44100;
+ dmabuf->rate = 48000;
}
return dev;
for (j = 0; j < AD_MAX_STATES; j++) {
dmabuf = &dev->state[j].dmabuf;
- if (dmabuf->rawbuf != NULL)
- kfree(dmabuf->rawbuf);
+ kfree(dmabuf->rawbuf);
}
kfree(dev);
ad1889_start_wav(&dev->state[AD_WAV_STATE]);
}
-int ad1889_read_proc (char *page, char **start, off_t off,
- int count, int *eof, void *data)
+static int ad1889_read_proc (char *page, char **start, off_t off,
+ int count, int *eof, void *data)
{
char *out = page;
int len, i;
ad1889_dev_t *dev = data;
ad1889_reg_t regs[] = {
- { "WSMC", AD_DSWSMC, 16 },
- { "RAMC", AD_DSRAMC, 16 },
- { "WADA", AD_DSWADA, 16 },
- { "SYDA", AD_DSSYDA, 16 },
- { "WAS", AD_DSWAS, 16 },
- { "RES", AD_DSRES, 16 },
- { "CCS", AD_DSCCS, 16 },
- { "ADCBA", AD_DMAADCBA, 32 },
- { "ADCCA", AD_DMAADCCA, 32 },
- { "ADCBC", AD_DMAADCBC, 32 },
- { "ADCCC", AD_DMAADCCC, 32 },
- { "ADCIBC", AD_DMAADCIBC, 32 },
- { "ADCICC", AD_DMAADCICC, 32 },
- { "ADCCTRL", AD_DMAADCCTRL, 16 },
- { "WAVBA", AD_DMAWAVBA, 32 },
- { "WAVCA", AD_DMAWAVCA, 32 },
- { "WAVBC", AD_DMAWAVBC, 32 },
- { "WAVCC", AD_DMAWAVCC, 32 },
- { "WAVIBC", AD_DMAWAVIBC, 32 },
- { "WAVICC", AD_DMAWAVICC, 32 },
- { "WAVCTRL", AD_DMAWAVCTRL, 16 },
- { "DISR", AD_DMADISR, 32 },
- { "CHSS", AD_DMACHSS, 32 },
- { "IPC", AD_GPIOIPC, 16 },
- { "OP", AD_GPIOOP, 16 },
- { "IP", AD_GPIOIP, 16 },
- { "ACIC", AD_ACIC, 16 },
- { "AC97_RESET", 0x100 + AC97_RESET, 16 },
- { "AC97_MASTER_VOL_STEREO", 0x100 + AC97_MASTER_VOL_STEREO, 16 },
- { "AC97_HEADPHONE_VOL", 0x100 + AC97_HEADPHONE_VOL, 16 },
- { "AC97_MASTER_VOL_MONO", 0x100 + AC97_MASTER_VOL_MONO, 16 },
- { "AC97_MASTER_TONE", 0x100 + AC97_MASTER_TONE, 16 },
- { "AC97_PCBEEP_VOL", 0x100 + AC97_PCBEEP_VOL, 16 },
- { "AC97_PHONE_VOL", 0x100 + AC97_PHONE_VOL, 16 },
- { "AC97_MIC_VOL", 0x100 + AC97_MIC_VOL, 16 },
- { "AC97_LINEIN_VOL", 0x100 + AC97_LINEIN_VOL, 16 },
- { "AC97_CD_VOL", 0x100 + AC97_CD_VOL, 16 },
- { "AC97_VIDEO_VOL", 0x100 + AC97_VIDEO_VOL, 16 },
- { "AC97_AUX_VOL", 0x100 + AC97_AUX_VOL, 16 },
- { "AC97_PCMOUT_VOL", 0x100 + AC97_PCMOUT_VOL, 16 },
- { "AC97_RECORD_SELECT", 0x100 + AC97_RECORD_SELECT, 16 },
- { "AC97_RECORD_GAIN", 0x100 + AC97_RECORD_GAIN, 16 },
- { "AC97_RECORD_GAIN_MIC", 0x100 + AC97_RECORD_GAIN_MIC, 16 },
- { "AC97_GENERAL_PURPOSE", 0x100 + AC97_GENERAL_PURPOSE, 16 },
- { "AC97_3D_CONTROL", 0x100 + AC97_3D_CONTROL, 16 },
- { "AC97_MODEM_RATE", 0x100 + AC97_MODEM_RATE, 16 },
- { "AC97_POWER_CONTROL", 0x100 + AC97_POWER_CONTROL, 16 },
+ { "WSMC", AD_DS_WSMC, 16 },
+ { "RAMC", AD_DS_RAMC, 16 },
+ { "WADA", AD_DS_WADA, 16 },
+ { "SYDA", AD_DS_SYDA, 16 },
+ { "WAS", AD_DS_WAS, 16 },
+ { "RES", AD_DS_RES, 16 },
+ { "CCS", AD_DS_CCS, 16 },
+ { "ADCBA", AD_DMA_ADCBA, 32 },
+ { "ADCCA", AD_DMA_ADCCA, 32 },
+ { "ADCBC", AD_DMA_ADCBC, 32 },
+ { "ADCCC", AD_DMA_ADCCC, 32 },
+ { "ADCIBC", AD_DMA_ADCIBC, 32 },
+ { "ADCICC", AD_DMA_ADCICC, 32 },
+ { "ADCCTRL", AD_DMA_ADCCTRL, 16 },
+ { "WAVBA", AD_DMA_WAVBA, 32 },
+ { "WAVCA", AD_DMA_WAVCA, 32 },
+ { "WAVBC", AD_DMA_WAVBC, 32 },
+ { "WAVCC", AD_DMA_WAVCC, 32 },
+ { "WAVIBC", AD_DMA_WAVIBC, 32 },
+ { "WAVICC", AD_DMA_WAVICC, 32 },
+ { "WAVCTRL", AD_DMA_WAVCTRL, 16 },
+ { "DISR", AD_DMA_DISR, 32 },
+ { "CHSS", AD_DMA_CHSS, 32 },
+ { "IPC", AD_GPIO_IPC, 16 },
+ { "OP", AD_GPIO_OP, 16 },
+ { "IP", AD_GPIO_IP, 16 },
+ { "ACIC", AD_AC97_ACIC, 16 },
+ { "AC97_RESET", AD_AC97_BASE + AC97_RESET, 16 },
+ { "AC97_MASTER_VOL_STEREO", AD_AC97_BASE + AC97_MASTER_VOL_STEREO, 16 },
+ { "AC97_HEADPHONE_VOL", AD_AC97_BASE + AC97_HEADPHONE_VOL, 16 },
+ { "AC97_MASTER_VOL_MONO", AD_AC97_BASE + AC97_MASTER_VOL_MONO, 16 },
+ { "AC97_MASTER_TONE", AD_AC97_BASE + AC97_MASTER_TONE, 16 },
+ { "AC97_PCBEEP_VOL", AD_AC97_BASE + AC97_PCBEEP_VOL, 16 },
+ { "AC97_PHONE_VOL", AD_AC97_BASE + AC97_PHONE_VOL, 16 },
+ { "AC97_MIC_VOL", AD_AC97_BASE + AC97_MIC_VOL, 16 },
+ { "AC97_LINEIN_VOL", AD_AC97_BASE + AC97_LINEIN_VOL, 16 },
+ { "AC97_CD_VOL", AD_AC97_BASE + AC97_CD_VOL, 16 },
+ { "AC97_VIDEO_VOL", AD_AC97_BASE + AC97_VIDEO_VOL, 16 },
+ { "AC97_AUX_VOL", AD_AC97_BASE + AC97_AUX_VOL, 16 },
+ { "AC97_PCMOUT_VOL", AD_AC97_BASE + AC97_PCMOUT_VOL, 16 },
+ { "AC97_RECORD_SELECT", AD_AC97_BASE + AC97_RECORD_SELECT, 16 },
+ { "AC97_RECORD_GAIN", AD_AC97_BASE + AC97_RECORD_GAIN, 16 },
+ { "AC97_RECORD_GAIN_MIC", AD_AC97_BASE + AC97_RECORD_GAIN_MIC, 16 },
+ { "AC97_GENERAL_PURPOSE", AD_AC97_BASE + AC97_GENERAL_PURPOSE, 16 },
+ { "AC97_3D_CONTROL", AD_AC97_BASE + AC97_3D_CONTROL, 16 },
+ { "AC97_MODEM_RATE", AD_AC97_BASE + AC97_MODEM_RATE, 16 },
+ { "AC97_POWER_CONTROL", AD_AC97_BASE + AC97_POWER_CONTROL, 16 },
{ NULL }
};
}
if (dmabuf->enable & DAC_RUNNING)
- offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAWAVBA));
+ offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_WAVBA));
else
- offset = le32_to_cpu(AD1889_READL(state->card, AD_DMAADCBA));
+ offset = le32_to_cpu(AD1889_READL(state->card, AD_DMA_ADCBA));
return (unsigned long)bus_to_virt((unsigned long)offset) - (unsigned long)dmabuf->rawbuf;
}
ssize_t ret = 0;
DECLARE_WAITQUEUE(wait, current);
- down(&state->sem);
+ mutex_lock(&state->mutex);
#if 0
if (dmabuf->mapped) {
ret = -ENXIO;
long cnt = count;
unsigned long flags;
-
for (;;) {
long used_bytes;
long timeout; /* max time for DMA in jiffies */
}
set_current_state(TASK_INTERRUPTIBLE);
- if (!schedule_timeout(timeout + 1))
- printk(KERN_WARNING "AD1889 timeout(%ld) r/w %lx/%lx len %lx\n",
- timeout+1,
- dmabuf->rd_ptr, dmabuf->wr_ptr,
- dmabuf->dma_len);
-
+ schedule_timeout(timeout + 1);
if (signal_pending(current)) {
ret = -ERESTARTSYS;
goto err2;
}
-
}
/* watch out for wrapping around static buffer */
err2:
remove_wait_queue(&state->dmabuf.wait, &wait);
err1:
- up(&state->sem);
+ mutex_unlock(&state->mutex);
return ret;
}
audio_buf_info abinfo;
int __user *p = (int __user *)arg;
+ DBG("ad1889_ioctl cmd 0x%x arg %lu\n", cmd, arg);
+
switch (cmd)
{
case OSS_GETVERSION:
if (val > 5400 && val < 48000)
{
if (file->f_mode & FMODE_WRITE)
- AD1889_WRITEW(ad1889_dev, AD_DSWAS, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_WAS, val);
if (file->f_mode & FMODE_READ)
- AD1889_WRITEW(ad1889_dev, AD_DSRES, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RES, val);
}
return 0;
if (get_user(val, p))
return -EFAULT;
if (file->f_mode & FMODE_READ) {
- val = AD1889_READW(ad1889_dev, AD_DSWSMC);
+ val = AD1889_READW(ad1889_dev, AD_DS_WSMC);
if (val) {
val |= 0x0200; /* set WAST */
} else {
val &= ~0x0200; /* clear WAST */
}
- AD1889_WRITEW(ad1889_dev, AD_DSWSMC, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_WSMC, val);
}
if (file->f_mode & FMODE_WRITE) {
- val = AD1889_READW(ad1889_dev, AD_DSRAMC);
+ val = AD1889_READW(ad1889_dev, AD_DS_RAMC);
if (val) {
val |= 0x0002; /* set ADST */
} else {
val &= ~0x0002; /* clear ADST */
}
- AD1889_WRITEW(ad1889_dev, AD_DSRAMC, val);
+ AD1889_WRITEW(ad1889_dev, AD_DS_RAMC, val);
}
return 0;
if (get_user(val, p))
return -EFAULT;
- if (file->f_mode & FMODE_READ)
- ad1889_set_adc_fmt(dev, val);
+ if (val == 0) {
+ if (file->f_mode & FMODE_READ)
+ ad1889_set_adc_fmt(dev, val);
- if (file->f_mode & FMODE_WRITE)
- ad1889_set_wav_fmt(dev, val);
+ if (file->f_mode & FMODE_WRITE)
+ ad1889_set_wav_fmt(dev, val);
+ } else {
+ val = AFMT_S16_LE | AFMT_U8;
+ }
return put_user(val, p);
break;
case SOUND_PCM_READ_RATE:
- return put_user(AD1889_READW(ad1889_dev, AD_DSWAS), p);
+ return put_user(AD1889_READW(ad1889_dev, AD_DS_WAS), p);
case SOUND_PCM_READ_CHANNELS:
case SOUND_PCM_READ_BITS:
file->private_data = ad1889_dev;
- ad1889_set_wav_rate(ad1889_dev, 44100);
+ ad1889_set_wav_rate(ad1889_dev, 48000);
ad1889_set_wav_fmt(ad1889_dev, AFMT_S16_LE);
- AD1889_WRITEW(ad1889_dev, AD_DSWADA, 0x0404); /* attenuation */
+ AD1889_WRITEW(ad1889_dev, AD_DS_WADA, 0x0404); /* attenuation */
return nonseekable_open(inode, file);
}
{
ad1889_dev_t *dev = ac97->private_data;
- //DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + 0x100 + reg);
- AD1889_WRITEW(dev, 0x100 + reg, val);
+ //DBG("Writing 0x%x to 0x%lx\n", val, dev->regbase + AD_AC97_BASE + reg);
+ AD1889_WRITEW(dev, AD_AC97_BASE + reg, val);
}
static u16 ad1889_codec_read(struct ac97_codec *ac97, u8 reg)
{
ad1889_dev_t *dev = ac97->private_data;
- //DBG("Reading from 0x%lx\n", dev->regbase + 0x100 + reg);
- return AD1889_READW(dev, 0x100 + reg);
+ //DBG("Reading from 0x%lx\n", dev->regbase + AD_AC97_BASE + reg);
+ return AD1889_READW(dev, AD_AC97_BASE + reg);
}
static int ad1889_ac97_init(ad1889_dev_t *dev, int id)
int retry = 200;
ad1889_dev_t *dev = pci_get_drvdata(pcidev);
- AD1889_WRITEW(dev, AD_DSCCS, 0x8000); /* turn on clock */
- AD1889_READW(dev, AD_DSCCS);
+ AD1889_WRITEW(dev, AD_DS_CCS, 0x8000); /* turn on clock */
+ AD1889_READW(dev, AD_DS_CCS);
WAIT_10MS();
- stat = AD1889_READW(dev, AD_ACIC);
+ stat = AD1889_READW(dev, AD_AC97_ACIC);
stat |= 0x0002; /* Reset Disable */
- AD1889_WRITEW(dev, AD_ACIC, stat);
- (void) AD1889_READW(dev, AD_ACIC); /* flush posted write */
+ AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
+ (void) AD1889_READW(dev, AD_AC97_ACIC); /* flush posted write */
udelay(10);
- stat = AD1889_READW(dev, AD_ACIC);
+ stat = AD1889_READW(dev, AD_AC97_ACIC);
stat |= 0x0001; /* Interface Enable */
- AD1889_WRITEW(dev, AD_ACIC, stat);
+ AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
do {
- if (AD1889_READW(dev, AD_ACIC) & 0x8000) /* Ready */
+ if (AD1889_READW(dev, AD_AC97_ACIC) & 0x8000) /* Ready */
break;
WAIT_10MS();
retry--;
if (!retry) {
printk(KERN_ERR "ad1889_aclink_reset: codec is not ready [0x%x]\n",
- AD1889_READW(dev, AD_ACIC));
+ AD1889_READW(dev, AD_AC97_ACIC));
return -EBUSY;
}
/* TODO reset AC97 codec */
/* TODO set wave/adc pci ctrl status */
- stat = AD1889_READW(dev, AD_ACIC);
+ stat = AD1889_READW(dev, AD_AC97_ACIC);
stat |= 0x0004; /* Audio Stream Output Enable */
- AD1889_WRITEW(dev, AD_ACIC, stat);
+ AD1889_WRITEW(dev, AD_AC97_ACIC, stat);
return 0;
}
};
MODULE_DEVICE_TABLE(pci, ad1889_id_tbl);
-static irqreturn_t ad1889_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t ad1889_interrupt(int irq, void *dev_id)
{
u32 stat;
ad1889_dev_t *dev = (ad1889_dev_t *)dev_id;
- stat = AD1889_READL(dev, AD_DMADISR);
+ stat = AD1889_READL(dev, AD_DMA_DISR);
/* clear ISR */
- AD1889_WRITEL(dev, AD_DMADISR, stat);
+ AD1889_WRITEL(dev, AD_DMA_DISR, stat);
if (stat & 0x8) { /* WAVI */
DBG("WAV interrupt\n");
ad1889_stop_wav(&dev->state[AD_WAV_STATE]); /* clean up */
ad1889_start_wav(&dev->state[AD_WAV_STATE]); /* start new */
}
-
}
if ((stat & 0x2) && dev->state[AD_ADC_STATE].dmabuf.ready) { /* ADCI */
static void ad1889_initcfg(ad1889_dev_t *dev)
{
- u16 tmp;
+ u16 tmp16;
+ u32 tmp32;
/* make sure the interrupt bits are setup the way we want */
- tmp = AD1889_READW(dev, AD_DMAWAVCTRL);
- tmp &= ~0x00ff; /* flat dma, no sg, mask out the intr bits */
- tmp |= 0x0004; /* intr on count, loop */
- AD1889_WRITEW(dev, AD_DMAWAVCTRL, tmp);
+ tmp32 = AD1889_READL(dev, AD_DMA_WAVCTRL);
+ tmp32 &= ~0xff; /* flat dma, no sg, mask out the intr bits */
+ tmp32 |= 0x6; /* intr on count, loop */
+ AD1889_WRITEL(dev, AD_DMA_WAVCTRL, tmp32);
/* unmute... */
- tmp = AD1889_READW(dev, AD_DSWADA);
- tmp &= ~0x8080;
- AD1889_WRITEW(dev, AD_DSWADA, tmp);
+ tmp16 = AD1889_READW(dev, AD_DS_WADA);
+ tmp16 &= ~0x8080;
+ AD1889_WRITEW(dev, AD_DS_WADA, tmp16);
}
static int __devinit ad1889_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
if (!(pci_resource_flags(pcidev, 0) & IORESOURCE_MEM)) {
printk(KERN_ERR DEVNAME ": memory region not assigned\n");
- goto err_free_mem;
+ goto out1;
}
- if (request_irq(pcidev->irq, ad1889_interrupt, SA_SHIRQ, DEVNAME, dev) != 0) {
- printk(KERN_ERR DEVNAME ": unable to request interrupt\n");
- goto err_free_mem;
+ if (pci_request_region(pcidev, 0, DEVNAME)) {
+ printk(KERN_ERR DEVNAME ": unable to request memory region\n");
+ goto out1;
}
- request_mem_region(bar, AD_DSIOMEMSIZE, DEVNAME);
- dev->regbase = (unsigned long)ioremap_nocache(bar, AD_DSIOMEMSIZE);
+ dev->regbase = ioremap_nocache(bar, AD_DS_IOMEMSIZE);
+ if (!dev->regbase) {
+ printk(KERN_ERR DEVNAME ": unable to remap iomem\n");
+ goto out2;
+ }
- printk(KERN_INFO DEVNAME ": %s at 0x%lx IRQ %d\n",
+ if (request_irq(pcidev->irq, ad1889_interrupt, IRQF_SHARED, DEVNAME, dev) != 0) {
+ printk(KERN_ERR DEVNAME ": unable to request interrupt\n");
+ goto out3;
+ }
+
+ printk(KERN_INFO DEVNAME ": %s at %p IRQ %d\n",
(char *)ent->driver_data, dev->regbase, pcidev->irq);
if (ad1889_aclink_reset(pcidev) != 0)
- goto err_free_mem;
+ goto out4;
/* register /dev/dsp */
if ((dev->dev_audio = register_sound_dsp(&ad1889_fops, -1)) < 0) {
printk(KERN_ERR DEVNAME ": cannot register /dev/dsp\n");
- goto err_free_irq;
+ goto out4;
}
if ((err = ad1889_ac97_init(dev, 0)) != 0)
- goto err_free_dsp;
+ goto out5;
+ /* XXX: cleanups */
if (((proc_root = proc_mkdir("driver/ad1889", NULL)) == NULL) ||
create_proc_read_entry("ac97", S_IFREG|S_IRUGO, proc_root, ac97_read_proc, dev->ac97_codec) == NULL ||
create_proc_read_entry("info", S_IFREG|S_IRUGO, proc_root, ad1889_read_proc, dev) == NULL)
- goto err_free_dsp;
+ goto out5;
ad1889_initcfg(dev);
return 0;
-err_free_dsp:
+out5:
unregister_sound_dsp(dev->dev_audio);
-
-err_free_irq:
+out4:
free_irq(pcidev->irq, dev);
-
-err_free_mem:
+out3:
+ iounmap(dev->regbase);
+out2:
+ pci_release_region(pcidev, 0);
+out1:
ad1889_free_dev(dev);
pci_set_drvdata(pcidev, NULL);
unregister_sound_mixer(dev->ac97_codec->dev_mixer);
unregister_sound_dsp(dev->dev_audio);
free_irq(pcidev->irq, dev);
- release_mem_region(dev->regbase, AD_DSIOMEMSIZE);
+ iounmap(dev->regbase);
+ pci_release_region(pcidev, 0);
/* any hw programming needed? */
ad1889_free_dev(dev);
+ pci_set_drvdata(pcidev, NULL);
}
MODULE_AUTHOR("Randolph Chung");
static int __init ad1889_init_module(void)
{
- return pci_module_init(&ad1889_driver);
+ return pci_register_driver(&ad1889_driver);
}
static void ad1889_exit_module(void)