Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
184a7e14
Commit
184a7e14
authored
Dec 01, 2002
by
Alan Cox
Committed by
James Bottomley
Dec 01, 2002
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] update i810 audio to match 2.4
Primarily adds Nvidia + some i845G
parent
19602b94
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
374 additions
and
87 deletions
+374
-87
sound/oss/i810_audio.c
sound/oss/i810_audio.c
+374
-87
No files found.
sound/oss/i810_audio.c
View file @
184a7e14
...
@@ -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_A
UDIO
,
{
PCI_VENDOR_ID_AMD
,
PCI_DEVICE_ID_AMD_8111_A
C97
,
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
;
u
8
reg_set
=
((
dev
->
id
)
?
((
reg
&
0x7f
)
|
0x80
)
:
(
reg
&
0x7f
)
);
u
16
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 a
n 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
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment