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
4a6b58ed
Commit
4a6b58ed
authored
Jul 11, 2003
by
Alan Cox
Committed by
Steve French
Jul 11, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[PATCH] update the i810 audio driver
parent
dbf3cb27
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
52 additions
and
80 deletions
+52
-80
sound/oss/i810_audio.c
sound/oss/i810_audio.c
+52
-80
No files found.
sound/oss/i810_audio.c
View file @
4a6b58ed
...
...
@@ -117,6 +117,9 @@
#ifndef PCI_DEVICE_ID_INTEL_ICH4
#define PCI_DEVICE_ID_INTEL_ICH4 0x24c5
#endif
#ifndef PCI_DEVICE_ID_INTEL_ICH5
#define PCI_DEVICE_ID_INTEL_ICH5 0x24d5
#endif
#ifndef PCI_DEVICE_ID_INTEL_440MX
#define PCI_DEVICE_ID_INTEL_440MX 0x7195
#endif
...
...
@@ -272,6 +275,7 @@ enum {
INTELICH2
,
INTELICH3
,
INTELICH4
,
INTELICH5
,
SI7012
,
NVIDIA_NFORCE
,
AMD768
,
...
...
@@ -285,6 +289,7 @@ static char * card_names[] = {
"Intel ICH2"
,
"Intel ICH3"
,
"Intel ICH4"
,
"Intel ICH5"
,
"SiS 7012"
,
"NVIDIA nForce Audio"
,
"AMD 768"
,
...
...
@@ -303,7 +308,8 @@ static struct {
{
1
,
0x0000
},
/* INTEL440MX */
{
1
,
0x0000
},
/* INTELICH2 */
{
2
,
0x0000
},
/* INTELICH3 */
{
3
,
0x0003
},
/* INTELICH4 */
{
3
,
0x0003
},
/* INTELICH4 */
{
3
,
0x0003
},
/* INTELICH5 */
/*@FIXME to be verified*/
{
2
,
0x0000
},
/* SI7012 */
/*@FIXME to be verified*/
{
2
,
0x0000
},
/* NVIDIA_NFORCE */
/*@FIXME to be verified*/
{
2
,
0x0000
},
/* AMD768 */
...
...
@@ -323,6 +329,8 @@ static struct pci_device_id i810_pci_tbl [] __initdata = {
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
INTELICH3
},
{
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ICH4
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
INTELICH4
},
{
PCI_VENDOR_ID_INTEL
,
PCI_DEVICE_ID_INTEL_ICH5
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
INTELICH5
},
{
PCI_VENDOR_ID_SI
,
PCI_DEVICE_ID_SI_7012
,
PCI_ANY_ID
,
PCI_ANY_ID
,
0
,
0
,
SI7012
},
{
PCI_VENDOR_ID_NVIDIA
,
PCI_DEVICE_ID_NVIDIA_MCP1_AUDIO
,
...
...
@@ -419,6 +427,9 @@ struct i810_card {
/* The i810 has a certain amount of cross channel interaction
so we use a single per card lock */
spinlock_t
lock
;
/* Control AC97 access serialization */
spinlock_t
ac97_lock
;
/* PCI device stuff */
struct
pci_dev
*
pci_dev
;
...
...
@@ -547,80 +558,42 @@ static int i810_valid_spdif_rate ( struct ac97_codec *codec, int rate )
* The DSP sample rate must already be set to a supported
* S/PDIF rate (32kHz, 44.1kHz, or 48kHz) or we abort.
*/
static
void
i810_set_spdif_output
(
struct
i810_state
*
state
,
int
slots
,
int
rate
)
static
int
i810_set_spdif_output
(
struct
i810_state
*
state
,
int
slots
,
int
rate
)
{
int
vol
;
int
aud_reg
;
int
r
=
0
;
struct
ac97_codec
*
codec
=
state
->
card
->
ac97_codec
[
0
];
if
(
!
(
state
->
card
->
ac97_features
&
4
))
{
#ifdef DEBUG
printk
(
KERN_WARNING
"i810_audio: S/PDIF transmitter not available.
\n
"
);
#endif
if
(
!
codec
->
codec_ops
->
digital
)
{
state
->
card
->
ac97_status
&=
~
SPDIF_ON
;
}
else
{
if
(
slots
==
-
1
)
{
/* Turn off S/PDIF */
aud_reg
=
i810_ac97_get
(
codec
,
AC97_EXTENDED_STATUS
);
i810_ac97_set
(
codec
,
AC97_EXTENDED_STATUS
,
(
aud_reg
&
~
AC97_EA_SPDIF
));
codec
->
codec_ops
->
digital
(
codec
,
0
,
0
,
0
);
/* If the volume wasn't muted before we turned on S/PDIF, unmute it */
if
(
!
(
state
->
card
->
ac97_status
&
VOL_MUTED
)
)
{
aud_reg
=
i810_ac97_get
(
codec
,
AC97_MASTER_VOL_STEREO
);
i810_ac97_set
(
codec
,
AC97_MASTER_VOL_STEREO
,
(
aud_reg
&
~
VOL_MUTED
));
}
state
->
card
->
ac97_status
&=
~
(
VOL_MUTED
|
SPDIF_ON
);
return
;
return
0
;
}
vol
=
i810_ac97_get
(
codec
,
AC97_MASTER_VOL_STEREO
);
state
->
card
->
ac97_status
=
vol
&
VOL_MUTED
;
/* Set S/PDIF transmitter sample rate */
aud_reg
=
i810_ac97_get
(
codec
,
AC97_SPDIF_CONTROL
);
switch
(
rate
)
{
case
32000
:
aud_reg
=
(
aud_reg
&
AC97_SC_SPSR_MASK
)
|
AC97_SC_SPSR_32K
;
break
;
case
44100
:
aud_reg
=
(
aud_reg
&
AC97_SC_SPSR_MASK
)
|
AC97_SC_SPSR_44K
;
break
;
case
48000
:
aud_reg
=
(
aud_reg
&
AC97_SC_SPSR_MASK
)
|
AC97_SC_SPSR_48K
;
break
;
default:
#ifdef DEBUG
printk
(
KERN_WARNING
"i810_audio: %d sample rate not supported by S/PDIF.
\n
"
,
rate
);
#endif
/* turn off S/PDIF */
aud_reg
=
i810_ac97_get
(
codec
,
AC97_EXTENDED_STATUS
);
i810_ac97_set
(
codec
,
AC97_EXTENDED_STATUS
,
(
aud_reg
&
~
AC97_EA_SPDIF
));
state
->
card
->
ac97_status
&=
~
SPDIF_ON
;
return
;
}
i810_ac97_set
(
codec
,
AC97_SPDIF_CONTROL
,
aud_reg
);
aud_reg
=
i810_ac97_get
(
codec
,
AC97_EXTENDED_STATUS
);
aud_reg
=
(
aud_reg
&
AC97_EA_SLOT_MASK
)
|
slots
|
AC97_EA_VRA
|
AC97_EA_SPDIF
;
i810_ac97_set
(
codec
,
AC97_EXTENDED_STATUS
,
aud_reg
);
state
->
card
->
ac97_status
|=
SPDIF_ON
;
/* Check to make sure the configuration is valid */
aud_reg
=
i810_ac97_get
(
codec
,
AC97_EXTENDED_STATUS
);
if
(
!
(
aud_reg
&
0x0400
)
)
{
#ifdef DEBUG
printk
(
KERN_WARNING
"i810_audio: S/PDIF transmitter configuration not valid (0x%04x).
\n
"
,
aud_reg
);
#endif
r
=
codec
->
codec_ops
->
digital
(
codec
,
slots
,
rate
,
0
);
/* turn off S/PDIF */
i810_ac97_set
(
codec
,
AC97_EXTENDED_STATUS
,
(
aud_reg
&
~
AC97_EA_SPDIF
));
if
(
r
)
state
->
card
->
ac97_status
|=
SPDIF_ON
;
else
state
->
card
->
ac97_status
&=
~
SPDIF_ON
;
return
;
}
/* Mute the analog output */
/* Should this only mute the PCM volume??? */
i810_ac97_set
(
codec
,
AC97_MASTER_VOL_STEREO
,
(
vol
|
VOL_MUTED
));
}
return
r
;
}
/* i810_set_dac_channels
...
...
@@ -642,8 +615,9 @@ static void i810_set_dac_channels(struct i810_state *state, int channel)
{
int
aud_reg
;
struct
ac97_codec
*
codec
=
state
->
card
->
ac97_codec
[
0
];
/* No codec, no setup */
if
(
codec
==
NULL
)
return
;
...
...
@@ -1835,6 +1809,7 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
}
spin_unlock_irqrestore
(
&
state
->
card
->
lock
,
flags
);
synchronize_irq
(
state
->
card
->
pci_dev
->
irq
);
dmabuf
->
ready
=
0
;
dmabuf
->
swptr
=
dmabuf
->
hwptr
=
0
;
dmabuf
->
count
=
dmabuf
->
total_bytes
=
0
;
...
...
@@ -2493,11 +2468,9 @@ static int i810_open(struct inode *inode, struct file *file)
}
if
(
file
->
f_mode
&
FMODE_WRITE
)
{
if
((
dmabuf
->
write_channel
=
card
->
alloc_pcm_channel
(
card
))
==
NULL
)
{
/*
free any read channel allocated earlier
*/
/*
make sure we free the record channel allocated above
*/
if
(
file
->
f_mode
&
FMODE_READ
)
card
->
free_pcm_channel
(
card
,
dmabuf
->
read_channel
->
num
);
card
->
free_pcm_channel
(
card
,
dmabuf
->
read_channel
->
num
);
kfree
(
card
->
states
[
i
]);
card
->
states
[
i
]
=
NULL
;;
return
-
EBUSY
;
...
...
@@ -2641,23 +2614,32 @@ static void i810_ac97_set_io(struct ac97_codec *dev, u8 reg, u16 data)
static
u16
i810_ac97_get
(
struct
ac97_codec
*
dev
,
u8
reg
)
{
struct
i810_card
*
card
=
dev
->
private_data
;
u16
ret
;
spin_lock
(
&
card
->
ac97_lock
);
if
(
card
->
use_mmio
)
{
ret
urn
i810_ac97_get_mmio
(
dev
,
reg
);
ret
=
i810_ac97_get_mmio
(
dev
,
reg
);
}
else
{
ret
urn
i810_ac97_get_io
(
dev
,
reg
);
ret
=
i810_ac97_get_io
(
dev
,
reg
);
}
spin_unlock
(
&
card
->
ac97_lock
);
return
ret
;
}
static
void
i810_ac97_set
(
struct
ac97_codec
*
dev
,
u8
reg
,
u16
data
)
{
struct
i810_card
*
card
=
dev
->
private_data
;
spin_lock
(
&
card
->
ac97_lock
);
if
(
card
->
use_mmio
)
{
i810_ac97_set_mmio
(
dev
,
reg
,
data
);
}
else
{
i810_ac97_set_io
(
dev
,
reg
,
data
);
}
spin_unlock
(
&
card
->
ac97_lock
);
}
...
...
@@ -2803,7 +2785,7 @@ static int i810_ac97_power_up_bus(struct i810_card *card)
*/
/* see i810_ac97_init for the next 7 lines (jsaw) */
inw
(
card
->
ac97base
);
if
((
card
->
pci_id
==
PCI_DEVICE_ID_INTEL_ICH4
)
if
((
card
->
pci_id
==
PCI_DEVICE_ID_INTEL_ICH4
||
card
->
pci_id
==
PCI_DEVICE_ID_INTEL_ICH5
)
&&
(
card
->
use_mmio
))
{
primary_codec_id
=
(
int
)
readl
(
card
->
iobase_mmio
+
SDM
)
&
0x3
;
printk
(
KERN_INFO
"i810_audio: Primary codec has ID %d
\n
"
,
...
...
@@ -2873,7 +2855,7 @@ static int __init i810_ac97_init(struct i810_card *card)
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
)
if
((
card
->
pci_id
==
PCI_DEVICE_ID_INTEL_ICH4
||
card
->
pci_id
==
PCI_DEVICE_ID_INTEL_ICH5
)
&&
(
card
->
use_mmio
))
{
ac97_id
=
(
int
)
readl
(
card
->
iobase_mmio
+
SDM
)
&
0x3
;
printk
(
KERN_INFO
"i810_audio: Connection %d with codec id %d
\n
"
,
...
...
@@ -2892,9 +2874,8 @@ static int __init i810_ac97_init(struct i810_card *card)
printk
(
KERN_ERR
"i810_audio: Primary codec not ready.
\n
"
);
}
if
((
codec
=
kmalloc
(
sizeof
(
struct
ac97_codec
),
GFP_KERNEL
))
==
NULL
)
if
((
codec
=
ac97_alloc_codec
(
))
==
NULL
)
return
-
ENOMEM
;
memset
(
codec
,
0
,
sizeof
(
struct
ac97_codec
));
/* initialize some basic codec information, other fields will be filled
in ac97_probe_codec */
...
...
@@ -2913,7 +2894,7 @@ static int __init i810_ac97_init(struct i810_card *card)
if
(
!
i810_ac97_probe_and_powerup
(
card
,
codec
))
{
printk
(
KERN_ERR
"i810_audio: timed out waiting for codec %d analog ready.
\n
"
,
ac97_id
);
kfree
(
codec
);
ac97_release_codec
(
codec
);
break
;
/* it didn't work */
}
/* Store state information about S/PDIF transmitter */
...
...
@@ -2922,32 +2903,22 @@ static int __init i810_ac97_init(struct i810_card *card)
/* Don't attempt to get eid until powerup is complete */
eid
=
i810_ac97_get
(
codec
,
AC97_EXTENDED_ID
);
if
(
eid
==
0xFFFF
FF
)
if
(
eid
==
0xFFFF
)
{
printk
(
KERN_WARNING
"i810_audio: no codec attached ?
\n
"
);
kfree
(
codec
);
ac97_release_codec
(
codec
);
break
;
}
/* Check for an AC97 1.0 soft modem (ID1) */
if
(
codec
->
codec_read
(
codec
,
AC97_RESET
)
&
2
)
if
(
codec
->
modem
)
{
printk
(
KERN_WARNING
"i810_audio: codec %d is a
n AC97 1.0
softmodem - skipping.
\n
"
,
ac97_id
);
kfree
(
codec
);
printk
(
KERN_WARNING
"i810_audio: codec %d is a softmodem - skipping.
\n
"
,
ac97_id
);
ac97_release_codec
(
codec
);
continue
;
}
/* Check for an AC97 2.x soft modem */
codec
->
codec_write
(
codec
,
AC97_EXTENDED_MODEM_ID
,
0L
);
if
(
codec
->
codec_read
(
codec
,
AC97_EXTENDED_MODEM_ID
)
&
1
)
{
printk
(
KERN_WARNING
"i810_audio: codec %d is an AC97 2.x softmodem - skipping.
\n
"
,
ac97_id
);
kfree
(
codec
);
continue
;
}
card
->
ac97_features
=
eid
;
/* Now check the codec for useful features to make up for
...
...
@@ -3027,7 +2998,7 @@ static int __init i810_ac97_init(struct i810_card *card)
if
((
codec
->
dev_mixer
=
register_sound_mixer
(
&
i810_mixer_fops
,
-
1
))
<
0
)
{
printk
(
KERN_ERR
"i810_audio: couldn't register mixer!
\n
"
);
kfree
(
codec
);
ac97_release_codec
(
codec
);
break
;
}
...
...
@@ -3158,6 +3129,7 @@ static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id
card
->
pm_suspended
=
0
;
#endif
spin_lock_init
(
&
card
->
lock
);
spin_lock_init
(
&
card
->
ac97_lock
);
devs
=
card
;
pci_set_master
(
pci_dev
);
...
...
@@ -3253,7 +3225,7 @@ static int __init i810_probe(struct pci_dev *pci_dev, const struct pci_device_id
for
(
i
=
0
;
i
<
NR_AC97
;
i
++
)
if
(
card
->
ac97_codec
[
i
]
!=
NULL
)
{
unregister_sound_mixer
(
card
->
ac97_codec
[
i
]
->
dev_mixer
);
kfree
(
card
->
ac97_codec
[
i
]);
ac97_release_codec
(
card
->
ac97_codec
[
i
]);
}
goto
out_iospace
;
}
...
...
@@ -3297,7 +3269,7 @@ static void __devexit i810_remove(struct pci_dev *pci_dev)
for
(
i
=
0
;
i
<
NR_AC97
;
i
++
)
if
(
card
->
ac97_codec
[
i
]
!=
NULL
)
{
unregister_sound_mixer
(
card
->
ac97_codec
[
i
]
->
dev_mixer
);
kfree
(
card
->
ac97_codec
[
i
]);
ac97_release_codec
(
card
->
ac97_codec
[
i
]);
card
->
ac97_codec
[
i
]
=
NULL
;
}
unregister_sound_dsp
(
card
->
dev_audio
);
...
...
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