Commit 184a7e14 authored by Alan Cox's avatar Alan Cox Committed by James Bottomley

[PATCH] update i810 audio to match 2.4

Primarily adds Nvidia + some i845G
parent 19602b94
...@@ -65,29 +65,41 @@ ...@@ -65,29 +65,41 @@
* If you need to force a specific rate set the clocking= option * If you need to force a specific rate set the clocking= option
* *
* This driver is cursed. (Ben LaHaise) * This driver is cursed. (Ben LaHaise)
*
*
* ICH 4 caveats
*
* The ICH4 has the feature, that the codec ID doesn't have to be
* congruent with the IO connection.
*
* Therefore, from driver version 0.23 on, there is a "codec ID" <->
* "IO register base offset" mapping (card->ac97_id_map) field.
*
* Juergen "George" Sawinski (jsaw)
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/version.h> #include <linux/version.h>
#include <linux/string.h> #include <linux/string.h>
#include <linux/interrupt.h> #include <linux/ctype.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/wait.h> #include <linux/sched.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/sound.h> #include <linux/sound.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/soundcard.h> #include <linux/soundcard.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/poll.h> #include <linux/poll.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/smp_lock.h> #include <linux/smp_lock.h>
#include <linux/ac97_codec.h> #include <linux/ac97_codec.h>
#include <linux/wrapper.h> #include <linux/wrapper.h>
#include <asm/io.h>
#include <asm/page.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/hardirq.h>
#ifndef PCI_DEVICE_ID_INTEL_82801 #ifndef PCI_DEVICE_ID_INTEL_82801
#define PCI_DEVICE_ID_INTEL_82801 0x2415 #define PCI_DEVICE_ID_INTEL_82801 0x2415
...@@ -113,9 +125,18 @@ ...@@ -113,9 +125,18 @@
#ifndef PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO #ifndef PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO
#define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO 0x01b1 #define PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO 0x01b1
#endif #endif
#ifndef PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO
#define PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO 0x006a
#endif
#ifndef PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO
#define PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO 0x00da
#endif
#ifndef PCI_DEVICE_ID_AMD_768_AUDIO #ifndef PCI_DEVICE_ID_AMD_768_AUDIO
#define PCI_DEVICE_ID_AMD_768_AUDIO 0x7445 #define PCI_DEVICE_ID_AMD_768_AUDIO 0x7445
#endif #endif
#ifndef PCI_DEVICE_ID_AMD_8111_AC97
#define PCI_DEVICE_ID_AMD_8111_AC97 0x746d
#endif
static int ftsodell=0; static int ftsodell=0;
static int strict_clocking=0; static int strict_clocking=0;
...@@ -126,6 +147,7 @@ static int spdif_locked=0; ...@@ -126,6 +147,7 @@ static int spdif_locked=0;
//#define DEBUG2 //#define DEBUG2
//#define DEBUG_INTERRUPTS //#define DEBUG_INTERRUPTS
//#define DEBUG_MMAP //#define DEBUG_MMAP
//#define DEBUG_MMIO
#define ADC_RUNNING 1 #define ADC_RUNNING 1
#define DAC_RUNNING 2 #define DAC_RUNNING 2
...@@ -168,6 +190,11 @@ struct i810_channel ...@@ -168,6 +190,11 @@ struct i810_channel
* each dma engine has controlling registers. These goofy * each dma engine has controlling registers. These goofy
* names are from the datasheet, but make it easy to write * names are from the datasheet, but make it easy to write
* code while leafing through it. * code while leafing through it.
*
* ICH4 has 6 dma engines, pcm in, pcm out, mic, pcm in 2,
* mic in 2, s/pdif. Of special interest is the fact that
* the upper 3 DMA engines on the ICH4 *must* be accessed
* via mmio access instead of pio access.
*/ */
#define ENUM_ENGINE(PRE,DIG) \ #define ENUM_ENGINE(PRE,DIG) \
...@@ -192,6 +219,14 @@ enum { ...@@ -192,6 +219,14 @@ enum {
CAS = 0x34 /* Codec Write Semaphore Register */ CAS = 0x34 /* Codec Write Semaphore Register */
}; };
ENUM_ENGINE(MC2,4); /* Mic In 2 */
ENUM_ENGINE(PI2,5); /* PCM In 2 */
ENUM_ENGINE(SP,6); /* S/PDIF */
enum {
SDM = 0x80 /* SDATA_IN Map Register */
};
/* interrupts for a dma engine */ /* interrupts for a dma engine */
#define DMA_INT_FIFO (1<<4) /* fifo under/over flow */ #define DMA_INT_FIFO (1<<4) /* fifo under/over flow */
#define DMA_INT_COMPLETE (1<<3) /* buffer read/write complete and ioc set */ #define DMA_INT_COMPLETE (1<<3) /* buffer read/write complete and ioc set */
...@@ -211,8 +246,7 @@ enum { ...@@ -211,8 +246,7 @@ enum {
#define INT_GPI (1<<0) #define INT_GPI (1<<0)
#define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI) #define INT_MASK (INT_SEC|INT_PRI|INT_MC|INT_PO|INT_PI|INT_MO|INT_NI|INT_GPI)
#define DRIVER_VERSION "0.24"
#define DRIVER_VERSION "0.21"
/* magic numbers to protect our data structures */ /* magic numbers to protect our data structures */
#define I810_CARD_MAGIC 0x5072696E /* "Prin" */ #define I810_CARD_MAGIC 0x5072696E /* "Prin" */
...@@ -221,7 +255,7 @@ enum { ...@@ -221,7 +255,7 @@ enum {
#define NR_HW_CH 3 #define NR_HW_CH 3
/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */ /* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
#define NR_AC97 2 #define NR_AC97 4
/* Please note that an 8bit mono stream is not valid on this card, you must have a 16bit */ /* Please note that an 8bit mono stream is not valid on this card, you must have a 16bit */
/* stream at a minimum for this card to be happy */ /* stream at a minimum for this card to be happy */
...@@ -256,6 +290,25 @@ static char * card_names[] = { ...@@ -256,6 +290,25 @@ static char * card_names[] = {
"AMD-8111 IOHub" "AMD-8111 IOHub"
}; };
/* These are capabilities (and bugs) the chipsets _can_ have */
static struct {
int16_t nr_ac97;
#define CAP_MMIO 0x0001
#define CAP_20BIT_AUDIO_SUPPORT 0x0002
u_int16_t flags;
} card_cap[] = {
{ 1, 0x0000 }, /* ICH82801AA */
{ 1, 0x0000 }, /* ICH82901AB */
{ 1, 0x0000 }, /* INTEL440MX */
{ 1, 0x0000 }, /* INTELICH2 */
{ 2, 0x0000 }, /* INTELICH3 */
{ 3, 0x0003 }, /* INTELICH4 */
/*@FIXME to be verified*/ { 2, 0x0000 }, /* SI7012 */
/*@FIXME to be verified*/ { 2, 0x0000 }, /* NVIDIA_NFORCE */
/*@FIXME to be verified*/ { 2, 0x0000 }, /* AMD768 */
/*@FIXME to be verified*/ { 3, 0x0001 }, /* AMD8111 */
};
static struct pci_device_id i810_pci_tbl [] __initdata = { static struct pci_device_id i810_pci_tbl [] __initdata = {
{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801, {PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82801AA}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ICH82801AA},
...@@ -273,9 +326,13 @@ static struct pci_device_id i810_pci_tbl [] __initdata = { ...@@ -273,9 +326,13 @@ static struct pci_device_id i810_pci_tbl [] __initdata = {
PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SI7012},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP2_AUDIO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
{PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_MCP3_AUDIO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, NVIDIA_NFORCE},
{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_768_AUDIO, {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_768_AUDIO,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD768},
{PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AUDIO, {PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_AC97,
PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111}, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AMD8111},
{0,} {0,}
}; };
...@@ -365,6 +422,7 @@ struct i810_card { ...@@ -365,6 +422,7 @@ struct i810_card {
/* PCI device stuff */ /* PCI device stuff */
struct pci_dev * pci_dev; struct pci_dev * pci_dev;
u16 pci_id; u16 pci_id;
u16 pci_id_internal; /* used to access card_cap[] */
#ifdef CONFIG_PM #ifdef CONFIG_PM
u16 pm_suspended; u16 pm_suspended;
u32 pm_save_state[64/sizeof(u32)]; u32 pm_save_state[64/sizeof(u32)];
...@@ -374,6 +432,7 @@ struct i810_card { ...@@ -374,6 +432,7 @@ struct i810_card {
int dev_audio; int dev_audio;
/* structures for abstraction of hardware facilities, codecs, banks and channels*/ /* structures for abstraction of hardware facilities, codecs, banks and channels*/
u16 ac97_id_map[NR_AC97];
struct ac97_codec *ac97_codec[NR_AC97]; struct ac97_codec *ac97_codec[NR_AC97];
struct i810_state *states[NR_HW_CH]; struct i810_state *states[NR_HW_CH];
struct i810_channel *channel; /* 1:1 to states[] but diff. lifetime */ struct i810_channel *channel; /* 1:1 to states[] but diff. lifetime */
...@@ -384,10 +443,17 @@ struct i810_card { ...@@ -384,10 +443,17 @@ struct i810_card {
u16 channels; u16 channels;
/* hardware resources */ /* hardware resources */
unsigned long iobase;
unsigned long ac97base; unsigned long ac97base;
unsigned long iobase;
u32 irq; u32 irq;
unsigned long ac97base_mmio_phys;
unsigned long iobase_mmio_phys;
u_int8_t *ac97base_mmio;
u_int8_t *iobase_mmio;
int use_mmio;
/* Function support */ /* Function support */
struct i810_channel *(*alloc_pcm_channel)(struct i810_card *); struct i810_channel *(*alloc_pcm_channel)(struct i810_card *);
struct i810_channel *(*alloc_rec_pcm_channel)(struct i810_card *); struct i810_channel *(*alloc_rec_pcm_channel)(struct i810_card *);
...@@ -399,6 +465,12 @@ struct i810_card { ...@@ -399,6 +465,12 @@ struct i810_card {
int initializing; int initializing;
}; };
/* extract register offset from codec struct */
#define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])
/* set LVI from CIV */
#define CIV_TO_LVI(port, off) outb((inb(port+OFF_CIV)+off) & 31, port+OFF_LVI)
static struct i810_card *devs = NULL; static struct i810_card *devs = NULL;
static int i810_open_mixdev(struct inode *inode, struct file *file); static int i810_open_mixdev(struct inode *inode, struct file *file);
...@@ -406,6 +478,10 @@ static int i810_ioctl_mixdev(struct inode *inode, struct file *file, ...@@ -406,6 +478,10 @@ static int i810_ioctl_mixdev(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg); unsigned int cmd, unsigned long arg);
static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg); static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg);
static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data); static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data);
static u16 i810_ac97_get_mmio(struct ac97_codec *dev, u8 reg);
static void i810_ac97_set_mmio(struct ac97_codec *dev, u8 reg, u16 data);
static u16 i810_ac97_get_io(struct ac97_codec *dev, u8 reg);
static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data);
static struct i810_channel *i810_alloc_pcm_channel(struct i810_card *card) static struct i810_channel *i810_alloc_pcm_channel(struct i810_card *card)
{ {
...@@ -757,7 +833,8 @@ static inline void __start_adc(struct i810_state *state) ...@@ -757,7 +833,8 @@ static inline void __start_adc(struct i810_state *state)
if (dmabuf->count < dmabuf->dmasize && dmabuf->ready && !dmabuf->enable && if (dmabuf->count < dmabuf->dmasize && dmabuf->ready && !dmabuf->enable &&
(dmabuf->trigger & PCM_ENABLE_INPUT)) { (dmabuf->trigger & PCM_ENABLE_INPUT)) {
dmabuf->enable |= ADC_RUNNING; dmabuf->enable |= ADC_RUNNING;
outb((1<<4) | (1<<2) | 1, state->card->iobase + PI_CR); // Interrupt enable, LVI enable, DMA enable
outb(0x10 | 0x04 | 0x01, state->card->iobase + PI_CR);
} }
} }
...@@ -806,7 +883,8 @@ static inline void __start_dac(struct i810_state *state) ...@@ -806,7 +883,8 @@ static inline void __start_dac(struct i810_state *state)
if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable && if (dmabuf->count > 0 && dmabuf->ready && !dmabuf->enable &&
(dmabuf->trigger & PCM_ENABLE_OUTPUT)) { (dmabuf->trigger & PCM_ENABLE_OUTPUT)) {
dmabuf->enable |= DAC_RUNNING; dmabuf->enable |= DAC_RUNNING;
outb((1<<4) | (1<<2) | 1, state->card->iobase + PO_CR); // Interrupt enable, LVI enable, DMA enable
outb(0x10 | 0x04 | 0x01, state->card->iobase + PO_CR);
} }
} }
static void start_dac(struct i810_state *state) static void start_dac(struct i810_state *state)
...@@ -973,11 +1051,11 @@ static int prog_dmabuf(struct i810_state *state, unsigned rec) ...@@ -973,11 +1051,11 @@ static int prog_dmabuf(struct i810_state *state, unsigned rec)
} }
spin_lock_irqsave(&state->card->lock, flags); spin_lock_irqsave(&state->card->lock, flags);
outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */ outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */
while( inb(state->card->iobase+c->port+OFF_CR) & 0x02 ) ;
outl((u32)state->card->chandma + outl((u32)state->card->chandma +
c->num*sizeof(struct i810_channel), c->num*sizeof(struct i810_channel),
state->card->iobase+c->port+OFF_BDBAR); state->card->iobase+c->port+OFF_BDBAR);
outb(0, state->card->iobase+c->port+OFF_CIV); CIV_TO_LVI(state->card->iobase+c->port, 0);
outb(0, state->card->iobase+c->port+OFF_LVI);
spin_unlock_irqrestore(&state->card->lock, flags); spin_unlock_irqrestore(&state->card->lock, flags);
...@@ -1023,13 +1101,13 @@ static void __i810_update_lvi(struct i810_state *state, int rec) ...@@ -1023,13 +1101,13 @@ static void __i810_update_lvi(struct i810_state *state, int rec)
if(rec && dmabuf->count < dmabuf->dmasize && if(rec && dmabuf->count < dmabuf->dmasize &&
(dmabuf->trigger & PCM_ENABLE_INPUT)) (dmabuf->trigger & PCM_ENABLE_INPUT))
{ {
outb((inb(port+OFF_CIV)+1)&31, port+OFF_LVI); CIV_TO_LVI(port, 1);
__start_adc(state); __start_adc(state);
while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ; while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ;
} else if (!rec && dmabuf->count && } else if (!rec && dmabuf->count &&
(dmabuf->trigger & PCM_ENABLE_OUTPUT)) (dmabuf->trigger & PCM_ENABLE_OUTPUT))
{ {
outb((inb(port+OFF_CIV)+1)&31, port+OFF_LVI); CIV_TO_LVI(port, 1);
__start_dac(state); __start_dac(state);
while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ; while( !(inb(port + OFF_CR) & ((1<<4) | (1<<2))) ) ;
} }
...@@ -1297,7 +1375,6 @@ static void i810_channel_interrupt(struct i810_card *card) ...@@ -1297,7 +1375,6 @@ static void i810_channel_interrupt(struct i810_card *card)
if (dmabuf->enable & ADC_RUNNING) if (dmabuf->enable & ADC_RUNNING)
__stop_adc(state); __stop_adc(state);
dmabuf->enable = 0; dmabuf->enable = 0;
wake_up(&dmabuf->wait);
#ifdef DEBUG_INTERRUPTS #ifdef DEBUG_INTERRUPTS
printk(" STOP "); printk(" STOP ");
#endif #endif
...@@ -1743,11 +1820,12 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -1743,11 +1820,12 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
} }
if (c != NULL) { if (c != NULL) {
outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */ outb(2, state->card->iobase+c->port+OFF_CR); /* reset DMA machine */
while ( inb(state->card->iobase+c->port+OFF_CR) & 2 )
cpu_relax();
outl((u32)state->card->chandma + outl((u32)state->card->chandma +
c->num*sizeof(struct i810_channel), c->num*sizeof(struct i810_channel),
state->card->iobase+c->port+OFF_BDBAR); state->card->iobase+c->port+OFF_BDBAR);
outb(0, state->card->iobase+c->port+OFF_CIV); CIV_TO_LVI(state->card->iobase+c->port, 0);
outb(0, state->card->iobase+c->port+OFF_LVI);
} }
spin_unlock_irqrestore(&state->card->lock, flags); spin_unlock_irqrestore(&state->card->lock, flags);
...@@ -1868,7 +1946,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -1868,7 +1946,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
} }
/* ICH and ICH0 only support 2 channels */ /* ICH and ICH0 only support 2 channels */
if ( state->card->pci_id == 0x2415 || state->card->pci_id == 0x2425 ) if ( state->card->pci_id == PCI_DEVICE_ID_INTEL_82801
|| state->card->pci_id == PCI_DEVICE_ID_INTEL_82901)
return put_user(2, (int *)arg); return put_user(2, (int *)arg);
/* Multi-channel support was added with ICH2. Bits in */ /* Multi-channel support was added with ICH2. Bits in */
...@@ -1887,12 +1966,14 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -1887,12 +1966,14 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
switch ( val ) { switch ( val ) {
case 2: /* 2 channels is always supported */ case 2: /* 2 channels is always supported */
outl(state->card->iobase + GLOB_CNT, (i_glob_cnt & 0xcfffff)); outl(i_glob_cnt & 0xffcfffff,
state->card->iobase + GLOB_CNT);
/* Do we need to change mixer settings???? */ /* Do we need to change mixer settings???? */
break; break;
case 4: /* Supported on some chipsets, better check first */ case 4: /* Supported on some chipsets, better check first */
if ( state->card->channels >= 4 ) { if ( state->card->channels >= 4 ) {
outl(state->card->iobase + GLOB_CNT, ((i_glob_cnt & 0xcfffff) | 0x0100000)); outl((i_glob_cnt & 0xffcfffff) | 0x100000,
state->card->iobase + GLOB_CNT);
/* Do we need to change mixer settings??? */ /* Do we need to change mixer settings??? */
} else { } else {
val = ret; val = ret;
...@@ -1900,7 +1981,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -1900,7 +1981,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
break; break;
case 6: /* Supported on some chipsets, better check first */ case 6: /* Supported on some chipsets, better check first */
if ( state->card->channels >= 6 ) { if ( state->card->channels >= 6 ) {
outl(state->card->iobase + GLOB_CNT, ((i_glob_cnt & 0xcfffff) | 0x0200000)); outl((i_glob_cnt & 0xffcfffff) | 0x200000,
state->card->iobase + GLOB_CNT);
/* Do we need to change mixer settings??? */ /* Do we need to change mixer settings??? */
} else { } else {
val = ret; val = ret;
...@@ -2037,9 +2119,7 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -2037,9 +2119,7 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
printk("SNDCTL_DSP_GETOPTR %d, %d, %d, %d\n", cinfo.bytes, printk("SNDCTL_DSP_GETOPTR %d, %d, %d, %d\n", cinfo.bytes,
cinfo.blocks, cinfo.ptr, dmabuf->count); cinfo.blocks, cinfo.ptr, dmabuf->count);
#endif #endif
if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo))) return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
return -EFAULT;
return 0;
case SNDCTL_DSP_GETISPACE: case SNDCTL_DSP_GETISPACE:
if (!(file->f_mode & FMODE_READ)) if (!(file->f_mode & FMODE_READ))
...@@ -2078,9 +2158,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd, ...@@ -2078,9 +2158,8 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
printk("SNDCTL_DSP_GETIPTR %d, %d, %d, %d\n", cinfo.bytes, printk("SNDCTL_DSP_GETIPTR %d, %d, %d, %d\n", cinfo.bytes,
cinfo.blocks, cinfo.ptr, dmabuf->count); cinfo.blocks, cinfo.ptr, dmabuf->count);
#endif #endif
if (copy_to_user((void *)arg, &cinfo, sizeof(cinfo))) return copy_to_user((void *)arg, &cinfo, sizeof(cinfo)) ? -EFAULT : 0;
return -EFAULT;
return 0;
case SNDCTL_DSP_NONBLOCK: case SNDCTL_DSP_NONBLOCK:
#ifdef DEBUG #ifdef DEBUG
printk("SNDCTL_DSP_NONBLOCK\n"); printk("SNDCTL_DSP_NONBLOCK\n");
...@@ -2421,6 +2500,9 @@ static int i810_open(struct inode *inode, struct file *file) ...@@ -2421,6 +2500,9 @@ static int i810_open(struct inode *inode, struct file *file)
i810_set_spdif_output(state, AC97_EA_SPSA_3_4, spdif_locked); i810_set_spdif_output(state, AC97_EA_SPSA_3_4, spdif_locked);
} else { } else {
i810_set_dac_rate(state, 8000); i810_set_dac_rate(state, 8000);
/* Put the ACLink in 2 channel mode by default */
i = inl(card->iobase + GLOB_CNT);
outl(i & 0xffcfffff, card->iobase + GLOB_CNT);
} }
} }
...@@ -2485,11 +2567,31 @@ static /*const*/ struct file_operations i810_audio_fops = { ...@@ -2485,11 +2567,31 @@ static /*const*/ struct file_operations i810_audio_fops = {
/* Write AC97 codec registers */ /* Write AC97 codec registers */
static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg) static u16 i810_ac97_get_mmio(struct ac97_codec *dev, u8 reg)
{ {
struct i810_card *card = dev->private_data; struct i810_card *card = dev->private_data;
int count = 100; int count = 100;
u8 reg_set = ((dev->id)?((reg&0x7f)|0x80):(reg&0x7f)); u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
while(count-- && (readb(card->iobase_mmio + CAS) & 1))
udelay(1);
#ifdef DEBUG_MMIO
{
u16 ans = readw(card->ac97base_mmio + reg_set);
printk(KERN_DEBUG "i810_audio: ac97_get_mmio(%d) -> 0x%04X\n", ((int) reg_set) & 0xffff, (u32) ans);
return ans;
}
#else
return readw(card->ac97base_mmio + reg_set);
#endif
}
static u16 i810_ac97_get_io(struct ac97_codec *dev, u8 reg)
{
struct i810_card *card = dev->private_data;
int count = 100;
u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
while(count-- && (inb(card->iobase + CAS) & 1)) while(count-- && (inb(card->iobase + CAS) & 1))
udelay(1); udelay(1);
...@@ -2497,24 +2599,63 @@ static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg) ...@@ -2497,24 +2599,63 @@ static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg)
return inw(card->ac97base + reg_set); return inw(card->ac97base + reg_set);
} }
static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data) static void i810_ac97_set_mmio(struct ac97_codec *dev, u8 reg, u16 data)
{
struct i810_card *card = dev->private_data;
int count = 100;
u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
while(count-- && (readb(card->iobase_mmio + CAS) & 1))
udelay(1);
writew(data, card->ac97base_mmio + reg_set);
#ifdef DEBUG_MMIO
printk(KERN_DEBUG "i810_audio: ac97_set_mmio(0x%04X, %d)\n", (u32) data, ((int) reg_set) & 0xffff);
#endif
}
static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data)
{ {
struct i810_card *card = dev->private_data; struct i810_card *card = dev->private_data;
int count = 100; int count = 100;
u8 reg_set = ((dev->id)?((reg&0x7f)|0x80):(reg&0x7f)); u16 reg_set = IO_REG_OFF(dev) | (reg&0x7f);
while(count-- && (inb(card->iobase + CAS) & 1)) while(count-- && (inb(card->iobase + CAS) & 1))
udelay(1); udelay(1);
outw(data, card->ac97base + reg_set); outw(data, card->ac97base + reg_set);
} }
static u16 i810_ac97_get(struct ac97_codec *dev, u8 reg)
{
struct i810_card *card = dev->private_data;
if (card->use_mmio) {
return i810_ac97_get_mmio(dev, reg);
}
else {
return i810_ac97_get_io(dev, reg);
}
}
static void i810_ac97_set(struct ac97_codec *dev, u8 reg, u16 data)
{
struct i810_card *card = dev->private_data;
if (card->use_mmio) {
i810_ac97_set_mmio(dev, reg, data);
}
else {
i810_ac97_set_io(dev, reg, data);
}
}
/* OSS /dev/mixer file operation methods */ /* OSS /dev/mixer file operation methods */
static int i810_open_mixdev(struct inode *inode, struct file *file) static int i810_open_mixdev(struct inode *inode, struct file *file)
{ {
int i; int i;
unsigned int minor = minor(inode->i_rdev); int minor = minor(inode->i_rdev);
struct i810_card *card = devs; struct i810_card *card = devs;
for (card = devs; card != NULL; card = card->next) { for (card = devs; card != NULL; card = card->next) {
...@@ -2558,10 +2699,18 @@ static /*const*/ struct file_operations i810_mixer_fops = { ...@@ -2558,10 +2699,18 @@ static /*const*/ struct file_operations i810_mixer_fops = {
/* AC97 codec initialisation. These small functions exist so we don't /* AC97 codec initialisation. These small functions exist so we don't
duplicate code between module init and apm resume */ duplicate code between module init and apm resume */
static inline int i810_ac97_exists(struct i810_card *card,int ac97_number) static inline int i810_ac97_exists(struct i810_card *card, int ac97_number)
{ {
u32 reg = inl(card->iobase + GLOB_STA); u32 reg = inl(card->iobase + GLOB_STA);
return (reg & (0x100 << ac97_number)); switch (ac97_number) {
case 0:
return reg & (1<<8);
case 1:
return reg & (1<<9);
case 2:
return reg & (1<<28);
}
return 0;
} }
static inline int i810_ac97_enable_variable_rate(struct ac97_codec *codec) static inline int i810_ac97_enable_variable_rate(struct ac97_codec *codec)
...@@ -2584,10 +2733,9 @@ static int i810_ac97_probe_and_powerup(struct i810_card *card,struct ac97_codec ...@@ -2584,10 +2733,9 @@ static int i810_ac97_probe_and_powerup(struct i810_card *card,struct ac97_codec
/* power it all up */ /* power it all up */
i810_ac97_set(codec, AC97_POWER_CONTROL, i810_ac97_set(codec, AC97_POWER_CONTROL,
i810_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00); i810_ac97_get(codec, AC97_POWER_CONTROL) & ~0x7f00);
/* wait for analog ready */ /* wait for analog ready */
for (i=10; for (i=10; i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf); i--)
i && ((i810_ac97_get(codec, AC97_POWER_CONTROL) & 0xf) != 0xf);
i--)
{ {
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/20); schedule_timeout(HZ/20);
...@@ -2595,11 +2743,18 @@ static int i810_ac97_probe_and_powerup(struct i810_card *card,struct ac97_codec ...@@ -2595,11 +2743,18 @@ static int i810_ac97_probe_and_powerup(struct i810_card *card,struct ac97_codec
return i; return i;
} }
/* if I knew what this did, I'd give it a better name */ /**
static int i810_ac97_random_init_stuff(struct i810_card *card) * i810_ac97_power_up_bus - bring up AC97 link
* @card : ICH audio device to power up
*
* Bring up the ACLink AC97 codec bus
*/
static int i810_ac97_power_up_bus(struct i810_card *card)
{ {
u32 reg = inl(card->iobase + GLOB_CNT); u32 reg = inl(card->iobase + GLOB_CNT);
int i; int i;
int primary_codec_id = 0;
if((reg&2)==0) /* Cold required */ if((reg&2)==0) /* Cold required */
reg|=2; reg|=2;
...@@ -2607,8 +2762,13 @@ static int i810_ac97_random_init_stuff(struct i810_card *card) ...@@ -2607,8 +2762,13 @@ static int i810_ac97_random_init_stuff(struct i810_card *card)
reg|=4; /* Warm */ reg|=4; /* Warm */
reg&=~8; /* ACLink on */ reg&=~8; /* ACLink on */
/* At this point we deassert AC_RESET # */
outl(reg , card->iobase + GLOB_CNT); outl(reg , card->iobase + GLOB_CNT);
/* We must now allow time for the Codec initialisation.
600mS is the specified time */
for(i=0;i<10;i++) for(i=0;i<10;i++)
{ {
if((inl(card->iobase+GLOB_CNT)&4)==0) if((inl(card->iobase+GLOB_CNT)&4)==0)
...@@ -2625,7 +2785,31 @@ static int i810_ac97_random_init_stuff(struct i810_card *card) ...@@ -2625,7 +2785,31 @@ static int i810_ac97_random_init_stuff(struct i810_card *card)
set_current_state(TASK_UNINTERRUPTIBLE); set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ/2); schedule_timeout(HZ/2);
reg = inl(card->iobase + GLOB_STA);
/*
* See if the primary codec comes ready. This must happen
* before we start doing DMA stuff
*/
/* see i810_ac97_init for the next 7 lines (jsaw) */
inw(card->ac97base);
if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4)
&& (card->use_mmio)) {
primary_codec_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
printk(KERN_INFO "i810_audio: Primary codec has ID %d\n",
primary_codec_id);
}
if(! i810_ac97_exists(card, primary_codec_id))
{
printk(KERN_INFO "i810_audio: Codec not ready.. wait.. ");
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ); /* actually 600mS by the spec */
if(i810_ac97_exists(card, primary_codec_id))
printk("OK\n");
else
printk("no response.\n");
}
inw(card->ac97base); inw(card->ac97base);
return 1; return 1;
} }
...@@ -2633,12 +2817,14 @@ static int i810_ac97_random_init_stuff(struct i810_card *card) ...@@ -2633,12 +2817,14 @@ static int i810_ac97_random_init_stuff(struct i810_card *card)
static int __init i810_ac97_init(struct i810_card *card) static int __init i810_ac97_init(struct i810_card *card)
{ {
int num_ac97 = 0; int num_ac97 = 0;
int ac97_id;
int total_channels = 0; int total_channels = 0;
int nr_ac97_max = card_cap[card->pci_id_internal].nr_ac97;
struct ac97_codec *codec; struct ac97_codec *codec;
u16 eid; u16 eid;
u32 reg; u32 reg;
if(!i810_ac97_random_init_stuff(card)) return 0; if(!i810_ac97_power_up_bus(card)) return 0;
/* Number of channels supported */ /* Number of channels supported */
/* What about the codec? Just because the ICH supports */ /* What about the codec? Just because the ICH supports */
...@@ -2654,24 +2840,45 @@ static int __init i810_ac97_init(struct i810_card *card) ...@@ -2654,24 +2840,45 @@ static int __init i810_ac97_init(struct i810_card *card)
card->channels = 6; card->channels = 6;
else if ( reg & 0x0100000 ) else if ( reg & 0x0100000 )
card->channels = 4; card->channels = 4;
printk("i810_audio: Audio Controller supports %d channels.\n", card->channels); printk(KERN_INFO "i810_audio: Audio Controller supports %d channels.\n", card->channels);
printk(KERN_INFO "i810_audio: Defaulting to base 2 channel mode.\n");
reg = inl(card->iobase + GLOB_CNT);
outl(reg & 0xffcfffff, card->iobase + GLOB_CNT);
inw(card->ac97base); for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++)
card->ac97_codec[num_ac97] = NULL;
for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { /*@FIXME I don't know, if I'm playing to safe here... (jsaw) */
if ((nr_ac97_max > 2) && !card->use_mmio) nr_ac97_max = 2;
/* Assume codec isn't available until we go through the for (num_ac97 = 0; num_ac97 < nr_ac97_max; num_ac97++) {
* gauntlet below */ /* codec reset */
card->ac97_codec[num_ac97] = NULL; printk(KERN_INFO "i810_audio: Resetting connection %d\n", num_ac97);
if (card->use_mmio) readw(card->ac97base_mmio + 0x80*num_ac97);
else inw(card->ac97base + 0x80*num_ac97);
/* If we have the SDATA_IN Map Register, as on ICH4, we
do not loop thru all possible codec IDs but thru all
possible IO channels. Bit 0:1 of SDM then holds the
last codec ID spoken to.
*/
if ((card->pci_id == PCI_DEVICE_ID_INTEL_ICH4)
&& (card->use_mmio)) {
ac97_id = (int) readl(card->iobase_mmio + SDM) & 0x3;
printk(KERN_INFO "i810_audio: Connection %d with codec id %d\n",
num_ac97, ac97_id);
}
else {
ac97_id = num_ac97;
}
/* The ICH programmer's reference says you should */ /* The ICH programmer's reference says you should */
/* check the ready status before probing. So we chk */ /* check the ready status before probing. So we chk */
/* What do we do if it's not ready? Wait and try */ /* What do we do if it's not ready? Wait and try */
/* again, or abort? */ /* again, or abort? */
if (!i810_ac97_exists(card,num_ac97)) { if (!i810_ac97_exists(card, ac97_id)) {
if(num_ac97 == 0) if(num_ac97 == 0)
printk(KERN_ERR "i810_audio: Primary codec not ready.\n"); printk(KERN_ERR "i810_audio: Primary codec not ready.\n");
break; /* I think this works, if not ready stop */
} }
if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL) if ((codec = kmalloc(sizeof(struct ac97_codec), GFP_KERNEL)) == NULL)
...@@ -2681,13 +2888,20 @@ static int __init i810_ac97_init(struct i810_card *card) ...@@ -2681,13 +2888,20 @@ static int __init i810_ac97_init(struct i810_card *card)
/* initialize some basic codec information, other fields will be filled /* initialize some basic codec information, other fields will be filled
in ac97_probe_codec */ in ac97_probe_codec */
codec->private_data = card; codec->private_data = card;
codec->id = num_ac97; codec->id = ac97_id;
card->ac97_id_map[ac97_id] = num_ac97 * 0x80;
codec->codec_read = i810_ac97_get; if (card->use_mmio) {
codec->codec_write = i810_ac97_set; codec->codec_read = i810_ac97_get_mmio;
codec->codec_write = i810_ac97_set_mmio;
}
else {
codec->codec_read = i810_ac97_get_io;
codec->codec_write = i810_ac97_set_io;
}
if(!i810_ac97_probe_and_powerup(card,codec)) { if(!i810_ac97_probe_and_powerup(card,codec)) {
printk("i810_audio: timed out waiting for codec %d analog ready.\n", num_ac97); printk(KERN_ERR "i810_audio: timed out waiting for codec %d analog ready.\n", ac97_id);
kfree(codec); kfree(codec);
break; /* it didn't work */ break; /* it didn't work */
} }
...@@ -2704,10 +2918,21 @@ static int __init i810_ac97_init(struct i810_card *card) ...@@ -2704,10 +2918,21 @@ static int __init i810_ac97_init(struct i810_card *card)
break; break;
} }
/* Check for an AC97 1.0 soft modem (ID1) */
if(codec->codec_read(codec, AC97_RESET) & 2)
{
printk(KERN_WARNING "i810_audio: codec %d is an AC97 1.0 softmodem - skipping.\n", ac97_id);
kfree(codec);
continue;
}
/* Check for an AC97 2.x soft modem */
codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0L); codec->codec_write(codec, AC97_EXTENDED_MODEM_ID, 0L);
if(codec->codec_read(codec, AC97_EXTENDED_MODEM_ID)) if(codec->codec_read(codec, AC97_EXTENDED_MODEM_ID) & 1)
{ {
printk(KERN_WARNING "i810_audio: codec %d is a softmodem - skipping.\n", num_ac97); printk(KERN_WARNING "i810_audio: codec %d is an AC97 2.x softmodem - skipping.\n", ac97_id);
kfree(codec); kfree(codec);
continue; continue;
} }
...@@ -2727,6 +2952,11 @@ static int __init i810_ac97_init(struct i810_card *card) ...@@ -2727,6 +2952,11 @@ static int __init i810_ac97_init(struct i810_card *card)
} }
} }
/* Turn on the amplifier */
codec->codec_write(codec, AC97_POWER_CONTROL,
codec->codec_read(codec, AC97_POWER_CONTROL) & ~0x8000);
/* Determine how many channels the codec(s) support */ /* Determine how many channels the codec(s) support */
/* - The primary codec always supports 2 */ /* - The primary codec always supports 2 */
/* - If the codec supports AMAP, surround DACs will */ /* - If the codec supports AMAP, surround DACs will */
...@@ -2752,7 +2982,7 @@ static int __init i810_ac97_init(struct i810_card *card) ...@@ -2752,7 +2982,7 @@ static int __init i810_ac97_init(struct i810_card *card)
total_channels += 2; total_channels += 2;
if (eid & 0x0140) /* LFE and Center channels */ if (eid & 0x0140) /* LFE and Center channels */
total_channels += 2; total_channels += 2;
printk("i810_audio: AC'97 codec %d supports AMAP, total channels = %d\n", num_ac97, total_channels); printk("i810_audio: AC'97 codec %d supports AMAP, total channels = %d\n", ac97_id, total_channels);
} else if (eid & 0x0400) { /* this only works on 2.2 compliant codecs */ } else if (eid & 0x0400) { /* this only works on 2.2 compliant codecs */
eid &= 0xffcf; eid &= 0xffcf;
if((eid & 0xc000) != 0) { if((eid & 0xc000) != 0) {
...@@ -2774,14 +3004,14 @@ static int __init i810_ac97_init(struct i810_card *card) ...@@ -2774,14 +3004,14 @@ static int __init i810_ac97_init(struct i810_card *card)
} }
i810_ac97_set(codec, AC97_EXTENDED_ID, eid); i810_ac97_set(codec, AC97_EXTENDED_ID, eid);
eid = i810_ac97_get(codec, AC97_EXTENDED_ID); eid = i810_ac97_get(codec, AC97_EXTENDED_ID);
printk("i810_audio: AC'97 codec %d, new EID value = 0x%04x\n", num_ac97, eid); printk("i810_audio: AC'97 codec %d, new EID value = 0x%04x\n", ac97_id, eid);
if (eid & 0x0080) /* L/R Surround channels */ if (eid & 0x0080) /* L/R Surround channels */
total_channels += 2; total_channels += 2;
if (eid & 0x0140) /* LFE and Center channels */ if (eid & 0x0140) /* LFE and Center channels */
total_channels += 2; total_channels += 2;
printk("i810_audio: AC'97 codec %d, DAC map configured, total channels = %d\n", num_ac97, total_channels); printk("i810_audio: AC'97 codec %d, DAC map configured, total channels = %d\n", ac97_id, total_channels);
} else { } else {
printk("i810_audio: AC'97 codec %d Unable to map surround DAC's (or DAC's not present), total channels = %d\n", num_ac97, total_channels); printk("i810_audio: AC'97 codec %d Unable to map surround DAC's (or DAC's not present), total channels = %d\n", ac97_id, total_channels);
} }
if ((codec->dev_mixer = register_sound_mixer(&i810_mixer_fops, -1)) < 0) { if ((codec->dev_mixer = register_sound_mixer(&i810_mixer_fops, -1)) < 0) {
...@@ -2830,6 +3060,8 @@ static void __init i810_configure_clocking (void) ...@@ -2830,6 +3060,8 @@ static void __init i810_configure_clocking (void)
init_MUTEX(&state->open_sem); init_MUTEX(&state->open_sem);
dmabuf->fmt = I810_FMT_STEREO | I810_FMT_16BIT; dmabuf->fmt = I810_FMT_STEREO | I810_FMT_16BIT;
dmabuf->trigger = PCM_ENABLE_OUTPUT; dmabuf->trigger = PCM_ENABLE_OUTPUT;
i810_set_spdif_output(state, -1, 0);
i810_set_dac_channels(state, 2);
i810_set_dac_rate(state, 48000); i810_set_dac_rate(state, 48000);
if(prog_dmabuf(state, 0) != 0) { if(prog_dmabuf(state, 0) != 0) {
goto config_out_nodmabuf; goto config_out_nodmabuf;
...@@ -2838,17 +3070,16 @@ static void __init i810_configure_clocking (void) ...@@ -2838,17 +3070,16 @@ static void __init i810_configure_clocking (void)
goto config_out; goto config_out;
} }
dmabuf->count = dmabuf->dmasize; dmabuf->count = dmabuf->dmasize;
outb(31,card->iobase+dmabuf->write_channel->port+OFF_LVI); CIV_TO_LVI(card->iobase+dmabuf->write_channel->port, 31);
local_irq_save(flags); local_irq_save(flags);
start_dac(state); start_dac(state);
offset = i810_get_dma_addr(state, 0); offset = i810_get_dma_addr(state, 0);
mdelay(50); mdelay(50);
new_offset = i810_get_dma_addr(state, 0); new_offset = i810_get_dma_addr(state, 0);
stop_dac(state); stop_dac(state);
outb(2,card->iobase+dmabuf->write_channel->port+OFF_CR);
local_irq_restore(flags); local_irq_restore(flags);
i = new_offset - offset; i = new_offset - offset;
#ifdef DEBUG #ifdef DEBUG_INTERRUPTS
printk("i810_audio: %d bytes in 50 milliseconds\n", i); printk("i810_audio: %d bytes in 50 milliseconds\n", i);
#endif #endif
if(i == 0) if(i == 0)
...@@ -2890,10 +3121,25 @@ static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id ...@@ -2890,10 +3121,25 @@ static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id
memset(card, 0, sizeof(*card)); memset(card, 0, sizeof(*card));
card->initializing = 1; card->initializing = 1;
card->iobase = pci_resource_start (pci_dev, 1);
card->ac97base = pci_resource_start (pci_dev, 0);
card->pci_dev = pci_dev; card->pci_dev = pci_dev;
card->pci_id = pci_id->device; card->pci_id = pci_id->device;
card->ac97base = pci_resource_start (pci_dev, 0);
card->iobase = pci_resource_start (pci_dev, 1);
/* if chipset could have mmio capability, check it */
if (card_cap[pci_id->driver_data].flags & CAP_MMIO) {
card->ac97base_mmio_phys = pci_resource_start (pci_dev, 2);
card->iobase_mmio_phys = pci_resource_start (pci_dev, 3);
if ((card->ac97base_mmio_phys) && (card->iobase_mmio_phys)) {
card->use_mmio = 1;
}
else {
card->ac97base_mmio_phys = 0;
card->iobase_mmio_phys = 0;
}
}
card->irq = pci_dev->irq; card->irq = pci_dev->irq;
card->next = devs; card->next = devs;
card->magic = I810_CARD_MAGIC; card->magic = I810_CARD_MAGIC;
...@@ -2905,8 +3151,11 @@ static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id ...@@ -2905,8 +3151,11 @@ static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id
pci_set_master(pci_dev); pci_set_master(pci_dev);
printk(KERN_INFO "i810: %s found at IO 0x%04lx and 0x%04lx, IRQ %d\n", printk(KERN_INFO "i810: %s found at IO 0x%04lx and 0x%04lx, "
card_names[pci_id->driver_data], card->iobase, card->ac97base, "MEM 0x%04lx and 0x%04lx, IRQ %d\n",
card_names[pci_id->driver_data],
card->iobase, card->ac97base,
card->ac97base_mmio_phys, card->iobase_mmio_phys,
card->irq); card->irq);
card->alloc_pcm_channel = i810_alloc_pcm_channel; card->alloc_pcm_channel = i810_alloc_pcm_channel;
...@@ -2941,17 +3190,42 @@ static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id ...@@ -2941,17 +3190,42 @@ static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id
if (request_irq(card->irq, &i810_interrupt, SA_SHIRQ, if (request_irq(card->irq, &i810_interrupt, SA_SHIRQ,
card_names[pci_id->driver_data], card)) { card_names[pci_id->driver_data], card)) {
printk(KERN_ERR "i810_audio: unable to allocate irq %d\n", card->irq); printk(KERN_ERR "i810_audio: unable to allocate irq %d\n", card->irq);
release_region(card->iobase, 64); goto out_pio;
release_region(card->ac97base, 256); }
goto out_chan;
if (card->use_mmio) {
if (request_mem_region(card->ac97base_mmio_phys, 512, "ich_audio MMBAR")) {
if ((card->ac97base_mmio = ioremap(card->ac97base_mmio_phys, 512))) { /*@FIXME can ioremap fail? don't know (jsaw) */
if (request_mem_region(card->iobase_mmio_phys, 256, "ich_audio MBBAR")) {
if ((card->iobase_mmio = ioremap(card->iobase_mmio_phys, 256))) {
printk(KERN_INFO "i810: %s mmio at 0x%04lx and 0x%04lx\n",
card_names[pci_id->driver_data],
(unsigned long) card->ac97base_mmio,
(unsigned long) card->iobase_mmio);
}
else {
iounmap(card->ac97base_mmio);
release_mem_region(card->ac97base_mmio_phys, 512);
release_mem_region(card->iobase_mmio_phys, 512);
card->use_mmio = 0;
}
}
else {
iounmap(card->ac97base_mmio);
release_mem_region(card->ac97base_mmio_phys, 512);
card->use_mmio = 0;
}
}
}
else {
card->use_mmio = 0;
}
} }
/* initialize AC97 codec and register /dev/mixer */ /* initialize AC97 codec and register /dev/mixer */
if (i810_ac97_init(card) <= 0) { if (i810_ac97_init(card) <= 0) {
release_region(card->iobase, 64);
release_region(card->ac97base, 256);
free_irq(card->irq, card); free_irq(card->irq, card);
goto out_chan; goto out_iospace;
} }
pci_set_drvdata(pci_dev, card); pci_set_drvdata(pci_dev, card);
...@@ -2964,23 +3238,31 @@ static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id ...@@ -2964,23 +3238,31 @@ static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id
if ((card->dev_audio = register_sound_dsp(&i810_audio_fops, -1)) < 0) { if ((card->dev_audio = register_sound_dsp(&i810_audio_fops, -1)) < 0) {
int i; int i;
printk(KERN_ERR "i810_audio: couldn't register DSP device!\n"); printk(KERN_ERR "i810_audio: couldn't register DSP device!\n");
release_region(card->iobase, 64);
release_region(card->ac97base, 256);
free_irq(card->irq, card); free_irq(card->irq, card);
for (i = 0; i < NR_AC97; i++) for (i = 0; i < NR_AC97; i++)
if (card->ac97_codec[i] != NULL) { if (card->ac97_codec[i] != NULL) {
unregister_sound_mixer(card->ac97_codec[i]->dev_mixer); unregister_sound_mixer(card->ac97_codec[i]->dev_mixer);
kfree (card->ac97_codec[i]); kfree (card->ac97_codec[i]);
} }
goto out_chan; goto out_iospace;
} }
card->initializing = 0; card->initializing = 0;
return 0; return 0;
out_chan: out_iospace:
if (card->use_mmio) {
iounmap(card->ac97base_mmio);
iounmap(card->iobase_mmio);
release_mem_region(card->ac97base_mmio_phys, 512);
release_mem_region(card->iobase_mmio_phys, 256);
}
out_pio:
release_region(card->iobase, 64);
release_region(card->ac97base, 256);
pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH, pci_free_consistent(pci_dev, sizeof(struct i810_channel)*NR_HW_CH,
card->channel, card->chandma); card->channel, card->chandma);
out_mem: out_mem:
kfree(card); kfree(card);
return -ENODEV; return -ENODEV;
} }
...@@ -2993,6 +3275,12 @@ static void __devexit i810_remove(struct pci_dev *pci_dev) ...@@ -2993,6 +3275,12 @@ static void __devexit i810_remove(struct pci_dev *pci_dev)
free_irq(card->irq, devs); free_irq(card->irq, devs);
release_region(card->iobase, 64); release_region(card->iobase, 64);
release_region(card->ac97base, 256); release_region(card->ac97base, 256);
if (card->use_mmio) {
iounmap(card->ac97base_mmio);
iounmap(card->iobase_mmio);
release_mem_region(card->ac97base_mmio_phys, 512);
release_mem_region(card->iobase_mmio_phys, 256);
}
/* unregister audio devices */ /* unregister audio devices */
for (i = 0; i < NR_AC97; i++) for (i = 0; i < NR_AC97; i++)
...@@ -3075,7 +3363,7 @@ static int i810_pm_resume(struct pci_dev *dev) ...@@ -3075,7 +3363,7 @@ static int i810_pm_resume(struct pci_dev *dev)
hardware has to be more or less completely reinitialized from hardware has to be more or less completely reinitialized from
scratch after an apm suspend. Works For Me. -dan */ scratch after an apm suspend. Works For Me. -dan */
i810_ac97_random_init_stuff(card); i810_ac97_power_up_bus(card);
for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) { for (num_ac97 = 0; num_ac97 < NR_AC97; num_ac97++) {
struct ac97_codec *codec = card->ac97_codec[num_ac97]; struct ac97_codec *codec = card->ac97_codec[num_ac97];
...@@ -3160,7 +3448,6 @@ static int __init i810_init_module (void) ...@@ -3160,7 +3448,6 @@ static int __init i810_init_module (void)
printk(KERN_INFO "Intel 810 + AC97 Audio, version " printk(KERN_INFO "Intel 810 + AC97 Audio, version "
DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n"); DRIVER_VERSION ", " __TIME__ " " __DATE__ "\n");
printk(KERN_WARNING "This driver is deprecated, please use the ALSA drivers.\n");
if (!pci_register_driver(&i810_pci_driver)) { if (!pci_register_driver(&i810_pci_driver)) {
pci_unregister_driver(&i810_pci_driver); pci_unregister_driver(&i810_pci_driver);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment