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
nexedi
linux
Commits
dbf3cb27
Commit
dbf3cb27
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 ITE audio
parent
8019adb6
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
1637 additions
and
1333 deletions
+1637
-1333
sound/oss/ite8172.c
sound/oss/ite8172.c
+1637
-1333
No files found.
sound/oss/ite8172.c
View file @
dbf3cb27
...
@@ -42,15 +42,17 @@
...
@@ -42,15 +42,17 @@
* * Memory mapping the audio buffers, and the ioctl controls that go
* * Memory mapping the audio buffers, and the ioctl controls that go
* with it.
* with it.
* * S/PDIF output.
* * S/PDIF output.
* * I2S support.
* 3. The following is not supported:
* 3. The following is not supported:
* * I2S input.
* * legacy audio mode.
* * legacy audio mode.
* 4. Support for volume button interrupts is implemented but doesn't
* 4. Support for volume button interrupts is implemented but doesn't
* work yet.
* work yet.
*
*
* Revision history
* Revision history
* 02.08.2001 0.1 Initial release
* 02.08.2001 Initial release
* 06.22.2001 Added I2S support
*/
*/
#include <linux/version.h>
#include <linux/module.h>
#include <linux/module.h>
#include <linux/string.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <linux/ioport.h>
...
@@ -80,6 +82,19 @@
...
@@ -80,6 +82,19 @@
#undef IT8172_VERBOSE_DEBUG
#undef IT8172_VERBOSE_DEBUG
#define DBG(x) {}
#define DBG(x) {}
#define IT8172_MODULE_NAME "IT8172 audio"
#define PFX IT8172_MODULE_NAME
#ifdef IT8172_DEBUG
#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg)
#else
#define dbg(format, arg...) do {} while (0)
#endif
#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg)
#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg)
#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg)
static
const
unsigned
sample_shift
[]
=
{
0
,
1
,
1
,
2
};
static
const
unsigned
sample_shift
[]
=
{
0
,
1
,
1
,
2
};
...
@@ -226,9 +241,16 @@ static const unsigned sample_shift[] = { 0, 1, 1, 2 };
...
@@ -226,9 +241,16 @@ static const unsigned sample_shift[] = { 0, 1, 1, 2 };
#define POLL_COUNT 0x5000
#define POLL_COUNT 0x5000
#define IT8172_MODULE_NAME "IT8172 audio"
/* --------------------------------------------------------------------- */
#define PFX IT8172_MODULE_NAME ": "
/*
* Define DIGITAL1 as the I2S channel, since it is not listed in
* soundcard.h.
*/
#define SOUND_MIXER_I2S SOUND_MIXER_DIGITAL1
#define SOUND_MASK_I2S SOUND_MASK_DIGITAL1
#define SOUND_MIXER_READ_I2S MIXER_READ(SOUND_MIXER_I2S)
#define SOUND_MIXER_WRITE_I2S MIXER_WRITE(SOUND_MIXER_I2S)
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
...
@@ -253,6 +275,8 @@ struct it8172_state {
...
@@ -253,6 +275,8 @@ struct it8172_state {
/* options */
/* options */
int
spdif_volume
;
/* S/PDIF output is enabled if != -1 */
int
spdif_volume
;
/* S/PDIF output is enabled if != -1 */
int
i2s_volume
;
/* current I2S out volume, in OSS format */
int
i2s_recording
;
/* 1 = recording from I2S, 0 = not */
#ifdef IT8172_DEBUG
#ifdef IT8172_DEBUG
/* debug /proc entry */
/* debug /proc entry */
...
@@ -260,7 +284,7 @@ struct it8172_state {
...
@@ -260,7 +284,7 @@ struct it8172_state {
struct
proc_dir_entry
*
ac97_ps
;
struct
proc_dir_entry
*
ac97_ps
;
#endif
/* IT8172_DEBUG */
#endif
/* IT8172_DEBUG */
struct
ac97_codec
codec
;
struct
ac97_codec
*
codec
;
unsigned
short
pcc
,
capcc
;
unsigned
short
pcc
,
capcc
;
unsigned
dacrate
,
adcrate
;
unsigned
dacrate
,
adcrate
;
...
@@ -431,7 +455,7 @@ static u16 rdcodec(struct ac97_codec *codec, u8 addr)
...
@@ -431,7 +455,7 @@ static u16 rdcodec(struct ac97_codec *codec, u8 addr)
if
(
!
(
inw
(
s
->
io
+
IT_AC_CIRCP
)
&
CIRCP_CPS
))
if
(
!
(
inw
(
s
->
io
+
IT_AC_CIRCP
)
&
CIRCP_CPS
))
break
;
break
;
if
(
i
==
POLL_COUNT
)
if
(
i
==
POLL_COUNT
)
printk
(
KERN_INFO
PFX
"rdcodec: codec ready poll expired!
\n
"
);
err
(
"rdcodec: codec ready poll expired!
"
);
circp
=
addr
&
CIRCP_CIA_MASK
;
circp
=
addr
&
CIRCP_CIA_MASK
;
circp
|=
(
codec
->
id
<<
CIRCP_CID_BIT
);
circp
|=
(
codec
->
id
<<
CIRCP_CID_BIT
);
...
@@ -443,7 +467,7 @@ static u16 rdcodec(struct ac97_codec *codec, u8 addr)
...
@@ -443,7 +467,7 @@ static u16 rdcodec(struct ac97_codec *codec, u8 addr)
if
(
inw
(
s
->
io
+
IT_AC_CIRCP
)
&
CIRCP_DPVF
)
if
(
inw
(
s
->
io
+
IT_AC_CIRCP
)
&
CIRCP_DPVF
)
break
;
break
;
if
(
i
==
POLL_COUNT
)
if
(
i
==
POLL_COUNT
)
printk
(
KERN_INFO
PFX
"rdcodec: read poll expired!
\n
"
);
err
(
"rdcodec: read poll expired!
"
);
data
=
inw
(
s
->
io
+
IT_AC_CIRDP
);
data
=
inw
(
s
->
io
+
IT_AC_CIRDP
);
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
...
@@ -465,7 +489,7 @@ static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
...
@@ -465,7 +489,7 @@ static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data)
if
(
!
(
inw
(
s
->
io
+
IT_AC_CIRCP
)
&
CIRCP_CPS
))
if
(
!
(
inw
(
s
->
io
+
IT_AC_CIRCP
)
&
CIRCP_CPS
))
break
;
break
;
if
(
i
==
POLL_COUNT
)
if
(
i
==
POLL_COUNT
)
printk
(
KERN_INFO
PFX
"wrcodec: codec ready poll expired!
\n
"
);
err
(
"wrcodec: codec ready poll expired!
"
);
circp
=
addr
&
CIRCP_CIA_MASK
;
circp
=
addr
&
CIRCP_CIA_MASK
;
circp
|=
(
codec
->
id
<<
CIRCP_CID_BIT
);
circp
|=
(
codec
->
id
<<
CIRCP_CID_BIT
);
...
@@ -499,8 +523,7 @@ static void waitcodec(struct ac97_codec *codec)
...
@@ -499,8 +523,7 @@ static void waitcodec(struct ac97_codec *codec)
// Check if Codec REF,ANL,DAC,ADC ready***/
// Check if Codec REF,ANL,DAC,ADC ready***/
if
((
temp
&
0x3f0f
)
!=
0x000f
)
{
if
((
temp
&
0x3f0f
)
!=
0x000f
)
{
printk
(
KERN_INFO
PFX
"codec reg 26 status (0x%x) not ready!!
\n
"
,
err
(
"codec reg 26 status (0x%x) not ready!!"
,
temp
);
temp
);
return
;
return
;
}
}
}
}
...
@@ -637,9 +660,10 @@ static inline void dealloc_dmabuf(struct it8172_state *s, struct dmabuf *db)
...
@@ -637,9 +660,10 @@ static inline void dealloc_dmabuf(struct it8172_state *s, struct dmabuf *db)
if
(
db
->
rawbuf
)
{
if
(
db
->
rawbuf
)
{
/* undo marking the pages as reserved */
/* undo marking the pages as reserved */
pend
=
virt_to_page
(
db
->
rawbuf
+
(
PAGE_SIZE
<<
db
->
buforder
)
-
1
);
pend
=
virt_to_page
(
db
->
rawbuf
+
(
PAGE_SIZE
<<
db
->
buforder
)
-
1
);
for
(
page
=
virt_to_page
(
db
->
rawbuf
);
page
<=
pend
;
page
++
)
for
(
page
=
virt_to_page
(
db
->
rawbuf
);
page
<=
pend
;
page
++
)
ClearPageReserved
(
page
);
mem_map_unreserve
(
page
);
pci_free_consistent
(
s
->
dev
,
PAGE_SIZE
<<
db
->
buforder
,
pci_free_consistent
(
s
->
dev
,
PAGE_SIZE
<<
db
->
buforder
,
db
->
rawbuf
,
db
->
dmaaddr
);
db
->
rawbuf
,
db
->
dmaaddr
);
}
}
...
@@ -657,8 +681,10 @@ static int prog_dmabuf(struct it8172_state *s, struct dmabuf *db,
...
@@ -657,8 +681,10 @@ static int prog_dmabuf(struct it8172_state *s, struct dmabuf *db,
if
(
!
db
->
rawbuf
)
{
if
(
!
db
->
rawbuf
)
{
db
->
ready
=
db
->
mapped
=
0
;
db
->
ready
=
db
->
mapped
=
0
;
for
(
order
=
DMABUF_DEFAULTORDER
;
order
>=
DMABUF_MINORDER
;
order
--
)
for
(
order
=
DMABUF_DEFAULTORDER
;
if
((
db
->
rawbuf
=
pci_alloc_consistent
(
s
->
dev
,
order
>=
DMABUF_MINORDER
;
order
--
)
if
((
db
->
rawbuf
=
pci_alloc_consistent
(
s
->
dev
,
PAGE_SIZE
<<
order
,
PAGE_SIZE
<<
order
,
&
db
->
dmaaddr
)))
&
db
->
dmaaddr
)))
break
;
break
;
...
@@ -667,9 +693,10 @@ static int prog_dmabuf(struct it8172_state *s, struct dmabuf *db,
...
@@ -667,9 +693,10 @@ static int prog_dmabuf(struct it8172_state *s, struct dmabuf *db,
db
->
buforder
=
order
;
db
->
buforder
=
order
;
/* now mark the pages as reserved;
/* now mark the pages as reserved;
otherwise remap_page_range doesn't do what we want */
otherwise remap_page_range doesn't do what we want */
pend
=
virt_to_page
(
db
->
rawbuf
+
(
PAGE_SIZE
<<
db
->
buforder
)
-
1
);
pend
=
virt_to_page
(
db
->
rawbuf
+
(
PAGE_SIZE
<<
db
->
buforder
)
-
1
);
for
(
page
=
virt_to_page
(
db
->
rawbuf
);
page
<=
pend
;
page
++
)
for
(
page
=
virt_to_page
(
db
->
rawbuf
);
page
<=
pend
;
page
++
)
SetPageReserved
(
page
);
mem_map_reserve
(
page
);
}
}
db
->
count
=
0
;
db
->
count
=
0
;
...
@@ -698,7 +725,12 @@ static int prog_dmabuf(struct it8172_state *s, struct dmabuf *db,
...
@@ -698,7 +725,12 @@ static int prog_dmabuf(struct it8172_state *s, struct dmabuf *db,
db
->
numfrag
=
db
->
ossmaxfrags
;
db
->
numfrag
=
db
->
ossmaxfrags
;
db
->
fragsamples
=
db
->
fragsize
>>
sample_shift
[
fmt
];
db
->
fragsamples
=
db
->
fragsize
>>
sample_shift
[
fmt
];
db
->
dmasize
=
db
->
numfrag
<<
db
->
fragshift
;
db
->
dmasize
=
db
->
numfrag
<<
db
->
fragshift
;
memset
(
db
->
rawbuf
,
(
fmt
&
(
CC_DF
>>
CC_FMT_BIT
))
?
0
:
0x80
,
db
->
dmasize
);
memset
(
db
->
rawbuf
,
(
fmt
&
(
CC_DF
>>
CC_FMT_BIT
))
?
0
:
0x80
,
bufs
);
#ifdef IT8172_VERBOSE_DEBUG
dbg
(
"rate=%d, fragsize=%d, numfrag=%d, dmasize=%d"
,
rate
,
db
->
fragsize
,
db
->
numfrag
,
db
->
dmasize
);
#endif
// set data length register
// set data length register
outw
(
db
->
fragsize
,
s
->
io
+
reg
+
2
);
outw
(
db
->
fragsize
,
s
->
io
+
reg
+
2
);
...
@@ -748,8 +780,8 @@ static irqreturn_t it8172_interrupt(int irq, void *dev_id, struct pt_regs *regs)
...
@@ -748,8 +780,8 @@ static irqreturn_t it8172_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* clear audio interrupts first */
/* clear audio interrupts first */
outb
(
isc
|
ISC_VCI
|
ISC_CCI
|
ISC_PCI
,
s
->
io
+
IT_AC_ISC
);
outb
(
isc
|
ISC_VCI
|
ISC_CCI
|
ISC_PCI
,
s
->
io
+
IT_AC_ISC
);
/* handle volume button events
*/
/* handle volume button events (ignore if S/PDIF enabled)
*/
if
(
isc
&
ISC_VCI
)
{
if
((
isc
&
ISC_VCI
)
&&
s
->
spdif_volume
==
-
1
)
{
vs
=
inb
(
s
->
io
+
IT_AC_VS
);
vs
=
inb
(
s
->
io
+
IT_AC_VS
);
outb
(
0
,
s
->
io
+
IT_AC_VS
);
outb
(
0
,
s
->
io
+
IT_AC_VS
);
vol
=
inw
(
s
->
io
+
IT_AC_PCMOV
);
vol
=
inw
(
s
->
io
+
IT_AC_PCMOV
);
...
@@ -771,7 +803,7 @@ static irqreturn_t it8172_interrupt(int irq, void *dev_id, struct pt_regs *regs)
...
@@ -771,7 +803,7 @@ static irqreturn_t it8172_interrupt(int irq, void *dev_id, struct pt_regs *regs)
// Overrun. Stop ADC and log the error
// Overrun. Stop ADC and log the error
stop_adc
(
s
);
stop_adc
(
s
);
adc
->
error
++
;
adc
->
error
++
;
printk
(
KERN_INFO
PFX
"adc overrun
\
n
"
);
dbg
(
"adc overru
n"
);
}
else
{
}
else
{
newptr
=
virt_to_bus
(
adc
->
nextIn
)
+
2
*
adc
->
fragsize
;
newptr
=
virt_to_bus
(
adc
->
nextIn
)
+
2
*
adc
->
fragsize
;
if
(
newptr
>=
adc
->
dmaaddr
+
adc
->
dmasize
)
if
(
newptr
>=
adc
->
dmaaddr
+
adc
->
dmasize
)
...
@@ -825,9 +857,15 @@ static irqreturn_t it8172_interrupt(int irq, void *dev_id, struct pt_regs *regs)
...
@@ -825,9 +857,15 @@ static irqreturn_t it8172_interrupt(int irq, void *dev_id, struct pt_regs *regs)
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
static
loff_t
it8172_llseek
(
struct
file
*
file
,
loff_t
offset
,
int
origin
)
{
return
-
ESPIPE
;
}
static
int
it8172_open_mixdev
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
it8172_open_mixdev
(
struct
inode
*
inode
,
struct
file
*
file
)
{
{
int
minor
=
minor
(
inode
->
i_rdev
);
int
minor
=
MINOR
(
inode
->
i_rdev
);
struct
list_head
*
list
;
struct
list_head
*
list
;
struct
it8172_state
*
s
;
struct
it8172_state
*
s
;
...
@@ -835,7 +873,7 @@ static int it8172_open_mixdev(struct inode *inode, struct file *file)
...
@@ -835,7 +873,7 @@ static int it8172_open_mixdev(struct inode *inode, struct file *file)
if
(
list
==
&
devs
)
if
(
list
==
&
devs
)
return
-
ENODEV
;
return
-
ENODEV
;
s
=
list_entry
(
list
,
struct
it8172_state
,
devs
);
s
=
list_entry
(
list
,
struct
it8172_state
,
devs
);
if
(
s
->
codec
.
dev_mixer
==
minor
)
if
(
s
->
codec
->
dev_mixer
==
minor
)
break
;
break
;
}
}
file
->
private_data
=
s
;
file
->
private_data
=
s
;
...
@@ -848,9 +886,110 @@ static int it8172_release_mixdev(struct inode *inode, struct file *file)
...
@@ -848,9 +886,110 @@ static int it8172_release_mixdev(struct inode *inode, struct file *file)
}
}
static
u16
cvt_ossvol
(
unsigned
int
gain
)
{
u16
ret
;
if
(
gain
==
0
)
return
0
;
if
(
gain
>
100
)
gain
=
100
;
ret
=
(
100
-
gain
+
32
)
/
4
;
ret
=
ret
>
31
?
31
:
ret
;
return
ret
;
}
static
int
mixdev_ioctl
(
struct
ac97_codec
*
codec
,
unsigned
int
cmd
,
static
int
mixdev_ioctl
(
struct
ac97_codec
*
codec
,
unsigned
int
cmd
,
unsigned
long
arg
)
unsigned
long
arg
)
{
{
struct
it8172_state
*
s
=
(
struct
it8172_state
*
)
codec
->
private_data
;
unsigned
int
left
,
right
;
unsigned
long
flags
;
int
val
;
u16
vol
;
/*
* When we are in S/PDIF mode, we want to disable any analog output so
* we filter the master/PCM channel volume ioctls.
*
* Also filter I2S channel, which AC'97 knows nothing about.
*/
switch
(
cmd
)
{
case
SOUND_MIXER_WRITE_VOLUME
:
// if not in S/PDIF mode, pass to AC'97
if
(
s
->
spdif_volume
==
-
1
)
break
;
return
0
;
case
SOUND_MIXER_WRITE_PCM
:
// if not in S/PDIF mode, pass to AC'97
if
(
s
->
spdif_volume
==
-
1
)
break
;
if
(
get_user
(
val
,
(
int
*
)
arg
))
return
-
EFAULT
;
right
=
((
val
>>
8
)
&
0xff
);
left
=
(
val
&
0xff
);
if
(
right
>
100
)
right
=
100
;
if
(
left
>
100
)
left
=
100
;
s
->
spdif_volume
=
(
right
<<
8
)
|
left
;
vol
=
cvt_ossvol
(
left
);
vol
|=
(
cvt_ossvol
(
right
)
<<
PCMOV_PCMRCG_BIT
);
if
(
vol
==
0
)
vol
=
PCMOV_PCMOM
;
// mute
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
outw
(
vol
,
s
->
io
+
IT_AC_PCMOV
);
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
return
put_user
(
s
->
spdif_volume
,
(
int
*
)
arg
);
case
SOUND_MIXER_READ_PCM
:
// if not in S/PDIF mode, pass to AC'97
if
(
s
->
spdif_volume
==
-
1
)
break
;
return
put_user
(
s
->
spdif_volume
,
(
int
*
)
arg
);
case
SOUND_MIXER_WRITE_I2S
:
if
(
get_user
(
val
,
(
int
*
)
arg
))
return
-
EFAULT
;
right
=
((
val
>>
8
)
&
0xff
);
left
=
(
val
&
0xff
);
if
(
right
>
100
)
right
=
100
;
if
(
left
>
100
)
left
=
100
;
s
->
i2s_volume
=
(
right
<<
8
)
|
left
;
vol
=
cvt_ossvol
(
left
);
vol
|=
(
cvt_ossvol
(
right
)
<<
I2SV_I2SRCG_BIT
);
if
(
vol
==
0
)
vol
=
I2SV_I2SOM
;
// mute
outw
(
vol
,
s
->
io
+
IT_AC_I2SV
);
return
put_user
(
s
->
i2s_volume
,
(
int
*
)
arg
);
case
SOUND_MIXER_READ_I2S
:
return
put_user
(
s
->
i2s_volume
,
(
int
*
)
arg
);
case
SOUND_MIXER_WRITE_RECSRC
:
if
(
get_user
(
val
,
(
int
*
)
arg
))
return
-
EFAULT
;
if
(
val
&
SOUND_MASK_I2S
)
{
s
->
i2s_recording
=
1
;
outb
(
DRSS_I2S
,
s
->
io
+
IT_AC_DRSS
);
return
0
;
}
else
{
s
->
i2s_recording
=
0
;
outb
(
DRSS_AC97_PRIM
,
s
->
io
+
IT_AC_DRSS
);
// now let AC'97 select record source
break
;
}
case
SOUND_MIXER_READ_RECSRC
:
if
(
s
->
i2s_recording
)
return
put_user
(
SOUND_MASK_I2S
,
(
int
*
)
arg
);
else
// let AC'97 report recording source
break
;
}
return
codec
->
mixer_ioctl
(
codec
,
cmd
,
arg
);
return
codec
->
mixer_ioctl
(
codec
,
cmd
,
arg
);
}
}
...
@@ -858,17 +997,17 @@ static int it8172_ioctl_mixdev(struct inode *inode, struct file *file,
...
@@ -858,17 +997,17 @@ static int it8172_ioctl_mixdev(struct inode *inode, struct file *file,
unsigned
int
cmd
,
unsigned
long
arg
)
unsigned
int
cmd
,
unsigned
long
arg
)
{
{
struct
it8172_state
*
s
=
(
struct
it8172_state
*
)
file
->
private_data
;
struct
it8172_state
*
s
=
(
struct
it8172_state
*
)
file
->
private_data
;
struct
ac97_codec
*
codec
=
&
s
->
codec
;
struct
ac97_codec
*
codec
=
s
->
codec
;
return
mixdev_ioctl
(
codec
,
cmd
,
arg
);
return
mixdev_ioctl
(
codec
,
cmd
,
arg
);
}
}
static
/*const*/
struct
file_operations
it8172_mixer_fops
=
{
static
/*const*/
struct
file_operations
it8172_mixer_fops
=
{
.
owner
=
THIS_MODULE
,
owner:
THIS_MODULE
,
.
llseek
=
no
_llseek
,
llseek:
it8172
_llseek
,
.
ioctl
=
it8172_ioctl_mixdev
,
ioctl:
it8172_ioctl_mixdev
,
.
open
=
it8172_open_mixdev
,
open:
it8172_open_mixdev
,
.
release
=
it8172_release_mixdev
,
release:
it8172_release_mixdev
,
};
};
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
...
@@ -878,7 +1017,7 @@ static int drain_dac(struct it8172_state *s, int nonblock)
...
@@ -878,7 +1017,7 @@ static int drain_dac(struct it8172_state *s, int nonblock)
unsigned
long
flags
;
unsigned
long
flags
;
int
count
,
tmo
;
int
count
,
tmo
;
if
(
s
->
dma_dac
.
mapped
||
!
s
->
dma_dac
.
ready
)
if
(
s
->
dma_dac
.
mapped
||
!
s
->
dma_dac
.
ready
||
s
->
dma_dac
.
stopped
)
return
0
;
return
0
;
for
(;;)
{
for
(;;)
{
...
@@ -889,8 +1028,8 @@ static int drain_dac(struct it8172_state *s, int nonblock)
...
@@ -889,8 +1028,8 @@ static int drain_dac(struct it8172_state *s, int nonblock)
break
;
break
;
if
(
signal_pending
(
current
))
if
(
signal_pending
(
current
))
break
;
break
;
if
(
nonblock
)
//
if (nonblock)
return
-
EBUSY
;
//
return -EBUSY;
tmo
=
1000
*
count
/
s
->
dacrate
;
tmo
=
1000
*
count
/
s
->
dacrate
;
tmo
>>=
sample_shift
[(
s
->
pcc
&
CC_FMT_MASK
)
>>
CC_FMT_BIT
];
tmo
>>=
sample_shift
[(
s
->
pcc
&
CC_FMT_MASK
)
>>
CC_FMT_BIT
];
it8172_delay
(
tmo
);
it8172_delay
(
tmo
);
...
@@ -902,6 +1041,48 @@ static int drain_dac(struct it8172_state *s, int nonblock)
...
@@ -902,6 +1041,48 @@ static int drain_dac(struct it8172_state *s, int nonblock)
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
/*
* Copy audio data to/from user buffer from/to dma buffer, taking care
* that we wrap when reading/writing the dma buffer. Returns actual byte
* count written to or read from the dma buffer.
*/
static
int
copy_dmabuf_user
(
struct
dmabuf
*
db
,
char
*
userbuf
,
int
count
,
int
to_user
)
{
char
*
bufptr
=
to_user
?
db
->
nextOut
:
db
->
nextIn
;
char
*
bufend
=
db
->
rawbuf
+
db
->
dmasize
;
if
(
bufptr
+
count
>
bufend
)
{
int
partial
=
(
int
)(
bufend
-
bufptr
);
if
(
to_user
)
{
if
(
copy_to_user
(
userbuf
,
bufptr
,
partial
))
return
-
EFAULT
;
if
(
copy_to_user
(
userbuf
+
partial
,
db
->
rawbuf
,
count
-
partial
))
return
-
EFAULT
;
}
else
{
if
(
copy_from_user
(
bufptr
,
userbuf
,
partial
))
return
-
EFAULT
;
if
(
copy_from_user
(
db
->
rawbuf
,
userbuf
+
partial
,
count
-
partial
))
return
-
EFAULT
;
}
}
else
{
if
(
to_user
)
{
if
(
copy_to_user
(
userbuf
,
bufptr
,
count
))
return
-
EFAULT
;
}
else
{
if
(
copy_from_user
(
bufptr
,
userbuf
,
count
))
return
-
EFAULT
;
}
}
return
count
;
}
static
ssize_t
it8172_read
(
struct
file
*
file
,
char
*
buffer
,
static
ssize_t
it8172_read
(
struct
file
*
file
,
char
*
buffer
,
size_t
count
,
loff_t
*
ppos
)
size_t
count
,
loff_t
*
ppos
)
{
{
...
@@ -909,7 +1090,7 @@ static ssize_t it8172_read(struct file *file, char *buffer,
...
@@ -909,7 +1090,7 @@ static ssize_t it8172_read(struct file *file, char *buffer,
struct
dmabuf
*
db
=
&
s
->
dma_adc
;
struct
dmabuf
*
db
=
&
s
->
dma_adc
;
ssize_t
ret
;
ssize_t
ret
;
unsigned
long
flags
;
unsigned
long
flags
;
int
cnt
,
bufcnt
,
avail
;
int
cnt
,
remainder
,
avail
;
if
(
ppos
!=
&
file
->
f_pos
)
if
(
ppos
!=
&
file
->
f_pos
)
return
-
ESPIPE
;
return
-
ESPIPE
;
...
@@ -942,16 +1123,9 @@ static ssize_t it8172_read(struct file *file, char *buffer,
...
@@ -942,16 +1123,9 @@ static ssize_t it8172_read(struct file *file, char *buffer,
}
}
}
while
(
avail
<=
0
);
}
while
(
avail
<=
0
);
cnt
=
count
>
avail
?
avail
:
count
;
bufcnt
=
cnt
;
if
(
cnt
%
db
->
fragsize
)
{
// round count up to nearest fragment
int
newcnt
=
db
->
fragsize
*
((
cnt
+
db
->
fragsize
)
/
db
->
fragsize
);
cnt
=
newcnt
;
}
// copy from nextOut to user
// copy from nextOut to user
if
(
copy_to_user
(
buffer
,
db
->
nextOut
,
bufcnt
))
{
if
((
cnt
=
copy_dmabuf_user
(
db
,
buffer
,
count
>
avail
?
avail
:
count
,
1
))
<
0
)
{
if
(
!
ret
)
if
(
!
ret
)
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
return
ret
;
return
ret
;
...
@@ -965,11 +1139,30 @@ static ssize_t it8172_read(struct file *file, char *buffer,
...
@@ -965,11 +1139,30 @@ static ssize_t it8172_read(struct file *file, char *buffer,
if
(
db
->
nextOut
>=
db
->
rawbuf
+
db
->
dmasize
)
if
(
db
->
nextOut
>=
db
->
rawbuf
+
db
->
dmasize
)
db
->
nextOut
-=
db
->
dmasize
;
db
->
nextOut
-=
db
->
dmasize
;
count
-=
buf
cnt
;
count
-=
cnt
;
buffer
+=
buf
cnt
;
buffer
+=
cnt
;
ret
+=
buf
cnt
;
ret
+=
cnt
;
}
// while (count > 0)
}
// while (count > 0)
/*
* See if the dma buffer count after this read call is
* aligned on a fragsize boundary. If not, read from
* buffer until we reach a boundary, and let's hope this
* is just the last remainder of an audio record. If not
* it means the user is not reading in fragsize chunks, in
* which case it's his/her fault that there are audio gaps
* in their record.
*/
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
remainder
=
db
->
count
%
db
->
fragsize
;
if
(
remainder
)
{
db
->
nextOut
+=
remainder
;
if
(
db
->
nextOut
>=
db
->
rawbuf
+
db
->
dmasize
)
db
->
nextOut
-=
db
->
dmasize
;
db
->
count
-=
remainder
;
}
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
return
ret
;
return
ret
;
}
}
...
@@ -980,7 +1173,7 @@ static ssize_t it8172_write(struct file *file, const char *buffer,
...
@@ -980,7 +1173,7 @@ static ssize_t it8172_write(struct file *file, const char *buffer,
struct
dmabuf
*
db
=
&
s
->
dma_dac
;
struct
dmabuf
*
db
=
&
s
->
dma_dac
;
ssize_t
ret
;
ssize_t
ret
;
unsigned
long
flags
;
unsigned
long
flags
;
int
cnt
,
bufcnt
,
avail
;
int
cnt
,
remainder
,
avail
;
if
(
ppos
!=
&
file
->
f_pos
)
if
(
ppos
!=
&
file
->
f_pos
)
return
-
ESPIPE
;
return
-
ESPIPE
;
...
@@ -1011,23 +1204,15 @@ static ssize_t it8172_write(struct file *file, const char *buffer,
...
@@ -1011,23 +1204,15 @@ static ssize_t it8172_write(struct file *file, const char *buffer,
}
}
}
while
(
avail
<=
0
);
}
while
(
avail
<=
0
);
cnt
=
count
>
avail
?
avail
:
count
;
// copy to nextIn
// copy to nextIn
if
(
copy_from_user
(
db
->
nextIn
,
buffer
,
cnt
))
{
if
((
cnt
=
copy_dmabuf_user
(
db
,
(
char
*
)
buffer
,
count
>
avail
?
avail
:
count
,
0
))
<
0
)
{
if
(
!
ret
)
if
(
!
ret
)
ret
=
-
EFAULT
;
ret
=
-
EFAULT
;
return
ret
;
return
ret
;
}
}
bufcnt
=
cnt
;
if
(
cnt
%
db
->
fragsize
)
{
// round count up to nearest fragment, and fill remainder of
// fragment with silence
int
newcnt
=
db
->
fragsize
*
((
cnt
+
db
->
fragsize
)
/
db
->
fragsize
);
memset
(
db
->
nextIn
+
cnt
,
(
s
->
pcc
&
CC_DF
)
?
0
:
0x80
,
newcnt
-
cnt
);
cnt
=
newcnt
;
}
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
db
->
count
+=
cnt
;
db
->
count
+=
cnt
;
if
(
db
->
stopped
)
if
(
db
->
stopped
)
...
@@ -1038,11 +1223,32 @@ static ssize_t it8172_write(struct file *file, const char *buffer,
...
@@ -1038,11 +1223,32 @@ static ssize_t it8172_write(struct file *file, const char *buffer,
if
(
db
->
nextIn
>=
db
->
rawbuf
+
db
->
dmasize
)
if
(
db
->
nextIn
>=
db
->
rawbuf
+
db
->
dmasize
)
db
->
nextIn
-=
db
->
dmasize
;
db
->
nextIn
-=
db
->
dmasize
;
count
-=
buf
cnt
;
count
-=
cnt
;
buffer
+=
buf
cnt
;
buffer
+=
cnt
;
ret
+=
buf
cnt
;
ret
+=
cnt
;
}
// while (count > 0)
}
// while (count > 0)
/*
* See if the dma buffer count after this write call is
* aligned on a fragsize boundary. If not, fill buffer
* with silence to the next boundary, and let's hope this
* is just the last remainder of an audio playback. If not
* it means the user is not sending us fragsize chunks, in
* which case it's his/her fault that there are audio gaps
* in their playback.
*/
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
remainder
=
db
->
count
%
db
->
fragsize
;
if
(
remainder
)
{
int
fill_cnt
=
db
->
fragsize
-
remainder
;
memset
(
db
->
nextIn
,
0
,
fill_cnt
);
db
->
nextIn
+=
fill_cnt
;
if
(
db
->
nextIn
>=
db
->
rawbuf
+
db
->
dmasize
)
db
->
nextIn
-=
db
->
dmasize
;
db
->
count
+=
fill_cnt
;
}
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
return
ret
;
return
ret
;
}
}
...
@@ -1054,10 +1260,17 @@ static unsigned int it8172_poll(struct file *file,
...
@@ -1054,10 +1260,17 @@ static unsigned int it8172_poll(struct file *file,
unsigned
long
flags
;
unsigned
long
flags
;
unsigned
int
mask
=
0
;
unsigned
int
mask
=
0
;
if
(
file
->
f_mode
&
FMODE_WRITE
)
if
(
file
->
f_mode
&
FMODE_WRITE
)
{
if
(
!
s
->
dma_dac
.
ready
)
return
0
;
poll_wait
(
file
,
&
s
->
dma_dac
.
wait
,
wait
);
poll_wait
(
file
,
&
s
->
dma_dac
.
wait
,
wait
);
if
(
file
->
f_mode
&
FMODE_READ
)
}
if
(
file
->
f_mode
&
FMODE_READ
)
{
if
(
!
s
->
dma_adc
.
ready
)
return
0
;
poll_wait
(
file
,
&
s
->
dma_adc
.
wait
,
wait
);
poll_wait
(
file
,
&
s
->
dma_adc
.
wait
,
wait
);
}
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
if
(
file
->
f_mode
&
FMODE_READ
)
{
if
(
file
->
f_mode
&
FMODE_READ
)
{
if
(
s
->
dma_adc
.
count
>=
(
signed
)
s
->
dma_adc
.
fragsize
)
if
(
s
->
dma_adc
.
count
>=
(
signed
)
s
->
dma_adc
.
fragsize
)
...
@@ -1173,9 +1386,10 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
...
@@ -1173,9 +1386,10 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
break
;
break
;
}
}
if
(
count
<
sizeof
(
ioctl_str
)
/
sizeof
(
ioctl_str
[
0
]))
if
(
count
<
sizeof
(
ioctl_str
)
/
sizeof
(
ioctl_str
[
0
]))
printk
(
KERN_INFO
PFX
"ioctl %s
\n
"
,
ioctl_str
[
count
].
str
);
dbg
(
"ioctl %s, arg=0x%08x"
,
ioctl_str
[
count
].
str
,
(
unsigned
int
)
arg
);
else
else
printk
(
KERN_INFO
PFX
"ioctl unknown, 0x%x
\n
"
,
cmd
);
dbg
(
"ioctl unknown, 0x%x
"
,
cmd
);
#endif
#endif
switch
(
cmd
)
{
switch
(
cmd
)
{
...
@@ -1197,15 +1411,17 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
...
@@ -1197,15 +1411,17 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
case
SNDCTL_DSP_RESET
:
case
SNDCTL_DSP_RESET
:
if
(
file
->
f_mode
&
FMODE_WRITE
)
{
if
(
file
->
f_mode
&
FMODE_WRITE
)
{
stop_dac
(
s
);
stop_dac
(
s
);
synchronize_irq
(
s
->
irq
);
synchronize_irq
(
);
s
->
dma_dac
.
count
=
s
->
dma_dac
.
total_bytes
=
0
;
s
->
dma_dac
.
count
=
s
->
dma_dac
.
total_bytes
=
0
;
s
->
dma_dac
.
nextIn
=
s
->
dma_dac
.
nextOut
=
s
->
dma_dac
.
rawbuf
;
s
->
dma_dac
.
nextIn
=
s
->
dma_dac
.
nextOut
=
s
->
dma_dac
.
rawbuf
;
}
}
if
(
file
->
f_mode
&
FMODE_READ
)
{
if
(
file
->
f_mode
&
FMODE_READ
)
{
stop_adc
(
s
);
stop_adc
(
s
);
synchronize_irq
(
s
->
irq
);
synchronize_irq
(
);
s
->
dma_adc
.
count
=
s
->
dma_adc
.
total_bytes
=
0
;
s
->
dma_adc
.
count
=
s
->
dma_adc
.
total_bytes
=
0
;
s
->
dma_adc
.
nextIn
=
s
->
dma_adc
.
nextOut
=
s
->
dma_adc
.
rawbuf
;
s
->
dma_adc
.
nextIn
=
s
->
dma_adc
.
nextOut
=
s
->
dma_adc
.
rawbuf
;
}
}
return
0
;
return
0
;
...
@@ -1325,9 +1541,11 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
...
@@ -1325,9 +1541,11 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
}
}
}
else
{
}
else
{
if
(
file
->
f_mode
&
FMODE_READ
)
if
(
file
->
f_mode
&
FMODE_READ
)
val
=
(
s
->
capcc
&
CC_DF
)
?
AFMT_S16_LE
:
AFMT_U8
;
val
=
(
s
->
capcc
&
CC_DF
)
?
AFMT_S16_LE
:
AFMT_U8
;
else
else
val
=
(
s
->
pcc
&
CC_DF
)
?
AFMT_S16_LE
:
AFMT_U8
;
val
=
(
s
->
pcc
&
CC_DF
)
?
AFMT_S16_LE
:
AFMT_U8
;
}
}
return
put_user
(
val
,
(
int
*
)
arg
);
return
put_user
(
val
,
(
int
*
)
arg
);
...
@@ -1368,14 +1586,16 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
...
@@ -1368,14 +1586,16 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
count
=
s
->
dma_dac
.
count
;
count
=
s
->
dma_dac
.
count
;
if
(
!
s
->
dma_dac
.
stopped
)
if
(
!
s
->
dma_dac
.
stopped
)
count
-=
(
s
->
dma_dac
.
fragsize
-
inw
(
s
->
io
+
IT_AC_PCDL
));
count
-=
(
s
->
dma_dac
.
fragsize
-
inw
(
s
->
io
+
IT_AC_PCDL
));
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
if
(
count
<
0
)
if
(
count
<
0
)
count
=
0
;
count
=
0
;
abinfo
.
bytes
=
s
->
dma_dac
.
dmasize
-
count
;
abinfo
.
bytes
=
s
->
dma_dac
.
dmasize
-
count
;
abinfo
.
fragstotal
=
s
->
dma_dac
.
numfrag
;
abinfo
.
fragstotal
=
s
->
dma_dac
.
numfrag
;
abinfo
.
fragments
=
abinfo
.
bytes
>>
s
->
dma_dac
.
fragshift
;
abinfo
.
fragments
=
abinfo
.
bytes
>>
s
->
dma_dac
.
fragshift
;
return
copy_to_user
((
void
*
)
arg
,
&
abinfo
,
sizeof
(
abinfo
))
?
-
EFAULT
:
0
;
return
copy_to_user
((
void
*
)
arg
,
&
abinfo
,
sizeof
(
abinfo
))
?
-
EFAULT
:
0
;
case
SNDCTL_DSP_GETISPACE
:
case
SNDCTL_DSP_GETISPACE
:
if
(
!
(
file
->
f_mode
&
FMODE_READ
))
if
(
!
(
file
->
f_mode
&
FMODE_READ
))
...
@@ -1384,14 +1604,16 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
...
@@ -1384,14 +1604,16 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
count
=
s
->
dma_adc
.
count
;
count
=
s
->
dma_adc
.
count
;
if
(
!
s
->
dma_adc
.
stopped
)
if
(
!
s
->
dma_adc
.
stopped
)
count
+=
(
s
->
dma_adc
.
fragsize
-
inw
(
s
->
io
+
IT_AC_CAPCDL
));
count
+=
(
s
->
dma_adc
.
fragsize
-
inw
(
s
->
io
+
IT_AC_CAPCDL
));
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
if
(
count
<
0
)
if
(
count
<
0
)
count
=
0
;
count
=
0
;
abinfo
.
bytes
=
count
;
abinfo
.
bytes
=
count
;
abinfo
.
fragstotal
=
s
->
dma_adc
.
numfrag
;
abinfo
.
fragstotal
=
s
->
dma_adc
.
numfrag
;
abinfo
.
fragments
=
abinfo
.
bytes
>>
s
->
dma_adc
.
fragshift
;
abinfo
.
fragments
=
abinfo
.
bytes
>>
s
->
dma_adc
.
fragshift
;
return
copy_to_user
((
void
*
)
arg
,
&
abinfo
,
sizeof
(
abinfo
))
?
-
EFAULT
:
0
;
return
copy_to_user
((
void
*
)
arg
,
&
abinfo
,
sizeof
(
abinfo
))
?
-
EFAULT
:
0
;
case
SNDCTL_DSP_NONBLOCK
:
case
SNDCTL_DSP_NONBLOCK
:
file
->
f_flags
|=
O_NONBLOCK
;
file
->
f_flags
|=
O_NONBLOCK
;
...
@@ -1403,7 +1625,8 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
...
@@ -1403,7 +1625,8 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
spin_lock_irqsave
(
&
s
->
lock
,
flags
);
count
=
s
->
dma_dac
.
count
;
count
=
s
->
dma_dac
.
count
;
if
(
!
s
->
dma_dac
.
stopped
)
if
(
!
s
->
dma_dac
.
stopped
)
count
-=
(
s
->
dma_dac
.
fragsize
-
inw
(
s
->
io
+
IT_AC_PCDL
));
count
-=
(
s
->
dma_dac
.
fragsize
-
inw
(
s
->
io
+
IT_AC_PCDL
));
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
if
(
count
<
0
)
if
(
count
<
0
)
count
=
0
;
count
=
0
;
...
@@ -1419,18 +1642,18 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
...
@@ -1419,18 +1642,18 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
diff
=
s
->
dma_adc
.
fragsize
-
inw
(
s
->
io
+
IT_AC_CAPCDL
);
diff
=
s
->
dma_adc
.
fragsize
-
inw
(
s
->
io
+
IT_AC_CAPCDL
);
count
+=
diff
;
count
+=
diff
;
cinfo
.
bytes
+=
diff
;
cinfo
.
bytes
+=
diff
;
cinfo
.
ptr
=
inl
(
s
->
io
+
s
->
dma_adc
.
curBufPtr
)
-
s
->
dma_adc
.
dmaaddr
;
cinfo
.
ptr
=
inl
(
s
->
io
+
s
->
dma_adc
.
curBufPtr
)
-
s
->
dma_adc
.
dmaaddr
;
}
else
}
else
cinfo
.
ptr
=
virt_to_bus
(
s
->
dma_adc
.
nextIn
)
-
s
->
dma_adc
.
dmaaddr
;
cinfo
.
ptr
=
virt_to_bus
(
s
->
dma_adc
.
nextIn
)
-
s
->
dma_adc
.
dmaaddr
;
if
(
s
->
dma_adc
.
mapped
)
if
(
s
->
dma_adc
.
mapped
)
s
->
dma_adc
.
count
&=
s
->
dma_adc
.
fragsize
-
1
;
s
->
dma_adc
.
count
&=
s
->
dma_adc
.
fragsize
-
1
;
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
if
(
count
<
0
)
if
(
count
<
0
)
count
=
0
;
count
=
0
;
cinfo
.
blocks
=
count
>>
s
->
dma_adc
.
fragshift
;
cinfo
.
blocks
=
count
>>
s
->
dma_adc
.
fragshift
;
if
(
copy_to_user
((
void
*
)
arg
,
&
cinfo
,
sizeof
(
cinfo
)))
return
copy_to_user
((
void
*
)
arg
,
&
cinfo
,
sizeof
(
cinfo
));
return
-
EFAULT
;
return
0
;
case
SNDCTL_DSP_GETOPTR
:
case
SNDCTL_DSP_GETOPTR
:
if
(
!
(
file
->
f_mode
&
FMODE_READ
))
if
(
!
(
file
->
f_mode
&
FMODE_READ
))
...
@@ -1442,18 +1665,18 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
...
@@ -1442,18 +1665,18 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
diff
=
s
->
dma_dac
.
fragsize
-
inw
(
s
->
io
+
IT_AC_CAPCDL
);
diff
=
s
->
dma_dac
.
fragsize
-
inw
(
s
->
io
+
IT_AC_CAPCDL
);
count
-=
diff
;
count
-=
diff
;
cinfo
.
bytes
+=
diff
;
cinfo
.
bytes
+=
diff
;
cinfo
.
ptr
=
inl
(
s
->
io
+
s
->
dma_dac
.
curBufPtr
)
-
s
->
dma_dac
.
dmaaddr
;
cinfo
.
ptr
=
inl
(
s
->
io
+
s
->
dma_dac
.
curBufPtr
)
-
s
->
dma_dac
.
dmaaddr
;
}
else
}
else
cinfo
.
ptr
=
virt_to_bus
(
s
->
dma_dac
.
nextOut
)
-
s
->
dma_dac
.
dmaaddr
;
cinfo
.
ptr
=
virt_to_bus
(
s
->
dma_dac
.
nextOut
)
-
s
->
dma_dac
.
dmaaddr
;
if
(
s
->
dma_dac
.
mapped
)
if
(
s
->
dma_dac
.
mapped
)
s
->
dma_dac
.
count
&=
s
->
dma_dac
.
fragsize
-
1
;
s
->
dma_dac
.
count
&=
s
->
dma_dac
.
fragsize
-
1
;
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
if
(
count
<
0
)
if
(
count
<
0
)
count
=
0
;
count
=
0
;
cinfo
.
blocks
=
count
>>
s
->
dma_dac
.
fragshift
;
cinfo
.
blocks
=
count
>>
s
->
dma_dac
.
fragshift
;
if
(
copy_to_user
((
void
*
)
arg
,
&
cinfo
,
sizeof
(
cinfo
)))
return
copy_to_user
((
void
*
)
arg
,
&
cinfo
,
sizeof
(
cinfo
));
return
-
EFAULT
;
return
0
;
case
SNDCTL_DSP_GETBLKSIZE
:
case
SNDCTL_DSP_GETBLKSIZE
:
if
(
file
->
f_mode
&
FMODE_WRITE
)
if
(
file
->
f_mode
&
FMODE_WRITE
)
...
@@ -1520,15 +1743,19 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
...
@@ -1520,15 +1743,19 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
case
SOUND_PCM_READ_CHANNELS
:
case
SOUND_PCM_READ_CHANNELS
:
if
(
file
->
f_mode
&
FMODE_READ
)
if
(
file
->
f_mode
&
FMODE_READ
)
return
put_user
((
s
->
capcc
&
CC_SM
)
?
2
:
1
,
(
int
*
)
arg
);
return
put_user
((
s
->
capcc
&
CC_SM
)
?
2
:
1
,
(
int
*
)
arg
);
else
else
return
put_user
((
s
->
pcc
&
CC_SM
)
?
2
:
1
,
(
int
*
)
arg
);
return
put_user
((
s
->
pcc
&
CC_SM
)
?
2
:
1
,
(
int
*
)
arg
);
case
SOUND_PCM_READ_BITS
:
case
SOUND_PCM_READ_BITS
:
if
(
file
->
f_mode
&
FMODE_READ
)
if
(
file
->
f_mode
&
FMODE_READ
)
return
put_user
((
s
->
capcc
&
CC_DF
)
?
16
:
8
,
(
int
*
)
arg
);
return
put_user
((
s
->
capcc
&
CC_DF
)
?
16
:
8
,
(
int
*
)
arg
);
else
else
return
put_user
((
s
->
pcc
&
CC_DF
)
?
16
:
8
,
(
int
*
)
arg
);
return
put_user
((
s
->
pcc
&
CC_DF
)
?
16
:
8
,
(
int
*
)
arg
);
case
SOUND_PCM_WRITE_FILTER
:
case
SOUND_PCM_WRITE_FILTER
:
case
SNDCTL_DSP_SETSYNCRO
:
case
SNDCTL_DSP_SETSYNCRO
:
...
@@ -1536,19 +1763,26 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
...
@@ -1536,19 +1763,26 @@ static int it8172_ioctl(struct inode *inode, struct file *file,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
return
mixdev_ioctl
(
&
s
->
codec
,
cmd
,
arg
);
return
mixdev_ioctl
(
s
->
codec
,
cmd
,
arg
);
}
}
static
int
it8172_open
(
struct
inode
*
inode
,
struct
file
*
file
)
static
int
it8172_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
{
int
minor
=
minor
(
inode
->
i_rdev
);
int
minor
=
MINOR
(
inode
->
i_rdev
);
DECLARE_WAITQUEUE
(
wait
,
current
);
DECLARE_WAITQUEUE
(
wait
,
current
);
unsigned
long
flags
;
unsigned
long
flags
;
struct
list_head
*
list
;
struct
list_head
*
list
;
struct
it8172_state
*
s
;
struct
it8172_state
*
s
;
int
ret
;
int
ret
;
#ifdef IT8172_VERBOSE_DEBUG
if
(
file
->
f_flags
&
O_NONBLOCK
)
dbg
(
__FUNCTION__
": non-blocking"
);
else
dbg
(
__FUNCTION__
": blocking"
);
#endif
for
(
list
=
devs
.
next
;
;
list
=
list
->
next
)
{
for
(
list
=
devs
.
next
;
;
list
=
list
->
next
)
{
if
(
list
==
&
devs
)
if
(
list
==
&
devs
)
return
-
ENODEV
;
return
-
ENODEV
;
...
@@ -1585,9 +1819,11 @@ static int it8172_open(struct inode *inode, struct file *file)
...
@@ -1585,9 +1819,11 @@ static int it8172_open(struct inode *inode, struct file *file)
if
((
minor
&
0xf
)
==
SND_DEV_DSP16
)
if
((
minor
&
0xf
)
==
SND_DEV_DSP16
)
s
->
capcc
|=
CC_DF
;
s
->
capcc
|=
CC_DF
;
outw
(
s
->
capcc
,
s
->
io
+
IT_AC_CAPCC
);
outw
(
s
->
capcc
,
s
->
io
+
IT_AC_CAPCC
);
if
((
ret
=
prog_dmabuf_adc
(
s
)))
if
((
ret
=
prog_dmabuf_adc
(
s
)))
{
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
return
ret
;
return
ret
;
}
}
}
if
(
file
->
f_mode
&
FMODE_WRITE
)
{
if
(
file
->
f_mode
&
FMODE_WRITE
)
{
s
->
dma_dac
.
ossfragshift
=
s
->
dma_dac
.
ossmaxfrags
=
s
->
dma_dac
.
ossfragshift
=
s
->
dma_dac
.
ossmaxfrags
=
s
->
dma_dac
.
subdivision
=
s
->
dma_dac
.
total_bytes
=
0
;
s
->
dma_dac
.
subdivision
=
s
->
dma_dac
.
total_bytes
=
0
;
...
@@ -1596,13 +1832,15 @@ static int it8172_open(struct inode *inode, struct file *file)
...
@@ -1596,13 +1832,15 @@ static int it8172_open(struct inode *inode, struct file *file)
if
((
minor
&
0xf
)
==
SND_DEV_DSP16
)
if
((
minor
&
0xf
)
==
SND_DEV_DSP16
)
s
->
pcc
|=
CC_DF
;
s
->
pcc
|=
CC_DF
;
outw
(
s
->
pcc
,
s
->
io
+
IT_AC_PCC
);
outw
(
s
->
pcc
,
s
->
io
+
IT_AC_PCC
);
if
((
ret
=
prog_dmabuf_dac
(
s
)))
if
((
ret
=
prog_dmabuf_dac
(
s
)))
{
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
return
ret
;
return
ret
;
}
}
}
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
s
->
lock
,
flags
);
s
->
open_mode
|=
file
->
f_mode
&
(
FMODE_READ
|
FMODE_WRITE
);
s
->
open_mode
|=
(
file
->
f_mode
&
(
FMODE_READ
|
FMODE_WRITE
)
);
up
(
&
s
->
open_sem
);
up
(
&
s
->
open_sem
);
return
0
;
return
0
;
}
}
...
@@ -1611,6 +1849,9 @@ static int it8172_release(struct inode *inode, struct file *file)
...
@@ -1611,6 +1849,9 @@ static int it8172_release(struct inode *inode, struct file *file)
{
{
struct
it8172_state
*
s
=
(
struct
it8172_state
*
)
file
->
private_data
;
struct
it8172_state
*
s
=
(
struct
it8172_state
*
)
file
->
private_data
;
#ifdef IT8172_VERBOSE_DEBUG
dbg
(
__FUNCTION__
);
#endif
lock_kernel
();
lock_kernel
();
if
(
file
->
f_mode
&
FMODE_WRITE
)
if
(
file
->
f_mode
&
FMODE_WRITE
)
drain_dac
(
s
,
file
->
f_flags
&
O_NONBLOCK
);
drain_dac
(
s
,
file
->
f_flags
&
O_NONBLOCK
);
...
@@ -1623,7 +1864,7 @@ static int it8172_release(struct inode *inode, struct file *file)
...
@@ -1623,7 +1864,7 @@ static int it8172_release(struct inode *inode, struct file *file)
stop_adc
(
s
);
stop_adc
(
s
);
dealloc_dmabuf
(
s
,
&
s
->
dma_adc
);
dealloc_dmabuf
(
s
,
&
s
->
dma_adc
);
}
}
s
->
open_mode
&=
(
~
file
->
f_mode
)
&
(
FMODE_READ
|
FMODE_WRITE
);
s
->
open_mode
&=
((
~
file
->
f_mode
)
&
(
FMODE_READ
|
FMODE_WRITE
)
);
up
(
&
s
->
open_sem
);
up
(
&
s
->
open_sem
);
wake_up
(
&
s
->
open_wait
);
wake_up
(
&
s
->
open_wait
);
unlock_kernel
();
unlock_kernel
();
...
@@ -1631,15 +1872,15 @@ static int it8172_release(struct inode *inode, struct file *file)
...
@@ -1631,15 +1872,15 @@ static int it8172_release(struct inode *inode, struct file *file)
}
}
static
/*const*/
struct
file_operations
it8172_audio_fops
=
{
static
/*const*/
struct
file_operations
it8172_audio_fops
=
{
.
owner
=
THIS_MODULE
,
owner:
THIS_MODULE
,
.
llseek
=
no
_llseek
,
llseek:
it8172
_llseek
,
.
read
=
it8172_read
,
read:
it8172_read
,
.
write
=
it8172_write
,
write:
it8172_write
,
.
poll
=
it8172_poll
,
poll:
it8172_poll
,
.
ioctl
=
it8172_ioctl
,
ioctl:
it8172_ioctl
,
.
mmap
=
it8172_mmap
,
mmap:
it8172_mmap
,
.
open
=
it8172_open
,
open:
it8172_open
,
.
release
=
it8172_release
,
release:
it8172_release
,
};
};
...
@@ -1690,7 +1931,7 @@ static int proc_it8172_dump (char *buf, char **start, off_t fpos,
...
@@ -1690,7 +1931,7 @@ static int proc_it8172_dump (char *buf, char **start, off_t fpos,
len
+=
sprintf
(
buf
+
len
,
"----------------------
\n
"
);
len
+=
sprintf
(
buf
+
len
,
"----------------------
\n
"
);
for
(
cnt
=
0
;
cnt
<=
0x7e
;
cnt
=
cnt
+
2
)
for
(
cnt
=
0
;
cnt
<=
0x7e
;
cnt
=
cnt
+
2
)
len
+=
sprintf
(
buf
+
len
,
"reg %02x = %04x
\n
"
,
len
+=
sprintf
(
buf
+
len
,
"reg %02x = %04x
\n
"
,
cnt
,
rdcodec
(
&
s
->
codec
,
cnt
));
cnt
,
rdcodec
(
s
->
codec
,
cnt
));
if
(
fpos
>=
len
){
if
(
fpos
>=
len
){
*
start
=
buf
;
*
start
=
buf
;
...
@@ -1712,15 +1953,17 @@ static int proc_it8172_dump (char *buf, char **start, off_t fpos,
...
@@ -1712,15 +1953,17 @@ static int proc_it8172_dump (char *buf, char **start, off_t fpos,
#define NR_DEVICE 5
#define NR_DEVICE 5
static
int
spdif
[
NR_DEVICE
]
=
{
0
,
};
static
int
spdif
[
NR_DEVICE
]
=
{
0
,
};
static
int
i2s_fmt
[
NR_DEVICE
]
=
{
0
,
};
static
unsigned
int
devindex
=
0
;
static
unsigned
int
devindex
=
0
;
MODULE_PARM
(
spdif
,
"1-"
__MODULE_STRING
(
NR_DEVICE
)
"i"
);
MODULE_PARM
(
spdif
,
"1-"
__MODULE_STRING
(
NR_DEVICE
)
"i"
);
MODULE_PARM_DESC
(
spdif
,
"if 1 the S/PDIF digital output is enabled"
);
MODULE_PARM_DESC
(
spdif
,
"if 1 the S/PDIF digital output is enabled"
);
MODULE_PARM
(
i2s_fmt
,
"1-"
__MODULE_STRING
(
NR_DEVICE
)
"i"
);
MODULE_PARM_DESC
(
i2s_fmt
,
"the format of I2S"
);
MODULE_AUTHOR
(
"Monta Vista Software, stevel@mvista.com"
);
MODULE_AUTHOR
(
"Monta Vista Software, stevel@mvista.com"
);
MODULE_DESCRIPTION
(
"IT8172 AudioPCI97 Driver"
);
MODULE_DESCRIPTION
(
"IT8172 Audio Driver"
);
MODULE_LICENSE
(
"GPL"
);
/* --------------------------------------------------------------------- */
/* --------------------------------------------------------------------- */
...
@@ -1737,7 +1980,7 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
...
@@ -1737,7 +1980,7 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
return
-
1
;
return
-
1
;
if
(
!
(
s
=
kmalloc
(
sizeof
(
struct
it8172_state
),
GFP_KERNEL
)))
{
if
(
!
(
s
=
kmalloc
(
sizeof
(
struct
it8172_state
),
GFP_KERNEL
)))
{
printk
(
KERN_ERR
PFX
"alloc of device struct failed
\n
"
);
err
(
"alloc of device struct failed
"
);
return
-
1
;
return
-
1
;
}
}
...
@@ -1753,35 +1996,40 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
...
@@ -1753,35 +1996,40 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
s
->
vendor
=
pcidev
->
vendor
;
s
->
vendor
=
pcidev
->
vendor
;
s
->
device
=
pcidev
->
device
;
s
->
device
=
pcidev
->
device
;
pci_read_config_byte
(
pcidev
,
PCI_REVISION_ID
,
&
s
->
rev
);
pci_read_config_byte
(
pcidev
,
PCI_REVISION_ID
,
&
s
->
rev
);
s
->
codec
.
private_data
=
s
;
s
->
codec
.
id
=
0
;
s
->
codec
=
ac97_alloc_codec
();
s
->
codec
.
codec_read
=
rdcodec
;
if
(
s
->
codec
==
NULL
)
s
->
codec
.
codec_write
=
wrcodec
;
goto
err_codec
;
s
->
codec
.
codec_wait
=
waitcodec
;
s
->
codec
->
private_data
=
s
;
s
->
codec
->
id
=
0
;
s
->
codec
->
codec_read
=
rdcodec
;
s
->
codec
->
codec_write
=
wrcodec
;
s
->
codec
->
codec_wait
=
waitcodec
;
if
(
!
request_region
(
s
->
io
,
pci_resource_len
(
pcidev
,
0
),
if
(
!
request_region
(
s
->
io
,
pci_resource_len
(
pcidev
,
0
),
IT8172_MODULE_NAME
))
{
IT8172_MODULE_NAME
))
{
printk
(
KERN_ERR
PFX
"io ports %#lx->%#lx in use
\n
"
,
err
(
"io ports %#lx->%#lx in use
"
,
s
->
io
,
s
->
io
+
pci_resource_len
(
pcidev
,
0
)
-
1
);
s
->
io
,
s
->
io
+
pci_resource_len
(
pcidev
,
0
)
-
1
);
goto
err_region
;
goto
err_region
;
}
}
if
(
request_irq
(
s
->
irq
,
it8172_interrupt
,
SA_INTERRUPT
,
if
(
request_irq
(
s
->
irq
,
it8172_interrupt
,
SA_INTERRUPT
,
IT8172_MODULE_NAME
,
s
))
{
IT8172_MODULE_NAME
,
s
))
{
printk
(
KERN_ERR
PFX
"irq %u in use
\n
"
,
s
->
irq
);
err
(
"irq %u in use
"
,
s
->
irq
);
goto
err_irq
;
goto
err_irq
;
}
}
printk
(
KERN_INFO
PFX
"IO at %#lx, IRQ %d
\n
"
,
s
->
io
,
s
->
irq
);
info
(
"IO at %#lx, IRQ %d
"
,
s
->
io
,
s
->
irq
);
/* register devices */
/* register devices */
if
((
s
->
dev_audio
=
register_sound_dsp
(
&
it8172_audio_fops
,
-
1
))
<
0
)
if
((
s
->
dev_audio
=
register_sound_dsp
(
&
it8172_audio_fops
,
-
1
))
<
0
)
goto
err_dev1
;
goto
err_dev1
;
if
((
s
->
codec
.
dev_mixer
=
if
((
s
->
codec
->
dev_mixer
=
register_sound_mixer
(
&
it8172_mixer_fops
,
-
1
))
<
0
)
register_sound_mixer
(
&
it8172_mixer_fops
,
-
1
))
<
0
)
goto
err_dev2
;
goto
err_dev2
;
#ifdef IT8172_DEBUG
#ifdef IT8172_DEBUG
/* ini
tialize the debug proc device */
/* in
tialize the debug proc device */
s
->
ps
=
create_proc_read_entry
(
IT8172_MODULE_NAME
,
0
,
NULL
,
s
->
ps
=
create_proc_read_entry
(
IT8172_MODULE_NAME
,
0
,
NULL
,
proc_it8172_dump
,
NULL
);
proc_it8172_dump
,
NULL
);
#endif
/* IT8172_DEBUG */
#endif
/* IT8172_DEBUG */
...
@@ -1801,7 +2049,7 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
...
@@ -1801,7 +2049,7 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
IT_IO_READ16
(
IT_PM_PCISR
,
pcisr
);
IT_IO_READ16
(
IT_PM_PCISR
,
pcisr
);
}
}
if
(
i
==
10
)
{
if
(
i
==
10
)
{
printk
(
KERN_ERR
PFX
"chip reset timeout!
\n
"
);
err
(
"chip reset timeout!
"
);
goto
err_dev3
;
goto
err_dev3
;
}
}
...
@@ -1817,14 +2065,22 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
...
@@ -1817,14 +2065,22 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
s
->
spdif_volume
=
-
1
;
s
->
spdif_volume
=
-
1
;
/* check to see if s/pdif mode is being requested */
/* check to see if s/pdif mode is being requested */
if
(
spdif
[
devindex
])
{
if
(
spdif
[
devindex
])
{
printk
(
KERN_INFO
PFX
"enabling S/PDIF output
\n
"
);
info
(
"enabling S/PDIF output
"
);
s
->
spdif_volume
=
0
;
s
->
spdif_volume
=
0
;
outb
(
GC_SOE
,
s
->
io
+
IT_AC_GC
);
outb
(
GC_SOE
,
s
->
io
+
IT_AC_GC
);
}
else
{
}
else
{
printk
(
KERN_INFO
PFX
"disabling S/PDIF output
\n
"
);
info
(
"disabling S/PDIF output
"
);
outb
(
0
,
s
->
io
+
IT_AC_GC
);
outb
(
0
,
s
->
io
+
IT_AC_GC
);
}
}
/* check to see if I2S format requested */
if
(
i2s_fmt
[
devindex
])
{
info
(
"setting I2S format to 0x%02x"
,
i2s_fmt
[
devindex
]);
outb
(
i2s_fmt
[
devindex
],
s
->
io
+
IT_AC_I2SMC
);
}
else
{
outb
(
I2SMC_I2SF_I2S
,
s
->
io
+
IT_AC_I2SMC
);
}
/* cold reset the AC97 */
/* cold reset the AC97 */
outw
(
CODECC_CR
,
s
->
io
+
IT_AC_CODECC
);
outw
(
CODECC_CR
,
s
->
io
+
IT_AC_CODECC
);
udelay
(
1000
);
udelay
(
1000
);
...
@@ -1839,9 +2095,12 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
...
@@ -1839,9 +2095,12 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
outw
(
0
,
s
->
io
+
IT_AC_CODECC
);
outw
(
0
,
s
->
io
+
IT_AC_CODECC
);
/* codec init */
/* codec init */
if
(
!
ac97_probe_codec
(
&
s
->
codec
))
if
(
!
ac97_probe_codec
(
s
->
codec
))
goto
err_dev3
;
goto
err_dev3
;
/* add I2S as allowable recording source */
s
->
codec
->
record_sources
|=
SOUND_MASK_I2S
;
/* Enable Volume button interrupts */
/* Enable Volume button interrupts */
imc
=
inb
(
s
->
io
+
IT_AC_IMC
);
imc
=
inb
(
s
->
io
+
IT_AC_IMC
);
outb
(
imc
&
~
IMC_VCIM
,
s
->
io
+
IT_AC_IMC
);
outb
(
imc
&
~
IMC_VCIM
,
s
->
io
+
IT_AC_IMC
);
...
@@ -1860,21 +2119,23 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
...
@@ -1860,21 +2119,23 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
/* set mic to be the recording source */
/* set mic to be the recording source */
val
=
SOUND_MASK_MIC
;
val
=
SOUND_MASK_MIC
;
mixdev_ioctl
(
&
s
->
codec
,
SOUND_MIXER_WRITE_RECSRC
,
(
unsigned
long
)
&
val
);
mixdev_ioctl
(
s
->
codec
,
SOUND_MIXER_WRITE_RECSRC
,
(
unsigned
long
)
&
val
);
/* mute
master and PCM when in S/PDIF mode */
/* mute AC'97
master and PCM when in S/PDIF mode */
if
(
s
->
spdif_volume
!=
-
1
)
{
if
(
s
->
spdif_volume
!=
-
1
)
{
val
=
0x0000
;
val
=
0x0000
;
mixdev_ioctl
(
&
s
->
codec
,
SOUND_MIXER_WRITE_VOLUME
,
s
->
codec
->
mixer_ioctl
(
s
->
codec
,
SOUND_MIXER_WRITE_VOLUME
,
(
unsigned
long
)
&
val
);
(
unsigned
long
)
&
val
);
mixdev_ioctl
(
&
s
->
codec
,
SOUND_MIXER_WRITE_PCM
,
s
->
codec
->
mixer_ioctl
(
s
->
codec
,
SOUND_MIXER_WRITE_PCM
,
(
unsigned
long
)
&
val
);
(
unsigned
long
)
&
val
);
}
}
#ifdef IT8172_DEBUG
#ifdef IT8172_DEBUG
sprintf
(
proc_str
,
"driver/%s/%d/ac97"
,
IT8172_MODULE_NAME
,
s
->
codec
.
id
);
sprintf
(
proc_str
,
"driver/%s/%d/ac97"
,
IT8172_MODULE_NAME
,
s
->
codec
->
id
);
s
->
ac97_ps
=
create_proc_read_entry
(
proc_str
,
0
,
NULL
,
s
->
ac97_ps
=
create_proc_read_entry
(
proc_str
,
0
,
NULL
,
ac97_read_proc
,
&
s
->
codec
);
ac97_read_proc
,
s
->
codec
);
#endif
#endif
/* store it in the driver field */
/* store it in the driver field */
...
@@ -1888,15 +2149,17 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
...
@@ -1888,15 +2149,17 @@ static int __devinit it8172_probe(struct pci_dev *pcidev,
return
0
;
return
0
;
err_dev3:
err_dev3:
unregister_sound_mixer
(
s
->
codec
.
dev_mixer
);
unregister_sound_mixer
(
s
->
codec
->
dev_mixer
);
err_dev2:
err_dev2:
unregister_sound_dsp
(
s
->
dev_audio
);
unregister_sound_dsp
(
s
->
dev_audio
);
err_dev1:
err_dev1:
printk
(
KERN_ERR
PFX
"cannot register misc device
\n
"
);
err
(
"cannot register misc device
"
);
free_irq
(
s
->
irq
,
s
);
free_irq
(
s
->
irq
,
s
);
err_irq:
err_irq:
release_region
(
s
->
io
,
pci_resource_len
(
pcidev
,
0
));
release_region
(
s
->
io
,
pci_resource_len
(
pcidev
,
0
));
err_region:
err_region:
ac97_release_codec
(
s
->
codec
);
err_codec:
kfree
(
s
);
kfree
(
s
);
return
-
1
;
return
-
1
;
}
}
...
@@ -1912,11 +2175,12 @@ static void __devinit it8172_remove(struct pci_dev *dev)
...
@@ -1912,11 +2175,12 @@ static void __devinit it8172_remove(struct pci_dev *dev)
if
(
s
->
ps
)
if
(
s
->
ps
)
remove_proc_entry
(
IT8172_MODULE_NAME
,
NULL
);
remove_proc_entry
(
IT8172_MODULE_NAME
,
NULL
);
#endif
/* IT8172_DEBUG */
#endif
/* IT8172_DEBUG */
synchronize_irq
(
s
->
irq
);
synchronize_irq
(
);
free_irq
(
s
->
irq
,
s
);
free_irq
(
s
->
irq
,
s
);
release_region
(
s
->
io
,
pci_resource_len
(
dev
,
0
));
release_region
(
s
->
io
,
pci_resource_len
(
dev
,
0
));
unregister_sound_dsp
(
s
->
dev_audio
);
unregister_sound_dsp
(
s
->
dev_audio
);
unregister_sound_mixer
(
s
->
codec
.
dev_mixer
);
unregister_sound_mixer
(
s
->
codec
->
dev_mixer
);
ac97_codec_release
(
s
->
codec
);
kfree
(
s
);
kfree
(
s
);
pci_set_drvdata
(
dev
,
NULL
);
pci_set_drvdata
(
dev
,
NULL
);
}
}
...
@@ -1932,24 +2196,64 @@ static struct pci_device_id id_table[] __devinitdata = {
...
@@ -1932,24 +2196,64 @@ static struct pci_device_id id_table[] __devinitdata = {
MODULE_DEVICE_TABLE
(
pci
,
id_table
);
MODULE_DEVICE_TABLE
(
pci
,
id_table
);
static
struct
pci_driver
it8172_driver
=
{
static
struct
pci_driver
it8172_driver
=
{
.
name
=
IT8172_MODULE_NAME
,
name:
IT8172_MODULE_NAME
,
.
id_table
=
id_table
,
id_table:
id_table
,
.
probe
=
it8172_probe
,
probe:
it8172_probe
,
.
remove
=
it8172_remove
,
remove:
it8172_remove
};
};
static
int
__init
init_it8172
(
void
)
static
int
__init
init_it8172
(
void
)
{
{
printk
(
"version v0.26 time "
__TIME__
" "
__DATE__
"
\n
"
);
if
(
!
pci_present
())
/* No PCI bus in this machine! */
return
-
ENODEV
;
info
(
"version v0.5 time "
__TIME__
" "
__DATE__
);
return
pci_module_init
(
&
it8172_driver
);
return
pci_module_init
(
&
it8172_driver
);
}
}
static
void
__exit
cleanup_it8172
(
void
)
static
void
__exit
cleanup_it8172
(
void
)
{
{
printk
(
KERN_INFO
PFX
"unloading
\n
"
);
info
(
"unloading
"
);
pci_unregister_driver
(
&
it8172_driver
);
pci_unregister_driver
(
&
it8172_driver
);
}
}
module_init
(
init_it8172
);
module_init
(
init_it8172
);
module_exit
(
cleanup_it8172
);
module_exit
(
cleanup_it8172
);
/* --------------------------------------------------------------------- */
#ifndef MODULE
/* format is: it8172=[spdif],[i2s:<I2S format>] */
static
int
__init
it8172_setup
(
char
*
options
)
{
char
*
this_opt
;
static
unsigned
__initdata
nr_dev
=
0
;
if
(
nr_dev
>=
NR_DEVICE
)
return
0
;
if
(
!
options
||
!*
options
)
return
0
;
for
(
this_opt
=
strtok
(
options
,
","
);
this_opt
;
this_opt
=
strtok
(
NULL
,
","
))
{
if
(
!
strncmp
(
this_opt
,
"spdif"
,
5
))
{
spdif
[
nr_dev
]
=
1
;
}
else
if
(
!
strncmp
(
this_opt
,
"i2s:"
,
4
))
{
if
(
!
strncmp
(
this_opt
+
4
,
"dac"
,
3
))
i2s_fmt
[
nr_dev
]
=
I2SMC_I2SF_DAC
;
else
if
(
!
strncmp
(
this_opt
+
4
,
"adc"
,
3
))
i2s_fmt
[
nr_dev
]
=
I2SMC_I2SF_ADC
;
else
if
(
!
strncmp
(
this_opt
+
4
,
"i2s"
,
3
))
i2s_fmt
[
nr_dev
]
=
I2SMC_I2SF_I2S
;
}
}
nr_dev
++
;
return
1
;
}
__setup
(
"it8172="
,
it8172_setup
);
#endif
/* MODULE */
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