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
2cf05d78
Commit
2cf05d78
authored
May 14, 2004
by
Jeff Garzik
Browse files
Options
Browse Files
Download
Plain Diff
Merge redhat.com:/spare/repo/linux-2.6
into redhat.com:/spare/repo/i810-audio-2.6
parents
5ea484a8
81da67b3
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
136 additions
and
111 deletions
+136
-111
sound/oss/i810_audio.c
sound/oss/i810_audio.c
+136
-111
No files found.
sound/oss/i810_audio.c
View file @
2cf05d78
...
@@ -99,6 +99,7 @@
...
@@ -99,6 +99,7 @@
#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/bitops.h>
#include <asm/uaccess.h>
#include <asm/uaccess.h>
#include <asm/hardirq.h>
#include <asm/hardirq.h>
...
@@ -148,6 +149,9 @@
...
@@ -148,6 +149,9 @@
#define PCI_DEVICE_ID_AMD_8111_AC97 0x746d
#define PCI_DEVICE_ID_AMD_8111_AC97 0x746d
#endif
#endif
#define MODULOP2(a, b) ((a) & ((b) - 1))
#define MASKP2(a, b) ((a) & ~((b) - 1))
static
int
ftsodell
;
static
int
ftsodell
;
static
int
strict_clocking
;
static
int
strict_clocking
;
static
unsigned
int
clocking
;
static
unsigned
int
clocking
;
...
@@ -209,6 +213,7 @@ struct i810_channel
...
@@ -209,6 +213,7 @@ struct i810_channel
#define ENUM_ENGINE(PRE,DIG) \
#define ENUM_ENGINE(PRE,DIG) \
enum { \
enum { \
PRE##_BASE = 0x##DIG##0,
/* Base Address */
\
PRE##_BDBAR = 0x##DIG##0,
/* Buffer Descriptor list Base Address */
\
PRE##_BDBAR = 0x##DIG##0,
/* Buffer Descriptor list Base Address */
\
PRE##_CIV = 0x##DIG##4,
/* Current Index Value */
\
PRE##_CIV = 0x##DIG##4,
/* Current Index Value */
\
PRE##_LVI = 0x##DIG##5,
/* Last Valid Index */
\
PRE##_LVI = 0x##DIG##5,
/* Last Valid Index */
\
...
@@ -491,8 +496,12 @@ struct i810_card {
...
@@ -491,8 +496,12 @@ struct i810_card {
/* extract register offset from codec struct */
/* extract register offset from codec struct */
#define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])
#define IO_REG_OFF(codec) (((struct i810_card *) codec->private_data)->ac97_id_map[codec->id])
#define GET_CIV(port) MODULOP2(inb((port) + OFF_CIV), SG_LEN)
#define GET_LVI(port) MODULOP2(inb((port) + OFF_LVI), SG_LEN)
/* set LVI from CIV */
/* set LVI from CIV */
#define CIV_TO_LVI(port, off) outb((inb(port+OFF_CIV)+off) & 31, port+OFF_LVI)
#define CIV_TO_LVI(port, off) \
outb(MODULOP2(GET_CIV((port)) + (off), SG_LEN), (port) + OFF_LVI)
static
struct
i810_card
*
devs
=
NULL
;
static
struct
i810_card
*
devs
=
NULL
;
...
@@ -762,7 +771,7 @@ static inline unsigned i810_get_dma_addr(struct i810_state *state, int rec)
...
@@ -762,7 +771,7 @@ static inline unsigned i810_get_dma_addr(struct i810_state *state, int rec)
port_picb
=
port
+
OFF_PICB
;
port_picb
=
port
+
OFF_PICB
;
do
{
do
{
civ
=
inb
(
port
+
OFF_CIV
)
&
31
;
civ
=
GET_CIV
(
port
)
;
offset
=
inw
(
port_picb
);
offset
=
inw
(
port_picb
);
/* Must have a delay here! */
/* Must have a delay here! */
if
(
offset
==
0
)
if
(
offset
==
0
)
...
@@ -782,7 +791,7 @@ static inline unsigned i810_get_dma_addr(struct i810_state *state, int rec)
...
@@ -782,7 +791,7 @@ static inline unsigned i810_get_dma_addr(struct i810_state *state, int rec)
* that we won't have to worry about the chip still being
* that we won't have to worry about the chip still being
* out of sync with reality ;-)
* out of sync with reality ;-)
*/
*/
}
while
(
civ
!=
(
inb
(
port
+
OFF_CIV
)
&
31
)
||
offset
!=
inw
(
port_picb
));
}
while
(
civ
!=
GET_CIV
(
port
)
||
offset
!=
inw
(
port_picb
));
return
(((
civ
+
1
)
*
dmabuf
->
fragsize
-
(
bytes
*
offset
))
return
(((
civ
+
1
)
*
dmabuf
->
fragsize
-
(
bytes
*
offset
))
%
dmabuf
->
dmasize
);
%
dmabuf
->
dmasize
);
...
@@ -992,6 +1001,7 @@ static int prog_dmabuf(struct i810_state *state, unsigned rec)
...
@@ -992,6 +1001,7 @@ static int prog_dmabuf(struct i810_state *state, unsigned rec)
dmabuf
->
numfrag
=
SG_LEN
;
dmabuf
->
numfrag
=
SG_LEN
;
dmabuf
->
fragsize
=
dmabuf
->
dmasize
/
dmabuf
->
numfrag
;
dmabuf
->
fragsize
=
dmabuf
->
dmasize
/
dmabuf
->
numfrag
;
dmabuf
->
fragsamples
=
dmabuf
->
fragsize
>>
1
;
dmabuf
->
fragsamples
=
dmabuf
->
fragsize
>>
1
;
dmabuf
->
fragshift
=
ffs
(
dmabuf
->
fragsize
)
-
1
;
dmabuf
->
userfragsize
=
dmabuf
->
ossfragsize
;
dmabuf
->
userfragsize
=
dmabuf
->
ossfragsize
;
dmabuf
->
userfrags
=
dmabuf
->
dmasize
/
dmabuf
->
ossfragsize
;
dmabuf
->
userfrags
=
dmabuf
->
dmasize
/
dmabuf
->
ossfragsize
;
...
@@ -999,16 +1009,12 @@ static int prog_dmabuf(struct i810_state *state, unsigned rec)
...
@@ -999,16 +1009,12 @@ static int prog_dmabuf(struct i810_state *state, unsigned rec)
if
(
dmabuf
->
ossmaxfrags
==
4
)
{
if
(
dmabuf
->
ossmaxfrags
==
4
)
{
fragint
=
8
;
fragint
=
8
;
dmabuf
->
fragshift
=
2
;
}
else
if
(
dmabuf
->
ossmaxfrags
==
8
)
{
}
else
if
(
dmabuf
->
ossmaxfrags
==
8
)
{
fragint
=
4
;
fragint
=
4
;
dmabuf
->
fragshift
=
3
;
}
else
if
(
dmabuf
->
ossmaxfrags
==
16
)
{
}
else
if
(
dmabuf
->
ossmaxfrags
==
16
)
{
fragint
=
2
;
fragint
=
2
;
dmabuf
->
fragshift
=
4
;
}
else
{
}
else
{
fragint
=
1
;
fragint
=
1
;
dmabuf
->
fragshift
=
5
;
}
}
/*
/*
* Now set up the ring
* Now set up the ring
...
@@ -1072,41 +1078,41 @@ static void __i810_update_lvi(struct i810_state *state, int rec)
...
@@ -1072,41 +1078,41 @@ static void __i810_update_lvi(struct i810_state *state, int rec)
{
{
struct
dmabuf
*
dmabuf
=
&
state
->
dmabuf
;
struct
dmabuf
*
dmabuf
=
&
state
->
dmabuf
;
int
x
,
port
;
int
x
,
port
;
int
trigger
;
int
count
,
fragsize
;
void
(
*
start
)(
struct
i810_state
*
);
count
=
dmabuf
->
count
;
port
=
state
->
card
->
iobase
;
port
=
state
->
card
->
iobase
;
if
(
rec
)
if
(
rec
)
{
port
+=
dmabuf
->
read_channel
->
port
;
port
+=
dmabuf
->
read_channel
->
port
;
else
trigger
=
PCM_ENABLE_INPUT
;
start
=
__start_adc
;
count
=
dmabuf
->
dmasize
-
count
;
}
else
{
port
+=
dmabuf
->
write_channel
->
port
;
port
+=
dmabuf
->
write_channel
->
port
;
trigger
=
PCM_ENABLE_OUTPUT
;
start
=
__start_dac
;
}
/* Do not process partial fragments. */
fragsize
=
dmabuf
->
fragsize
;
if
(
count
<
fragsize
)
return
;
/* if we are currently stopped, then our CIV is actually set to our
* *last* sg segment and we are ready to wrap to the next. However,
* if we set our LVI to the last sg segment, then it won't wrap to
* the next sg segment, it won't even get a start. So, instead, when
* we are stopped, we set both the LVI value and also we increment
* the CIV value to the next sg segment to be played so that when
* we call start_{dac,adc}, things will operate properly
*/
if
(
!
dmabuf
->
enable
&&
dmabuf
->
ready
)
{
if
(
!
dmabuf
->
enable
&&
dmabuf
->
ready
)
{
if
(
rec
&&
dmabuf
->
count
<
dmabuf
->
dmasize
&&
if
(
!
(
dmabuf
->
trigger
&
trigger
))
(
dmabuf
->
trigger
&
PCM_ENABLE_INPUT
))
return
;
{
CIV_TO_LVI
(
port
,
1
);
start
(
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
&&
(
dmabuf
->
trigger
&
PCM_ENABLE_OUTPUT
))
{
CIV_TO_LVI
(
port
,
1
);
__start_dac
(
state
);
while
(
!
(
inb
(
port
+
OFF_CR
)
&
((
1
<<
4
)
|
(
1
<<
2
)))
)
;
}
}
}
/*
swptr
- 1 is the tail of our transfer */
/*
MASKP2(swptr, fragsize)
- 1 is the tail of our transfer */
x
=
(
dmabuf
->
dmasize
+
dmabuf
->
swptr
-
1
)
%
dmabuf
->
dmasize
;
x
=
MODULOP2
(
MASKP2
(
dmabuf
->
swptr
,
fragsize
)
-
1
,
dmabuf
->
dmasize
)
;
x
/=
dmabuf
->
fragsize
;
x
>>=
dmabuf
->
fragshift
;
outb
(
x
,
port
+
OFF_LVI
);
outb
(
x
,
port
+
OFF_LVI
);
}
}
static
void
i810_update_lvi
(
struct
i810_state
*
state
,
int
rec
)
static
void
i810_update_lvi
(
struct
i810_state
*
state
,
int
rec
)
...
@@ -1126,13 +1132,17 @@ static void i810_update_ptr(struct i810_state *state)
...
@@ -1126,13 +1132,17 @@ static void i810_update_ptr(struct i810_state *state)
{
{
struct
dmabuf
*
dmabuf
=
&
state
->
dmabuf
;
struct
dmabuf
*
dmabuf
=
&
state
->
dmabuf
;
unsigned
hwptr
;
unsigned
hwptr
;
unsigned
fragmask
,
dmamask
;
int
diff
;
int
diff
;
/* error handling and process wake up for DAC */
fragmask
=
MASKP2
(
~
0
,
dmabuf
->
fragsize
);
dmamask
=
MODULOP2
(
~
0
,
dmabuf
->
dmasize
);
/* error handling and process wake up for ADC */
if
(
dmabuf
->
enable
==
ADC_RUNNING
)
{
if
(
dmabuf
->
enable
==
ADC_RUNNING
)
{
/* update hardware pointer */
/* update hardware pointer */
hwptr
=
i810_get_dma_addr
(
state
,
1
);
hwptr
=
i810_get_dma_addr
(
state
,
1
)
&
fragmask
;
diff
=
(
dmabuf
->
dmasize
+
hwptr
-
dmabuf
->
hwptr
)
%
dmabuf
->
dmasize
;
diff
=
(
hwptr
-
dmabuf
->
hwptr
)
&
dmamask
;
#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
printk
(
"ADC HWP %d,%d,%d
\n
"
,
hwptr
,
dmabuf
->
hwptr
,
diff
);
printk
(
"ADC HWP %d,%d,%d
\n
"
,
hwptr
,
dmabuf
->
hwptr
,
diff
);
#endif
#endif
...
@@ -1144,20 +1154,20 @@ static void i810_update_ptr(struct i810_state *state)
...
@@ -1144,20 +1154,20 @@ static void i810_update_ptr(struct i810_state *state)
/* this is normal for the end of a read */
/* this is normal for the end of a read */
/* only give an error if we went past the */
/* only give an error if we went past the */
/* last valid sg entry */
/* last valid sg entry */
if
((
inb
(
state
->
card
->
iobase
+
PI_CIV
)
&
31
)
!=
if
(
GET_CIV
(
state
->
card
->
iobase
+
PI_BASE
)
!=
(
inb
(
state
->
card
->
iobase
+
PI_LVI
)
&
31
))
{
GET_LVI
(
state
->
card
->
iobase
+
PI_BASE
))
{
printk
(
KERN_WARNING
"i810_audio: DMA overrun on read
\n
"
);
printk
(
KERN_WARNING
"i810_audio: DMA overrun on read
\n
"
);
dmabuf
->
error
++
;
dmabuf
->
error
++
;
}
}
}
}
if
(
d
mabuf
->
count
>
dmabuf
->
userfragsize
)
if
(
d
iff
)
wake_up
(
&
dmabuf
->
wait
);
wake_up
(
&
dmabuf
->
wait
);
}
}
/* error handling and process wake up for DAC */
/* error handling and process wake up for DAC */
if
(
dmabuf
->
enable
==
DAC_RUNNING
)
{
if
(
dmabuf
->
enable
==
DAC_RUNNING
)
{
/* update hardware pointer */
/* update hardware pointer */
hwptr
=
i810_get_dma_addr
(
state
,
0
);
hwptr
=
i810_get_dma_addr
(
state
,
0
)
&
fragmask
;
diff
=
(
dmabuf
->
dmasize
+
hwptr
-
dmabuf
->
hwptr
)
%
dmabuf
->
dmasize
;
diff
=
(
hwptr
-
dmabuf
->
hwptr
)
&
dmamask
;
#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
#if defined(DEBUG_INTERRUPTS) || defined(DEBUG_MMAP)
printk
(
"DAC HWP %d,%d,%d
\n
"
,
hwptr
,
dmabuf
->
hwptr
,
diff
);
printk
(
"DAC HWP %d,%d,%d
\n
"
,
hwptr
,
dmabuf
->
hwptr
,
diff
);
#endif
#endif
...
@@ -1169,18 +1179,18 @@ static void i810_update_ptr(struct i810_state *state)
...
@@ -1169,18 +1179,18 @@ static void i810_update_ptr(struct i810_state *state)
/* this is normal for the end of a write */
/* this is normal for the end of a write */
/* only give an error if we went past the */
/* only give an error if we went past the */
/* last valid sg entry */
/* last valid sg entry */
if
((
inb
(
state
->
card
->
iobase
+
PO_CIV
)
&
31
)
!=
if
(
GET_CIV
(
state
->
card
->
iobase
+
PO_BASE
)
!=
(
inb
(
state
->
card
->
iobase
+
PO_LVI
)
&
31
))
{
GET_LVI
(
state
->
card
->
iobase
+
PO_BASE
))
{
printk
(
KERN_WARNING
"i810_audio: DMA overrun on write
\n
"
);
printk
(
KERN_WARNING
"i810_audio: DMA overrun on write
\n
"
);
printk
(
"i810_audio: CIV %d, LVI %d, hwptr %x, "
printk
(
"i810_audio: CIV %d, LVI %d, hwptr %x, "
"count %d
\n
"
,
"count %d
\n
"
,
inb
(
state
->
card
->
iobase
+
PO_CIV
)
&
31
,
GET_CIV
(
state
->
card
->
iobase
+
PO_BASE
)
,
inb
(
state
->
card
->
iobase
+
PO_LVI
)
&
31
,
GET_LVI
(
state
->
card
->
iobase
+
PO_BASE
)
,
dmabuf
->
hwptr
,
dmabuf
->
count
);
dmabuf
->
hwptr
,
dmabuf
->
count
);
dmabuf
->
error
++
;
dmabuf
->
error
++
;
}
}
}
}
if
(
d
mabuf
->
count
<
(
dmabuf
->
dmasize
-
dmabuf
->
userfragsize
)
)
if
(
d
iff
)
wake_up
(
&
dmabuf
->
wait
);
wake_up
(
&
dmabuf
->
wait
);
}
}
}
}
...
@@ -1197,7 +1207,6 @@ static inline int i810_get_free_write_space(struct i810_state *state)
...
@@ -1197,7 +1207,6 @@ static inline int i810_get_free_write_space(struct i810_state *state)
dmabuf
->
swptr
=
dmabuf
->
hwptr
;
dmabuf
->
swptr
=
dmabuf
->
hwptr
;
}
}
free
=
dmabuf
->
dmasize
-
dmabuf
->
count
;
free
=
dmabuf
->
dmasize
-
dmabuf
->
count
;
free
-=
(
dmabuf
->
hwptr
%
dmabuf
->
fragsize
);
if
(
free
<
0
)
if
(
free
<
0
)
return
(
0
);
return
(
0
);
return
(
free
);
return
(
free
);
...
@@ -1215,12 +1224,27 @@ static inline int i810_get_available_read_data(struct i810_state *state)
...
@@ -1215,12 +1224,27 @@ static inline int i810_get_available_read_data(struct i810_state *state)
dmabuf
->
swptr
=
dmabuf
->
hwptr
;
dmabuf
->
swptr
=
dmabuf
->
hwptr
;
}
}
avail
=
dmabuf
->
count
;
avail
=
dmabuf
->
count
;
avail
-=
(
dmabuf
->
hwptr
%
dmabuf
->
fragsize
);
if
(
avail
<
0
)
if
(
avail
<
0
)
return
(
0
);
return
(
0
);
return
(
avail
);
return
(
avail
);
}
}
static
inline
void
fill_partial_frag
(
struct
dmabuf
*
dmabuf
)
{
unsigned
fragsize
;
unsigned
swptr
,
len
;
fragsize
=
dmabuf
->
fragsize
;
swptr
=
dmabuf
->
swptr
;
len
=
fragsize
-
MODULOP2
(
dmabuf
->
swptr
,
fragsize
);
if
(
len
==
fragsize
)
return
;
memset
(
dmabuf
->
rawbuf
+
swptr
,
'\0'
,
len
);
dmabuf
->
swptr
=
MODULOP2
(
swptr
+
len
,
dmabuf
->
dmasize
);
dmabuf
->
count
+=
len
;
}
static
int
drain_dac
(
struct
i810_state
*
state
,
int
signals_allowed
)
static
int
drain_dac
(
struct
i810_state
*
state
,
int
signals_allowed
)
{
{
DECLARE_WAITQUEUE
(
wait
,
current
);
DECLARE_WAITQUEUE
(
wait
,
current
);
...
@@ -1235,30 +1259,28 @@ static int drain_dac(struct i810_state *state, int signals_allowed)
...
@@ -1235,30 +1259,28 @@ static int drain_dac(struct i810_state *state, int signals_allowed)
stop_dac
(
state
);
stop_dac
(
state
);
return
0
;
return
0
;
}
}
spin_lock_irqsave
(
&
state
->
card
->
lock
,
flags
);
fill_partial_frag
(
dmabuf
);
/*
* This will make sure that our LVI is correct, that our
* pointer is updated, and that the DAC is running. We
* have to force the setting of dmabuf->trigger to avoid
* any possible deadlocks.
*/
dmabuf
->
trigger
=
PCM_ENABLE_OUTPUT
;
__i810_update_lvi
(
state
,
0
);
spin_unlock_irqrestore
(
&
state
->
card
->
lock
,
flags
);
add_wait_queue
(
&
dmabuf
->
wait
,
&
wait
);
add_wait_queue
(
&
dmabuf
->
wait
,
&
wait
);
for
(;;)
{
for
(;;)
{
spin_lock_irqsave
(
&
state
->
card
->
lock
,
flags
);
spin_lock_irqsave
(
&
state
->
card
->
lock
,
flags
);
i810_update_ptr
(
state
);
i810_update_ptr
(
state
);
count
=
dmabuf
->
count
;
count
=
dmabuf
->
count
;
spin_unlock_irqrestore
(
&
state
->
card
->
lock
,
flags
);
if
(
count
<=
0
)
break
;
/*
* This will make sure that our LVI is correct, that our
* pointer is updated, and that the DAC is running. We
* have to force the setting of dmabuf->trigger to avoid
* any possible deadlocks.
*/
if
(
!
dmabuf
->
enable
)
{
dmabuf
->
trigger
=
PCM_ENABLE_OUTPUT
;
i810_update_lvi
(
state
,
0
);
}
if
(
signal_pending
(
current
)
&&
signals_allowed
)
{
break
;
}
/* It seems that we have to set the current state to
/* It seems that we have to set the current state to
* TASK_INTERRUPTIBLE every time to make the process
* TASK_INTERRUPTIBLE every time to make the process
...
@@ -1269,7 +1291,17 @@ static int drain_dac(struct i810_state *state, int signals_allowed)
...
@@ -1269,7 +1291,17 @@ static int drain_dac(struct i810_state *state, int signals_allowed)
* instead of actually sleeping and waiting for an
* instead of actually sleeping and waiting for an
* interrupt to wake us up!
* interrupt to wake us up!
*/
*/
set_current_state
(
TASK_INTERRUPTIBLE
);
__set_current_state
(
signals_allowed
?
TASK_INTERRUPTIBLE
:
TASK_UNINTERRUPTIBLE
);
spin_unlock_irqrestore
(
&
state
->
card
->
lock
,
flags
);
if
(
count
<=
0
)
break
;
if
(
signal_pending
(
current
)
&&
signals_allowed
)
{
break
;
}
/*
/*
* set the timeout to significantly longer than it *should*
* set the timeout to significantly longer than it *should*
* take for the DAC to drain the DMA buffer
* take for the DAC to drain the DMA buffer
...
@@ -1350,11 +1382,10 @@ static void i810_channel_interrupt(struct i810_card *card)
...
@@ -1350,11 +1382,10 @@ static void i810_channel_interrupt(struct i810_card *card)
if
(
status
&
DMA_INT_DCH
)
if
(
status
&
DMA_INT_DCH
)
printk
(
"DCH -"
);
printk
(
"DCH -"
);
#endif
#endif
if
(
dmabuf
->
enable
&
DAC_RUNNING
)
count
=
dmabuf
->
count
;
count
=
dmabuf
->
count
;
if
(
dmabuf
->
enable
&
ADC_RUNNING
)
else
count
=
dmabuf
->
dmasize
-
count
;
count
=
dmabuf
->
dmasize
-
dmabuf
->
count
;
if
(
count
>=
(
int
)
dmabuf
->
fragsize
)
{
if
(
count
>
0
)
{
outb
(
inb
(
port
+
OFF_CR
)
|
1
,
port
+
OFF_CR
);
outb
(
inb
(
port
+
OFF_CR
)
|
1
,
port
+
OFF_CR
);
#ifdef DEBUG_INTERRUPTS
#ifdef DEBUG_INTERRUPTS
printk
(
" CONTINUE "
);
printk
(
" CONTINUE "
);
...
@@ -1417,6 +1448,7 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
...
@@ -1417,6 +1448,7 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
unsigned
long
flags
;
unsigned
long
flags
;
unsigned
int
swptr
;
unsigned
int
swptr
;
int
cnt
;
int
cnt
;
int
pending
;
DECLARE_WAITQUEUE
(
waita
,
current
);
DECLARE_WAITQUEUE
(
waita
,
current
);
#ifdef DEBUG2
#ifdef DEBUG2
...
@@ -1442,6 +1474,8 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
...
@@ -1442,6 +1474,8 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
return
-
EFAULT
;
return
-
EFAULT
;
ret
=
0
;
ret
=
0
;
pending
=
0
;
add_wait_queue
(
&
dmabuf
->
wait
,
&
waita
);
add_wait_queue
(
&
dmabuf
->
wait
,
&
waita
);
while
(
count
>
0
)
{
while
(
count
>
0
)
{
set_current_state
(
TASK_INTERRUPTIBLE
);
set_current_state
(
TASK_INTERRUPTIBLE
);
...
@@ -1455,8 +1489,8 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
...
@@ -1455,8 +1489,8 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
}
}
continue
;
continue
;
}
}
swptr
=
dmabuf
->
swptr
;
cnt
=
i810_get_available_read_data
(
state
);
cnt
=
i810_get_available_read_data
(
state
);
swptr
=
dmabuf
->
swptr
;
// this is to make the copy_to_user simpler below
// this is to make the copy_to_user simpler below
if
(
cnt
>
(
dmabuf
->
dmasize
-
swptr
))
if
(
cnt
>
(
dmabuf
->
dmasize
-
swptr
))
cnt
=
dmabuf
->
dmasize
-
swptr
;
cnt
=
dmabuf
->
dmasize
-
swptr
;
...
@@ -1464,15 +1498,6 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
...
@@ -1464,15 +1498,6 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
if
(
cnt
>
count
)
if
(
cnt
>
count
)
cnt
=
count
;
cnt
=
count
;
/* Lop off the last two bits to force the code to always
* write in full samples. This keeps software that sets
* O_NONBLOCK but doesn't check the return value of the
* write call from getting things out of state where they
* think a full 4 byte sample was written when really only
* a portion was, resulting in odd sound and stereo
* hysteresis.
*/
cnt
&=
~
0x3
;
if
(
cnt
<=
0
)
{
if
(
cnt
<=
0
)
{
unsigned
long
tmo
;
unsigned
long
tmo
;
/*
/*
...
@@ -1526,7 +1551,7 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
...
@@ -1526,7 +1551,7 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
goto
done
;
goto
done
;
}
}
swptr
=
(
swptr
+
cnt
)
%
dmabuf
->
dmasize
;
swptr
=
MODULOP2
(
swptr
+
cnt
,
dmabuf
->
dmasize
)
;
spin_lock_irqsave
(
&
card
->
lock
,
flags
);
spin_lock_irqsave
(
&
card
->
lock
,
flags
);
...
@@ -1535,7 +1560,7 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
...
@@ -1535,7 +1560,7 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
continue
;
continue
;
}
}
dmabuf
->
swptr
=
swptr
;
dmabuf
->
swptr
=
swptr
;
dmabuf
->
count
-=
cnt
;
pending
=
dmabuf
->
count
-=
cnt
;
spin_unlock_irqrestore
(
&
card
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
card
->
lock
,
flags
);
count
-=
cnt
;
count
-=
cnt
;
...
@@ -1543,7 +1568,9 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
...
@@ -1543,7 +1568,9 @@ static ssize_t i810_read(struct file *file, char *buffer, size_t count, loff_t *
ret
+=
cnt
;
ret
+=
cnt
;
}
}
done:
done:
i810_update_lvi
(
state
,
1
);
pending
=
dmabuf
->
dmasize
-
pending
;
if
(
dmabuf
->
enable
||
pending
>=
dmabuf
->
userfragsize
)
i810_update_lvi
(
state
,
1
);
set_current_state
(
TASK_RUNNING
);
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
dmabuf
->
wait
,
&
waita
);
remove_wait_queue
(
&
dmabuf
->
wait
,
&
waita
);
...
@@ -1560,7 +1587,8 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
...
@@ -1560,7 +1587,8 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
ssize_t
ret
;
ssize_t
ret
;
unsigned
long
flags
;
unsigned
long
flags
;
unsigned
int
swptr
=
0
;
unsigned
int
swptr
=
0
;
int
cnt
,
x
;
int
pending
;
int
cnt
;
DECLARE_WAITQUEUE
(
waita
,
current
);
DECLARE_WAITQUEUE
(
waita
,
current
);
#ifdef DEBUG2
#ifdef DEBUG2
...
@@ -1585,6 +1613,8 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
...
@@ -1585,6 +1613,8 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
return
-
EFAULT
;
return
-
EFAULT
;
ret
=
0
;
ret
=
0
;
pending
=
0
;
add_wait_queue
(
&
dmabuf
->
wait
,
&
waita
);
add_wait_queue
(
&
dmabuf
->
wait
,
&
waita
);
while
(
count
>
0
)
{
while
(
count
>
0
)
{
set_current_state
(
TASK_INTERRUPTIBLE
);
set_current_state
(
TASK_INTERRUPTIBLE
);
...
@@ -1599,8 +1629,8 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
...
@@ -1599,8 +1629,8 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
continue
;
continue
;
}
}
swptr
=
dmabuf
->
swptr
;
cnt
=
i810_get_free_write_space
(
state
);
cnt
=
i810_get_free_write_space
(
state
);
swptr
=
dmabuf
->
swptr
;
/* Bound the maximum size to how much we can copy to the
/* Bound the maximum size to how much we can copy to the
* dma buffer before we hit the end. If we have more to
* dma buffer before we hit the end. If we have more to
* copy then it will get done in a second pass of this
* copy then it will get done in a second pass of this
...
@@ -1615,15 +1645,6 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
...
@@ -1615,15 +1645,6 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
#endif
#endif
if
(
cnt
>
count
)
if
(
cnt
>
count
)
cnt
=
count
;
cnt
=
count
;
/* Lop off the last two bits to force the code to always
* write in full samples. This keeps software that sets
* O_NONBLOCK but doesn't check the return value of the
* write call from getting things out of state where they
* think a full 4 byte sample was written when really only
* a portion was, resulting in odd sound and stereo
* hysteresis.
*/
cnt
&=
~
0x3
;
if
(
cnt
<=
0
)
{
if
(
cnt
<=
0
)
{
unsigned
long
tmo
;
unsigned
long
tmo
;
// There is data waiting to be played
// There is data waiting to be played
...
@@ -1668,7 +1689,7 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
...
@@ -1668,7 +1689,7 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
goto
ret
;
goto
ret
;
}
}
swptr
=
(
swptr
+
cnt
)
%
dmabuf
->
dmasize
;
swptr
=
MODULOP2
(
swptr
+
cnt
,
dmabuf
->
dmasize
)
;
spin_lock_irqsave
(
&
state
->
card
->
lock
,
flags
);
spin_lock_irqsave
(
&
state
->
card
->
lock
,
flags
);
if
(
PM_SUSPENDED
(
card
))
{
if
(
PM_SUSPENDED
(
card
))
{
...
@@ -1677,19 +1698,16 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
...
@@ -1677,19 +1698,16 @@ static ssize_t i810_write(struct file *file, const char *buffer, size_t count, l
}
}
dmabuf
->
swptr
=
swptr
;
dmabuf
->
swptr
=
swptr
;
dmabuf
->
count
+=
cnt
;
pending
=
dmabuf
->
count
+=
cnt
;
count
-=
cnt
;
count
-=
cnt
;
buffer
+=
cnt
;
buffer
+=
cnt
;
ret
+=
cnt
;
ret
+=
cnt
;
spin_unlock_irqrestore
(
&
state
->
card
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
state
->
card
->
lock
,
flags
);
}
}
if
(
swptr
%
dmabuf
->
fragsize
)
{
x
=
dmabuf
->
fragsize
-
(
swptr
%
dmabuf
->
fragsize
);
memset
(
dmabuf
->
rawbuf
+
swptr
,
'\0'
,
x
);
}
ret:
ret:
i810_update_lvi
(
state
,
0
);
if
(
dmabuf
->
enable
||
pending
>=
dmabuf
->
userfragsize
)
i810_update_lvi
(
state
,
0
);
set_current_state
(
TASK_RUNNING
);
set_current_state
(
TASK_RUNNING
);
remove_wait_queue
(
&
dmabuf
->
wait
,
&
waita
);
remove_wait_queue
(
&
dmabuf
->
wait
,
&
waita
);
...
@@ -2179,6 +2197,13 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
...
@@ -2179,6 +2197,13 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
#if defined(DEBUG) || defined(DEBUG_MMAP)
#if defined(DEBUG) || defined(DEBUG_MMAP)
printk
(
"SNDCTL_DSP_SETTRIGGER 0x%x
\n
"
,
val
);
printk
(
"SNDCTL_DSP_SETTRIGGER 0x%x
\n
"
,
val
);
#endif
#endif
/* silently ignore invalid PCM_ENABLE_xxx bits,
* like the other drivers do
*/
if
(
!
(
file
->
f_mode
&
FMODE_READ
))
val
&=
~
PCM_ENABLE_INPUT
;
if
(
!
(
file
->
f_mode
&
FMODE_WRITE
))
val
&=
~
PCM_ENABLE_OUTPUT
;
if
((
file
->
f_mode
&
FMODE_READ
)
&&
!
(
val
&
PCM_ENABLE_INPUT
)
&&
dmabuf
->
enable
==
ADC_RUNNING
)
{
if
((
file
->
f_mode
&
FMODE_READ
)
&&
!
(
val
&
PCM_ENABLE_INPUT
)
&&
dmabuf
->
enable
==
ADC_RUNNING
)
{
stop_adc
(
state
);
stop_adc
(
state
);
}
}
...
@@ -2186,7 +2211,7 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
...
@@ -2186,7 +2211,7 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
stop_dac
(
state
);
stop_dac
(
state
);
}
}
dmabuf
->
trigger
=
val
;
dmabuf
->
trigger
=
val
;
if
((
file
->
f_mode
&
FMODE_WRITE
)
&&
(
val
&
PCM_ENABLE_OUTPUT
)
&&
!
(
dmabuf
->
enable
&
DAC_RUNNING
))
{
if
((
val
&
PCM_ENABLE_OUTPUT
)
&&
!
(
dmabuf
->
enable
&
DAC_RUNNING
))
{
if
(
!
dmabuf
->
write_channel
)
{
if
(
!
dmabuf
->
write_channel
)
{
dmabuf
->
ready
=
0
;
dmabuf
->
ready
=
0
;
dmabuf
->
write_channel
=
state
->
card
->
alloc_pcm_channel
(
state
->
card
);
dmabuf
->
write_channel
=
state
->
card
->
alloc_pcm_channel
(
state
->
card
);
...
@@ -2202,12 +2227,12 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
...
@@ -2202,12 +2227,12 @@ static int i810_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
dmabuf
->
swptr
=
dmabuf
->
hwptr
;
dmabuf
->
swptr
=
dmabuf
->
hwptr
;
dmabuf
->
count
=
i810_get_free_write_space
(
state
);
dmabuf
->
count
=
i810_get_free_write_space
(
state
);
dmabuf
->
swptr
=
(
dmabuf
->
swptr
+
dmabuf
->
count
)
%
dmabuf
->
dmasize
;
dmabuf
->
swptr
=
(
dmabuf
->
swptr
+
dmabuf
->
count
)
%
dmabuf
->
dmasize
;
__i810_update_lvi
(
state
,
0
);
spin_unlock_irqrestore
(
&
state
->
card
->
lock
,
flags
);
spin_unlock_irqrestore
(
&
state
->
card
->
lock
,
flags
);
}
else
}
start_dac
(
state
);
i810_update_lvi
(
state
,
0
);
start_dac
(
state
);
}
}
if
((
file
->
f_mode
&
FMODE_READ
)
&&
(
val
&
PCM_ENABLE_INPUT
)
&&
!
(
dmabuf
->
enable
&
ADC_RUNNING
))
{
if
((
val
&
PCM_ENABLE_INPUT
)
&&
!
(
dmabuf
->
enable
&
ADC_RUNNING
))
{
if
(
!
dmabuf
->
read_channel
)
{
if
(
!
dmabuf
->
read_channel
)
{
dmabuf
->
ready
=
0
;
dmabuf
->
ready
=
0
;
dmabuf
->
read_channel
=
state
->
card
->
alloc_rec_pcm_channel
(
state
->
card
);
dmabuf
->
read_channel
=
state
->
card
->
alloc_rec_pcm_channel
(
state
->
card
);
...
@@ -3065,7 +3090,7 @@ static void __devinit i810_configure_clocking (void)
...
@@ -3065,7 +3090,7 @@ static void __devinit i810_configure_clocking (void)
goto
config_out
;
goto
config_out
;
}
}
dmabuf
->
count
=
dmabuf
->
dmasize
;
dmabuf
->
count
=
dmabuf
->
dmasize
;
CIV_TO_LVI
(
card
->
iobase
+
dmabuf
->
write_channel
->
port
,
3
1
);
CIV_TO_LVI
(
card
->
iobase
+
dmabuf
->
write_channel
->
port
,
-
1
);
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
);
...
...
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